机密—生成用于 Management 机密的安全随机数

3.6 版的新Function。

源代码: Lib/secrets.py


secrets模块用于生成适用于 Management 数据(例如密码,帐户身份验证,安全令牌和相关机密)的高密码强度随机数。

特别是,应该优先使用secrets而不是random模块中的默认伪随机数生成器,后者是为建模和仿真而设计的,而不是安全性或加密技术。

See also

Random numbers

secrets模块提供对 os 提供的最安全的随机性源的访问。

  • 类别 secrets. SystemRandom

    • 使用 os 提供的最高质量的源生成随机数的类。有关更多详细信息,请参见random.SystemRandom
  • secrets. choice(序列)

    • 从非空序列返回一个随机选择的元素。
  • secrets. randbelow(* n *)

    • 返回范围为[0,* n *)的随机整数。
  • secrets. randbits(* k *)

    • 返回带有* k *个随机位的 int。

Generating tokens

secrets模块提供了用于生成安全令牌的Function,适用于密码重置,难以猜测的 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'

令牌应使用多少个字节?

为了安全防范brute-force attacks,令牌必须具有足够的随机性。不幸的是,随着计算机变得越来越强大并且能够在较短的时间内做出更多的猜测,被认为足够的东西必然会增加。到 2015 年为止,对于secrets模块预期的典型用例,我们相信 32 字节(256 位)的随机性就足够了。

对于那些想要 Management 自己的令牌长度的用户,您可以pass为各种token_*函数提供int参数来显式指定令牌使用的随机性。该参数被视为要使用的随机字节数。

否则,如果未提供参数,或者参数为None,则token_*函数将使用合理的默认值。

Note

该默认值随时可能更改,包括在维护版本中。

Other functions

  • secrets. compare_digest(* a b *)

食谱和最佳做法

本节介绍了使用secretsManagement 基本安全级别的方法和最佳实践。

生成一个八个字符的字母数字密码:

import string
import secrets
alphabet = string.ascii_letters + string.digits
password = ''.join(secrets.choice(alphabet) for i in range(8))

Note

应用程序不应为以可恢复的格式存储密码,无论是纯文本还是加密的。应该使用加密强度高的单向(不可逆)哈希函数对它们进行加盐和哈希处理。

生成一个十个字符的字母数字密码,至少包含一个小写字符,至少一个大写字符和至少三位数字:

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-style passphrase

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://mydomain.com/reset=' + secrets.token_urlsafe()