У меня есть система, которая должна планировать некоторые вещи и возвращать идентификаторы запланированным задачам некоторым сторонним объектам. Пользователь в основном сделает это:
identifier = MyLib.Schedule(something)
# Nah, let's unschedule it.
MyLib.Unschedule(identifier)
Я часто использую этот тип шаблона во внутреннем коде, и я всегда использую простые целые числа в качестве идентификатора. Но если идентификаторы используются ненадежным кодом, злоумышленник может взломать всю систему, выполнив один Unschedule(randint())
.
Мне нужно, чтобы пользователи кода могли только распланировать идентификаторы, которые они на самом деле запланировали.
Единственное решение, которое я могу придумать, - это генерировать 64-битные случайные числа в качестве идентификаторов и отслеживать, какие идентификаторы в настоящее время раздаются, чтобы избежать смехотворно маловероятных дубликатов. Или 128-битный? Когда я могу сказать «это достаточно случайно, дубликаты не могут возникнуть», если вообще когда-либо?
Или, еще лучше, есть ли более разумный способ сделать это? Есть ли способ генерировать токены идентификаторов, которые генератор может легко отслеживать (избегая дубликатов), но неотличимый от случайных чисел для получателя?
РЕДАКТИРОВАТЬ - Решение на основе принятого ответа:
from Crypto.Cipher import AES
import struct, os, itertools
class AES_UniqueIdentifier(object):
def __init__(self):
self.salt = os.urandom(8)
self.count = itertools.count(0)
self.cipher = AES.new(os.urandom(16), AES.MODE_ECB)
def Generate(self):
return self.cipher.encrypt(self.salt +
struct.pack("Q", next(self.count)))
def Verify(self, identifier):
"Return true if identifier was generated by this object."
return self.cipher.decrypt(identifier)[0:8] == self.salt