有人可以分享在Python中为OAuth请求创建nonce的最佳实践吗?
有人可以分享在Python中为OAuth请求创建nonce的最佳实践吗?
尽管这个问题创建时可能还不存在,但Python 3.6引入了secrets模块,旨在生成密码,账户认证,安全令牌和相关机密数据等管理所需的加密强度随机数。
在此情况下,可以轻松生成一个nonce(这里是一个base64编码字符串):
nonce = secrets.token_urlsafe()
可供选择的是token_bytes用于获取二进制标记或token_hex用于获取十六进制字符串。
对于大多数实际目的,这提供了非常好的一次性随机数:
import uuid
uuid.uuid4().hex
# 'b46290528cd949498ce4cc86ca854173'
uuid4()
使用的是 Python 中最好的随机函数 os.urandom()
。
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不够随机”,该问题提议:
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]
os.urandom()
,而决不能使用 random.random
或 random.randint
。否则,您可能会遇到严重的安全问题。 - Aur Sarafrandom.randint
很容易被坏人猜测,从而危及安全。https://www.cigital.com/papers/download/developer_gambling.php - Aur Sarafsha1
之前,它还调用.encode('ascii')
。可能是为了与Python 3兼容? - A T这里有一些与Emailage相关的想法。generate_nonce是他们代码中的内容,但我使用generate_nonce_timestamp并使用了uuid。它给我一个随机的字母数字字符串和时间戳(以秒为单位):
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
>>> generate_nonce_timestamp()
('a89faa84-6c35-11e5-8a36-080027c336f0', '136634341422770820')
-
,使用 nonce.get_hex()
。
uuid1 - 从主机ID、序列号和当前时间生成UUID。更多信息请参见 uuid。random.randint
的评论(简而言之:永远不要用)。 - Aur Saraf
nonce
是一个数字,取决于令牌提供者的实现方式(它不是 JWT 标准的严格部分)。我见过的所有提供者都很乐意使用字符串。重要的是它是一个单次使用的值。只增加的数字是好的,但你必须解决系统重置的问题。使用一个大的随机字符串通常更容易。 - Erdős-Bacon