I have a system that needs to plan some things and return identifiers to scheduled tasks to some extraneous objects. The user will basically do this:
identifier = MyLib.Schedule(something)
MyLib.Unschedule(identifier)
I use this type of pattern in the internal code, and I always use prime integers as an identifier. But if identifiers are used by untrusted code, an attacker could break the entire system by doing a single one Unschedule(randint()).
I need the code users to be able to send out only those schedules that they really have planned.
The only solution I can think of is to generate 64-bit random numbers as identifiers and keep track of which identifiers are currently transmitted in order to avoid ridiculously unlikely duplicates. Or 128-bit? When can I say “this is a random enough case, no duplicates could happen”, if ever?
Or better yet, is there a smarter way to do this? Is there a way to generate identifier tokens that the generator can easily track (avoiding duplicates), but indistinguishable from random numbers to the recipient?
EDIT is a solution based on the accepted answer:
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
source
share