secrets --- 機密を扱うために安全な乱数を生成する

Added in version 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

OS が提供する最も高品質なソースを用いて乱数を生成するためのクラスです。更に詳しいことについては random.SystemRandom を参照してください。

secrets.choice(seq)

空でないシーケンスから要素をランダムに選択して返します。

secrets.randbelow(exclusive_upper_bound)

[0, exclusive_upper_bound) の範囲のランダムな整数を返します。

secrets.randbits(k)

ランダムな k ビットの非負の整数を返します。

トークンの生成

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

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'

トークンは何バイト使うべきか?

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 引数で渡すことで、トークンに使用するランダムさを明示的に指定することができます。引数はランダムさのバイト数として使用されます。

それ以外の場合、すなわち引数がない場合や None の場合、token_* 関数は妥当なデフォルト値を代わりに使います。

注釈

デフォルトはメンテナンスリリースの間を含め、いつでも変更される可能性があります。

その他の関数

secrets.compare_digest(a, b)

文字列または bytes-like オブジェクト ab が等しければ True を、そうでなければ False を返します。比較は タイミング攻撃 のリスクを減らす "定数時間比較" の方法で行われます。詳細については hmac.compare_digest() を参照してください。

レシピとベストプラクティス

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

8文字のアルファベットと数字を含むパスワードを生成するには:

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

注釈

アプリケーションは、平文であろうと暗号化されていようと、 復元可能な形式でパスワードを保存 してはいけません。パスワードは暗号学的に強い一方向 (非可逆) ハッシュ関数を用いてソルトしハッシュしなければなりません。

アルファべットと数字からなり、小文字を少なくとも1つと数字を少なくとも3つ含む、10文字のパスワードを生成するには:

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