random.choice不是随机的

Mar*_*wis 13 python random

我在Linux上使用Python 2.5,在多个并行的FCGI进程中.我用

    chars = string.ascii_letters + string.digits
    cookie = ''.join([random.choice(chars) for x in range(32)])
Run Code Online (Sandbox Code Playgroud)

生成不同的cookie.假设RNG是从/ dev/urandom播种的,并且随机数序列来自Mersenne twister,我预计几乎没有碰撞机会.

但是,我确实看到了常规冲突,即使只有少数(<100)用户随时登录.

为什么随机数不随机?

Gle*_*ard 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
Run Code Online (Sandbox Code Playgroud)

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))
Run Code Online (Sandbox Code Playgroud)

...这应该是非常安全的(也就是说,难以获取一串会话cookie并猜测其他现有的会话cookie).

  • 仅仅因为随机数发生器具有长周期并不意味着难以在周期内获取序列并找出它的位置.如果我给你序列0,1,2,3 ...,它有一个非常长的周期(无限),但是找出下一个值是多么微不足道.您需要一个加密安全的序列 - 从输出中很难确定引擎的状态.这就是安全哈希的用途.我更喜欢通过SHA-1散列urandom,但是通过SHA-1散列MT也可能很好. (9认同)
  • 来自维基百科:"本机形式的算法不适合加密(与Blum Blum Shub不同).观察足够数量的迭代(MT19937为624),可以预测所有未来的迭代." (http://en.wikipedia.org/wiki/Mersenne_twister) (3认同)
  • 我刚刚检查过:在Linux上,/ dev/urandom确实哈希其输出. (2认同)