10 façons de générer des mots de passe en Python (bibliothèque standard uniquement)

Générer des mots de passe et des jetons sécurisés est un besoin courant dans tout projet logiciel. Bonne nouvelle : Python dispose de tout ce qu’il faut dans sa bibliothèque standard, sans aucune dépendance externe. Cet article présente 10 techniques éprouvées, chacune avec son cas d’usage idéal.

Règle d’or : pour tout ce qui touche à la sécurité, utilisez le module secrets (Python 3.6+). Le module random n’est pas cryptographiquement sûr et ne doit jamais être utilisé pour des mots de passe en production.

1. secrets.token_urlsafe()

La méthode la plus simple pour générer un jeton sécurisé. Le résultat est encodé en base64 URL-safe, ce qui le rend parfait pour les URLs, les jetons de réinitialisation de mot de passe et les clés API.

Python
import secrets

token = secrets.token_urlsafe(32)
print(token)       # ex: Dz-M4Kq9x7R2bN5vLpWs...
print(len(token))  # 43 caractères

Le paramètre 32 correspond au nombre d’octets aléatoires avant l’encodage base64. Le jeton résultant fait environ 43 caractères. C’est la méthode recommandée pour la plupart des cas d’usage.

2. secrets.token_hex()

Génère une chaîne hexadécimale aléatoire. Utile quand vous avez besoin d’un jeton composé uniquement de caractères 0-9 et a-f.

Python
import secrets

token = secrets.token_hex(16)
print(token)       # ex: a3f2b1c4d5e6f7081920abcdef123456
print(len(token))  # 32 caractères hexadécimaux

Chaque octet produit deux caractères hexadécimaux. Avec 16 octets, vous obtenez un jeton de 32 caractères offrant 128 bits d’entropie, ce qui est largement suffisant pour la plupart des applications.

3. secrets.token_bytes() + base64

Pour un contrôle total sur l’encodage, combinez secrets.token_bytes() avec le module base64 :

Python
import secrets
import base64

raw = secrets.token_bytes(24)
password = base64.b64encode(raw).decode("ascii")
print(password)       # ex: K7vB2mP9xQ4nR1jL8wY3dFhT...
print(len(password))  # 32 caractères

Cette approche est utile lorsque vous devez choisir un encodage spécifique (base64, base32, base85). L’encodage base64 produit un rapport de 4 caractères pour 3 octets.

4. secrets.choice() avec un alphabet alphanumérique

Quand vous avez besoin d’un mot de passe composé uniquement de lettres et de chiffres :

Python
import secrets
import string

alphabet = string.ascii_letters + string.digits
password = "".join(secrets.choice(alphabet) for _ in range(16))
print(password)  # ex: aB3kM9pQ2wX7nL5j

Le module string fournit des constantes pratiques : ascii_letters (a-z + A-Z), digits (0-9), punctuation (caractères spéciaux). secrets.choice() sélectionne un caractère aléatoire de manière cryptographiquement sûre.

5. secrets.choice() avec caractères spéciaux (et garantie de complexité)

Pour des mots de passe qui satisfont les exigences de complexité (majuscule, minuscule, chiffre, caractère spécial) :

Python
import secrets
import string

def mot_de_passe_fort(longueur=16):
    alphabet = string.ascii_letters + string.digits + "!@#$%&*+-_"
    while True:
        mdp = "".join(secrets.choice(alphabet) for _ in range(longueur))
        if (any(c in string.ascii_lowercase for c in mdp)
                and any(c in string.ascii_uppercase for c in mdp)
                and any(c in string.digits for c in mdp)
                and any(c in "!@#$%&*+-_" for c in mdp)):
            return mdp


print(mot_de_passe_fort())     # ex: aB3$kM9&pQ2!wX7@
print(mot_de_passe_fort(24))   # version plus longue

La boucle while True régénère le mot de passe jusqu’à ce qu’il contienne au moins un caractère de chaque catégorie. En pratique, avec un alphabet large et une longueur de 16+, la boucle ne fait qu’une ou deux itérations.

6. os.urandom() + base64

Le module os donne accès au générateur d’entropie du système d’exploitation. C’est d’ailleurs la source que secrets utilise en interne.

Python
import os
import base64

raw = os.urandom(32)
token = base64.urlsafe_b64encode(raw).decode("ascii").rstrip("=")
print(token)       # ex: Dz-M4Kq9x7R2bN5vLpWs...
print(len(token))  # 43 caractères

Cette technique est équivalente à secrets.token_urlsafe() mais vous donne un contrôle plus fin. Elle est utile si vous travaillez avec Python 2 ou un environnement où secrets n’est pas disponible.

7. uuid.uuid4() pour des identifiants uniques

Les UUID version 4 sont générés aléatoirement et offrent 122 bits d’entropie. Ils sont parfaits comme identifiants uniques, mais ne sont pas recommandés comme mots de passe car leur format est prévisible.

Python
import uuid

token = str(uuid.uuid4())
print(token)  # ex: 550e8400-e29b-41d4-a716-446655440000

# Version compacte (sans tirets)
compact = token.replace("-", "")
print(compact)  # ex: 550e8400e29b41d4a716446655440000
print(len(compact))  # 32 caractères

Les UUID sont idéaux pour les identifiants de session, les clés primaires de base de données ou les noms de fichiers temporaires. Leur format standardisé les rend facilement reconnaissables.

8. hashlib + secrets pour des jetons dérivés

Combinez hashlib et secrets pour créer des jetons de longueur fixe, parfaits pour des signatures ou des clés de vérification :

Python
import hashlib
import secrets

salt = secrets.token_bytes(16)
data = secrets.token_bytes(32)
token = hashlib.sha256(salt + data).hexdigest()
print(token)       # 64 caractères hexadécimaux
print(len(token))  # toujours 64

Le sel (salt) rend chaque jeton unique même si les données d’entrée étaient identiques. SHA-256 produit toujours exactement 64 caractères hexadécimaux. Vous pouvez aussi utiliser sha512 pour un jeton de 128 caractères.

9. random (NON sécurisé – à éviter en production)

Attention : le module random utilise l’algorithme Mersenne Twister qui n’est pas cryptographiquement sûr. Son état interne peut être reconstitué à partir de 624 valeurs consécutives. Ne l’utilisez jamais pour des mots de passe en production.

Python
import random
import string

# ATTENTION : NON cryptographiquement sur !
# A utiliser UNIQUEMENT pour des tests ou des donnees non sensibles
alphabet = string.ascii_letters + string.digits
password = "".join(random.choice(alphabet) for _ in range(16))
print(password)

Le seul cas acceptable pour random est la génération de données de test ou de mots de passe jetables dans un contexte de développement local. Pour tout le reste, utilisez secrets.

10. Générateur configurable tout-en-un

Voici une fonction réutilisable qui combine les meilleures pratiques et permet de personnaliser chaque aspect du mot de passe généré :

Python
import secrets
import string


def generer_mot_de_passe(
    longueur=16,
    majuscules=True,
    minuscules=True,
    chiffres=True,
    speciaux=True,
    caracteres_speciaux="!@#$%&*+-_=",
):
    alphabet = ""
    requis = []

    if minuscules:
        alphabet += string.ascii_lowercase
        requis.append(secrets.choice(string.ascii_lowercase))
    if majuscules:
        alphabet += string.ascii_uppercase
        requis.append(secrets.choice(string.ascii_uppercase))
    if chiffres:
        alphabet += string.digits
        requis.append(secrets.choice(string.digits))
    if speciaux:
        alphabet += caracteres_speciaux
        requis.append(secrets.choice(caracteres_speciaux))

    if not alphabet:
        raise ValueError("Au moins un type de caractère doit être activé")

    reste = longueur - len(requis)
    mdp = requis + [secrets.choice(alphabet) for _ in range(reste)]
    secrets.SystemRandom().shuffle(mdp)
    return "".join(mdp)


print(generer_mot_de_passe())
print(generer_mot_de_passe(longueur=32, speciaux=False))
print(generer_mot_de_passe(longueur=8, caracteres_speciaux="!@#"))

Cette fonction garantit qu’au moins un caractère de chaque catégorie activée est présent dans le mot de passe final. Le mélange aléatoire via secrets.SystemRandom().shuffle() assure que les caractères obligatoires ne sont pas toujours au début.

Récapitulatif

Voici un résumé rapide pour choisir la bonne technique selon votre besoin :

Jeton URL-safe : secrets.token_urlsafe()

Jeton hexadécimal : secrets.token_hex()

Encodage personnalisé : secrets.token_bytes() + base64

Mot de passe alphanumérique : secrets.choice() + string

Mot de passe complexe : secrets.choice() avec validation

Compatibilité bas niveau : os.urandom()

Identifiant unique : uuid.uuid4()

Jeton de longueur fixe : hashlib + secrets

Quelle que soit la technique choisie, retenez la règle essentielle : utilisez toujours le module secrets pour tout ce qui concerne la sécurité. Votre futur vous en remerciera.

Comments

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *