Stockage des valeurs de hachage SHA1 dans MySQL

160

J'ai une question simple qui s'est produite lorsque je voulais stocker le résultat d'un hachage SHA1 dans une base de données MySQL:

Combien de temps doit durer le champ VARCHAR dans lequel je stocke le résultat du hachage?

Niklasfi
la source
9
Si vous venez de googler sha1 cliquez sur je me sens chanceux et vous devriez être sur wikipedia où vous pouvez le trouver toujours 160 bits.
Tim Matthews

Réponses:

315

J'utiliserais VARCHARpour des données de longueur variable, mais pas avec des données de longueur fixe. Comme une valeur SHA-1 est toujours longue de 160 bits, le VARCHARgaspillerait simplement un octet supplémentaire pour la longueur du champ de longueur fixe .

Et je ne conserverais pas non plus la valeur SHA1renvoyée. Parce qu'il utilise seulement 4 bits par caractère et aurait donc besoin de 160/4 = 40 caractères. Mais si vous utilisez 8 bits par caractère, vous n'aurez besoin que d'un champ de 160/8 = 20 caractères.

Je vous recommande donc d'utiliser BINARY(20)et la UNHEXfonction pour convertir la SHA1valeur en binaire.

J'ai comparé les besoins de stockage pour BINARY(20)et CHAR(40).

CREATE TABLE `binary` (
    `id` int unsigned auto_increment primary key,
    `password` binary(20) not null
);
CREATE TABLE `char` (
    `id` int unsigned auto_increment primary key,
    `password` char(40) not null
);

Avec un million d'enregistrements binary(20)prend 44,56 millions, tandis que char(40)prend 64,57 millions. InnoDBmoteur.

Gombo
la source
2
Dans PostgreSQL, cela se traduirait par l'utilisation d'un champ bytea, non?
mvexel le
La solution est excellente, mais il y a un autre point à utiliser char (40) avec sha1 hexadécimal - c'est beaucoup plus largement utilisé, et il y aura moins de problèmes de conversion dans un code d'application.
Arthur Kushman
2
Remarque pour les utilisateurs de phpmyadmin. Lors du stockage du hachage sous forme binaire, phpmyadmin l'affichera sous forme de chaîne hexadécimale, mais pma ne pourra pas l'utiliser dans l '"onglet de recherche" fourni. Ne fonctionnera que si vous ajoutez UNHEX()manuellement le fichier sql.
Timo Huovinen le
2
@Gumbo Vous pouvez stocker un nombre variable d'octets dans un bytea. Vous faites référence aux exigences de stockage du type bytea. Qui est "1 ou 4 octets plus la chaîne binaire réelle". Ce à quoi le "1 ou 4" fait référence peut être la longueur des données stockées, car vous ne pouvez pas utiliser un octet de zéro pour terminer la chaîne comme vous le faites avec varchar. Cela implique, mais ce n'est pas indiqué dans le manuel, que vous pouvez stocker jusqu'à 2 ^ (8 * 4) ou 4+ gigaoctets dans un bytea. postgresql.org/docs/9.0/static/datatype-binary.html Le stockage du hachage dans une base de données postgres serait probablement le plus petit sous forme de colonne bit ou bytea.
Viktor
2
dev.mysql.com/doc/refman/5.5/en/… fournit des informations sur les performances et le stockage lors du stockage des résultats des fonctions de
cryptage
45

Un hachage SHA1 fait 40 caractères!

schmilblick
la source
11

Référence tirée de ce blog:

Vous trouverez ci-dessous une liste d'algorithmes de hachage avec leur taille de bit requise:

  • MD5 = valeur de hachage de 128 bits.
  • SHA1 = valeur de hachage de 160 bits.
  • SHA224 = valeur de hachage de 224 bits.
  • SHA256 = valeur de hachage de 256 bits.
  • SHA384 = valeur de hachage de 384 bits.
  • SHA512 = valeur de hachage de 512 bits.

Création d'un exemple de table avec require CHAR (n):

CREATE TABLE tbl_PasswordDataType
(
    ID INTEGER
    ,MD5_128_bit CHAR(32)
    ,SHA_160_bit CHAR(40)
    ,SHA_224_bit CHAR(56)
    ,SHA_256_bit CHAR(64)
    ,SHA_384_bit CHAR(96)
    ,SHA_512_bit CHAR(128)
); 
INSERT INTO tbl_PasswordDataType
VALUES 
(
    1
    ,MD5('SamplePass_WithAddedSalt')
    ,SHA1('SamplePass_WithAddedSalt')
    ,SHA2('SamplePass_WithAddedSalt',224)
    ,SHA2('SamplePass_WithAddedSalt',256)
    ,SHA2('SamplePass_WithAddedSalt',384)
    ,SHA2('SamplePass_WithAddedSalt',512)
);
Anvesh
la source
10
S'il vous plaît , veuillez ne pas stocker de mots de passe comme celui-ci.
Berry M.
Hey berry, pouvez-vous expliquer votre POURQUOI? en détails
Anvesh
4
Le stockage de simples hachages de mots de passe facilite beaucoup «l'extraction» des mots de passe si votre base de données est compromise que si vous utilisez un hachage de mot de passe salé (avec un peu de chance). Suggestion de lecture: paragonie.com/blog/2016/02/how-safely-store-password-in-2016
matt
2
@BerryM. lire ceci un an plus tard, et je n'ai pas pensé pendant une seconde que quiconque parlait de mots de passe ou que si les gens utilisaient encore un simple hachage pour stocker les données d'authentification. Mais ils le font: D
Rohit Hazra
6

La taille de sortie de sha1 est de 160 bits. Ce qui est 160/8 == 20 caractères (si vous utilisez des caractères 8 bits) ou 160/16 = 10 (si vous utilisez des caractères 16 bits).

inazaruk
la source
En supposant des caractères binaires 8 bits. 40 caractères si stocké en hexadécimal.
Tyzoid
3

La longueur est donc comprise entre 10 caractères 16 bits et 40 chiffres hexadécimaux.

Dans tous les cas, décidez du format que vous allez stocker et faites du champ une taille fixe basée sur ce format. De cette façon, vous n'aurez pas d'espace perdu.

Douglas Leeder
la source
2

Vous pouvez toujours utiliser VARCHAR dans les cas où vous ne stockez pas toujours un hachage pour l'utilisateur (c.-à-d. Authentification des comptes / URL de connexion oublié). Une fois qu'un utilisateur a authentifié / modifié ses informations de connexion, il ne devrait pas pouvoir utiliser le hachage et ne devrait avoir aucune raison de le faire. Vous pouvez créer une table séparée pour stocker le hachage temporaire -> les associations d'utilisateurs qui pourraient être supprimées mais je ne pense pas que la plupart des gens prennent la peine de le faire.

Keith Harty
la source
2

Si vous avez besoin d'un index sur la colonne sha1, je suggère CHAR (40) pour des raisons de performances. Dans mon cas, la colonne sha1 est un jeton de confirmation par e-mail, donc sur la page de destination, la requête entre uniquement avec le jeton. Dans ce cas, CHAR (40) avec INDEX, à mon avis, est le meilleur choix :)

Si vous souhaitez adopter cette méthode, n'oubliez pas de laisser $ raw_output = false.

Francesco Casula
la source
1
Pourquoi n'indexeriez-vous pas BINARY (20)? Ne serait-ce pas aussi rapide et deux fois moins grand?
nickdnk
Eh bien, il y a ~ 5 ans, mais je pense que je faisais référence au fait que vous devez encore unhex ce qui ajoute une certaine charge (+ rend l'application plus difficile à maintenir et moins portable?). Cela dépend aussi de votre matériel, si vous avez moins de stockage et qu'il est lent, mieux vaut probablement s'en tenir au binaire (20) sinon je dirais char (40). Difficile à dire sans exécuter des tests avec le langage et le matériel que vous utiliseriez et voir ce qui vous convient le mieux.
Francesco Casula
1
Je suppose que si vous faites autre chose que sélectionner d'où unhex (hash) = hash pour récupérer une seule ligne, alors peut-être que vous avez raison. Mais garder l'index en mémoire tampon prendra deux fois plus de mémoire de cette façon.
nickdnk