secrets — 用於管理金鑰的安全隨機數生成

在 3.6 版本中新增。

原始碼: Lib/secrets.py


secrets 模組用於生成密碼學上安全的隨機數,適用於管理密碼、賬戶認證、安全令牌和相關金鑰等資料。

特別是,secrets 應該優先於 random 模組中的預設偽隨機數生成器,後者是為建模和模擬而設計的,而不是為了安全或密碼學。

另請參閱

PEP 506

隨機數

secrets 模組提供了對您的作業系統提供的最安全隨機性來源的訪問。

class secrets.SystemRandom

一個使用作業系統提供的最高質量來源生成隨機數的類。有關更多詳細資訊,請參閱 random.SystemRandom

secrets.choice(seq)

從非空序列中返回隨機選擇的元素。

secrets.randbelow(exclusive_upper_bound)

返回範圍 [0, exclusive_upper_bound) 中的隨機整數。

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])

返回一個包含 nbytes 個隨機位元組的隨機 URL 安全文字字串。文字是 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
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,其中包含適用於密碼恢復應用程式的安全令牌

import secrets
url = 'https://example.com/reset=' + secrets.token_urlsafe()