关于随机:rng种子的Python数量

Python number of rng seeds

在用于从种子初始化随机数的文档(python 3.5)中:

random.seed(a=None, version=2)

Initialize the random number generator.

If a is omitted or None, the current system time is used. If
randomness sources are provided by the operating system, they are used
instead of the system time (see the os.urandom() function for details
on availability).

If a is an int, it is used directly.

With version 2 (the default), a str, bytes, or bytearray object gets
converted to an int and all of its bits are used. With version 1, the
hash() of a is used instead.

它不清楚有多少种子。一个int通常只有40亿个不同的值,但是pythons包含任意精度:

1
2
3
4
5
6
x = 1
type(x) # <class 'int'>
y = 123456789123456789123456789123456789123456789123456789123456789123456789
type(y) # <class 'int'>
z = x+y
z-y # 1 (no rounding error for a 71 digit number)

他们说所有的位都被使用了,但这可能意味着这些位被用来做一个正常的32位整数的摘要。为什么这很重要?我需要一个随机的种子模式。反过来,我需要生成随机的模式序列(顺序依次有一个种子)。一个随机数生成器流将受到"生日攻击",其中在大约10万之后,如果只有32位,几乎肯定会有一个副本。虽然这不适用于密码术,但仍然是不可取的。


开放源码最棒的是能够简单地查看带有问题的代码。这是random.seed的来源:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if a is None:
    try:
        # Seed with enough bytes to span the 19937 bit
        # state space for the Mersenne Twister
        a = int.from_bytes(_urandom(2500), 'big')
    except NotImplementedError:
        import time
        a = int(time.time() * 256) # use fractional seconds

if version == 2:
    if isinstance(a, (str, bytes, bytearray)):
        if isinstance(a, str):
            a = a.encode()
        a += _sha512(a).digest()
        a = int.from_bytes(a, 'big')

super().seed(a)
self.gauss_next = None

您可以看到,如果提供了version == 2strbytes,则需要a的sha512,附加它,并使用int.from_bytes,生成非常大的int,并保证至少512位种子,即使使用非常小的自定义输入。

如下文所述,最终结果是保证种子的长度至少为624位。