secrets
--- 生成管理密碼的安全隨機(jī)數(shù)?
3.6 新版功能.
源代碼: Lib/secrets.py
secrets
模塊用于生成高度加密的隨機(jī)數(shù),適于管理密碼、賬戶驗(yàn)證、安全憑據(jù)及機(jī)密數(shù)據(jù)。
最好用 secrets
替代 random
模塊的默認(rèn)偽隨機(jī)數(shù)生成器,該生成器適用于建模和模擬,不宜用于安全與加密。
參見
隨機(jī)數(shù)?
secrets
模塊是操作系統(tǒng)提供的最安全地隨機(jī)性來(lái)源。
- class secrets.SystemRandom?
用操作系統(tǒng)提供的最高質(zhì)量源生成隨機(jī)數(shù)的類。詳見
random.SystemRandom
。
- secrets.choice(sequence)?
返回從非空序列中隨機(jī)選取的元素。
- secrets.randbelow(n)?
返回 [0, n) 范圍內(nèi)的隨機(jī)整數(shù)。
- secrets.randbits(k)?
返回 k 個(gè)隨機(jī)比特位的整數(shù)。
生成 Token?
secrets
模塊提供了生成安全 Token 的函數(shù),適用于密碼重置、密保 URL 等應(yīng)用場(chǎng)景。
- secrets.token_bytes([nbytes=None])?
返回含 nbytes 個(gè)字節(jié)的隨機(jī)字節(jié)字符串。如果未提供 nbytes,或*nbytes* 為
None
,則使用合理的默認(rèn)值。>>> token_bytes(16) b'\xebr\x17D*t\xae\xd4\xe3S\xb6\xe2\xebP1\x8b'
- secrets.token_hex([nbytes=None])?
返回十六進(jìn)制隨機(jī)文本字符串。字符串有 nbytes 個(gè)隨機(jī)字節(jié),每個(gè)字節(jié)轉(zhuǎn)換為兩個(gè)十六進(jìn)制數(shù)碼。未提供 nbytes 或?yàn)?
None
時(shí),則使用合理的默認(rèn)值。>>> token_hex(16) 'f9bf78b9a18ce6d46a0cd2b0b86df9da'
- secrets.token_urlsafe([nbytes=None])?
返回安全的 URL 隨機(jī)文本字符串,包含 nbytes 個(gè)隨機(jī)字節(jié)。文本用 Base64 編碼,平均來(lái)說,每個(gè)字節(jié)對(duì)應(yīng) 1.3 個(gè)結(jié)果字符。未提供 nbytes 或?yàn)?
None
時(shí),則使用合理的默認(rèn)值。>>> token_urlsafe(16) 'Drmhze6EPcv0fN_81Bj-nA'
Token 應(yīng)當(dāng)使用多少個(gè)字節(jié)??
為了在面對(duì) 暴力攻擊 時(shí)保證安全,Token 的隨機(jī)性必須足夠高。隨著計(jì)算機(jī)推衍能力的不斷提升,隨機(jī)性的安全標(biāo)準(zhǔn)也要不斷提高。比如 2015 年,32 字節(jié)(256 位)的隨機(jī)性對(duì)于 secrets
模塊的典型用例就已經(jīng)足夠了。
要自行管理 Token 長(zhǎng)度的用戶,可以通過為 token_*
函數(shù)指定 int
參數(shù)顯式指定 Token 要使用多大的隨機(jī)性。該參數(shù)以字節(jié)數(shù)表示隨機(jī)性大小。
反之,如果未提供參數(shù),或參數(shù)為 None
,則 token_*
函數(shù)將使用合理的默認(rèn)值。
備注
該默認(rèn)值隨時(shí)可能會(huì)改變,比如,版本更新的時(shí)候。
其他功能?
- secrets.compare_digest(a, b)?
字符串 a 與 b 相等則返回
True
,否則返回False
,這種方式可降低 定時(shí)攻擊 的風(fēng)險(xiǎn)。詳見hmac.compare_digest()
。
應(yīng)用技巧與最佳實(shí)踐?
本節(jié)展示了一些使用 secrets
管理基本安全級(jí)別的應(yīng)用技巧和最佳實(shí)踐。
生成長(zhǎng)度為八個(gè)字符的字母數(shù)字密碼:
import string
import secrets
alphabet = string.ascii_letters + string.digits
password = ''.join(secrets.choice(alphabet) for i in range(8))
備注
應(yīng)用程序不能 以可恢復(fù)的格式存儲(chǔ)密碼,無(wú)論是用純文本還是加密。 它們應(yīng)當(dāng)使用高加密強(qiáng)度的單向(不可恢復(fù))哈希函數(shù)來(lái)加鹽并生成哈希值。
生成長(zhǎng)度為十個(gè)字符的字母數(shù)字密碼,包含至少一個(gè)小寫字母,至少一個(gè)大寫字母以及至少三個(gè)數(shù)字:
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
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))
生成臨時(shí)密保 URL,包含密碼恢復(fù)應(yīng)用的安全 Token:
import secrets
url = 'https://example.com/reset=' + secrets.token_urlsafe()