20

我正在和一个朋友一起做一个项目,我们需要生成一个随机散列。在我们有时间讨论之前,我们都提出了不同的方法,并且因为他们使用不同的模块,所以我想问大家什么会更好——如果有这样的事情。

hashlib.sha1(str(random.random())).hexdigest()

或者

os.urandom(16).encode('hex')

输入这个问题让我觉得第二种方法更好。简单胜于复杂。如果您同意,这对于“随机”生成哈希有多可靠?我将如何测试这个?

4

5 回答 5

40

这个解决方案:

os.urandom(16).encode('hex')

是最好的,因为它使用操作系统来生成随机性,这应该可用于加密目的(取决于操作系统的实现)。

random.random()生成伪随机值

散列一个随机值不会增加任何新的随机性。

于 2012-04-26T20:43:03.270 回答
9

random.random()是一个伪 radmom 生成器,这意味着数字是从一个序列中生成的。如果您调用random.seed(some_number),那么之后生成的序列将始终相同。

os.urandom()从操作系统的 rng 中获取随机数,它使用熵池来收集真正的随机数,通常是通过来自硬件设备的随机事件,甚至存在用于生成大量随机数的系统的随机特殊熵生成器。

在 unix 系统上,传统上有两个随机数生成器:/dev/random/dev/urandom. 如果没有足够的熵可用,则调用第一个块,而当您读取/dev/urandom并且没有足够的熵数据可用时,它使用伪 rng 并且不会阻塞。

所以使用通常取决于你需要什么:如果你需要一些均匀分布的随机数,那么内置的 prng 应该就足够了。对于加密使用,使用实数随机数总是更好。

于 2012-04-26T20:55:14.573 回答
7

第二种解决方案显然比第一种解决方案具有更多的熵。假设随机比特源的质量对于os.urandom和是相同的random.random

  • 在第二种解决方案中,您正在获取 16 个字节 = 128 位的随机性
  • 在第一个解决方案中,您获取的浮点值具有大约 52 位随机性(IEEE 754 双精度,忽略次正规数等)。然后你散列它,当然,这不会增加任何随机性。

更重要的是,来自 的随机性的质量os.urandom被预期和记录为比来自 的随机性好得多random.randomos.urandom的文档字符串说“适合加密使用”。

于 2012-04-26T21:01:39.347 回答
2

测试随机性是出了名的困难 - 但是,我会选择第二种方法,但仅在这种情况下(或者,仅就我想到的而言),其中哈希是由随机数播种的。

哈希的全部意义在于创建一个基于输入的细微差异而大不相同的数字。对于您的用例,输入的随机性应该可以。但是,如果您想对文件进行哈希处理并检测一个 eensy 字节的差异,那就是哈希算法大放异彩的时候。

不过,我只是好奇:为什么要使用哈希算法?似乎您正在寻找一个纯粹的随机数,并且有很多生成 uuid 的库,它们比随机数生成器具有更强的唯一性保证。

于 2012-04-26T20:47:29.993 回答
2

如果你想要一个唯一标识符(uuid),那么你应该使用

import uuid
uuid.uuid4().hex

https://docs.python.org/3/library/uuid.html

于 2016-07-19T16:48:33.127 回答