Skip to content

Ce que font vraiment les sels (et ce qu'ils ne font pas)

Les sels tuent les rainbow tables et les fuites d'empreintes partagées. Ils ne ralentissent pas un cassage ciblé. Pourquoi le MD5 salé reste faible, et pourquoi il faut un KDF lent.

Publié le 6 min de lecture

Le sel est l'un des éléments les plus mal compris du stockage des mots de passe. On sait qu'il faut en ajouter un, on sait qu'il rend les choses « plus sûres », puis on décrit son rôle d'une manière simplement fausse. L'affirmation habituelle, c'est que le salage ralentit le cassage. C'est faux. Comprendre ce qu'un sel déjoue réellement, et ce qu'il laisse grand ouvert, fait toute la différence entre une défense qui marche et une case cochée qui rassure à tort.

Le précalcul est le problème que le sel résout

Une fonction de hachage est à sens unique, mais elle est aussi déterministe : la même entrée produit toujours la même sortie. Ce déterminisme invite à un raccourci. Au lieu de deviner des mots de passe contre une cible au moment de l'attaque, on effectue tout le hachage à l'avance et on stocke la correspondance mot de passe vers empreinte. Le cassage devient alors une recherche, pas un calcul.

Une rainbow table est la version économe en espace de cette idée : elle échange un peu de recalcul contre un stockage radicalement réduit, ce qui permet de couvrir des milliards de candidats dans un fichier gérable. Face à une empreinte rapide non salée comme MD5, c'est dévastateur. Quelqu'un a déjà haché tous les mots de passe courants et la plupart des courts. Donnez-lui un MD5 non salé et la récupération est instantanée, car le travail a eu lieu il y a des années sur le matériel de quelqu'un d'autre.

Il y a un second problème avec les empreintes non salées, même cause profonde. Des mots de passe identiques produisent des empreintes identiques. Cassez un compte et vous avez cassé, gratuitement, tous ceux de la fuite qui avaient choisi le même mot de passe, simplement en regroupant les empreintes identiques.

Ce qu'est un sel et ce qu'il change

Un sel est une valeur aléatoire unique générée par mot de passe et mêlée avant le hachage. Stockez le sel à côté de l'empreinte : il n'est pas secret. L'objectif est l'unicité, pas la dissimulation.

Ce seul changement casse net le précalcul. Une rainbow table construite pour des mots de passe nus devient inutile dès que chaque empreinte est salée, car l'attaquant aurait besoin d'une table distincte pour chaque valeur de sel possible, ce qui ruine toute l'économie du précalcul. Le problème des empreintes partagées meurt aussi : deux utilisateurs avec le même mot de passe ont désormais des sels différents, donc des empreintes différentes, et casser l'un ne dit rien sur l'autre. Les sels propres à chaque utilisateur obligent l'attaquant à un travail par cible. C'est toute la contribution du sel, et elle est réellement importante.

Ce que le sel ne fait pas

C'est ici que l'idée fausse mord. Un sel ne ralentit pas du tout un cassage ciblé unique.

Imaginez un attaquant qui veut un compte précis. Il lit le sel directement dans la fuite (il est juste là), le préfixe à chaque candidat, et hache. Le sel ne lui coûte rien. Face à un MD5 salé, le GPU enchaîne toujours des milliards d'essais par seconde sur ce seul compte, et un mot de passe faible tombe en quelques secondes. Le sel a empêché l'attaquant d'utiliser une table précalculée et de casser tout le monde d'un coup. Il n'a en rien ralenti l'attaque par cible, car la vitesse de l'algorithme est ce qui compte pour un cassage ciblé, et le salage ne touche pas à la vitesse de l'algorithme.

Voilà pourquoi le « MD5 salé » n'est pas la garantie que l'on croit. Le sel fait un vrai travail contre le précalcul et les empreintes partagées. Il ne fait absolument rien contre un GPU braqué sur un mot de passe faible.

La lenteur vient des itérations, pas du sel

Si le sel apporte l'unicité, qu'est-ce qui apporte le coût ? Les itérations. Un facteur de coût. Une fonction de hachage de mots de passe comme bcrypt, sha512crypt ou Argon2 exécute volontairement l'opération sous-jacente des milliers de fois, si bien qu'un essai unique qui prenait des microsecondes contre MD5 prend désormais des millisecondes. Cela effondre le rythme d'essai de l'attaquant, de milliards par seconde à des milliers, et c'est la seule chose qui rende un cassage ciblé réellement coûteux. Le facteur de coût est réglable : à mesure que le matériel s'accélère, on l'augmente et on garde le coût là où on le veut.

Les deux propriétés sont donc orthogonales. Le sel donne l'unicité, déjouant le précalcul et les fuites d'empreintes partagées. Le facteur de coût donne la lenteur, déjouant l'essai ciblé rapide. Il faut les deux, et l'un ne peut pas remplacer l'autre. Une empreinte de mot de passe moderne les regroupe : elle génère automatiquement un sel par empreinte et applique un nombre d'itérations configurable, et c'est pourquoi on stocke les mots de passe avec bcrypt ou Argon2 plutôt qu'en bricolant du MD5 salé à la main.

Le poivre est autre chose

Un poivre (pepper) se glisse parfois dans cette discussion et ne doit pas être confondu avec le sel. Un poivre est une valeur secrète, identique pour tous les utilisateurs, conservée en dehors de la base de données (dans la configuration applicative, un HSM, un gestionnaire de secrets). Le sel vit à côté de l'empreinte et n'est pas secret ; le poivre vit à part et l'est. L'idée est qu'un attaquant qui ne vole que la base de données, sans le secret applicatif, ne peut pas casser hors ligne du tout, car il lui manque une entrée. Utile en défense en profondeur, mais c'est un complément, pas un substitut. Il ne remplace ni un sel unique ni un KDF lent.

Le bon modèle mental : le sel pour l'unicité, le facteur de coût pour le coût, le poivre comme secret optionnel par-dessus. Réussissez les deux premiers avec un vrai KDF et vous avez défendu à la fois contre le précalcul et la force brute. Confondez-les, livrez du MD5 salé, et vous aurez arrêté les rainbow tables tout en laissant la porte d'entrée ouverte à un GPU.