secrets --- 生æˆ�管ç�†å¯†ç �的安全éš�机数¶
在 3.6 ç‰ˆæœ¬åŠ å…¥.
æº�代ç �: Lib/secrets.py
secrets 模å�—用于生æˆ�é«˜åº¦åŠ å¯†çš„éš�机数,适于管ç�†å¯†ç �ã€�账户验è¯�ã€�安免凿�®å�Šæœºå¯†æ•°æ�®ã€‚
最好用 secrets 替代 random 模å�—的默认伪éš�机数生æˆ�器,该生æˆ�器适用于建模和模拟,ä¸�å®œç”¨äºŽå®‰å…¨ä¸ŽåŠ å¯†ã€‚
��
�机数¶
secrets 模�是�作系统�供的最安全地�机性��。
- class secrets.SystemRandom¶
用�作系统�供的最高质��生��机数的类。详�
random.SystemRandom。
- secrets.choice(sequence)¶
返回一个从é�žç©ºåº�列ä¸éš�机选å�–çš„å…ƒç´ ã€‚
- secrets.randbelow(n)¶
返回 [0, n) 范围内的�机整数。
- secrets.randbits(k)¶
返回 k 个�机比特�的整数。
生� Token¶
secrets 模å�—æ��供了生æˆ�安全 Token 的函数,适用于密ç �é‡�ç½®ã€�密ä¿� URL ç‰åº”用场景。
- secrets.token_bytes([nbytes=None])¶
返回å�« nbytes 个å—节的éš�机å—节å—符串。如果未æ��ä¾› 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'
Token 应当使用多少个å—节?¶
为了在é�¢å¯¹ 暴力攻击 æ—¶ä¿�è¯�安全,Token çš„éš�机性必须足够高。éš�ç�€è®¡ç®—机推è¡�能力的ä¸�æ–æ��å�‡ï¼Œéš�æœºæ€§çš„å®‰å…¨æ ‡å‡†ä¹Ÿè¦�ä¸�æ–æ��高。比如 2015 年,32 å—节(256 ä½�)的éš�机性对于 secrets 模å�—的典型用例就已ç»�足够了。
è¦�自行管ç�† Token 长度的用户,å�¯ä»¥é€šè¿‡ä¸º token_* 函数指定 int å�‚数显å¼�指定 Token è¦�使用多大的éš�机性。该å�‚数以å—节数表示éš�机性大å°�。
�之,如果未�供�数,或�数为 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,包å�«å¯†ç �æ�¢å¤�应用的安全 Token:
import secrets
url = 'https://example.com/reset=' + secrets.token_urlsafe()