在Python中生成随机数的标准方法是什么?
有没有人能分享一下在Python中为OAuth请求创建nonce的最佳做法?
5 个回答
17
对于大多数实际应用来说,这种方法能生成非常好的随机数:
import uuid
uuid.uuid4().hex
# 'b46290528cd949498ce4cc86ca854173'
uuid4()
使用 os.urandom()
,这是在Python中能得到的最好的随机数生成方式。
随机数(nonce)应该只使用一次,而且很难被预测。需要注意的是,uuid4()
比 uuid1()
更难以预测,而后者在全球范围内更具唯一性。所以你可以通过将它们结合起来,来获得更强的随机性:
uuid.uuid4().hex + uuid.uuid1().hex
# 'a6d68f4d81ec440fb3d5ef6416079305f7a44a0c9e9011e684e2c42c0319303d'
28
虽然在这个问题提出时可能还不存在,但Python 3.6引入了一个叫做secrets的模块,这个模块的目的是为了生成非常安全的随机数,适合用来管理一些重要的数据,比如密码、账户认证、安全令牌和其他相关的秘密信息。
在这种情况下,生成一个随机数(这里是一个经过base64编码的字符串)是非常简单的:
nonce = secrets.token_urlsafe()
另外,还有一些替代方法,比如token_bytes可以用来获取一个二进制的令牌,或者token_hex可以用来获取一个十六进制的字符串。
15
这是 python-oauth2 的实现方式:
def generate_nonce(length=8):
"""Generate pseudorandom number."""
return ''.join([str(random.randint(0, 9)) for i in range(length)])
他们还有:
@classmethod
def make_nonce(cls):
"""Generate pseudorandom number."""
return str(random.randint(0, 100000000))
另外,还有一个问题标题为:"make_nonce 不够随机",这个问题提出了:
def gen_nonce(length):
""" Generates a random string of bytes, base64 encoded """
if length < 1:
return ''
string=base64.b64encode(os.urandom(length),altchars=b'-_')
b64len=4*floor(length,3)
if length%3 == 1:
b64len+=2
elif length%3 == 2:
b64len+=3
return string[0:b64len].decode()
同时也提到了 CVE-2013-4347。简单来说,就是建议使用 os.urandom
或者它的抽象接口 (SystemRandom)。
我喜欢我的 lambda
,而且不想要非字母数字的字符,所以我用了这个:
lambda length: filter(lambda s: s.isalpha(), b64encode(urandom(length * 2)))[:length]