"secrets" --- Gera números aleatórios seguros para gerenciar segredos
*********************************************************************

Adicionado na versão 3.6.

**Código-fonte:** Lib/secrets.py

======================================================================

O módulo "secrets" é usado para gerar números aleatórios
criptograficamente fortes, adequados para o gerenciamento de dados,
como senhas, autenticação de conta, tokens de segurança e segredos
relacionados.

Em particular, "secrets" deve ser usado em preferência ao gerador de
números pseudoaleatórios padrão no módulo "random", que é projetado
para modelagem e simulação, não segurança ou criptografia.

Ver também: **PEP 506**


Números aleatórios
==================

O módulo "secrets" fornece acesso à fonte mais segura de aleatoriedade
que seu sistema operacional fornece.

class secrets.SystemRandom

   Uma classe para gerar números aleatórios usando as fontes da mais
   alta qualidade fornecidas pelo sistema operacional. Veja
   "random.SystemRandom" para detalhes adicionais.

secrets.choice(seq)

   Retorna um elemento escolhido aleatoriamente de uma sequência não
   vazia.

secrets.randbelow(exclusive_upper_bound)

   Retorna um int aleatório no intervalo [0, *exclusive_upper_bound*).

secrets.randbits(k)

   Retorna um int não negativo com *k* bits aleatórios.


Gerando tokens
==============

O módulo "secrets" fornece funções para gerar tokens seguros,
adequados para aplicativos como redefinições de senha, URLs difíceis
de adivinhar e semelhantes.

secrets.token_bytes([nbytes=None])

   Retorna uma string de byte aleatória contendo *nbytes* número de
   bytes. Se *nbytes* for "None" ou não fornecido, um padrão razoável
   é usado.

      >>> token_bytes(16)
      b'\xebr\x17D*t\xae\xd4\xe3S\xb6\xe2\xebP1\x8b'

secrets.token_hex([nbytes=None])

   Retorna uma string de texto aleatória, em hexadecimal. A string tem
   *nbytes* bytes aleatórios, cada byte convertido em dois dígitos
   hexadecimais. Se *nbytes* for "None" ou não fornecido, um padrão
   razoável é usado.

      >>> token_hex(16)
      'f9bf78b9a18ce6d46a0cd2b0b86df9da'

secrets.token_urlsafe([nbytes=None])

   Retorna uma string de texto segura para URL aleatória, contendo
   *nbytes* bytes aleatórios. O texto é codificado em Base64,
   portanto, em média, cada byte resulta em aproximadamente 1,3
   caracteres. Se *nbytes* for "None" ou não fornecido, um padrão
   razoável é usado.

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


Quantos bytes os tokens devem usar?
-----------------------------------

Para estar seguro contra ataques de força bruta, os tokens precisam
ter aleatoriedade suficiente. Infelizmente, o que é considerado
suficiente necessariamente aumentará à medida que os computadores
ficarem mais poderosos e capazes de fazer mais suposições em um
período mais curto. A partir de 2015, acredita-se que 32 bytes (256
bits) de aleatoriedade são suficientes para o caso de uso típico
esperado para o módulo "secrets".

Para aqueles que desejam gerenciar seu próprio comprimento de token,
você pode especificar explicitamente quanta aleatoriedade é usada para
tokens, fornecendo um argumento "int" para as várias funções
"token_*". Esse argumento é considerado o número de bytes de
aleatoriedade a serem usados.

Caso contrário, se nenhum argumento for fornecido, ou se o argumento
for "None", as funções "token_*" usarão um padrão razoável.

Nota:

  Esse padrão está sujeito a alterações a qualquer momento, inclusive
  durante as versões de manutenção.


Outras funções
==============

secrets.compare_digest(a, b)

   Retorna "True" se as strings ou *objetos tipo arquivo* *a* e *b*
   forem iguais, caso contrário, "False", usando uma "comparação de
   tempo constante" para reduzir o risco de ataques de temporização.
   Veja "hmac.compare_digest()" para detalhes adicionais.


Receitas e melhores práticas
============================

Esta seção mostra as receitas e melhores práticas para usar "secrets"
para gerenciar um nível básico de segurança.

Gerar uma senha alfanumérica de oito caracteres:

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

Nota:

  As aplicações não devem **armazenar senhas em um formato
  recuperável**, seja em texto simples ou criptografado. Elas devem
  ser salgadas e transformadas em hash usando uma função hash de
  sentido único criptograficamente forte (irreversível).

Gerar uma senha alfanumérica de dez caracteres com pelo menos um
caractere minúsculo, pelo menos um caractere maiúsculo e pelo menos
três dígitos:

   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

Gerar uma senha longa do estilo XKCD:

   import secrets
   # Em sistemas Linux padrão, use um arquivo de dicionário conveniente.
   # Outras plataformas podem precisar fornecer sua própria lista de palavras.
   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))

Gerar uma URL temporária difícil de adivinhação contendo um token de
segurança adequado para aplicativos de recuperação de senha:

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