Une base d’utilisateurs a fuité
Pour stocker un mot de passe en sécurité, on garde son empreinte salée et lente, jamais le mot lui-même. Une clé secrète ne s’écrit jamais dans le code.
Le site d’un club de sport fuite sa base. Si elle contient les mots de passe en clair, tous les comptes sont perdus. Ceux d’autres sites aussi, si les gens ont réutilisé le même.
À la fin de cette leçon
Remarque
Je peux stocker des mots de passe et des clés de façon sûre.
Mots-clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Sel | une valeur aléatoire ajoutée au mot de passe avant le hachage | sel1 |
| Hachage lent | un hachage répété des milliers de fois pour ralentir un attaquant | PBKDF2 |
| Dictionnaire d’attaque | une liste de mots de passe courants que l’on essaie un à un | |
| Table précalculée | une liste d’empreintes déjà calculées pour des mots courants | |
| Gestionnaire de secrets | un service qui garde les clés hors du code | |
| Rotation | changer une clé régulièrement ou après une fuite |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
On stocke l’empreinte du mot de passe
Au lieu du mot de passe, la base garde son empreinte. À la connexion, le site hache ce que vous tapez et compare. Si la base fuit, l’attaquant lit des empreintes, pas des mots de passe.
Mais cela ne suffit pas. Beaucoup de gens choisissent des mots courants, et un même mot donne toujours la même empreinte.
L’empreinte d’azerty, seize premiers caractères
printf 'azerty' | sha256sum | cut -c1-16Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Un sel rend chaque empreinte unique
Le sel est une valeur aléatoire, différente pour chaque utilisateur. On l’ajoute au mot de passe avant de hacher, et on le stocke à côté de l’empreinte. Il n’est pas secret.
Deux utilisateurs au même mot de passe ont deux empreintes différentes. Une table précalculée ne sert plus : il faudrait en refaire une par sel.
Le mot azerty avec le sel sel1
python3 -c "import hashlib; print(hashlib.sha256(b'sel1' + b'azerty').hexdigest()[:16])"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Le même mot avec un autre sel
python3 -c "import hashlib; print(hashlib.sha256(b'sel2' + b'azerty').hexdigest()[:16])"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Exemple travaillé : sans sel et avec sel
| Utilisateur | Mot de passe | Sel | Seize premiers caractères de l’empreinte |
|---|---|---|---|
| Léa | azerty | aucun | f2d81a260dea8a10 |
| Karim | azerty | aucun | f2d81a260dea8a10, la même |
| Léa | azerty | sel1 | e31c7fb43ef28960 |
| Karim | azerty | sel2 | f67fb412085812c2, différente |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Erreur fréquente
Attention
Beaucoup de gens pensent que le sel doit rester secret, comme un mot de passe. Ce n’est pas le cas. Il sert à rendre les empreintes uniques, et il est lisible dans la base. Ce qui doit rester secret, c’est le mot de passe lui-même.
Un hachage lent freine les essais
Un attaquant qui possède la base essaie des millions de mots de passe. Plus le calcul est lent, moins il en essaie. Un hachage lent, comme PBKDF2, répète le calcul des milliers de fois.
Avec 1 000 répétitions, chaque essai coûte 1 000 calculs au lieu d’un. Pour vous, une connexion reste instantanée. Pour l’attaquant, c’est mille fois plus de travail.
PBKDF2 avec 1000 répétitions
python3 -c "import hashlib; print(hashlib.pbkdf2_hmac('sha256', b'azerty', b'sel1', 1000).hex()[:16])"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Une clé ne s’écrit jamais dans le code
Une clé écrite dans un programme part avec lui : dans le dépôt, dans les sauvegardes, chez toute personne qui lit le code. On la garde donc dehors : une variable d’environnement ou, mieux, un gestionnaire de secrets.
Une clé vient d’un générateur aléatoire sûr, jamais d’un mot que l’on a choisi. On la change régulièrement, et tout de suite après une fuite : c’est la rotation.
Une clé aléatoire de 16 octets : sa longueur
python3 -c "import secrets; print(len(secrets.token_hex(16)))"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.