Das wichtige Merkmal eines Passwortsalzes ( wie Terry Chia richtig bemerkt) ist, dass es global eindeutig sein sollte: Keine zwei Passwort-Hashes (auch nicht auf verschiedenen Websites) sollten jemals dasselbe Salz haben.
Die Verwendung eindeutiger Salze schützt vor verschiedenen verwandten Angriffsmethoden, die möglicherweise von einem Angreifer angewendet werden, der die Benutzerdatenbank kompromittiert hat und die Kennwörter aus seinen Hashes wiederherstellen möchte:
-
Erstens wird verhindert, dass ein Angreifer leicht erkennen kann, ob mehrere Benutzer dasselbe Kennwort haben (was diese Benutzer zu einem offensichtlichen Ziel machen würde, da ein solches gemeinsames Kennwort wahrscheinlich leicht zu erraten und eine hohe Auszahlung zu erzielen wäre).
-
Umgekehrt wird auch verhindert, dass ein Angreifer, der mehrere Websites kompromittiert hat, leicht erkennen kann, welche Benutzer auf beiden Websites dasselbe Kennwort verwendet haben.
-
Darüber hinaus verhindert die Verwendung eines eindeutigen Salt für jeden Benutzer, dass ein Angreifer einen Vorteil erhält, wenn er mehrere Konten gleichzeitig angreift. Ohne Salze (oder mit nicht eindeutigen Salzen) könnte ein Angreifer ein erratenes Passwort hashen und es dann mit jedem Passwort-Hash in der Datenbank vergleichen, wodurch es wahrscheinlicher wird, dass er mindestens eine Übereinstimmung erhält. Bei eindeutigen Salzen ist dies nicht möglich, da der Angreifer das Salz (und damit einen einzelnen Zielbenutzer) auswählen muss, bevor er jedes Passwort erraten kann.
-
Schließlich werden auch eindeutige Salze verwendet Es ist unpraktisch, vorberechnete Hash-Nachschlagetabellen (wie die sogenannten "Regenbogentabellen") zu verwenden, um das Knacken von Passwörtern zu beschleunigen, da im Wesentlichen für jeden Benutzer eine separate Tabelle erforderlich wäre.
Grundsätzlich besteht das Hauptziel des Salting darin, sicherzustellen, dass das Knacken mehrerer kompromittierter Passwort-Hashes nicht einfacher ist, als jedes einzelne einzeln zu knacken - nicht mehr und nicht weniger. Durch die Verwendung global einzigartiger Salze wird dieses Ziel erreicht.
Eine einfache Möglichkeit, die globale Eindeutigkeit (mit hoher Wahrscheinlichkeit) sicherzustellen, besteht darin, eine ausreichend lange zufällige Zeichenfolge als Salz zu verwenden. Es gibt jedoch auch andere Möglichkeiten.
Sie können beispielsweise ein global eindeutiges Salt erhalten, indem Sie eine lokal eindeutige Benutzerkennung (z. B. eine E-Mail-Adresse oder eine Kontonummer) mit einer festen, global eindeutigen ID kombinieren Site-ID (z. B. der Domain-Name einer Website) und möglicherweise einige andere Elemente wie ein Zweckbezeichner (falls Sie mehr als ein eindeutiges Salt pro Benutzer benötigen) und ein Zeitstempel (sodass ein neues Passwort immer ein anderes Salt erhält) ). Die folgende Zeichenfolge wäre beispielsweise für ein weltweit eindeutiges Salt perfekt geeignet:
"Dies ist ein Kennwort Salt für Benutzer 5457 auf security.stackexchange.com, das am 1. September 2013 um 13: 35: 23.94730 UTC erstellt wurde "
und dies auch:
" password_salt: 5457: security.stackexchange.com: 20130901T133523.94730 "
Wenn Sie möchten, dass Ihre Salze kompakter sind, können Sie auch eine der oben genannten Zeichenfolgen über eine kryptografische Hash-Funktion wie SHA-256 und Verwenden Sie die Ausgabe als Salz. Wenn Ihr System einen integrierten GUID -Generator bereitstellt, können Sie diesen einfach verwenden (vorausgesetzt, er funktioniert natürlich wie er sollte).
All das Es gibt jedoch einen potenziellen Vorteil, wenn Kennwortsalze nicht nur eindeutig, sondern auch unvorhersehbar sind: Sie verhindern, dass der Angreifer einen Brute-Force-Angriff startet, bevor er Ihre Datenbank kompromittiert hat .
Wenn ich als Angreifer wüsste, dass das Salz Ihres Administratorkontos beispielsweise "12345678" ist, könnte ich meine Computer so einstellen, dass sie eine Nachschlagetabelle mit mehr oder weniger gebräuchlichen Passwörtern erstellen, die mit diesem Salz gehasht wurden noch bevor ich einen Weg gefunden hatte, Ihren tatsächlichen Passwort-Hash zu erhalten . Sobald ich einen Weg gefunden hatte, dies zu tun (vielleicht Wochen oder Monate später), konnte ich den Hash in meiner Tabelle nachschlagen, in der Hoffnung, dass er mit einem der Passwörter übereinstimmt, die mein Programm in der Zwischenzeit bereits ausprobiert hatte, in diesem Fall ich würde das Passwort sofort kennen.
Wenn ich jedoch nicht einmal wüsste, welches Salz Sie tatsächlich verwendet haben, könnte ich das Passwort nicht erraten, bevor ich das richtige Salz zum ersten Mal erhalten habe. Dies würde zusätzliche Zeit in Anspruch nehmen und es Ihnen möglicherweise ermöglichen, das Passwort zu ändern, bevor ich es knacken konnte.
Auch hier sind lange zufällige Salze (mit hoher Wahrscheinlichkeit) nicht nur eindeutig, sondern auch unvorhersehbar. Es gibt jedoch auch andere Möglichkeiten, um dieses Ziel zu erreichen. Sie können beispielsweise eines der oben gezeigten eindeutigen Beispielsalze verwenden und einfach einen geheimen Wert (z. B. eine zufällige Zeichenfolge, die in einer Konfigurationsdatei gespeichert ist und möglicherweise regelmäßig geändert wird) anhängen. Da dieses Geheimnis für alle Benutzer gleich wäre, würde es nicht bei der Einzigartigkeit helfen, aber es würde sicherstellen, dass ich keinen Brute-Force-Angriff starten könnte, ohne vorher irgendwie das Geheimnis zu lernen.
Nachtrag: In Bezug auf Ihre Änderungen an der Frage würde ich sagen, dass Ihr Schema (unter Verwendung von Domainname + Benutzer-ID + Pfeffer als Salz) ausreichen sollte. Wenn möglich, würde ich auch einen Zeitstempel einfügen, aber dazu müssen Sie den Zeitstempel natürlich irgendwo speichern.
Trotzdem finde ich immer noch Ihre Prämisse ("das Salz ist nicht in der Datenbank gespeichert") a etwas rätselhaft. Wenn Sie den Passwort-Hash selbst in der Datenbank speichern können, warum nicht auch das Salz?
Tatsächlich verwenden viele gängige Kennwort-Hashing-Schemata überhaupt keine separate Datenbankspalte für das Salt, sondern speichern es nur als Teil der Hash-Zeichenfolge, z. Als -Methode $ salt $ hash
, wobei die -Methode
die verwendete Hashing-Methode identifiziert, sind salt
und hash
das Salt und Hash-Werte, die mit einem geeigneten Schema (z. B. base64) codiert wurden, und $
sind nur ein beliebiges Trennzeichen, das im codierten Salt oder Hash nicht vorkommt.