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

use*_*118 60 python random cryptography

我在python中创建一个项目,我想创建一个加密安全的随机数,我该怎么做?我在网上看到,常规随机数生成的数字不具有加密安全性,并且该函数os.urandom(n)返回一个字符串,而不是数字.

Tim*_*ers 64

由于您希望在某个特定范围内生成整数,因此使用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]
Run Code Online (Sandbox Code Playgroud)

等等.urandom()直接使用,你必须发明自己的算法,将它产生的随机字节转换成你想要的结果.不要这样做;-) SystemRandom为你做.

请注意这部分文档:

class random.SystemRandom([seed])

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

  • @ user2835118,它与操作系统os.urandom的实现一样安全(或不安全)。这意味着“就像编写您的操作系统的人一样知道如何安全”。生活中没有绝对的保证;-)但是对于所有实际目的,是的,如果基于当前的所有知识都不以密码方式保护它,那将是惊人的。 (3认同)
  • @ user2835118 http://security.stackexchange.com/a/3939/24680您可能想要查看此答案 (2认同)

the*_*eye 39

你可以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]
Run Code Online (Sandbox Code Playgroud)

引用os.urandom文档,

返回一串适合加密使用n随机字节.

此函数从特定于OS的随机源返回随机字节.对于加密应用程序,返回的数据应该是不可预测的,尽管其确切的质量取决于操作系统的实现.在类UNIX系统上,这将查询/dev/urandom,并在Windows上使用CryptGenRandom().

  • 对于那些想知道"urandom"是否真的适合加密使用的人来说,[显然它是](http://security.stackexchange.com/questions/3936/is-a-rand-from-dev-urandom-secure-for-一个登录键). (2认同)

Cod*_*all 27

Python 3.6引入了一个新的秘密模块,"可以访问操作系统提供的最安全的随机源." 为了生成一些加密安全号码,您可以拨打电话secrets.randbelow().

secrets.randbelow(n)
Run Code Online (Sandbox Code Playgroud)

这将返回0到0之间的数字n.

  • @BlackJack 请参阅 PEP 的[基本原理部分](https://www.python.org/dev/peps/pep-0506/#rationale) 了解添加模块的原因。除此之外,我想补充一点,直接使用“secrets”模块可以让代码的读者知道您的意图,而直接使用“random.SystemRandom”则不能。 (5认同)

jjl*_*lin 6

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

import random
random.SystemRandom().getrandbits(n)
Run Code Online (Sandbox Code Playgroud)

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