secrets --- 產生用於管理機密的安全亂數

在 3.6 版被加入.

原始碼:Lib/secrets.py


The secrets module is used for generating cryptographically strong random numbers suitable for managing data such as passwords, account authentication, security tokens, and related secrets.

In particular, secrets should be used in preference to the default pseudo-random number generator in the random module, which is designed for modelling and simulation, not security or cryptography.

也參考

PEP 506

亂數

The secrets module provides access to the most secure source of randomness that your operating system provides.

class secrets.SystemRandom

一個用來產生亂數的類別,用的是作業系統提供的最高品質來源。 請參閱 random.SystemRandom 以取得更多細節。

secrets.choice(seq)

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

secrets.randbelow(exclusive_upper_bound)

回傳一個 [0, exclusive_upper_bound) 範圍之內的隨機整數。

secrets.randbits(k)

回傳一個具 k 個隨機位元的非負整數。

產生權杖(token)

The secrets module provides functions for generating secure tokens, suitable for applications such as password resets, hard-to-guess URLs, and similar.

secrets.token_bytes(nbytes=None)

Return a random byte string containing nbytes number of bytes.

If nbytes is not specified or None, DEFAULT_ENTROPY is used instead.

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

Return a random text string, in hexadecimal. The string has nbytes random bytes, each byte converted to two hex digits.

If nbytes is not specified or None, DEFAULT_ENTROPY is used instead.

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

Return a random URL-safe text string, containing nbytes random bytes. The text is Base64 encoded, so on average each byte results in approximately 1.3 characters.

If nbytes is not specified or None, DEFAULT_ENTROPY is used instead.

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

權杖應當使用多少個位元組?

To be secure against brute-force attacks, tokens need to have sufficient randomness. Unfortunately, what is considered sufficient will necessarily increase as computers get more powerful and able to make more guesses in a shorter period. As of 2015, it is believed that 32 bytes (256 bits) of randomness is sufficient for the typical use-case expected for the secrets module.

對於想自行管理權杖長度的使用者,你可以對各種 token_* 函式明白地指定 int 引數(argument)來指定權杖要使用的隨機性程度。 該引數以位元組數來表示要使用的隨機性程度。

Otherwise, if no argument is provided, or if the argument is None, the token_* functions uses DEFAULT_ENTROPY instead.

secrets.DEFAULT_ENTROPY

Default number of bytes of randomness used by the token_* functions.

The exact value is subject to change at any time, including during maintenance releases.

其他函式

secrets.compare_digest(a, b)

如果字串或類位元組串物件 ab 相等則回傳 True,否則回傳 False,以"恆定時間比較 (constant-time compare) "的處理方式可降低時序攻擊的風險。 請參閱 hmac.compare_digest() 以了解更多細節。

應用技巧和典範實務(best practices)

This section shows recipes and best practices for using secrets to manage a basic level of security.

產生八個字元長的字母數字密碼:

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

備註

應用程式不能以可復原的格式儲存密碼,無論是用純文本還是經過加密。 它們應當先加鹽(salt),再使用高加密強度的單向(不可逆)雜湊函式來產生雜湊值。

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

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 風格的 passphrase:

import secrets
# 在標準 Linux 系統上,使用一個方便的字典檔案。
# 其他平台可能需要提供自己的字詞列表。
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()