24

有人可以分享在 Python 中为 OAuth 请求创建随机数的最佳实践吗?

4

5 回答 5

19

虽然这在创建此问题时可能不存在,但 Python 3.6 引入了secrets模块,该模块用于生成适用于管理数据(例如密码、帐户身份验证、安全令牌和相关机密)的加密强随机数

在这种情况下,可以轻松生成随机数(这里是 base64 编码的字符串):

nonce = secrets.token_urlsafe()

替代方法是获取二进制令牌的 token_bytes 或获取十六进制字符串的token_hex 。

于 2019-01-24T23:03:59.733 回答
15

对于大多数实际目的,这给出了非常好的随机数:

import uuid
uuid.uuid4().hex
# 'b46290528cd949498ce4cc86ca854173'

uuid4()使用os.urandom()你可以在 python 中获得的最好的随机选项。

Nonce 应该只使用一次并且难以预测。请注意,这uuid4()比后者更难预测,uuid1()而后者更具全球独特性。因此,您可以通过组合它们来获得更大的力量:

uuid.uuid4().hex + uuid.uuid1().hex
# 'a6d68f4d81ec440fb3d5ef6416079305f7a44a0c9e9011e684e2c42c0319303d'
于 2016-10-30T11:14:23.100 回答
14

以下是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 is not random enough ”的问题,它建议:

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。TL;DR 版本,使用os.urandom或它的抽象接口(SystemRandom)。

我喜欢我lambda的 s——并且不想要非字母数字字符——所以我使用了这个:

lambda length: filter(lambda s: s.isalpha(), b64encode(urandom(length * 2)))[:length]
于 2015-01-28T07:01:43.850 回答
4

这就是劳斯所做的。这里没有硬性规定。该规范似乎并不太自以为是。您的限制是,作为 nonce 的值应该是唯一的。除此之外,假设提供商没有抱怨,您可以使用任何您喜欢的方法。

于 2013-03-28T23:46:19.507 回答
1

以下是我对电子邮件的一些想法。generate_nonce 来自他们的代码,但我使用了我使用 uuid 的 generate_nonce_timestamp。它给了我一个随机的字母数字字符串和一个以秒为单位的时间戳:

import random
import time
import uuid


def generate_nonce(length=8):
    """Generate pseudo-random number."""
    return ''.join([str(random.randint(0, 9)) for i in range(length)])


def generate_timestamp():
    """Get seconds since epoch (UTC)."""
    return str(int(time.time()))

def generate_nonce_timestamp():
    """Generate pseudo-random number and seconds since epoch (UTC)."""
    nonce = uuid.uuid1()
    oauth_timestamp, oauth_nonce = str(nonce.time), nonce.hex
    return oauth_nonce, oauth_timestamp

我喜欢使用 uuid1,因为它会根据当前主机和时间生成 uuid,并且如果您需要两者都可以提取时间属性。对于电子邮件,您需要时间戳和随机数。

这是你得到的:

>>> generate_nonce_timestamp()
('a89faa84-6c35-11e5-8a36-080027c336f0', '136634341422770820')

如果要删除-,请使用nonce.get_hex()

uuid1 - 根据主机 ID、序列号和当前时间生成 UUID。更多关于uuid

于 2015-10-06T14:28:11.470 回答