secrets
- 生成用于管理密钥的安全随机数¶
3.6 版新增。
源代码: Lib/secrets.py
secrets
模块用于生成加密强随机数,适用于管理密码、帐户身份验证、安全令牌和相关密钥等数据。
特别是,应该优先使用 secrets
,而不是 random
模块中的默认伪随机数生成器,后者专为建模和仿真而设计,而不是为了安全或加密。
另请参阅
随机数¶
secrets
模块提供对操作系统提供的最安全的随机性来源的访问。
- class secrets.SystemRandom¶
一个使用操作系统提供的最高质量来源生成随机数的类。有关更多详细信息,请参阅
random.SystemRandom
。
- secrets.choice(seq)¶
从非空序列中返回一个随机选择的元素。
- secrets.randbelow(exclusive_upper_bound)¶
返回 [0, exclusive_upper_bound) 范围内的一个随机整数。
- secrets.randbits(k)¶
返回一个具有 k 个随机位的整数。
生成令牌¶
secrets
模块提供了用于生成安全令牌的函数,适用于密码重置、难以猜测的 URL 等应用程序。
- secrets.token_bytes([nbytes=None])¶
返回一个包含 nbytes 个字节的随机字节字符串。如果 nbytes 为
None
或未提供,则使用合理的默认值。>>> token_bytes(16) b'\xebr\x17D*t\xae\xd4\xe3S\xb6\xe2\xebP1\x8b'
- secrets.token_hex([nbytes=None])¶
返回一个十六进制的随机文本字符串。该字符串具有 nbytes 个随机字节,每个字节转换为两个十六进制数字。如果 nbytes 为
None
或未提供,则使用合理的默认值。>>> token_hex(16) 'f9bf78b9a18ce6d46a0cd2b0b86df9da'
- secrets.token_urlsafe([nbytes=None])¶
返回一个随机的 URL 安全文本字符串,包含 nbytes 个随机字节。文本采用 Base64 编码,因此平均每个字节产生大约 1.3 个字符。如果 nbytes 为
None
或未提供,则使用合理的默认值。>>> token_urlsafe(16) 'Drmhze6EPcv0fN_81Bj-nA'
令牌应该使用多少字节?¶
为了抵御 暴力攻击,令牌需要具有足够的随机性。不幸的是,随着计算机变得越来越强大,并且能够在更短的时间内进行更多次猜测,被认为足够的随机性必然会增加。截至 2015 年,人们认为 32 字节(256 位)的随机性足以满足 secrets
模块的典型用例预期。
对于那些想要管理自己的令牌长度的人,可以通过向各种 token_*
函数提供一个 int
参数来明确指定用于令牌的随机性数量。该参数被视为要使用的随机性字节数。
否则,如果没有提供参数,或者参数为 None
,则 token_*
函数将使用合理的默认值。
注意
该默认值可能会随时更改,包括在维护版本期间。
其他函数¶
- secrets.compare_digest(a, b)¶
如果字符串或 类字节对象 a 和 b 相等,则返回
True
,否则返回False
,使用“恒定时间比较”来降低 计时攻击 的风险。有关更多详细信息,请参阅hmac.compare_digest()
。
方法和最佳实践¶
本节介绍了使用 secrets
管理基本安全级别的方法和最佳实践。
生成一个八位数的字母数字密码
import string
import secrets
alphabet = string.ascii_letters + string.digits
password = ''.join(secrets.choice(alphabet) for i in range(8))
注意
应用程序不应 以可恢复的格式存储密码,无论是纯文本还是加密的。它们应该使用加密强单向(不可逆)哈希函数进行加盐和哈希处理。
生成一个十位数的字母数字密码,其中至少包含一个小写字母、至少一个大写字母和至少三个数字
import string
import secrets
alphabet = string.ascii_letters + string.digits
while True:
password = ''.join(secrets.choice(alphabet) for i in range(10))
if (any(c.islower() for c in password)
and any(c.isupper() for c in password)
and sum(c.isdigit() for c in password) >= 3):
break
生成一个 XKCD 风格的密码
import secrets
# On standard Linux systems, use a convenient dictionary file.
# Other platforms may need to provide their own word-list.
with open('/usr/share/dict/words') as f:
words = [word.strip() for word in f]
password = ' '.join(secrets.choice(words) for i in range(4))
生成一个难以猜测的临时 URL,其中包含适用于密码恢复应用程序的安全令牌
import secrets
url = 'https://example.com/reset=' + secrets.token_urlsafe()