Je voudrais autoriser les utilisateurs de mon application Web à avoir de longs mots de passe s'ils le souhaitent. Aujourd'hui, j'ai pris connaissance de la limitation de la longueur de mot de passe de bcrypt (72 caractères, le reste étant tronqué).
Serais-je sûr de faire ce qui suit? J'utilise PHP.
Mise en œuvre actuelle:
password_hash($password, PASSWORD_BCRYPT, $options);
Mise en œuvre en question:
password_hash(hash('sha256', $password), PASSWORD_BCRYPT, $option);
Quels sont les inconvénients de la mise en œuvre en question?
Je ne suis pas un expert en cryptographie, veuillez en informer.
L'implémentation en question limitera-t-elle la longueur du mot de passe qu'un utilisateur peut utiliser? Si oui, quelle sera la limite?
En général, ce sera bien. C'est même une méthode assez bien recommandée pour autoriser des mots de passe de longueur arbitraire dans bcrypt.
Mathématiquement, vous utilisez maintenant bcrypt sur une chaîne de 64 caractères, où il y a 2 ^ 256 valeurs possibles (SHA-256 donne une sortie de 256 bits, qui est généralement représentée comme une chaîne hexadécimale de 64 caractères). Même si quelqu'un a pré-calculé les mots de passe communs dans SHA-256, il devra les exécuter via bcrypt pour trouver quelle est l'entrée réelle pour un hachage donné.
Le principal inconvénient potentiel est les défauts de mise en œuvre: si vous stockez jamais les valeurs SHA-256, elles sont relativement rapides à casser, donc un attaquant n'aurait pas besoin de faire l'effort de casser les valeurs bcrypt.
Il serait toujours recommandé de conserver un nombre d'itérations suffisamment élevé pour l'étape bcrypt - cela ne devrait pas avoir d'effet particulièrement néfaste sur votre temps de traitement, mais rend les attaques par force brute beaucoup plus difficiles.
Voir Pré-hachage du mot de passe avant d'appliquer bcrypt pour éviter de restreindre la longueur du mot de passe pour le cas général.
Votre implémentation suggérée est sûre. Veillez cependant à documenter votre utilisation particulière de la fonction.
Veuillez noter que password_hash
tronquera le mot de passe au premier octet NULL, vous ne devez donc PAS utiliser l'option $raw_output=true
de la fonction hash
.
Ne le faites pas, vous limitez votre force de clé à bien moins que ce que bcrypt seul peut accepter.
Utilisez plutôt cette approche (pseudo-code PHP non valide):
if length($password) > 72 bytes
then
$hash = sha256($password)
$password = concat(substring($password, 320 bits), base255encode($hash))
end if
bcrypt($password)
De cette façon, les mots de passe compris entre 256 et 576 bits conservent leur entropie complète, et les mots de passe supérieurs à 576 bits utilisent non seulement les 256 bits du hachage, mais autant de l'entropie d'origine que possible à côté du hachage.
On peut se demander si le hachage doit être effectué sur l'ensemble du mot de passe, ou seulement la partie au-delà de 320 bits que le hachage remplace. Je doute sérieusement que cela fasse une différence lorsque vous avez choisi un hachage cryptographique avec de bonnes propriétés.
L'étape de base255encode évite qu'un octet NUL termine la clé plus tôt, comme l'a averti @ a-hersean.