有人可以分享在 Python 中为 OAuth 请求创建随机数的最佳实践吗?
5 回答
虽然这在创建此问题时可能不存在,但 Python 3.6 引入了secrets模块,该模块用于生成适用于管理数据(例如密码、帐户身份验证、安全令牌和相关机密)的加密强随机数。
在这种情况下,可以轻松生成随机数(这里是 base64 编码的字符串):
nonce = secrets.token_urlsafe()
替代方法是获取二进制令牌的 token_bytes 或获取十六进制字符串的token_hex 。
对于大多数实际目的,这给出了非常好的随机数:
import uuid
uuid.uuid4().hex
# 'b46290528cd949498ce4cc86ca854173'
uuid4()
使用os.urandom()
你可以在 python 中获得的最好的随机选项。
Nonce 应该只使用一次并且难以预测。请注意,这uuid4()
比后者更难预测,uuid1()
而后者更具全球独特性。因此,您可以通过组合它们来获得更大的力量:
uuid.uuid4().hex + uuid.uuid1().hex
# 'a6d68f4d81ec440fb3d5ef6416079305f7a44a0c9e9011e684e2c42c0319303d'
以下是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]
这就是劳斯所做的。这里没有硬性规定。该规范似乎并不太自以为是。您的限制是,作为 nonce 的值应该是唯一的。除此之外,假设提供商没有抱怨,您可以使用任何您喜欢的方法。
以下是我对电子邮件的一些想法。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。