web-dev-qa-db-fra.com

Un mot de passe HMAC-ed est-il plus sûr qu'un mot de passe bcrypt-ed ou scrypt-ed?

Étant donné une option, laquelle dois-je choisir, un HMAC pour stocker un mot de passe en toute sécurité ou une bibliothèque bcrypt ou scrypt?

25
user917279

Afin de vous donner une bonne idée des problèmes et des subtilités du calcul des hachages de mot de passe, ainsi que des raisons pour lesquelles HMAC ne convient pas à ce problème, je fournirai une réponse beaucoup plus large que ce qui est vraiment nécessaire pour répondre directement à la question.

Un algorithme de hachage HMAC n'est, pour l'essentiel, qu'une version à clé d'un algorithme de hachage normal. Il est généralement utilisé pour vérifier l'intégrité et l'authenticité. La notation habituelle est H(m,k) = h, où H est l'algorithme de hachage HMAC, m est le message, k est la clé et h est le hachage résultant. L'idée est que deux parties qui partagent un k secret peuvent vérifier que l'autre personne est l'auteur de m. De plus, un attaquant ne peut pas forger un hachage de message sans connaître k.

Cela se fait comme suit:

  1. Alice et Bob connaissent tous les deux une clé secrète partagée k.
  2. Alice écrit un message m et en calcule le hachage HMAC à l'aide de k, c'est-à-dire H(m,k) = h.
  3. Alice envoie le message m et le hachage h à Bob.
  4. Bob calcule H(m,k) et le compare au hachage h qu'Alice a envoyé. Si les hachages correspondent, il sait qu'Alice a envoyé le message et qu'il n'a pas été modifié après l'avoir haché.

Maintenant que vous comprenez ce qu'est HMAC, passons à ce que vous vraiment voulez faire - stocker les mots de passe dans une base de données.

Il y a de nombreuses années, il était courant de stocker les mots de passe en texte brut dans les bases de données. C'était une mauvaise idée car, lorsque la base de données a été compromise, l'attaquant a obtenu tous les mots de passe. Pour lutter contre cela, nous avons commencé à hacher les mots de passe dans la base de données à l'aide d'algorithmes de hachage cryptographique à sens unique. MD5 est devenu populaire, mais les faiblesses (collisions, pré-image partielle, etc.) découvertes en son sein signifient qu'il n'est plus recommandé. Beaucoup de gens sont passés à SHA1, qui est plus sûr.

Le problème avec cette approche est qu'il est possible de construire une énorme table de hachages et leurs textes en clair correspondants. Ceux-ci sont appelés Rainbow tables . Ils travaillent sur le concept qu'il est plus efficace de calculer une énorme liste de hachages pour tous les mots de passe possibles (dans un certain ensemble) puis de les stocker, de sorte qu'il puisse être rapidement interrogé plus tard. Ainsi, au lieu de forcer brutalement les hachages individuels, il est devenu possible de simplement interroger la base de données pour un hachage et de renvoyer immédiatement son texte en clair.

Afin de résoudre ce problème, les nerds de la sécurité ont inventé des sels. Les sels sont de grandes valeurs aléatoires uniques ajoutées aux mots de passe avant leur hachage. Ce sel est stocké avec le hachage, afin qu'il puisse être calculé à nouveau plus tard. Ainsi, nous calculons H(m+s) = h, puis stockons h et s dans la base de données. Cela fournit une importante protection contre les tables Rainbow car cela nécessite essentiellement la génération d'une table Rainbow distincte pour chaque sel.

Ainsi, les méchants sont revenus aux attaques par dictionnaire et au craquage par force brute. Avec l'avènement de l'informatique GPU, il est devenu possible de calculer des milliards de hachages par seconde sur une carte graphique modérément puissante. En fait, les gens ont construit des ordinateurs capables de calculer près de 50 milliards de hachages MD5 par seconde - assez impressionnant/effrayant. La raison pour laquelle les GPU en sont capables est qu'ils sont conçus pour effectuer un grand nombre d'opérations scalaires parallèles. Les opérations scalaires sont des opérations mathématiques et logiques qui n'impliquent pas de branches - c'est-à-dire qu'elles n'ont pas besoin de faire beaucoup/tout "si x alors faire y". Les algorithmes de hachage cryptographiques ont tendance à s'intégrer dans ce modèle.

Pour rendre cela difficile, nous devons rendre l'opération de hachage suffisamment lente pour rendre le forçage brut impossible. Les algorithmes de hachage normaux (par exemple SHA1) sont conçus pour être rapides, ce qui les rend inadaptés à cette fin. HMAC ajoute très peu de frais généraux et aucune marge de sécurité supplémentaire, il n'est donc pas très utile ici.

La création d'un algorithme de hachage cryptographique lent est plus facile à dire qu'à faire - il est très difficile d'en trouver un qui soit lent, irréductible (c'est-à-dire ne peut pas être optimisé au-delà de son état actuel) et sécurisé. Il existe trois fonctions de hachage populaires qui peuvent le faire: PBKDF2 , bcrypt et scrypt . Ces fonctions sont appelées fonctions de dérivation de clé adaptative, car elles acceptent une valeur de facteur de travail avec le texte en clair et le sel. Le facteur de travail modifie le temps nécessaire pour calculer le hachage et est conçu pour se prémunir contre de futures améliorations matérielles.

Ainsi, pour un algorithme de dérivation de clé adaptative H, nous calculons H(m,s,w) = h, où m est le message (mot de passe), s est le sel, et w est le facteur de travail. Le h résultant contient généralement s et w, de sorte qu'une fonction de vérification peut plus tard calculer le même hachage en utilisant les mêmes paramètres. Le facteur de travail contrôle généralement le nombre d'itérations effectuées d'une primitive cryptographique interne. L'objectif est de faire en sorte que le calcul prenne suffisamment de temps pour rendre la fissuration irréalisable, mais pas pour dépasser les ressources dont nous disposons.

Afin de fournir plus de sécurité contre le craquage matériel dédié, scrypt garantit que le calcul du hachage est à la fois dur et CPU, c'est-à-dire qu'il nécessite des ressources CPU et mémoire importantes pour produire la valeur de hachage. Ceci est important, car FPGA ont généralement accès à très peu de mémoire immédiate.

Maintenant, la question évidente se pose: si je configure mon site pour utiliser bcrypt, cela ne signifie-t-il pas que mon serveur doit toujours calculer des hachages gourmands en CPU? Eh bien, si vous les exécutez sur votre serveur, alors oui, c'est quelque chose à prendre en considération. Une meilleure solution consiste à demander au client de calculer le hachage, puis de l'envoyer au serveur via SSL. Le serveur peut ensuite le comparer à la valeur de la base de données. Cela garantit que le hachage de mot de passe ne peut pas être facilement craqué s'il est volé (par exemple via un compromis de base de données), et que votre serveur n'est pas submergé par la surcharge de calcul du hachage de mot de passe. Pour les sites Web, vous pouvez utiliser jsBcrypt .  Mise à jour: Cette méthode a été signalée comme défectueuse par un commentateur ci-dessous. Ne l'utilisez pas.

J'espère que cela vous donne un bon aperçu de la situation et pourquoi HMAC n'est pas adapté à ce type d'utilisation.

37
Polynomial

HMAC est un code d'authentification de message ; il utilise une clé. Bcrypt non. Ainsi, le choix n'est pas neutre; vous ne pouvez pas penser que toutes choses sont égales par ailleurs, car elles ne le sont pas.

Bien que nominalement pour les contrôles d'intégrité, il se trouve que HMAC (lorsqu'il est utilisé avec une fonction de hachage raisonnablement sécurisée, par exemple SHA-256 ou même SHA-1) se comporte d'une manière ou d'une autre comme "une fonction de hachage avec une clé". Ce n'est pas une propriété générique des algorithmes MAC , mais cela fonctionne avec HMAC (c'est pourquoi il peut être utilisé comme base pour un générateur aléatoire appelé Hmac_DRBG ). Cela fait de HMAC un choix potentiel pour le hachage de mot de passe.

Si vous "hachez" votre mot de passe avec HMAC, et que l'attaquant pourrait récupérer votre fichier/base de données de mot de passe haché mais pas la clé HMAC , alors l'attaquant ne pas pouvoir déchiffrer les mots de passe. Dans ce scénario, HMAC est "meilleur" que bcrypt/scrypt. Cependant, il s'agit d'un cas Edge. Nous hachons les mots de passe parce que nous nous inquiétons des scénarios marginaux où l'attaquant pourrait violer suffisamment la sécurité pour obtenir un accès en lecture seule à une partie des fichiers du serveur, mais pas un accès en lecture-écriture . La méthode de hachage avec HMAC est destinée à un scénario à la marge où l'attaquant en lecture seule pourrait obtenir le mot de passe haché mais pas la clé, qui est néanmoins stockée sur le même serveur.

Si l'attaquant pouvait obtenir la clé, alors HMAC devient seulement une simple fonction de hachage pour lui, et dans ce cas, HMAC est bien pire que bcrypt, car il est non salé et trop vite . C'est comme si les mots de passe étaient hachés avec une paire d'invocations SHA-1. Ce scénario n'est pas moins probable que le précédent, et donc nous devons considérer l'utilisation de HMAC seul comme trop risquée .


Pour le meilleur des deux mondes , appliquez HMAC sur le mot de passe utilisateur, puis traitez la sortie HMAC via - bcrypt ; vous stockerez la sortie de bcrypt. Puisque les implémentations de bcrypt attendent le mot de passe comme une chaîne de caractères , vous devrez encoder la sortie HMAC (hexadécimal, Base64 ...).

C'est plus complexe que bcrypt seul, à cause de l'utilisation de deux fonctions au lieu d'une, et à cause de la clé (ce qui pose tout le problème épineux de la gestion des clés: génération, stockage, sauvegarde ...). Étant donné que la complexité est mauvaise, je recommanderais contre elle; utilisez simplement bcrypt seul et n'ajoutez pas de HMAC. Cependant, c'est votre appel; si vous voulez vraiment le HMAC, utilisez-le en plus de bcrypt, pas au lieu de bcrypt.

(Remarque: c'est bcrypt sur la sortie HMAC, et non l'inverse, ce qui ne fonctionnerait pas en raison du sel qui est inclus dans la sortie bcrypt.)

9
Thomas Pornin

HMAC est conçu pour être très rapide et est dans ce contexte un bon moyen d'ajouter du sel au mot de passe au lieu de simplement l'ajouter. Bcrypt est beaucoup plus lent en raison d'une initialisation lente, tandis que scrypt est encore plus lent que Bcrypt car il est intentionnellement conçu de cette manière. Scrypt est conçu pour rendre le forçage brutal très coûteux en calcul. Il consomme beaucoup de CPU, de mémoire et est également lent à utiliser sur les GPU.

En savoir plus sur scrypt

2
Matrix