我有一个系统需要安排一些东西并将标识返回到某些外来对象的计划任务。用户基本上这样做:生成无法猜测的独特标记
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
大多数(伪)随机数字gerators将允许您跟踪生成的东西,通过始终使用相同的种子初始化发生器。这将产生完全相同的数字序列,因为您在同一台机器上使用它。因此,通过让种子应该是恒定的,以及生成多少个标识符的结果,可以检查是否以前生成了任何给定的数字。如果你可以重置标识符(比如当所有的计划都没有计划)时,这可能是一个简单的方法,但如果你需要跟踪一大组数字,则会变得很慢。 – Trinidad 2011-01-27 12:18:04
在安全系统上实现Unschedule()的代码是什么?客户无法检查的一种?否则,你不能指望保持客户端无法发现的秘密价值。 – 2011-01-27 12:33:56
@GregS:是的,基本上。客户端代码旨在运行沙盒。 @Trinidad:系统需要能够处理大量的数字。我至少会说每秒10000个数字。 (虽然Unschedule预计将是一个罕见的事件)。 – porgarmingduod 2011-01-27 12:37:45