Welcher Datentyp soll für das Hash-Passwortfeld verwendet werden und welche Länge?

268

Ich bin nicht sicher, wie das Passwort-Hashing funktioniert (wird später implementiert), muss aber jetzt ein Datenbankschema erstellen.

Ich denke darüber nach, Passwörter auf 4 bis 20 Zeichen zu beschränken, aber wie ich nach dem Verschlüsseln verstehe, wird die Hash-Zeichenfolge unterschiedlich lang sein.

Wie werden diese Passwörter in der Datenbank gespeichert?

Z-Boss
quelle
Siehe auch Openwalls PHP Passass Hashing Framework (PHPass). Es ist tragbar und gegen eine Reihe gängiger Angriffe auf Benutzerkennwörter geschützt. Der Typ, der das Framework geschrieben hat (SolarDesigner), ist derselbe, der John The Ripper geschrieben hat und als Richter am Passwort-Hashing-Wettbewerb teilnimmt . Er weiß also ein oder zwei Dinge über Angriffe auf Passwörter.
Jww
2
Bitte legen Sie keine Obergrenze für Ihre Passwörter fest. Wenn Sie sie haschen, gibt es keinen Speichergrund für eine Obergrenze. Wenn Sie sich Sorgen über DoS-Angriffe mit dem Kennwort-Hash machen, ist 1000 oder 1024 eine angemessene Obergrenze.
Iiridayn
Warum die Passwortlänge begrenzen? Lassen Sie mindestens einen Benutzer ein Passwort mit 100 Zeichen erstellen :)
Andrew
4 Zeichen sind eine ziemlich gefährliche Untergrenze für Passwörter, da diese trivial zu knacken sind. Verwenden Sie mindestens 8, aber 14 oder 16 ist viel besser.
Quikchange
Dies ist eine sehr alte Frage mit einer veralteten Antwort. Aktuelle Informationen finden Sie in der Gilles- Antwort .
Kelalaka

Antworten:

448

Update: Die einfache Verwendung einer Hash-Funktion ist nicht stark genug, um Passwörter zu speichern. Sie sollten die Antwort von Gilles in diesem Thread lesen, um eine detailliertere Erklärung zu erhalten.

Verwenden Sie für Kennwörter einen schlüsselverstärkenden Hash-Algorithmus wie Bcrypt oder Argon2i. Verwenden Sie in PHP beispielsweise die Funktion password_hash () , die standardmäßig Bcrypt verwendet.

$hash = password_hash("rasmuslerdorf", PASSWORD_DEFAULT);

Das Ergebnis ist eine 60-stellige Zeichenfolge, die der folgenden ähnelt (die Ziffern variieren jedoch, da sie ein eindeutiges Salz erzeugen).

$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

Verwenden Sie den SQL-Datentyp CHAR(60), um diese Codierung eines Bcrypt-Hash zu speichern. Beachten Sie, dass diese Funktion nicht als hexadezimale Zeichenfolge codiert, sodass wir die Speicherung in Binärdateien nicht so einfach aufheben können.

Andere Hash-Funktionen werden noch verwendet, jedoch nicht zum Speichern von Passwörtern. Daher behalte ich die ursprüngliche Antwort aus dem Jahr 2008 bei.


Dies hängt vom verwendeten Hashing-Algorithmus ab. Das Hashing erzeugt unabhängig von der Eingabe immer ein Ergebnis gleicher Länge. Es ist typisch, das binäre Hash-Ergebnis im Text als eine Reihe von hexadezimalen Ziffern darzustellen. Oder Sie können die UNHEX()Funktion verwenden, um eine Folge von Hex-Ziffern um die Hälfte zu reduzieren.

  • MD5 generiert einen 128-Bit-Hashwert. Sie können CHAR (32) oder BINARY (16) verwenden.
  • SHA-1 generiert einen 160-Bit-Hashwert. Sie können CHAR (40) oder BINARY (20) verwenden.
  • SHA-224 generiert einen 224-Bit-Hashwert. Sie können CHAR (56) oder BINARY (28) verwenden.
  • SHA-256 generiert einen 256-Bit-Hashwert. Sie können CHAR (64) oder BINARY (32) verwenden.
  • SHA-384 generiert einen 384-Bit-Hashwert. Sie können CHAR (96) oder BINARY (48) verwenden.
  • SHA-512 generiert einen 512-Bit-Hashwert. Sie können CHAR (128) oder BINARY (64) verwenden.
  • BCrypt generiert einen implementierungsabhängigen 448-Bit-Hashwert. Möglicherweise benötigen Sie CHAR (56), CHAR (60), CHAR (76), BINARY (56) oder BINARY (60).

Ab 2015 empfiehlt NIST die Verwendung von SHA-256 oder höher für alle Anwendungen von Hash-Funktionen, die Interoperabilität erfordern. NIST empfiehlt jedoch nicht, diese einfachen Hash-Funktionen zum sicheren Speichern von Kennwörtern zu verwenden.

Geringere Hashing-Algorithmen haben ihre Verwendung (wie anwendungsintern, nicht zum Austausch), aber sie sind bekanntermaßen knackbar .

Bill Karwin
quelle
47
@ Hippo: Bitte verwenden Sie nicht den Benutzernamen als Salz. Generieren Sie ein zufälliges Salz pro Benutzer.
Bill Karwin
11
Ja, es gibt keinen Grund, es nicht in derselben Zeile zu speichern. Selbst wenn ein Angreifer Zugriff auf Ihre Datenbank erhält, muss er seine Regenbogentabelle basierend auf diesem Salz erstellen. Und das ist genauso viel Arbeit wie das Erraten des Passworts.
Bill Karwin
5
@SgtPooki: Sie benötigen eine weitere Spalte, um das Salz im Klartext zu speichern. Anschließend können Sie das Kennwort des Benutzers beim Eingeben mit demselben Salt hashen und das Ergebnis mit dem in der Tabelle gespeicherten Hash-Digest vergleichen.
Bill Karwin
12
Wenn Sie das Salt in derselben Tabelle (oder an einem anderen Ort mit denselben Zugriffsberechtigungen) speichern, gibt es keinen Grund, den Benutzernamen nicht als Salt zu verwenden, da er pro Benutzer eindeutig ist. Jedes bekannte Salz macht den Hash jedoch kryptografisch schwächer als wenn kein Salz bekannt wäre. Ein Salz schafft nur dann einen Mehrwert, wenn es auch unbekannt ist.
Fidschiaaron
9
Ich verstehe den Umgang mit bekanntem und unbekanntem Salz nicht. Wenn Sie eine Site implementieren, muss das Salt der Anmeldeseite / dem Skript / dem Dienst bekannt sein, die bzw. der das Kennwort testet. Gehen Sie also - Sie "unbekannte" Salt-Befürworter - davon aus, dass der Code für den Anmeldevorgang dem Angreifer unbekannt ist? Andernfalls - kennt der Angreifer das Salz nicht immer , ob es zufällig, eindeutig, zusammen mit dem Hash-Passwort oder getrennt gespeichert ist?
Mattstuehler
13

Sie können tatsächlich CHAR(Länge des Hash) verwenden , um Ihren Datentyp für MySQL zu definieren, da jeder Hashing-Algorithmus immer die gleiche Anzahl von Zeichen ergibt. Gibt beispielsweise SHA1immer eine 40-stellige Hexadezimalzahl zurück.

Noah Goodrich
quelle
1
SHA-1 eignet sich nicht zum Hashing von Passwörtern.
Gilles 'SO - hör auf böse zu sein'
10

Verwenden Sie immer einen Passwort-Hashing-Algorithmus: Argon2 , scrypt , bcrypt oder PBKDF2 .

Argon2 hat den Passwort-Hashing-Wettbewerb 2015 gewonnen. Scrypt , bcrypt und PBKDF2 sind ältere Algorithmen, die derzeit als weniger bevorzugt gelten, aber dennoch grundsätzlich solide sind. Wenn Ihre Plattform Argon2 noch nicht unterstützt, ist es in Ordnung, vorerst einen anderen Algorithmus zu verwenden.

Speichern Sie niemals ein Passwort direkt in einer Datenbank. Verschlüsseln Sie es auch nicht: Andernfalls erhält der Angreifer bei einem Verstoß gegen Ihre Website den Entschlüsselungsschlüssel und kann so alle Kennwörter abrufen. Passwörter MÜSSEN gehasht werden .

Ein Kennwort-Hash hat andere Eigenschaften als ein Hash-Tabellen-Hash oder ein kryptografischer Hash. Verwenden Sie niemals einen normalen kryptografischen Hash wie MD5, SHA-256 oder SHA-512 für ein Passwort. Ein Passwort-Hashing-Algorithmus verwendet ein Salt , das eindeutig ist (nicht für andere Benutzer oder in der Datenbank anderer verwendet). Das Salt ist notwendig, damit Angreifer die Hashes gängiger Passwörter nicht einfach vorberechnen können: Mit einem Salt müssen sie die Berechnung für jedes Konto neu starten. Ein Passwort-Hashing-Algorithmus ist an sich langsam - so langsam, wie Sie es sich leisten können. Langsamkeit schmerzt den Angreifer viel mehr als Sie, weil der Angreifer viele verschiedene Passwörter ausprobieren muss. Weitere Informationen finden Sie unter So sichern Sie Kennwörter sicher .

Ein Passwort-Hash codiert vier Informationen:

  • Ein Indikator dafür, welcher Algorithmus verwendet wird. Dies ist für die Agilität erforderlich : Kryptografische Empfehlungen ändern sich im Laufe der Zeit. Sie müssen in der Lage sein, auf einen neuen Algorithmus umzusteigen.
  • Ein Schwierigkeits- oder Härteindikator. Je höher dieser Wert ist, desto mehr Berechnungen sind erforderlich, um den Hash zu berechnen. Dies sollte eine Konstante oder ein globaler Konfigurationswert in der Kennwortänderungsfunktion sein, sollte jedoch mit der Zeit zunehmen, wenn Computer schneller werden. Daher müssen Sie sich den Wert für jedes Konto merken. Einige Algorithmen haben einen einzigen numerischen Wert, andere haben dort mehr Parameter (zum Beispiel, um die CPU-Auslastung und die RAM-Auslastung getrennt abzustimmen).
  • Das Salz. Da das Salz global eindeutig sein muss, muss es für jedes Konto gespeichert werden. Das Salz sollte bei jeder Passwortänderung zufällig generiert werden.
  • Der eigentliche Hash, dh die Ausgabe der mathematischen Berechnung im Hashing-Algorithmus.

Viele Bibliotheken enthalten Paarfunktionen, die diese Informationen bequem als einzelne Zeichenfolge verpacken: eine, die den Algorithmusindikator, den Härteindikator und das Kennwort verwendet, ein zufälliges Salt generiert und die vollständige Hashzeichenfolge zurückgibt; und eine, die ein Passwort und die vollständige Hash-Zeichenfolge als Eingabe verwendet und einen Booleschen Wert zurückgibt, der angibt, ob das Passwort korrekt war. Es gibt keinen universellen Standard, aber eine übliche Kodierung

$ algorithm $ parameters $ salt $ output

wobei algorithmeine Zahl oder eine kurze alphanumerische Zeichenfolge codiert , die Wahl des Algorithmus parametersist eine druckbare Zeichenfolge und saltund outputist in Base64 codiert ohne zu Beenden =.

16 Bytes reichen für das Salt und die Ausgabe. (Siehe z. B. Empfehlungen für Argon2 .) In Base64 codiert, sind das jeweils 21 Zeichen. Die anderen beiden Teile hängen vom Algorithmus und den Parametern ab, aber 20 bis 40 Zeichen sind typisch. Das sind insgesamt ungefähr 82 ASCII-Zeichen ( CHAR(82)und kein Unicode erforderlich), zu denen Sie einen Sicherheitsspielraum hinzufügen sollten, wenn Sie der Meinung sind, dass es später schwierig sein wird, das Feld zu vergrößern.

Wenn Sie den Hash in einem Binärformat codieren, können Sie ihn für den Algorithmus auf 1 Byte, für die Härte auf 1 bis 4 Byte (wenn Sie einige der Parameter hart codieren) und für das Salt und die Ausgabe jeweils auf 16 Byte reduzieren für insgesamt 37 Bytes. Sagen Sie 40 Bytes ( BINARY(40)), um mindestens ein paar freie Bytes zu haben. Beachten Sie, dass dies 8-Bit-Bytes sind, keine druckbaren Zeichen. Insbesondere kann das Feld Null-Bytes enthalten.

Beachten Sie, dass die Länge des Hashs völlig unabhängig von der Länge des Passworts ist.

Gilles 'SO - hör auf böse zu sein'
quelle
9

Vielleicht lohnt sich dieser Wikipedia-Artikel zum Thema Salzen . Die Idee ist, ein festgelegtes Datenbit hinzuzufügen, um Ihren Hash-Wert zufällig zu bestimmen. Dies schützt Ihre Passwörter vor Wörterbuchangriffen, wenn jemand unbefugten Zugriff auf die Passwort-Hashes erhält.

Dana die Gesunde
quelle
2
Das ist zwar sehr lohnenswert (+1), beantwortet aber die Frage nicht! (-1)
Bill Karwin
3
Ja, aber definitiv relevant in diesem Zusammenhang (+1)
Treb
7

Als Zeichenfolge fester Länge (VARCHAR (n) oder wie auch immer MySQL es nennt). Ein Hash hat immer eine feste Länge von beispielsweise 12 Zeichen (abhängig vom verwendeten Hash-Algorithmus). Ein 20-Zeichen-Passwort würde also auf einen 12-Zeichen-Hash reduziert, und ein 4-Zeichen-Passwort würde auch einen 12-Zeichen-Hash ergeben.

Treb
quelle
3
'oder wie auch immer MySQL es nennt' - MYSQL nennt es CHAR. Dieser Typ gilt für Werte mit fester Länge. Ich denke, CHAR ist ein besserer Typ als VARCHAR.
t298712383
4

Aus TEXTGründen der Vorwärtskompatibilität sollten Sie (unbegrenzte Anzahl von Zeichen speichern) verwenden. Hashing-Algorithmen müssen (müssen) mit der Zeit stärker werden, und daher muss dieses Datenbankfeld mit der Zeit mehr Zeichen unterstützen. Abhängig von Ihrer Migrationsstrategie müssen Sie möglicherweise neue und alte Hashes im selben Feld speichern. Daher wird nicht empfohlen, die Länge auf einen Hash-Typ festzulegen.

Bart
quelle
3

Es hängt wirklich vom verwendeten Hashing-Algorithmus ab. Die Länge des Passworts hat wenig mit der Länge des Hash zu tun, wenn ich mich richtig erinnere. Suchen Sie nach den Spezifikationen des von Ihnen verwendeten Hashing-Algorithmus, führen Sie einige Tests durch und kürzen Sie direkt darüber.

willasaywhat
quelle
3

Hashes sind eine Folge von Bits (128 Bit, 160 Bit, 256 Bit usw., abhängig vom Algorithmus). Ihre Spalte sollte binär und nicht text- / zeichenartig sein, wenn MySQL dies zulässt (SQL Server-Datentyp ist binary(n)oder varbinary(n)). Sie sollten auch die Hashes salzen. Salze können Text oder Binär sein, und Sie benötigen eine entsprechende Spalte.

Yfeldblum
quelle
Die Gerechtigkeit ist hier völlig korrekt - MySQL speichert diese als numerische Werte und macht die Suche in dieser Spalte viel effizienter als eine Zeichenfolgenübereinstimmung. Salze sollten jedoch nicht in der Datenbank neben den gesalzenen Daten gespeichert werden - dies beseitigt die Sicherheit, die Salze bieten .
Tony Maro
6
Salze sind nicht geheim. Das einzige Geheimnis ist das Passwort. Stellen Sie einfach sicher, dass jedes neue Passwort ein neues Salz bekommt. Jedes Mal, wenn der Benutzer sein Passwort ändert, sollte das System ein neues Salt für dieses Passwort generieren. Salze sollten lang und zufällig sein, z. B. 16 Bytes, die aus einem kryptografisch sicheren PRNG generiert werden.
Yfeldblum
1
@TonyMaro Nicht sicher, ob eine Kennwortzeichenfolge auf SQL-Ebene übereinstimmt, ist eine gute Strategie. Mit anderen Worten, Sie sollten Ihre Datenbank nicht nach einem Kennwort durchsuchen, sondern den Benutzer anhand seines Benutzernamens abrufen und Kennwörter im Code anstatt in SQL vergleichen.
Bart
1

Ich habe immer getestet, um die maximale Zeichenfolgenlänge einer verschlüsselten Zeichenfolge zu ermitteln und diese als Zeichenlänge eines VARCHAR-Typs festzulegen. Abhängig davon, wie viele Datensätze Sie haben werden, kann dies die Datenbankgröße erheblich verbessern.

Stephen Walcher
quelle
0

für md5 ist vARCHAR (32) geeignet. Für diejenigen, die AES verwenden, ist es besser, Varbinary zu verwenden.

Hase Srinivasa
quelle
1
Weder MD5 noch AES eignen sich zum Hashing eines Passworts.
Gilles 'SO - hör auf böse zu sein'