Hash, sel, bcrypt et Argon2 : ce qu'un site bien fait fabrique avec votre mot de passe

Publié le par David Carrero

Un site bien fait ne connaît pas votre mot de passe. Ce n’est pas qu’il ne veuille pas : il ne peut pas.

Ça sonne comme un tour de passe-passe, parce que chaque fois que vous le tapez le système vous laisse entrer, et pour vous laisser entrer il doit bien vérifier quelque chose. Mais vérifier, ce n’est pas savoir. Le serveur garde une empreinte calculée à partir de votre mot de passe ; quand vous tapez, il recalcule l’empreinte et compare. Si les deux coïncident, entrez. À aucun moment le mot de passe n’a besoin d’être écrit où que ce soit.

D’où le signe le plus clair pour distinguer un service sérieux d’un service qui ne l’est pas : si, quand vous l’oubliez, on vous le renvoie par courriel, c’est qu’on le gardait. Et ce qui est gardé finit, tôt ou tard, entre les mains de quelqu’un d’autre.

1979 l’idée de ne pas les stocker — et celle de le faire lentement

En 1979, Robert Morris et Ken Thompson publient dans Communications of the ACM « Password Security: A Case History », où ils racontent ce qu’ils avaient fait dans Unix. C’est un récit d’expérience, et deux idées qui nous semblent aujourd’hui évidentes y sont posées.

La première n’est pas d’eux — stocker le hash au lieu du mot de passe se pratiquait déjà —, mais personne ne l’avait mieux expliquée : ne pas stocker le mot de passe, stocker son hash. Une fonction qui transforme votre mot de passe en une valeur d’allure arbitraire et qu’on ne peut pas remonter : du hash, on ne revient pas au mot de passe.

La seconde, en revanche, est bien la leur : le sel. Une valeur aléatoire différente pour chaque utilisateur, mélangée au mot de passe avant le calcul du hash. Sans sel, deux personnes qui ont le même mot de passe ont le même hash — le fichier volé devient un jeu des sept erreurs à l’envers, il suffit de chercher les doublons — et, pire, on peut précalculer une table géante une bonne fois et s’en servir contre toutes les bases de données du monde. Le sel ne rend pas votre mot de passe plus difficile à deviner : il fait que le deviner ne serve à personne d’autre.

Mais dans ce même article se trouve une troisième idée, bien moins citée, et c’est celle qui compte ici : ils ont rendu la fonction délibérément lente. Pas par négligence. Exprès. Chiffrer un mot de passe coûtait bien plus cher que ce qui était techniquement nécessaire, parce que celui qui se connecte une fois par matin s’en moque, et celui qui essaie des millions de candidats, non.

Toute l’affaire tient dans cette phrase vieille de presque cinquante ans.

Pourquoi la lenteur est la seule défense honnête

Presque toutes les défenses informatiques sont asymétriques : elles coûtent peu à qui se défend et cher à qui attaque. Chiffrer ne coûte rien ; déchiffrer sans la clé est hors de portée. Le défenseur joue avec un avantage structurel.

Le stockage des mots de passe, non. Ici, défenseur et attaquant exécutent exactement la même fonction. Vous calculez le hash pour vérifier que vous avez tapé juste ; lui le calcule pour vérifier s’il a tapé juste. C’est la seule course de la sécurité où les deux coureurs ont les mêmes jambes.

Quand on ne peut pas courir plus vite que l’adversaire, il ne reste qu’un coup à jouer : rendre la piste chère pour les deux. Vous payez ce coût une fois par connexion. Lui, une fois par tentative. Comme il lui faut des ordres de grandeur plus de tentatives que vous, la même facture ne vous touche pas du tout de la même manière. Voilà ce que fait un hash de mots de passe.

C’est pour ça que les fonctions rapides et excellentes pour autre chose — SHA-256, par exemple — sont un choix catastrophique ici. Elles sont rapides. Rapide, c’est exactement ce dont nous ne voulons pas.

1999 bcrypt, et le coût comme pièce réglable

L’ennui, avec une fonction lente, c’est que le matériel ne reste pas immobile. Ce qui était lent en 1979 devient instantané ensuite. Une défense calibrée contre les ordinateurs d’une décennie vieillit toute seule, sans que personne n’y touche.

En 1999, Niels Provos et David Mazières présentent bcrypt à l’USENIX Annual Technical Conference, avec un titre qui dit déjà tout : A Future-Adaptable Password Scheme.

L’idée : que le coût ne soit pas dans la fonction, mais dans un paramètre. bcrypt embarque un facteur de coût que vous décidez et qui est stocké à côté du hash. Si le matériel devient beaucoup plus rapide, vous augmentez le nombre et les nouveaux mots de passe coûtent à nouveau ce qu’ils doivent coûter, sans changer d’algorithme.

C’est une conception qui prend acte de sa propre obsolescence et s’y prépare. Il y a très peu de logiciels qui font ça.

2009 scrypt, et la découverte que le temps ne suffit pas

bcrypt renchérit le temps de calcul, et ça a marché. Jusqu’à ce que l’attaquant cesse d’utiliser le même genre de machine que le défenseur.

Un serveur a quelques cœurs rapides et généralistes. Un GPU a une quantité déraisonnable de petits cœurs qui font la même chose en parallèle, et un ASIC va plus loin : du silicium fabriqué pour exécuter une seule opération. Si votre défense consiste à dire « cette opération coûte X », quelqu’un peut construire du matériel qui fait beaucoup de X à la fois. Le défenseur, lui, en est toujours à son serveur.

En 2009, Colin Percival présente scrypt avec un autre argument : Stronger Key Derivation via Sequential Memory-Hard Functions. Si le coût n’est que dans le calcul, il se parallélise. Mais la mémoire, elle, ne se donne pas. Obligez la fonction à utiliser beaucoup de RAM et à la parcourir d’une façon qu’on ne peut pas contourner, et soudain l’attaquant ne peut plus multiplier les cœurs : chaque cœur aurait besoin de sa propre mémoire. Or les cœurs d’un GPU ont beaucoup de puissance et très peu de RAM chacun.

Percival n’a pas renchéri l’opération. Il a renchéri le matériel nécessaire pour la répéter en masse. C’est un changement de niveau : on s’attaque au budget de l’attaquant, pas à son horloge.

2015 Argon2, et la fin du débat

Que plusieurs options raisonnables existent n’aidait personne à choisir. Alors la communauté cryptographique a fait ce qu’elle fait d’habitude quand elle veut trancher : un concours public. La Password Hashing Competition a reçu des candidats, les a soumis pendant des années à une analyse ouverte et, en 2015, a proclamé Argon2 vainqueur.

Argon2 hérite des deux leçons : coût en temps et coût en mémoire, réglables séparément, plus le nombre de threads. Ce n’est pas magique. C’est la synthèse ordonnée de 1979, 1999 et 2009, relue par des gens dont le métier consistait à essayer de la casser.

Ce que ça veut dire pour vous

Presque rien de tout ça n’est entre vos mains, et il faut le dire : le hash, c’est le site qui le choisit, pas vous. Vous pouvez avoir le meilleur mot de passe du monde et qu’on le range en clair dans un tableur.

Mais l’autre côté de l’équation, lui, dépend de vous. Tout cet édifice — le sel, le coût, la mémoire — sert à renchérir chaque tentative de l’attaquant. Ce qui décide du nombre de tentatives dont il a besoin, c’est votre mot de passe. S’il est dans un dictionnaire, aucune fonction lente ne vous sauve : il tombera dans les premiers. S’il est long et ne ressemble à rien, ce prix par tentative se multiplie par un nombre de tentatives qui ne tient pas dans le temps disponible.

C’est pour ça que notre générateur mesure des bits d’entropie et pas des pourcentages, et pour ça que le vérificateur cherche votre mot de passe dans des dictionnaires avant de compter les symboles. Eux fixent le prix par tentative ; vous fixez le nombre de tentatives. Aucune des deux moitiés ne fonctionne sans l’autre.

Et oui : c’est toujours la même vieille question. Sauf que maintenant, de l’autre côté, quelqu’un essaie d’y répondre un très grand nombre de fois par seconde, et depuis 1979 nous essayons de faire en sorte que chacune de ces fois lui coûte de l’argent.


Sources : R. Morris et K. Thompson, « Password Security: A Case History », Communications of the ACM, 1979 · N. Provos et D. Mazières, « A Future-Adaptable Password Scheme », USENIX Annual Technical Conference, 1999 (bcrypt) · C. Percival, « Stronger Key Derivation via Sequential Memory-Hard Functions », 2009 (scrypt) · Password Hashing Competition, vainqueur Argon2, 2015.

← Retour au blog