370 votes

Quel type de colonne/longueur dois-je utiliser pour stocker un mot de passe haché par Bcrypt dans une base de données ?

Je veux stocker un mot de passe haché (en utilisant BCrypt) dans une base de données. Quel serait un bon type pour cela, et quelle serait la longueur correcte ? Les mots de passe hachés avec BCrypt ont-ils toujours la même longueur ?

EDITAR

Exemple de hachage :

$2a$10$KssILxWNR6k62B7yiX0GAe2Q7wwHlrzhF3LqtVvpyvHZf0MwvNfVu

Après avoir haché quelques mots de passe, il semble que BCrypt génère toujours des hachages de 60 caractères.

EDIT 2

Désolé de ne pas avoir mentionné l'implémentation. J'utilise jBCrypt .

0 votes

Voir également la page de l'Openwall Cadre de hachage de mots de passe en PHP (PHPass). Il est portable et renforcé contre un certain nombre d'attaques courantes sur les mots de passe des utilisateurs. L'auteur du framework (SolarDesigner) est le même qui a écrit John The Ripper et siège en tant que juge dans le Concours de hachage de mots de passe . Donc il connaît une chose ou deux sur les attaques sur les mots de passe.

1 votes

Si quelqu'un tombe sur cette recherche d'une solution pour scrypt : La réponse de Gumbo s'applique également à scrypt. J'ai personnellement appliqué BINARY(64) dans MySQL et cela m'a permis de tester l'égalité des octets sous Python par la suite.

417voto

Gumbo Points 279147

Le format de cryptage modulaire pour bcrypt se compose de

  • $2$ , $2a$ o $2y$ identifier les algorithme de hachage et format
  • une valeur à deux chiffres indiquant le paramètre de coût, suivie de $
  • une valeur codée en base-64 de 53 caractères (l'alphabet utilisé est le suivant . , / , 0 - 9 , A - Z , a - z qui est différente de la codage standard en base 64 alphabet) composé de :
    • 22 caractères de sel (en fait seulement 128 bits sur les 132 bits décodés)
    • 31 caractères de sortie cryptée (en fait seulement 184 bits sur les 186 bits décodés)

La longueur totale est donc de 59 ou 60 octets respectivement.

Comme vous utilisez le format 2a, vous aurez besoin de 60 octets. Et donc pour MySQL je vous recommande d'utiliser le format CHAR(60) BINARY ou BINARY(60) (voir El _bin y binaire Collations pour des informations sur la différence).

CHAR n'est pas binairement sûr et l'égalité ne dépend pas uniquement de la valeur de l'octet mais de la collation réelle ; dans le pire des cas, l'option A est considéré comme égal à a . Voir El _bin y binary Collations pour plus d'informations.

32 votes

Attention, le stockage en tant que binaire(60) peut entraîner un comportement inattendu pour l'égalité des chaînes de caractères (entre autres). En .NET, ce problème peut être résolu en utilisant String.Equals(fromDataBaseBinary60string, typicalishString, StringComparison.InvariantCulture).

11 votes

Si vous définissez la colonne comme CHAR(60) CHARACTER SET latin1 COLLATE latin1_bin, vous bénéficiez maintenant des avantages d'une comparaison précise des chaînes de caractères sans avoir besoin d'une colonne binaire.

0 votes

60voto

Andre D Points 1321

Un hachage Bcrypt peut être stocké dans un fichier BINARY(40) colonne.

BINARY(60) Comme les autres réponses le suggèrent, c'est le choix le plus simple et le plus naturel, mais si vous voulez maximiser l'efficacité du stockage, vous pouvez économiser 20 octets en déconstruisant sans perte le hachage. Je l'ai documenté plus en détail sur GitHub : https://github.com/ademarre/binary-mcf

Les hachages de Bcrypt suivent une structure appelée "modular crypt format" (MCF). Binaire MCF (BMCF) décode ces représentations de hachage textuelles en une structure binaire plus compacte. Dans le cas de Bcrypt, le hachage binaire résultant est de 40 octets.

Gumbo a fait un bon travail d'explication des quatre composants d'un hachage MCF de Bcrypt :

$<id>$<cost>$<salt><digest>

Le décodage en BMCF se fait comme suit :

  1. $<id>$ peut être représenté sur 3 bits.
  2. <cost>$ 04-31, peut être représenté sur 5 bits. Rassemblez-les pour obtenir un octet.
  3. Le sel à 22 caractères est une représentation (non standard) en base 64 de 128 bits. Le décodage en base-64 donne 16 octets.
  4. Le condensé de hachage de 31 caractères peut être décodé en base 64 en 23 octets.
  5. Mettez tout ça ensemble pour 40 octets : 1 + 16 + 23

Vous pouvez en lire plus au lien ci-dessus, ou examiner mon implémentation PHP également sur GitHub.

74 votes

Coût d'un champ plus long : 20 octets multipliés par un million d'enregistrements et plus : 20 Mo, dès que vous atteignez un million d'enregistrements +. Coût de la mise en œuvre incorrecte d'une longueur de champ réduite, dans un domaine très complexe de la sécurité et de l'ingénierie : $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$. Faites le calcul.

9 votes

@Kzqai, comme je l'ai dit, la plus grande colonne de 60 octets est le choix le plus naturel, mais l'agressivité avec laquelle il faut rechercher l'efficacité du stockage dépend du projet. Par exemple, il est courant d'essayer de faire tenir la totalité de la base de données en mémoire, et 20 Mo ici et 20 autres là peuvent s'additionner rapidement dans un environnement où la mémoire est limitée.

15 votes

Votre exemple alimente mon propos. --- Si vous voulez mettre votre base de données en mémoire, optimisez toutes les autres colonnes avant de toucher à la colonne de stockage bcrypt. --- Si vous avez optimisé toutes les autres colonnes à des degrés insensés, et qu'il ne reste que la colonne de hachage bcrypt, obtenez un autre giga de mémoire juste pour bcrypt. --- Si vous avez fait les deux choses ci-dessus... ...arrêtez, vous n'avez pas optimisé toutes les autres colonnes de fruits mûrs, et vous êtes sur le point d'endommager un système de sécurité cryptographique testé qui fonctionne, et de le remplacer par un système maison plus compliqué avec une chance d'échec de mise en œuvre.

27voto

Mike Points 5108

Si vous utilisez la fonction password_hash() avec le PASSWORD_DEFAULT pour générer le hachage bcrypt (ce qui, je suppose, représente un grand pourcentage des personnes lisant cette question), assurez-vous de garder à l'esprit qu'à l'avenir password_hash() pourrait utiliser un algorithme différent de celui utilisé par défaut, ce qui pourrait donc affecter la longueur du hachage (mais il ne sera pas nécessairement plus long).

De la page du manuel :

Notez que cette constante est conçue pour changer avec le temps, au fur et à mesure que de nouveaux et algorithmes plus puissants sont ajoutés à PHP. Pour cette raison, la longueur du résultat de l'utilisation de cet identifiant peut changer dans le temps. Par conséquent, il est recommandé de stocker le résultat dans une colonne de la base de données qui peut s'étendre au-delà de 60 caractères (255 caractères seraient un bon choix).

En utilisant bcrypt, même si vous avez 1 milliard d'utilisateurs (c'est-à-dire que vous êtes actuellement en concurrence avec facebook) pour stocker des hachages de mots de passe de 255 octets, cela ne représenterait que ~255 Go de données, soit environ la taille d'un disque dur SSD de petite taille. Il est extrêmement peu probable que le stockage du hachage du mot de passe soit le goulot d'étranglement de votre application. Cependant, dans le cas où l'espace de stockage es un problème pour une raison quelconque, vous pouvez utiliser PASSWORD_BCRYPT pour forcer password_hash() pour utiliser bcrypt, même si ce n'est pas la valeur par défaut. Assurez-vous de rester informé des vulnérabilités trouvées dans bcrypt et consultez les notes de mise à jour à chaque fois qu'une nouvelle version de PHP est publiée. Si l'algorithme par défaut est modifié, il serait bon de revoir les notes de mise à jour. pourquoi et prendre une décision éclairée quant à l'utilisation ou non du nouvel algorithme.

24voto

James C Points 9120

Je ne pense pas qu'il y ait de trucs astucieux à faire pour stocker cela, comme on peut le faire par exemple avec un hachage MD5.

Je pense que votre meilleure chance est de le stocker en tant que CHAR(60) car il est toujours de 60 caractères

0 votes

Bien que la documentation PHP indique que les colonnes devraient pouvoir contenir plus de données, pour les prochaines versions...

19 votes

Il n'y a pas de raison de faire de la dorure. Si le logiciel que vous utilisez nécessite soixante octets, alors allouez soixante octets. Si une future version de votre logiciel modifie ce point, vous pourrez vous en préoccuper lorsque cette version sera disponible. Vous ne devriez pas installer automatiquement des mises à jour modifiant les fonctionnalités.

2 votes

Je pense que c'est la meilleure réponse. Il n'est pas nécessaire d'entrer dans la complexité de l'algorithme comme le font les autres réponses. Tous les détails concernant le binaire, la collation, etc. devraient être gérés par la bibliothèque utilisée, quelle qu'elle soit. 60 caractères. C'est la réponse.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X