Salt Generation und Open Source Software


74

Soweit ich weiß, besteht die beste Vorgehensweise zur Erzeugung von Salzen darin, eine kryptische Formel (oder sogar eine magische Konstante) zu verwenden, die in Ihrem Quellcode gespeichert ist.

Ich arbeite an einem Projekt, das wir als Open Source veröffentlichen wollen, aber das Problem ist, dass mit der Quelle die geheime Formel zur Erzeugung von Salzen und damit die Fähigkeit zur Ausführung von Regenbogentischangriffen auf unserer Website einhergeht.

Ich denke, dass viele Leute dieses Problem vor mir in Betracht gezogen haben, und ich frage mich, was die beste Praxis ist. Es scheint mir, dass es keinen Sinn macht, überhaupt ein Salz zu haben, wenn der Code Open Source ist, weil Salze leicht rückentwickelt werden können.

Gedanken?

Antworten:


20

Wirklich Salze müssen nur für jeden Eintrag einzigartig sein. Selbst wenn der Angreifer berechnen kann, was das Salz ist, ist es äußerst schwierig, den Regenbogentisch zu erstellen. Dies liegt daran, dass das Salt dem Kennwort hinzugefügt wird, bevor es gehasht wird, sodass es effektiv zur Gesamtzahl der Einträge beiträgt, die die Regenbogentabelle enthalten muss, um eine Liste aller möglichen Werte für ein Kennwortfeld zu erhalten.


239

Da regelmäßig Fragen zum Salzen von Hashes gestellt werden und das Thema ziemlich verwirrend zu sein scheint, habe ich diese Antwort erweitert.


Was ist ein Salz?

Ein Salt ist eine zufällige Menge von Bytes fester Länge, die zur Eingabe eines Hash-Algorithmus hinzugefügt werden.


Warum ist das Salzen (oder Säen) eines Hash nützlich?

Durch Hinzufügen eines zufälligen Salt zu einem Hash wird sichergestellt, dass dasselbe Kennwort viele verschiedene Hashes erzeugt. Das Salz wird normalerweise zusammen mit dem Ergebnis der Hash-Funktion in der Datenbank gespeichert. Das Salzen eines Hashs ist aus mehreren Gründen gut:

  1. Das Salzen erhöht die Schwierigkeit / die Kosten vorberechneter Angriffe (einschließlich Regenbogentabellen ) erheblich.
  2. Durch das Salting wird sichergestellt, dass dasselbe Kennwort nicht zu demselben Hash führt. Dadurch wird sichergestellt, dass Sie nicht feststellen können, ob zwei Benutzer dasselbe Kennwort haben. Und was noch wichtiger ist , Sie können nicht feststellen, ob dieselbe Person auf verschiedenen Systemen dasselbe Kennwort verwendet.
  3. Salting erhöht die Komplexität von Passwörtern und verringert dadurch die Effektivität von Dictionary- und Birthday-Angriffen erheblich . (Dies gilt nur , wenn das Salz wird aus dem Hash separate gespeichert).
  4. Durch korrektes Salzen wird der Speicherbedarf für Vorberechnungsangriffe erheblich erhöht, bis sie nicht mehr praktikabel sind. (8-stellige alphanumerische Passwörter mit 16-Bit-Salt, die auf einen 128-Bit-Wert gehasht wurden, würden ohne Regenbogenreduzierung knapp 200 Exabyte belegen).


Das Salz muss nicht geheim sein.

Ein Salt ist kein geheimer Schlüssel, sondern ein Salt "funktioniert", indem es die Hash-Funktion für jede Instanz spezifisch macht. Bei gesalzenem Hash gibt es nicht eine Hash-Funktion, sondern eine für jeden möglichen Salzwert. Dies verhindert, dass der Angreifer N gehashte Passwörter für weniger als das N- fache der Kosten für den Angriff auf ein Passwort angreift. Dies ist der Punkt des Salzes.
Ein "geheimes Salt" ist kein Salt, es wird als "Schlüssel" bezeichnet und bedeutet, dass Sie keinen Hash mehr berechnen, sondern einen Message Authentication Code (MAC). Das Berechnen von MAC ist eine knifflige Angelegenheit (viel schwieriger als das einfache Zusammenfügen eines Schlüssels und eines Werts zu einer Hash-Funktion) und ein ganz anderes Thema.

Das Salz muss für jeden Fall, in dem es verwendet wird , zufällig sein . Dies stellt sicher, dass ein Angreifer jeden gesalzenen Hash separat angreifen muss.
Wenn Sie sich darauf verlassen, dass Ihr Salz (oder Salzalgorithmus) geheim ist, betreten Sie die Bereiche Sicherheit durch Dunkelheit (funktioniert nicht). Höchstwahrscheinlich erhalten Sie keine zusätzliche Sicherheit durch das Salzgeheimnis. Sie bekommen nur das warme, verschwommene Gefühl der Sicherheit. Anstatt Ihr System sicherer zu machen, lenkt es Sie nur von der Realität ab.


Warum muss das Salz zufällig sein?

Technisch sollte das Salz einzigartig sein . Der Punkt des Salzes muss für jedes gehashte Passwort unterschiedlich sein. Dies ist weltweit gemeint . Da es keine zentrale Organisation gibt, die einzigartige Salze nach Bedarf verteilt, müssen wir uns auf das nächstbeste verlassen, nämlich die zufällige Auswahl mit einem unvorhersehbaren Zufallsgenerator, vorzugsweise in einem Salzraum, der groß genug ist, um Kollisionen unwahrscheinlich zu machen (zwei Instanzen, die dieselbe verwenden) Salzwert).

Es ist verlockend zu versuchen, aus einigen Daten, die "vermutlich eindeutig" sind, wie z. B. der Benutzer-ID, ein Salz abzuleiten. Solche Schemata schlagen jedoch häufig aufgrund böser Details fehl:

  1. Wenn Sie beispielsweise die Benutzer-ID verwenden, bündeln einige Bösewichte, die unterschiedliche Systeme angreifen, möglicherweise nur ihre Ressourcen und erstellen vorberechnete Tabellen für die Benutzer-IDs 1 bis 50. Eine Benutzer-ID ist systemweit eindeutig , jedoch nicht weltweit .

  2. Gleiches gilt für den Benutzernamen : Es gibt eine "Wurzel" pro Unix-System, aber es gibt viele Wurzeln auf der Welt. Eine Regenbogentabelle für "root" wäre die Mühe wert, da sie auf Millionen von Systemen angewendet werden könnte. Schlimmer noch, es gibt auch viele "Bob" da draußen und viele haben kein Sysadmin-Training: Ihre Passwörter könnten ziemlich schwach sein.

  3. Einzigartigkeit ist auch zeitlich. Manchmal ändern Benutzer ihr Passwort. Für jedes neue Passwort muss ein neues Salz ausgewählt werden. Andernfalls könnte ein Angreifer den Hash des alten Passworts erhalten und der Hash des neuen könnte versuchen, beide gleichzeitig anzugreifen.

Die Verwendung eines zufälligen Salzes aus einem kryptografisch sicheren, unvorhersehbaren PRNG kann eine Art Overkill sein, schützt Sie jedoch nachweislich vor all diesen Gefahren. Es geht nicht darum, den Angreifer daran zu hindern, zu wissen, was ein einzelnes Salz ist, sondern darum, ihm nicht das große, fette Ziel zu geben, das für eine beträchtliche Anzahl potenzieller Ziele verwendet wird. Durch zufällige Auswahl werden die Ziele so dünn wie möglich.


Abschließend:

Verwenden Sie ein zufälliges, gleichmäßig verteiltes Salz mit hoher Entropie. Verwenden Sie ein neues Salz, wenn Sie ein neues Passwort erstellen oder ein Passwort ändern. Speichern Sie das Salz zusammen mit dem Hash-Passwort. Bevorzugen Sie große Salze (mindestens 10 Bytes, vorzugsweise 16 oder mehr).

Ein Salz macht aus einem schlechten Passwort kein gutes Passwort. Es stellt nur sicher, dass der Angreifer mindestens den Preis für den Wörterbuchangriff für jedes falsche Passwort zahlt, das er bricht.


Nützliche Quellen:
stackoverflow.com: Nicht zufälliges Salz für Passwort-Hashes
Bruce Schneier: Praktische Kryptographie (Buch)
Matasano Sicherheit: Genug mit den Regenbogentabellen
usenix.org: Unix-Krypta verwendet Salz seit 1976
owasp.org : Warum Salz hinzufügen
openwall.com : Salze

Haftungsausschluss:
Ich bin kein Sicherheitsexperte. (Obwohl diese Antwort von Thomas Pornin überprüft wurde )
Wenn einer der Sicherheitsexperten etwas falsch findet, kommentieren oder bearbeiten Sie diese Wiki-Antwort.


4
Es muss für jede Zeile auf allen Maschinen, auf denen das System verwendet wird, unterschiedlich sein. Das Salz muss auch unvorhersehbar sein. Dies wird erreicht, indem ein zufälliges Salz erzeugt wird. Siehe auch: stackoverflow.com/questions/536584/…
Jacco

1
@Jacco, das ist fantastisch. Und ich stimme Ihrem Argument für Zufälligkeit zu. Dies ist der effektivste Weg, um zu verhindern, dass Angreifer das Salz auf allen Systemen "erraten". (Obwohl ein Krypto-RNG definitiv übertrieben ist).
Jeremy Powell

3
Wenn Sie das Salz kennen, können Sie einen Brute-Force-Angriff auf diesen bestimmten Hash ausführen. Es ist nicht vorteilhaft, eine Regenbogentabelle zu erstellen, wenn Sie einen einzelnen Hash brechen möchten. Außerdem dauert das Erstellen einer Million Hashes für ein gutes Hashing-Schema länger, als Sie anscheinend annehmen.
Jacco

1
Danke für die schnelle Antwort. Denken Sie, dass schwache Passwörter nicht häufig sind oder dass adaptive Cost-Hashing-Algorithmen keine gute Idee sind? Ich schätze die Vorteile, nicht vom Fokus dieser Frage abzuweichen, aber ich sehe so viele schlechte Praktiken und Ratschläge zum Hashing von Passwörtern, dass ich denke, dass es sehr hilfreich wäre, zumindest auf eine andere gute Antwort im Bereich des Algorithmus zu verlinken. Kennen Sie einen Stapelüberlauf? Auf dem neuen it security stackexchange ist security.stackexchange.com/questions/211/password-hashing ziemlich gut, daher ist die Verknüpfung von hier aus der richtige Weg, um den Leuten zu helfen.
Nealmcb

2
Ein weiterer Punkt, der hier relevanter ist. Sie sagen "Technisch sollte das Salz einzigartig sein", aber das ist nicht stark genug. Es braucht auch viel Entropie, wie Sie anderswo sagen. Wenn es nur einzigartig wäre und von einer "zentralen Organisation" ausgegeben würde, könnten sie nur sequentielle Salze zuweisen, und das Wissen darüber, wie viele Salze bisher zugewiesen wurden oder welche Salze zu Ihrem Ziel gegangen waren, würde den Angriffsraum für a verringern vorberechneter Angriff.
Nealmcb

7

Seit Unix populär geworden ist, besteht der richtige Weg, ein Passwort zu speichern, darin, einen zufälligen Wert (das Salz) anzuhängen und ihn zu hashen. Bewahren Sie das Salz dort auf, wo Sie es später erreichen können, aber wo Sie hoffen, dass die Bösen es nicht bekommen.

Dies hat einige gute Auswirkungen. Erstens können die Bösen nicht einfach eine Liste der erwarteten Passwörter wie "Password1" erstellen, sie in eine Regenbogentabelle hashen und Ihre Passwortdatei nach Übereinstimmungen durchsuchen. Wenn Sie ein gutes Zwei-Byte-Salz haben, müssen sie 65.536 Werte für jedes erwartete Passwort generieren, und das macht die Regenbogentabelle viel weniger praktisch. Zweitens, wenn Sie das Salz von den Bösen fernhalten können, die Ihre Passwortdatei betrachten, haben Sie es viel schwieriger gemacht, mögliche Werte zu berechnen. Drittens haben Sie es den Bösen unmöglich gemacht, festzustellen, ob eine bestimmte Person auf verschiedenen Websites dasselbe Passwort verwendet.

Dazu erzeugen Sie ein zufälliges Salz. Dies sollte jede Zahl im gewünschten Bereich mit einheitlicher Wahrscheinlichkeit erzeugen. Das ist nicht schwierig; Ein einfacher linearer kongruenter Zufallszahlengenerator reicht aus.

Wenn Sie komplizierte Berechnungen haben, um das Salz herzustellen, machen Sie es falsch. Wenn Sie es basierend auf dem Passwort berechnen, machen Sie es WEG falsch. In diesem Fall komplizieren Sie lediglich den Hash und fügen kein Salz hinzu.

Niemand, der gut in Sicherheit ist, würde sich darauf verlassen, einen Algorithmus zu verbergen. Die moderne Kryptographie basiert auf Algorithmen, die ausgiebig getestet wurden, und um ausgiebig getestet zu werden, müssen sie bekannt sein. Im Allgemeinen hat es sich als sicherer erwiesen, Standardalgorithmen zu verwenden, als eigene zu rollen und zu hoffen, dass es gut ist. Es spielt keine Rolle, ob der Code Open Source ist oder nicht, es ist den Bösen immer noch oft möglich zu analysieren, was ein Programm tut.


1
+1 für "Es kann nicht festgestellt werden, ob eine bestimmte Person auf verschiedenen Websites dasselbe Passwort verwendet."
Jacco

1

Sie können zur Laufzeit einfach einen zufälligen Salt für jeden Datensatz generieren. Angenommen, Sie speichern gehashte Benutzerkennwörter in einer Datenbank. Sie können eine 8-stelliges zufällige Folge von Nieder- erzeugen und alphanumerischen Zeichen zur Laufzeit, prepend Großbuchstaben, die mit dem Passwort, Hash , dass String und speichern sie in der Datenbank. Da es 62 8 mögliche Salze gibt, ist die Erzeugung von Regenbogentabellen (für jedes mögliche Salz) unerschwinglich teuer; und da Sie für jeden Kennwortdatensatz ein eindeutiges Salt verwenden, kann ein Angreifer nicht jedes Kennwort knacken, selbst wenn er ein paar übereinstimmende Regenbogentabellen generiert hat .

Sie können die Parameter Ihrer Salzgenerierung basierend auf Ihren Sicherheitsanforderungen ändern. Sie könnten beispielsweise ein längeres Salz verwenden oder eine zufällige Zeichenfolge generieren, die auch Satzzeichen enthält, um die Anzahl der möglichen Salze zu erhöhen.


Sie müssen dann die Salze zusammen mit den Hash-Passwörtern in der Datenbank speichern, richtig?
user199085

2
Sie erhalten zusätzlichen Schutz, wenn Sie die Salze in einer separaten Datenbank speichern. Selbst wenn sie neben dem Hash-Passwort gespeichert werden, erhöht die Verwendung der Salt-Methode die Komplexität eines erfolgreichen Angriffs erheblich. Der Schlüssel hier ist, dass Sie durch das Einfügen eines zufälligen Elements in den Hash-Generierungsprozess das Knacken ALLER Passwörter erheblich erschwert haben. Weitere Informationen finden Sie in diesem Wikipedia-Eintrag: en.wikipedia.org/wiki/Salt_%28cryptography%29
Dave R.

0

Verwenden Sie einen Zufallsfunktionsgenerator, um das Salz zu generieren, und speichern Sie es in der Datenbank, erstellen Sie Salz pro Zeile und speichern Sie es in der Datenbank.

Mir gefällt, wie bei der Django-Registrierung Salz erzeugt wird. Referenz: http://bitbucket.org/ubernostrum/django-registration/src/tip/registration/models.py#cl-85

salt = sha_constructor(str(random.random())).hexdigest()[:5]
activation_key = sha_constructor(salt+user.username).hexdigest()
return self.create(user=user,
           activation_key=activation_key)

Er verwendet eine Kombination aus sha, die durch eine Zufallszahl generiert wird, und dem Benutzernamen, um einen Hash zu generieren.

Shaselbst ist bekannt dafür, stark und unzerbrechlich zu sein. Fügen Sie mehrere Dimensionen hinzu, um das Salz selbst zu erzeugen. Mit Zufallszahl, sha und der benutzerspezifischen Komponente haben Sie unzerbrechliche Sicherheit!


7
Unzerbrechliche Sicherheit? Ich finde das etwas zu optimistisch.
Jacco

6
SHA-1 ist defekt: schneier.com/blog/archives/2005/02/sha1_broken.html , verwenden Sie also SHA-256.
Jacco

2
SHA-256 ist jetzt ebenfalls veraltet. Derzeit vorgeschlagene Methoden sind BCrypt und PBKDF2.
Gnanz

0

Wie können Sie bei einer Desktop-Anwendung, die Daten verschlüsselt und auf einem Remote-Server sendet, jedes Mal ein anderes Salt verwenden?

Bei Verwendung von PKCS # 5 mit dem Kennwort des Benutzers wird ein Salt benötigt, um einen Verschlüsselungsschlüssel zu generieren und die Daten zu verschlüsseln. Ich weiß, dass es keine gute Idee ist, das Salz in der Desktop-Anwendung fest (verschleiert) zu halten.

Wenn der Remote-Server NIEMALS das Kennwort des Benutzers kennen darf, ist es dann möglich, jedes Mal ein anderes Salt zu verwenden? Wenn der Benutzer die Desktop-Anwendung auf einem anderen Computer verwendet, wie kann er die Daten auf dem Remote-Server entschlüsseln, wenn er nicht über den Schlüssel verfügt (dieser ist in der Software nicht fest codiert)?

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.