我在Linux上使用Python 2.5,在多个并行的FCGI进程中。我用
chars = string.ascii_letters + string.digits
cookie = ''.join([random.choice(chars) for x in range(32)])
生成不同的Cookie。假设RNG是从/ dev / urandom播种的,并且随机数序列来自Mersenne twister,我预计几乎没有碰撞机会。
但是,我确实看到了常规的冲突,即使只有少数(<100)用户在任何时间登录。
为什么随机数不是更随机?
答案 0 :(得分:12)
它不应该产生重复。
import random
chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
def gen():
return ''.join([random.choice(chars) for x in range(32)])
test = [gen() for i in range(100000)]
print len(test), len(set(test)) # 100000 100000
chars =“ab”,重复的可能性很大;在1000000次迭代中重复126次。它与62一样不存在。
也就是说,这不是生成cookie的好方法,因为会话cookie需要不可预测,以避免涉及窃取其他人的会话cookie的攻击。 Mersenne Twister不是为生成安全随机数而设计的。这就是我的工作:
import os, hashlib
def gen():
return hashlib.sha1(os.urandom(512)).hexdigest()
test = [gen() for i in range(100000)]
print len(test), len(set(test))
...这应该是非常安全的(也就是说,难以获取一串会话cookie并猜测其他现有的会话cookie)。
答案 1 :(得分:4)
这绝对不是正常的碰撞场景:
这可能是并发问题吗?
random.Random
个实例threading.local()
)os.urandom()
来播种它们 - 而不是系统时间 - 所以你应该为每个线程获得不同的流。答案 2 :(得分:1)
我不知道你的FCGI进程是如何产生的,但是在Python解释器启动后它是否可能使用fork()(随机模块已被某些东西导入),因此有效播种来自同一来源的两个进程'random._inst
?
也许进行一些调试,检查它是否正确地从urandom播种,而不是回到不那么严格的基于时间的种子?
eta re comment:男人!那是我难倒的;如果RNG在启动时总是有不同的状态,我看不出你怎么可能发生碰撞。奇怪的。我想,必须进行大量的状态记录来调查导致冲突的特定情况,这听起来像是通过日志进行的大量工作。可能是(1a)FCGI服务器通常不会分叉,但偶尔会(可能是负载或其他东西)吗?
或者(3)某些更高级别的问题,例如破坏的HTTP代理将同一个Set-Cookie传递给多个客户端?
答案 3 :(得分:0)
我必须删除我的原始答案,这表明生成器不是来自/dev/urandom
,因为source(对于Python 3.x)明确表示它是:
def seed(self, a=None):
"""Initialize internal state from hashable object.
None or no argument seeds from current time or from an operating
system specific randomness source if available.
If a is not None or an int or long, hash(a) is used instead.
"""
if a is None:
try:
a = int(_hexlify(_urandom(16)), 16)
except NotImplementedError:
import time
a = int(time.time() * 256) # use fractional seconds
super().seed(a)
self.gauss_next = None
因此,我谦卑地接受世界上有一些我可能无法解读的谜团。
答案 4 :(得分:-4)
为避免此问题,您可以使用一系列保证不同的Cookie(例如,您可以使用一组)。每次向某人提供cookie时,都会从序列中获取cookie,然后再添加另一个cookie。另一种选择是生成UUID并将其用作cookie。
避免此问题的另一种方法可能是保留私钥,并使用私钥的(例如MD5)校验和,并将计数器值加入其中。碰撞的概率将非常低。为了更安全,在校验和中添加一些变量,比如当前时间,用户的IP地址,......
存在生成cookie的库。任何WSGI实现都可能包含cookie生成器。
如果您只对字符串的随机性感兴趣,可以生成一个文件,例如一百万个Cookie,并对该文件执行随机检查。但是,这不是我的建议。