Cette question est une fourchette d'une question précédente ici: Est-il sûr/sage de stocker un sel dans le même champ que le mot de passe haché?
Supposons que vous exécutez un portail Web et stockez les mots de passe dans des hachages SHA1. Comment procédez-vous à la mise à niveau vers les hachages BCRYPT?
En règle générale, vous attendez que les utilisateurs se connectent et ré-hachez leurs mots de passe (à partir du texte en clair qu'ils ont entré) dans BCRYPT. Mais il peut s'écouler un certain temps avant que tous les utilisateurs se connectent à votre plate-forme, et il y aura toujours des utilisateurs inactifs qui ne reviendront jamais.
Une proposition distincte (que j'ai entendu pour la première fois de Troy Hunt) était de BCRYPT les mots de passe SHA1 existants dans votre base de données. En fait, vous seriez BCRYPT(SHA1(plaintext_password))
. De cette façon, tous les utilisateurs du système sont mis à niveau vers BCRYPT en même temps, quelle que soit leur activité.
De cette façon, une violation de votre base de données n'expose pas les utilisateurs qui ne se sont pas encore connectés et qui restent sur SHA1.
La question est:
BCRYPT(SHA1(plaintext_password))
est équivalent en sécurité à BCRYPT(plaintext_password)
La question se concentre sur BCRYPT (SHA1) mais pourrait facilement s'appliquer à deux algorithmes de hachage, le plus puissant étant appliqué en dernier.
Tout d'abord, merci d'avoir pris le temps de déterminer comment procéder correctement et d'améliorer la sécurité de vos utilisateurs!
La migration du stockage des mots de passe tout en tenant compte des hachages hérités est relativement courante .
Pour votre scénario de migration, bcrypt(base64(sha1(password)))
serait n équilibre raisonnable . Cela évite le problème nul ( important - vous ne voulez certainement pas omettre l'étape base64! ), évite bcrypt's limite native de 72 caractères et est 100% compatible avec vos hachages existants.
Vous devez simplement hacher tous les SHA1 existants avec bcrypt(base64(sha1))
, puis hacher tous les nouveaux mots de passe avec la séquence complète. (Vous pouvez également utiliser SHA256 à la place, bien que cela augmenterait légèrement la complexité de votre code, pour vérifier si SHA1 ou SHA25 a été utilisé (ou simplement les essayer tous les deux et réussir si l'un ou l'autre réussit). À long terme, SHA256 serait plus résistant aux collisions , serait donc un meilleur choix).
Pour la résistance à la bruteforce, ce serait non seulement équivalent à bcrypt, mais serait théoriquement supérieur (bien qu'en pratique, 72 caractères soit si grand pour le stockage de mot de passe qu'ils ne sont effectivement les mêmes).
Conseils bonus:
Cela limitera l'espace de touches à environ 2160, car SHA-1 génère des résumés de 20 octets, mais il est par ailleurs correct. En fait, bcrypt a une limite d'entrée de 72 octets, il n'est donc pas rare que les gens hachent d'abord un mot de passe en utilisant un hachage rapide et cryptographiquement sécurisé. Étant donné que la limite est supérieure à la taille de résumé de SHA-1, vous souhaiterez peut-être utiliser un hachage avec un résumé plus grand. Notez que le problème nul nécessite que le résumé soit converti en un autre encodage, tel que base64.
Si vous avez déjà une base de données pleine de hachages SHA-1, il est tout à fait correct de les exécuter via bcrypt.