En une phrase
Les algorithmes de hachage de mot de passe comme bcrypt et Argon2 transforment le mot de passe d'un utilisateur en une longue chaîne de caractères irréversible, conçue pour être lente et coûteuse à calculer, ce qui rend le cassage atrocement difficile pour les attaquants, même s'ils volent votre base de données utilisateurs complète.
Le problème que ça résout
À l'âge sombre du numérique, les développeurs stockaient les mots de passe des utilisateurs en clair. Si un hacker parvenait à pénétrer la base de données, il mettait la main sur un fichier contenant tous les noms d'utilisateur et leurs mots de passe correspondants. Game over. Vous imaginez le carnage.
La première amélioration fut le « hachage ». Au lieu de stocker P@ssword123, on stockait son hash, une chaîne de longueur fixe générée par un algorithme comme MD5 ou SHA-1. Quand l'utilisateur se connectait, on hachait le mot de passe qu'il saisissait et on vérifiait s'il correspondait au hash stocké. C'était mieux, mais avec une faille fatale : les tables arc-en-ciel (rainbow tables). Comme une fonction de hachage produit toujours le même résultat pour la même entrée (par ex., password donne toujours 5f4dcc3b5aa765d61d8327deb882cf99 avec MD5), les attaquants pré-calculaient les hashs de milliards de mots de passe courants et les stockaient dans une gigantesque table de correspondance. Un hash volé pouvait être inversé pour retrouver le mot de passe original en quelques millisecondes.
L'évolution suivante fut le « salage ». Avant de hacher le mot de passe, on y ajoute une chaîne aléatoire unique appelée un « sel ». Donc, au lieu de hacher P@ssword123, on hachait P@ssword123 + aBcDeFg12345. Le sel est ensuite stocké à côté du hash dans la base de données. Ça neutralise complètement les tables arc-en-ciel, car maintenant, le hash de chaque utilisateur est unique, même s'ils ont tous choisi « password » comme mot de passe. Un attaquant devrait générer une nouvelle table arc-en-ciel pour chaque sel unique de chaque utilisateur, ce qui est infaisable en termes de calcul.
Mais un nouveau méchant est entré en scène : la puissance de calcul brute. Les GPU modernes et le matériel personnalisé (ASIC) peuvent tester des milliards de combinaisons de mots de passe salés par seconde contre un seul hash volé. Les algorithmes de hachage comme SHA-256 sont conçus pour être rapides, ce qui est génial pour vérifier l'intégrité de fichiers mais terrible pour protéger des mots de passe.
C'est le problème que bcrypt et Argon2 sont nés pour résoudre. Ce sont des fonctions de hachage de mot de passe (PHF), une classe spéciale d'algorithmes de hachage qui sont délibérément, atrocement lents et gourmands en ressources. Ils rendent la vérification d'un seul mot de passe si coûteuse qu'une attaque par force brute sur une base de données volée devient un cauchemar économique et temporel pour l'attaquant.
Comment ça marche sous le capot
La magie derrière le hachage de mot de passe moderne ne réside pas seulement dans l'algorithme ; il s'agit de faire en sorte que cet algorithme effectue une quantité de « travail » configurable. C'est ce qu'on appelle souvent « l'étirement de clé » (key stretching).
L'idée de base : le coût adaptatif
Bcrypt et Argon2 ont tous deux des facteurs de « coût » ou de « travail » ajustables. C'est leur super-pouvoir. C'est un nombre que vous définissez et qui dicte à quel point le processus de hachage sera lent et gourmand en ressources. L'idée est d'ajuster ce coût pour que le hachage d'un mot de passe sur votre serveur prenne un temps raisonnable (disons, 100-500 millisecondes) — assez lent pour frustrer un attaquant, mais assez rapide pour ne pas agacer vos utilisateurs.
À mesure que les ordinateurs deviennent plus rapides conformément à la loi de Moore, vous pouvez simplement augmenter le facteur de coût tous les quelques années pour maintenir le même niveau de sécurité. Votre « séance de muscu » de hachage devient plus difficile à mesure que le matériel de l'attaquant devient plus puissant.
Bcrypt : Le vétéran de confiance
Bcrypt, introduit en 1999, est basé sur l'algorithme de chiffrement Blowfish. Sa principale défense contre les attaques par force brute est qu'il n'est pas seulement intensif en calcul, mais aussi gourmand en mémoire.
L'algorithme traite de manière répétée le mot de passe et le sel, mais une partie clé de son état interne est stockée de manière à nécessiter un accès fréquent à un bloc de RAM. Alors que les CPU sont bons à ce jeu, les GPU — l'arme de prédilection de l'attaquant — excellent dans les calculs simples et parallélisables avec un accès mémoire minimal. En forçant le processus à puiser constamment dans la mémoire, bcrypt met des bâtons dans les roues des machines de cassage à base de GPU.
Une chaîne de hash bcrypt typique ressemble à ceci :
$2b$12$J9yLsf9dTOZiCEpT1zO97uF2Yp3uG/yG4Q6V.C1rCg8u6d5qO5GqS
Décortiquons-la :
| Partie | Exemple | Signification |
|---|---|---|
| Algorithme | $2b |
Identifie l'algorithme bcrypt et sa version. |
| Facteur de coût | 12 |
Le facteur de travail. Le nombre d'itérations est de 212. L'augmenter de 1 double le temps. |
| Sel & Hash | J9yLsf...d5qO5GqS |
Les 22 premiers caractères sont le sel encodé en Base64. Le reste est le digest du mot de passe haché. |
Point crucial, toutes les informations nécessaires pour vérifier un mot de passe — l'algorithme, le coût et le sel — sont stockées directement dans cette chaîne unique et pratique.
Argon2 : Le champion moderne
Argon2 a été le vainqueur de la Password Hashing Competition (PHC) en 2015, un effort de plusieurs années pour trouver un nouvel algorithme de hachage de mot de passe standardisé. Il est conçu pour être encore plus résistant que bcrypt aux attaques matérielles modernes.
Il offre trois leviers distincts pour ajuster son coût :
- Coût mémoire (m) : La quantité de mémoire (en KiB) que l'algorithme utilisera. C'est sa principale défense contre l'accélération matérielle, car il peut être réglé pour exiger plus de mémoire que ce qui est disponible sur un seul cœur de GPU.
- Coût temporel (t) : Le nombre d'itérations, ou de passes, que l'algorithme effectue sur la mémoire. Cela augmente le temps de calcul total.
- Parallélisme (p) : Le nombre de threads ou de « voies » qui peuvent être utilisés. Cela permet à l'algorithme de tirer parti des CPU multi-cœurs pour le hachage, mais cela signifie aussi qu'un attaquant peut utiliser le même parallélisme. C'est un paramètre de compromis.
La variante recommandée est Argon2id, qui est un hybride de deux autres versions. Elle offre une résistance équilibrée à la fois contre les attaques par canal auxiliaire (où un attaquant analyse les effets sur le système comme la consommation d'énergie) et les attaques de cassage par GPU.
Une chaîne de hash Argon2id est tout aussi autonome :
$argon2id$v=19$m=65536,t=3,p=4$c29tZXNhbHQ$RdescudvJCsgt3ub+b+dWRWJTIT0T7cKLfgflAIk124
| Partie | Exemple | Signification |
|---|---|---|
| Algorithme | $argon2id |
Identifie l'algorithme Argon2id. |
| Version | v=19 |
Le numéro de version de l'algorithme. |
| Paramètres | m=65536,t=3,p=4 |
Les coûts en mémoire, temps et parallélisme. |
| Sel | c29tZXNhbHQ |
Le sel aléatoire encodé en Base64. (Ceci se décode en "somesalt"). |
| Hash | Rdescudv...flAIk124 |
Le digest du mot de passe haché, encodé en Base64. |
Le processus de vérification
C'est la partie la plus belle. On ne déchiffre jamais un hash. La vérification est à sens unique.
- Un utilisateur tente de se connecter avec
P@ssword123. - Votre application récupère sa chaîne de hash complète depuis la base de données (par ex., la chaîne Argon2id du tableau ci-dessus).
- Votre code analyse cette chaîne, en extrayant l'algorithme (
argon2id), la version (19), les facteurs de coût (m=65536, t=3, p=4), et le sel (c29tZXNhbHQ). - Il prend ensuite le mot de passe que l'utilisateur vient de saisir (
P@ssword123) et le hache en utilisant exactement les mêmes paramètres. - Enfin, il compare le hash nouvellement généré avec la partie hash de la chaîne de la base de données. S'ils sont identiques, le mot de passe est correct. Sinon, l'accès est refusé.
Histoires vécues
La fuite de données de LinkedIn en 2012 : une leçon de vitesse
En 2012, LinkedIn a subi une faille massive, et plus de 6,5 millions de hashs de mots de passe d'utilisateurs ont été divulgués sur un forum de hackers russe. Le problème ? Les hashs étaient du SHA-1 non salé. En quelques heures, les passionnés de sécurité et les black hats se sont lancés dans une course pour les cracker. Les listes de mots de passe crackés avec succès s'allongeaient de minute en minute. Parce que les hashs étaient « rapides » et non salés, une seule et énorme table arc-en-ciel a suffi. Les dommages en termes de réputation ont été immenses.
Leçon : Un hash rapide et non salé est à peine mieux que du texte en clair. La fuite de LinkedIn a été un électrochoc pour l'industrie qui a poussé d'innombrables entreprises à enfin adopter un hachage lent et salé comme bcrypt.
Le site e-commerce qui a gagné du temps
Un développeur avisé d'une startup, "CircuitCraze", a insisté pour utiliser Argon2id pour leur nouvelle base de données clients, en ajustant les paramètres pour que chaque connexion prenne environ 300 ms. Un an plus tard, un bucket de stockage cloud mal configuré a exposé une sauvegarde de la base de données. La table users, avec tous ses hashs Argon2id, a été téléchargée par un attaquant. L'équipe a immédiatement forcé une réinitialisation globale des mots de passe. L'attaquant, confronté à la perspective de dépenser des milliers de dollars en cloud computing juste pour cracker une poignée de mots de passe d'un jeu de données désormais inutile, a simplement abandonné et s'est tourné vers des cibles plus faciles.
Leçon : Un hachage de mot de passe robuste est votre principale défense après une faille. Il n'empêche pas la faille, mais il transforme une fuite de données catastrophique en un incident gérable en vous faisant gagner un temps crucial pour réagir.
La dérive du facteur de coût
Une équipe a lancé une nouvelle application web en 2015, choisissant judicieusement bcrypt avec un facteur de coût de 10. Ça fonctionnait très bien. Avance rapide jusqu'à aujourd'hui. La loi de Moore a fait son œuvre, et un facteur de coût de 10 est maintenant considéré comme faible. Un audit de sécurité le signale comme un risque de haute priorité. L'équipe est maintenant face à un dilemme : comment améliorer la sécurité pour des millions d'utilisateurs sans forcer une réinitialisation de masse des mots de passe ? La solution élégante : la prochaine fois qu'un utilisateur se connecte, le système vérifie son mot de passe par rapport à l'ancien hash à coût 10. Si c'est correct, il re-hache immédiatement le même mot de passe avec un nouveau coût de 13 et remplace l'ancien hash dans la base de données.
Leçon : La sécurité des mots de passe, ce n'est pas « on configure et on oublie ». Les facteurs de coût sont un paramètre vivant qui doit être périodiquement revu et augmenté pour suivre le rythme des capacités des attaquants.
Erreurs et pièges courants
- Utiliser un hash rapide. Ne le faites pas. MD5, SHA-1, SHA-256, SHA-512... ils sont faits pour les sommes de contrôle (checksums), pas pour les mots de passe. Ils sont conçus pour être rapides, ce qui est exactement ce que vous ne voulez pas.
- Créer son propre système de chiffrement. N'essayez jamais d'inventer votre propre schéma de hachage, comme
sha512(password + salt). Utilisez une bibliothèque standard, évaluée par des pairs et éprouvée au combat pour bcrypt ou Argon2 qui fait les choses correctement. - Utiliser un sel statique ou réutilisé. Un sel doit être aléatoire au sens cryptographique et unique pour chaque mot de passe que vous stockez. Stocker un sel unique à côté de chaque hash est la pratique correcte et standard.
- Définir un coût trop bas. Un facteur de coût bcrypt inférieur à 12 (en 2024) ou des paramètres Argon2 faibles vont à l'encontre de l'objectif. Vous ne faites que faciliter la tâche de l'attaquant. Réglez-le pour qu'il soit aussi lent que vous pouvez le tolérer.
- Définir un coût trop élevé. Si le hachage prend 10 secondes, votre formulaire de connexion expirera et semblera cassé. Pire encore, vous exposez votre serveur à une attaque par déni de service (DoS) où quelqu'un peut mettre vos CPU à genoux simplement en postant de manière répétée sur le formulaire de connexion.
- Stocker uniquement le digest du hash. Les chaînes générées par bcrypt et Argon2 contiennent l'algorithme, les coûts et le sel pour une bonne raison. Vous devez stocker cette chaîne entière (par ex., dans une colonne
VARCHAR(255)) pour pouvoir vérifier les mots de passe à l'avenir.
Pourquoi vous devriez vous y intéresser
Si votre travail consiste à construire quoi que ce soit qui ait un formulaire de connexion, vous devez comprendre cela.
- Devs Backend & Full-Stack : C'est votre responsabilité directe. Si vous vous plantez là-dessus, vous mettez tous vos utilisateurs en danger.
- Ingénieurs Sécurité & DevOps : C'est vous qui définissez les politiques, effectuez les audits et gérez l'infrastructure. Vous devez savoir à quoi ressemble un « bon » système et comment le tester.
- Devs Frontend : Comprendre qu'une connexion sécurisée peut prendre quelques centaines de millisecondes explique pourquoi vous devez fournir un retour à l'utilisateur (comme un spinner de chargement) pour l'empêcher de cliquer frénétiquement sur le bouton « Se connecter ».
Bref, si les mots « utilisateur », « compte » ou « mot de passe » apparaissent quelque part dans les specs de votre projet, le hachage de mot de passe est un concept fondamental que vous ne pouvez pas vous permettre d'ignorer.
Pour aller plus loin
- OWASP Password Storage Cheat Sheet — Le guide de référence essentiel pour les développeurs.
- Argon2 Specification — Le document formel décrivant le fonctionnement d'Argon2.
- How To Safely Store A Password by Coda Hale — Un article de blog classique de 2010 qui a expliqué le « pourquoi » de bcrypt à toute une génération de développeurs.
- Bcrypt on Wikipedia — Un bon aperçu de l'histoire et de la conception de l'algorithme.
- Argon2 on Wikipedia — Contexte sur la Password Hashing Competition et la conception d'Argon2.
- Password Hashing Competition — Le site officiel de la compétition qui a couronné Argon2.