"secrets" --- Generate secure random numbers for managing secrets
*****************************************************************

Ajouté dans la version 3.6.

**Code source :** Lib/secrets.py

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

Le module "secrets" permet de générer des nombres aléatoires forts au
sens de la cryptographie, adaptés à la gestion des mots de passe, à
l'authentification des comptes, à la gestion des jetons de sécurité et
des secrets associés.

Il faut préférer "secrets" par rapport au générateur pseudo-aléatoire
du module "random", ce dernier étant conçu pour la modélisation et la
simulation, et non pour la sécurité ou la cryptographie.

Voir aussi: **PEP 506**


Nombres aléatoires
==================

Le module "secrets" fournit un accès à la source d'aléa la plus sûre
disponible sur votre système d'exploitation.

class secrets.SystemRandom

   Classe permettant de générer des nombres aléatoires à partir des
   sources d'aléa les plus sûres fournies par le système
   d'exploitation. Se référer à "random.SystemRandom" pour plus de
   détails.

secrets.choice(seq)

   Return a randomly chosen element from a non-empty sequence.

secrets.randbelow(exclusive_upper_bound)

   Return a random int in the range [0, *exclusive_upper_bound*).

secrets.randbits(k)

   Renvoie un entier de *k* bits aléatoires.


Génération de jetons
====================

Le module "secrets" fournit des fonctions pour la génération sécurisée
de jetons adaptés à la réinitialisation de mots de passe, à la
production d'URLs difficiles à deviner, etc.

secrets.token_bytes([nbytes=None])

   Renvoie une chaîne d'octets aléatoire contenant *nbytes* octets. Si
   *nbytes* est "None" ou omis, une valeur par défaut raisonnable est
   utilisée.

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

secrets.token_hex([nbytes=None])

   Renvoie une chaîne de caractères aléatoire en hexadécimal. La
   chaîne comporte *nbytes* octets aléatoires, chaque octet étant
   écrit sous la forme de deux chiffres hexadécimaux. Si *nbytes* est
   "None" ou omis, une valeur par défaut raisonnable est utilisée.

      >>> token_hex(16)  
      'f9bf78b9a18ce6d46a0cd2b0b86df9da'

secrets.token_urlsafe([nbytes=None])

   Renvoie une chaîne de caractères aléatoire adaptée au format URL,
   contenant *nbytes* octets aléatoires. Le texte est encodé en
   base64, chaque octet produisant en moyenne 1,3 caractères. Si
   *nbytes* est "None" ou omis, une valeur par défaut raisonnable est
   utilisée.

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


Combien d'octets mon jeton doit-il comporter ?
----------------------------------------------

Afin de se prémunir des attaques par force brute, les jetons doivent
être suffisamment aléatoires. Malheureusement, l'augmentation de la
puissance de calcul des ordinateurs leur permet de réaliser plus de
tentatives dans le même laps de temps. De ce fait, le nombre de bits
recommandé pour l'aléa augmente aussi. En 2015, une longueur de 32
octets (256 bits) aléatoires est généralement considérée suffisante
pour les usages typiques du module "secrets".

Si vous souhaitez gérer la longueur des jetons par vous-même, vous
pouvez spécifier la quantité d'aléa à introduire dans les jetons en
passant un argument "int" aux différentes fonctions "token_*". Cet
argument indique alors le nombre d'octets aléatoires utilisés pour la
création du jeton.

Sinon, si aucun argument n'est passé ou si celui-ci est "None", les
fonctions "token_*" utilisent une valeur par défaut raisonnable à la
place.

Note:

  Cette valeur par défaut est susceptible de changer à n'importe quel
  moment, y compris lors des mises à jour de maintenance.


Autres fonctions
================

secrets.compare_digest(a, b)

   Return "True" if strings or *bytes-like objects* *a* and *b* are
   equal, otherwise "False", using a "constant-time compare" to reduce
   the risk of timing attacks. See "hmac.compare_digest()" for
   additional details.


Recettes et bonnes pratiques
============================

Cette section expose les recettes et les bonnes pratiques
d'utilisation de "secrets" pour gérer un niveau minimal de sécurité.

Générer un mot de passe à huit caractères alphanumériques :

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

Note:

  Applications should not store passwords in a recoverable format,
  whether plain text or encrypted.  They should be salted and hashed
  using a cryptographically strong one-way (irreversible) hash
  function.

Générer un mot de passe alphanumérique à dix caractères contenant au
moins un caractère en minuscule, au moins un caractère en majuscule et
au moins trois chiffres :

   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

Générer une phrase de passe dans le style 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))

Générer une URL temporaire difficile à deviner contenant un jeton de
sécurité adapté à réinitialisation d'un mot de passe :

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