secrets --- 生成安全隨機數字用于管理密碼?

3.6 新版功能.

源代碼: Lib/secrets.py


secrets 模塊可用于生成高加密強度的隨機數,適應管理密碼、賬戶驗證、安全憑據和相關機密數據管理的需要。

特別地,應當優先使用 secrets 來替代 random 模塊中默認的偽隨機數生成器,后者被設計用于建模和仿真,而不適用于安全和加密。

參見

PEP 506

隨機數?

通過 secrets 模塊可以訪問你的操作系統所能提供的最安全的隨機性來源。

class secrets.SystemRandom?

使用操作系統所提供的最高質量源來生成隨機數的類。 請參閱 random.SystemRandom 了解更多細節。

secrets.choice(sequence)?

返回從一個非空序列中隨機選取的元素。

secrets.randbelow(n)?

返回一個 [0, n) 范圍之內的隨機整數。

secrets.randbits(k)?

返回一個具有 k 個隨機比特位的整數。

生成憑據?

secrets 模塊提供了一些生成安全憑據的函數,適用于諸如密碼重置、難以猜測的 URL 之類的應用場景。

secrets.token_bytes([nbytes=None])?

返回一個包含 nbytes 個字節的隨機字節串。 如果 nbytesNone 或未提供,則會使用一個合理的默認值。

>>> token_bytes(16)  
b'\xebr\x17D*t\xae\xd4\xe3S\xb6\xe2\xebP1\x8b'
secrets.token_hex([nbytes=None])?

返回一個十六進制數碼形式的隨機字符串。 字符串具有 nbytes 個隨機字節,每個字節轉換為兩個十六進制數碼。 如果 nbytesNone 或未提供,則會使用一個合理的默認值。

>>> token_hex(16)  
'f9bf78b9a18ce6d46a0cd2b0b86df9da'
secrets.token_urlsafe([nbytes=None])?

返回一個 URL 安全的隨機字符串,包含 nbytes 個隨機字節。 文本將使用 Base64 編碼,因此平均來說每個字節將對應 1.3 個結果字符。 如果 nbytesNone 或未提供,則會使用一個合理的默認值。

>>> token_urlsafe(16)  
'Drmhze6EPcv0fN_81Bj-nA'

憑據應當使用多少個字節??

為了在面對 暴力攻擊 時保證安全,憑據必須具有足夠的隨機性。 不幸的是,對隨機性是否足夠的標準會隨著計算機越來越強大并能夠在更短時間內進行更多猜測而不斷提高。 在 2015 年時,人們認為 32 字節(256 位)的隨機性對于 secrets 模塊所適合的典型用例來說是足夠的。

作為想要自行管理憑據長度的用戶,你可以通過為各種 token_* 函數指定一個 int 參數來顯式地指定憑據要使用多大的隨機性。 該參數以字節數來表示要使用的隨機性大小。

在其他情況下,如果未提供參數,或者如果參數為 None,則 token_* 函數將改用一個合理的默認值。

注解

該默認值可能在任何時候被改變,包括在維護版本更新的時候。

其他功能?

secrets.compare_digest(a, b)?

如果字符串 ab 相等則返回 True,否則返回 False,該處理方式可降低 定時攻擊 的風險。 請參閱 hmac.compare_digest() 了解更多細節。

應用技巧與最佳實踐?

本節展示了一些使用 secrets 來管理基本安全級別的應用技巧和最佳實踐。

生成長度為八個字符的字母數字密碼:

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

注解

應用程序不能 以可恢復的格式存儲密碼,無論是用純文本還是加密。 它們應當使用高加密強度的單向(不可恢復)哈希函數來加鹽并生成哈希值。

生成長度為十個字符的字母數字密碼,其中包含至少一個小寫字母,至少一個大寫字母以及至少三個數字:

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

生成 XKCD 風格的密碼串:

# 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,其中包含適合密碼恢復應用的安全憑據:

url = 'https://mydomain.com/reset=' + token_urlsafe()