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

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

Otherwise, if no argument is provided, or if the argument is "None",
the "token_*" functions use "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)

   文字列または *bytes-like オブジェクト* *a* と *b* が等しければ
   "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()
