在Python中生成随机数的标准方法是什么?

30 投票
5 回答
42101 浏览
提问于 2025-04-16 15:19

有没有人能分享一下在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]

撰写回答