如何创建在python中加密安全的随机数?


68

我正在用python创建一个项目,我想创建一个加密安全的随机数,我该怎么做?我已经在线阅读了常规随机发生器生成的数字不是密码安全的信息,并且该函数os.urandom(n)返回的是一个字符串,而不是数字。


答案是正确的开始,但是您需要精确定义“数字”的含义。浮子?一个整数?签名还是未签名?什么范围 等等
蒂姆·彼得斯

我已经筋疲力尽了,但是我的意图是和整数(应该提到)。有什么办法可以设定四人提出的建议的特定范围?
user2835118 2014年

@TimPeters能否请您检查我更新的答案是否可以?
thefourtheye 2014年

@thefourtheye,就目前而言还不错;-)我添加了另一个答案,提出了一种更简单的方法。
蒂姆·彼得斯

5
没有加密安全的随机数,但是随机数生成器可以是加密安全的。;)
ntoskrnl 2014年

Answers:


44

您可以通过将ord函数应用于所返回的字节来获取随机数列表os.urandom,如下所示

>>> import os
>>> os.urandom(10)
'm\xd4\x94\x00x7\xbe\x04\xa2R'
>>> type(os.urandom(10))
<type 'str'>
>>> map(ord, os.urandom(10))
[65, 120, 218, 135, 66, 134, 141, 140, 178, 25]

报价os.urandom文件,

返回适合加密使用n随机字节字符串。

该函数从特定于操作系统的随机性源返回随机字节。尽管返回的数据的确切质量取决于操作系统的实现,但对于加密应用程序而言,返回的数据应该足够不可预测。在类似UNIX的系统上,它将进行查询/dev/urandom,而在Windows上,它将使用CryptGenRandom()


3
对于那些想知道是否urandom真正适合密码使用的人来说,显然是这样
Claudiu

如果我只需要一个,将参数更改os.urandom为1就足够了吗?即os.urandom(1)
查理·帕克

73

由于您要生成某个特定范围内的整数,因此使用random.SystemRandom该类要容易得多。创建该类的实例将为您提供一个对象,该对象支持random模块的所有方法,但os.urandom()在幕后使用。例子:

>>> from random import SystemRandom
>>> cryptogen = SystemRandom()
>>> [cryptogen.randrange(3) for i in range(20)] # random ints in range(3)
[2, 2, 2, 2, 1, 2, 1, 2, 1, 0, 0, 1, 1, 0, 0, 2, 0, 0, 0, 0]
>>> [cryptogen.random() for i in range(3)]  # random floats in [0., 1.)
[0.2710009745425236, 0.016722063038868695, 0.8207742461236148]

等等,urandom()直接使用,您必须发明自己的算法,将其产生的随机字节转换为所需的结果。不要那样做;-)SystemRandom为您做到 。

注意文档的这一部分:

类random.SystemRandom([seed])

使用os.urandom()函数从操作系统提供的源生成随机数的类。并非在所有系统上都可用。不依赖软件状态,并且序列不可复制。因此,seed()和jumpahead()方法无效,将被忽略。如果调用getstate()和setstate()方法,则会引发NotImplementedError。


这也是一个非常好的答案,我认为实施起来不正确(直到我得到另一个答案的范围之前,我都会摆弄摆弄)。您确定它是加密安全的吗?
user2835118 2014年

3
@ user2835118,它与操作系统的实现完全一样(安全或不安全)os.urandom。这意味着“就像编写您的操作系统的人一样知道如何安全”。生活中没有绝对的保证;-)但是对于所有实际目的,是的,如果基于当前的所有知识都不以加密方式保护它,那将是惊人的。
蒂姆·彼得斯


1
虽然base64.b64encode(os.urandom(32))''.join(random.choice(b64chars) for i in range(43)b64encode(bytes(random.randrange(256) for _ in range(32)))想要使用的任何其他变体要干净一些。
尼克T

seed()在这种情况下如何使用?
hola

32

Python 3.6引入了一个新的secrets模块,该模块“提供对操作系统提供的最安全的随机性源的访问”。为了生成一些密码安全的号码,您可以致电secrets.randbelow()

secrets.randbelow(n)

它将返回0到之间的数字n


random.SystemRandom用于此。所以我真的看不到通过此模块使用它的意义。
BlackJack

2
@BlackJack有关添加模块的原因,请参阅PEP基本原理部分。除此之外,我还要补充一点,secrets直接使用模块可以使您的代码读者知道您的意图,而random.SystemRandom直接使用则不会。
Cody Piersall

6

如果您想要一个n-bit随机数,在Python 2.4+下,我找到的最简单的方法是

import random
random.SystemRandom().getrandbits(n)

请注意,SystemRandom使用os.urandom(),因此此方法的结果仅与系统的urandom()实现一样好。


1

要生成加密安全的伪随机整数,可以使用以下代码:

int(binascii.hexlify(os.urandom(n)),16)

其中n为,整数越大n,生成的整数越大。

你将不得不进口osbinascii第一。

该代码的结果可能因平台而异。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.