Speichern von SHA1-Hashwerten in MySQL

160

Ich habe eine einfache Frage, die aufgetreten ist, als ich das Ergebnis eines SHA1-Hash in einer MySQL-Datenbank speichern wollte:

Wie lang sollte das VARCHAR- Feld sein, in dem ich das Hash-Ergebnis speichere?

niklasfi
quelle
9
Wenn Sie nur gehakt haben, klicken Sie auf Ich fühle mich glücklich und Sie sollten auf Wikipedia sein, wo Sie finden können, dass es immer 160 Bit sind.
Tim Matthews

Antworten:

315

Ich würde VARCHARfür Daten mit variabler Länge verwenden, aber nicht mit Daten mit fester Länge. Da ein SHA-1-Wert immer 160 Bit lang ist, VARCHARwürde nur ein zusätzliches Byte für die Länge des Feldes mit fester Länge verschwendet .

Und ich würde auch nicht den Wert speichern, den das SHA1zurückgibt. Weil es nur 4 Bit pro Zeichen verwendet und somit 160/4 = 40 Zeichen benötigt. Wenn Sie jedoch 8 Bit pro Zeichen verwenden, benötigen Sie nur ein Feld mit einer Länge von 160/8 = 20 Zeichen.

Daher empfehle ich Ihnen, BINARY(20)die UNHEXFunktion zu verwenden, um den SHA1Wert in binär umzuwandeln .

Ich habe die Speicheranforderungen für BINARY(20)und verglichen 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
);

Mit Millionen von Datensätzen binary(20)dauert 44,56 Millionen , während char(40)64,57 Millionen dauert. InnoDBMotor.

Gumbo
quelle
2
In PostgreSQL würde dies bedeuten, dass ein Bytea-Feld verwendet wird, oder?
Mvexel
Die Lösung ist großartig, aber es gibt noch einen weiteren Punkt, char (40) mit hexa sha1 zu verwenden - dies wird viel häufiger verwendet und es gibt weniger Konvertierungsprobleme in einem Anwendungscode.
Arthur Kushman
2
Hinweis für phpmyadmin Benutzer. Wenn der Hash als Binärdatei gespeichert wird, zeigt phpmyadmin ihn als Hex-Zeichenfolge an, pma kann ihn jedoch nicht auf der bereitgestellten "Suchregisterkarte" verwenden. Funktioniert nur, wenn Sie das UNHEX()manuell zum SQL hinzufügen.
Timo Huovinen
2
@Gumbo Sie können eine variable Anzahl von Bytes in einem Bytea speichern. Sie beziehen sich auf die Speicheranforderungen des Bytea-Typs. Welches ist "1 oder 4 Bytes plus die tatsächliche Binärzeichenfolge". Was sich auf "1 oder 4" bezieht, kann die Länge der gespeicherten Daten sein, da Sie nicht wie bei varchar ein Null-Byte verwenden können, um die Zeichenfolge zu beenden. Das bedeutet, wird aber im Handbuch nicht angegeben, dass Sie bis zu 2 ^ (8 * 4) oder 4+ Gigabyte in einem Bytea speichern können. postgresql.org/docs/9.0/static/datatype-binary.html Das Speichern des Hashs in einer Postgres-Datenbank wäre wahrscheinlich als Bit- oder Bytea-Spalte am kleinsten .
Viktor
2
dev.mysql.com/doc/refman/5.5/en/… bietet Informationen zu Leistung und Speicher beim Speichern der Ergebnisse von
Kryptafunktionen
45

Ein SHA1-Hash ist 40 Zeichen lang!

schmilblick
quelle
11

Referenz aus diesem Blog:

Unten finden Sie eine Liste der Hashing-Algorithmen sowie die erforderliche Bitgröße:

  • MD5 = 128-Bit-Hashwert.
  • SHA1 = 160-Bit-Hashwert.
  • SHA224 = 224-Bit-Hashwert.
  • SHA256 = 256-Bit-Hashwert.
  • SHA384 = 384-Bit-Hashwert.
  • SHA512 = 512-Bit-Hashwert.

Erstellt eine Beispieltabelle mit erforderlichem 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
quelle
10
Bitte, bitte , bitte speichern Sie solche Passwörter nicht.
Berry M.
Hey Berry, kannst du dein WARUM erklären? im Detail
Anvesh
4
Das Speichern einfacher Kennwort-Hashes erleichtert das "Extrahieren" der Kennwörter erheblich, wenn Ihre Datenbank kompromittiert wird, als wenn Sie einen gesalzenen (hoffentlich gestreckten) Kennwort-Hash verwenden. Empfohlene Lektüre: paragonie.com/blog/2016/02/how-safely-store-password-in-2016
matt
2
@BerryM. Lesen Sie dies ein Jahr später und denken Sie eine Sekunde lang nicht, dass jemand über Passwörter spricht oder dass, wenn die Leute immer noch einfachen Hash zum Speichern von Authentifizierungsdaten verwenden. Aber sie tun: D
Rohit Hazra
6

Die Ausgabegröße von sha1 beträgt 160 Bit. Das sind 160/8 == 20 Zeichen (wenn Sie 8-Bit-Zeichen verwenden) oder 160/16 = 10 (wenn Sie 16-Bit-Zeichen verwenden).

inazaruk
quelle
Angenommen, 8-Bit-Binärzeichen. 40 Zeichen, wenn als Hex gespeichert.
Tyzoid
3

Die Länge liegt also zwischen 10 16-Bit-Zeichen und 40 Hexadezimalstellen.

Entscheiden Sie in jedem Fall, welches Format Sie speichern möchten, und legen Sie basierend auf diesem Format eine feste Größe für das Feld fest. Auf diese Weise haben Sie keinen Platz verschwendet.

Douglas Leeder
quelle
2

Möglicherweise möchten Sie VARCHAR weiterhin verwenden, wenn Sie nicht immer einen Hash für den Benutzer speichern (z. B. Authentifizierung von Konten / vergessene Anmelde-URL). Sobald ein Benutzer seine Anmeldeinformationen authentifiziert / geändert hat, sollte er den Hash nicht mehr verwenden können und sollte keinen Grund dazu haben. Sie könnten eine separate Tabelle erstellen, um temporäre Hash-> Benutzerzuordnungen zu speichern, die gelöscht werden könnten, aber ich glaube nicht, dass sich die meisten Leute die Mühe machen, dies zu tun.

Keith Harty
quelle
2

Wenn Sie einen Index für die Spalte sha1 benötigen, empfehle ich aus Leistungsgründen CHAR (40). In meinem Fall ist die Spalte sha1 ein E-Mail-Bestätigungstoken. Auf der Zielseite wird die Abfrage also nur mit dem Token eingegeben. In diesem Fall ist CHAR (40) mit INDEX meiner Meinung nach die beste Wahl :)

Wenn Sie diese Methode anwenden möchten, denken Sie daran, $ raw_output = false zu belassen.

Francesco Casula
quelle
1
Warum sollten Sie BINARY (20) nicht indizieren? Wäre das nicht genauso schnell und halb so groß?
Nickdnk
Nun, das vor ~ 5 Jahren, aber ich denke, ich bezog mich auf die Tatsache, dass Sie immer noch die Freigabe vornehmen müssen, was eine gewisse Last hinzufügt (+ macht die Wartung der Anwendung schwieriger und weniger portabel?). Es hängt auch von Ihrer Hardware ab, wenn Sie weniger Speicher haben und es langsam ist, ist es wahrscheinlich auch am besten, sich an die Binärdatei (20) zu halten, sonst würde ich char (40) sagen. Schwer zu sagen, ohne einige Tests mit der Sprache und Hardware durchzuführen, die Sie verwenden würden, und zu sehen, was am besten zu Ihnen passt.
Francesco Casula
1
Ich nehme an, wenn Sie etwas anderes tun als auswählen, wo unhex (Hash) = Hash ist, um eine einzelne Zeile abzurufen, dann haben Sie vielleicht Recht. Wenn Sie den Index jedoch gepuffert halten, wird auf diese Weise doppelt so viel Speicher benötigt.
Nickdnk