secrets --- 生成安全隨機(jī)數(shù)字用于管理密碼?
3.6 新版功能.
源代碼: Lib/secrets.py
secrets 模塊可用于生成高加密強(qiáng)度的隨機(jī)數(shù),適應(yīng)管理密碼、賬戶驗(yàn)證、安全憑據(jù)和相關(guān)機(jī)密數(shù)據(jù)管理的需要。
特別地,應(yīng)當(dāng)優(yōu)先使用 secrets 來替代 random 模塊中默認(rèn)的偽隨機(jī)數(shù)生成器,后者被設(shè)計用于建模和仿真,而不適用于安全和加密。
參見
隨機(jī)數(shù)?
通過 secrets 模塊可以訪問你的操作系統(tǒng)所能提供的最安全的隨機(jī)性來源。
-
class
secrets.SystemRandom? 使用操作系統(tǒng)所提供的最高質(zhì)量源來生成隨機(jī)數(shù)的類。 請參閱
random.SystemRandom了解更多細(xì)節(jié)。
-
secrets.choice(sequence)? 返回從一個非空序列中隨機(jī)選取的元素。
-
secrets.randbelow(n)? 返回一個 [0, n) 范圍之內(nèi)的隨機(jī)整數(shù)。
-
secrets.randbits(k)? 返回一個具有 k 個隨機(jī)比特位的整數(shù)。
生成憑據(jù)?
secrets 模塊提供了一些生成安全憑據(jù)的函數(shù),適用于諸如密碼重置、難以猜測的 URL 之類的應(yīng)用場景。
-
secrets.token_bytes([nbytes=None])? 返回一個包含 nbytes 個字節(jié)的隨機(jī)字節(jié)串。 如果 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)制數(shù)碼形式的隨機(jī)字符串。 字符串具有 nbytes 個隨機(jī)字節(jié),每個字節(jié)轉(zhuǎn)換為兩個十六進(jìn)制數(shù)碼。 如果 nbytes 為
None或未提供,則會使用一個合理的默認(rèn)值。>>> token_hex(16) 'f9bf78b9a18ce6d46a0cd2b0b86df9da'
-
secrets.token_urlsafe([nbytes=None])? 返回一個 URL 安全的隨機(jī)字符串,包含 nbytes 個隨機(jī)字節(jié)。 文本將使用 Base64 編碼,因此平均來說每個字節(jié)將對應(yīng) 1.3 個結(jié)果字符。 如果 nbytes 為
None或未提供,則會使用一個合理的默認(rèn)值。>>> token_urlsafe(16) 'Drmhze6EPcv0fN_81Bj-nA'
憑據(jù)應(yīng)當(dāng)使用多少個字節(jié)??
為了在面對 暴力攻擊 時保證安全,憑據(jù)必須具有足夠的隨機(jī)性。 不幸的是,對隨機(jī)性是否足夠的標(biāo)準(zhǔn)會隨著計算機(jī)越來越強(qiáng)大并能夠在更短時間內(nèi)進(jìn)行更多猜測而不斷提高。 在 2015 年時,人們認(rèn)為 32 字節(jié)(256 位)的隨機(jī)性對于 secrets 模塊所適合的典型用例來說是足夠的。
作為想要自行管理憑據(jù)長度的用戶,你可以通過為各種 token_* 函數(shù)指定一個 int 參數(shù)來顯式地指定憑據(jù)要使用多大的隨機(jī)性。 該參數(shù)以字節(jié)數(shù)來表示要使用的隨機(jī)性大小。
在其他情況下,如果未提供參數(shù),或者如果參數(shù)為 None,則 token_* 函數(shù)將改用一個合理的默認(rèn)值。
注解
該默認(rèn)值可能在任何時候被改變,包括在維護(hù)版本更新的時候。
其他功能?
-
secrets.compare_digest(a, b)? 如果字符串 a 與 b 相等則返回
True,否則返回False,該處理方式可降低 定時攻擊 的風(fēng)險。 請參閱hmac.compare_digest()了解更多細(xì)節(jié)。
應(yīng)用技巧與最佳實(shí)踐?
本節(jié)展示了一些使用 secrets 來管理基本安全級別的應(yīng)用技巧和最佳實(shí)踐。
生成長度為八個字符的字母數(shù)字密碼:
import string
alphabet = string.ascii_letters + string.digits
password = ''.join(choice(alphabet) for i in range(8))
注解
應(yīng)用程序不能 以可恢復(fù)的格式存儲密碼,無論是用純文本還是加密。 它們應(yīng)當(dāng)使用高加密強(qiáng)度的單向(不可恢復(fù))哈希函數(shù)來加鹽并生成哈希值。
生成長度為十個字符的字母數(shù)字密碼,其中包含至少一個小寫字母,至少一個大寫字母以及至少三個數(shù)字:
import string
alphabet = string.ascii_letters + string.digits
while True:
password = ''.join(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
# 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(choice(words) for i in range(4))
生成難以猜測的臨時 URL,其中包含適合密碼恢復(fù)應(yīng)用的安全憑據(jù):
url = 'https://mydomain.com/reset=' + token_urlsafe()
