"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

   운영 체제에서 제공하는 최고 품질의 소스를 사용하여 난수를 생성하는
   클래스. 자세한 내용은 "random.SystemRandom"를 참조하십시오.

secrets.choice(seq)

   비어있지 않은 시퀀스로부터 무작위로 선택된 요소를 돌려줍니다.

secrets.randbelow(exclusive_upper_bound)

   범위 [0, *exclusive_upper_bound*)에서 무작위 int를 돌려줍니다.

secrets.randbits(k)

   *k* 무작위 비트를 가지는 음이 아닌 int를 돌려줍니다.


토큰 생성
=========

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)

   문자열 혹은 *바이트열류 객체* *a*와 *b*가 같으면 "True"를, 그렇지
   않으면 "False"를 반환하는데, "고정 시간 비교(constant-time
   compare)"를 사용하여 타이밍 공격의 위험을 줄입니다. 자세한 내용은
   "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))

참고:

  응용 프로그램은 평문인지 암호문인지 관계없이, **암호를 복원 가능한
  형식으로 저장**해서는 안 됩니다. 이들은 암호학적으로 강력한 단방향(
  비가역적) 해시 함수를 사용하여 솔트되고 해시 되어야 합니다.

적어도 하나의 소문자, 적어도 하나의 대문자 및 적어도 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
   # 표준 리눅스 시스템에서는, 편리한 딕셔너리 파일을 사용하십시오.
   # 다른 플랫폼에서는, 자신의 단어 목록을 제공해야 할 수도 있습니다.
   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()
