Das funktioniert normalerweise so:
Angenommen, Ihr Passwort lautet "Baseball". Ich könnte es einfach roh speichern, aber jeder, der meine Datenbank erhält, erhält das Passwort. Also mache ich stattdessen einen SHA1-Hash und erhalte Folgendes:
$ echo -n Baseball | sha1suma2c901c8c6dea98958c219f6f2d038c44dc5d362
Theoretisch ist es unmöglich, einen SHA1-Hash umzukehren. Wenn Sie jedoch eine Google-Suche nach genau dieser Zeichenfolge durchführen, haben Sie keine Probleme, das ursprüngliche Kennwort wiederherzustellen.
Wenn zwei Benutzer in der Datenbank dasselbe Kennwort haben, ist dies der Fall Sie werden den gleichen SHA1-Hash haben. Und wenn einer von ihnen einen Passworthinweis mit der Aufschrift hat, versuchen Sie es mit "Baseball"
- nun weiß ich, wie beide Benutzerpasswörter lauten.
Bevor wir es hashen, stellen wir eine eindeutige Zeichenfolge voran. Kein Geheimnis , nur etwas Einzigartiges. Wie wäre es mit WquZ012C
. Jetzt haben wir die Zeichenfolge WquZ012Cbaseball
gehasht. Das stimmt damit überein:
c5e635ec235a51e89f6ed7d4857afe58663d54f5
Wenn Sie diese Zeichenfolge googeln, wird nichts angezeigt (außer vielleicht this Seite), also sind wir jetzt bei etwas. Und wenn person2 auch "Baseball" als Passwort verwendet, verwenden wir ein anderes Salz und erhalten einen anderen Hash.
Um Ihr Passwort zu testen, müssen Sie natürlich wissen, was das Salz ist. Also müssen wir das irgendwo aufbewahren. Die meisten Implementierungen setzen es genau dort mit dem Hash fest, normalerweise mit einem Trennzeichen. Versuchen Sie dies, wenn Sie openssl
installiert haben:
[tylerl ~] $ openssl passwd -1Password: baseballVerifying - Passwort: baseball $ 1 $ oaagVya9 $ NMvf1IyubxEYvrZTRSLgk0
Dies gibt uns einen Hash unter Verwendung der Standardbibliothek crypt
. Unser Hash ist also $ 1 $ oaagVya9 $ NMvf1IyubxEYvrZTRSLgk0
: Es sind tatsächlich 3 Abschnitte, die durch $
getrennt sind. Ich werde das Trennzeichen durch ein Leerzeichen ersetzen, um es visuell klarer zu machen:
$ 1 $ oaagVya9 $ NMvf1IyubxEYvrZTRSLgk0 1 oaagVya9 NMvf1IyubxEYvrZTRSLgk0
1 bedeutet "Algorithmus Nummer 1", der etwas kompliziert ist, aber MD5 verwendet. Es gibt viele andere, die viel besser sind, aber dies ist unser Beispiel. oaagVya9 ist unser Salz. Genau dort drin mit unserem Hash. NMvf1IyubxEYvrZTRSLgk0 ist die tatsächliche MD5-Summe, base64-codiert. Wenn ich den Prozess ausführe wieder bekomme ich einen ganz anderen Hash mit einem anderen Salz. In diesem Beispiel gibt es ungefähr 10 14 sup> Möglichkeiten, dieses eine Kennwort zu speichern. Alle diese Angaben gelten für das Kennwort "Baseball":
$ 1 $ 9XsNo9.P $ kTPuyvrHqsJJuCci3zLwL. $ 1 $ nLEOCtx6 $ uSnz6PF8q3YuUhB3rLTC3 / $ 1 $ / jZJXTF3 $ cq. U $ KR0jkhpeb1sz.UIqvfYOR.
Wenn ich jedoch absichtlich das Salz spezifiziere, das ich überprüfen möchte, erhalte ich mein erwartetes Ergebnis zurück:
[ tylerl ~] $ openssl passwd -1 -salt oaagVya9Password: baseballVerifying - Passwort: baseball $ 1 $ oaagVya9 $ NMvf1IyubxEYvrZTRSLgk0
Und das ist der Test, den ich durchführe, um zu überprüfen, ob das Passwort korrekt ist. Suchen Sie den gespeicherten Hash für den Benutzer, suchen Sie das gespeicherte Salt, führen Sie denselben Hash mit gespeichertem Salt erneut aus und überprüfen Sie, ob das Ergebnis mit dem ursprünglichen Hash übereinstimmt.
Implementieren dieses selbst
Dieser Beitrag ist kein Implementierungsleitfaden. Salzen Sie Ihren MD5 nicht einfach und nennen Sie ihn gut. Das reicht im heutigen Risikoklima nicht aus. Sie möchten stattdessen einen iterativen -Prozess ausführen, der die Hash-Funktion tausende Male ausführt. Dies wurde an anderer Stelle viele Male erklärt, daher werde ich hier nicht auf das "Warum" eingehen.
Es gibt mehrere gut etablierte und vertrauenswürdige Optionen hierfür:
-
Krypta : Die oben verwendete Funktion ist eine ältere Variante des in alle integrierten Unix-Kennwort-Hashing-Mechanismus crypt
Unix / Linux-Betriebssysteme. Die ursprüngliche (DES-basierte) Version ist schrecklich unsicher; denke nicht einmal darüber nach. Das, was ich gezeigt habe (MD5-basiert), ist besser, sollte aber heute noch nicht verwendet werden. Spätere Variationen, einschließlich der SHA-256- und SHA-512-Variationen, sollten angemessen sein. Alle neueren Varianten implementieren mehrere Runden von Hashes.
-
bcrypt : Die Blowfish-Version der Krypta
oben genannter Funktionsaufruf. Profitiert von der Tatsache, dass Blowfish einen sehr teuren Schlüssel-Setup-Prozess hat und einen "Kosten" -Parameter verwendet, der die Schlüssel-Setup-Zeit entsprechend erhöht.
-
PBKDF2 : ("Kennwortbasierte Schlüsselableitungsfunktion Version 2") Erstellt, um starke kryptografische Schlüssel aus einfachen Kennwörtern zu erstellen. Dies ist die einzige hier aufgeführte Funktion, die tatsächlich über einen RFC verfügt. Führt eine konfigurierbare Anzahl von Runden aus, wobei jede Runde das Passwort sowie das Ergebnis der vorherigen Runde enthält. Die erste Runde verwendet ein Salz. Es ist erwähnenswert, dass der ursprünglich beabsichtigte Zweck darin besteht, starke Schlüssel zu erstellen, nicht Passwörter zu speichern , aber die Überschneidung von Zielen macht dies auch hier zu einer vertrauenswürdigen Lösung. Wenn Sie keine Bibliotheken zur Verfügung hatten und gezwungen waren, etwas von Grund auf neu zu implementieren, ist dies die einfachste und am besten dokumentierte Option. Die Verwendung einer gut überprüften Bibliothek ist natürlich immer am besten.
-
scrypt : Ein kürzlich eingeführtes System speziell schwierig auf dedizierter Hardware zu implementieren. Scrypt erfordert nicht nur mehrere Runden einer Hashing-Funktion, sondern verfügt auch über einen sehr großen Arbeitsspeicherstatus, um den RAM-Bedarf für Implementierungen zu erhöhen. Obwohl es sehr neu und größtenteils unbewiesen ist, sieht es mindestens so sicher aus wie die anderen und möglicherweise das sicherste von allen.