"secrets" — Générer des nombres aléatoires de façon sécurisée pour la gestion des secrets
*****************************************************************************************

Nouveau 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.

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.

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(sequence)

   Renvoie un élément choisi aléatoirement dans une séquence non-vide.

secrets.randbelow(n)

   Renvoie un entier aléatoire dans l'intervalle [0, *n*).

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)

   Renvoie "True" si les chaînes *a* et *b* sont égales et "False"
   sinon, d'une manière permettant de réduire le risque d'attaque
   temporelle. Se référer à "hmac.compare_digest()" pour plus de
   détails.


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:

  Les applications ne doivent jamais stocker des mots de passe dans un
  format permettant leur récupération, que ce soit en texte brut ou
  chiffré. Il convient que les mots de passe soient salés et
  transformés de façon irréversible par une fonction de hachage
  cryptographique.

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://mydomain.com/reset=' + secrets.token_urlsafe()
