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