Passwörter sicher speichern
Ein Salt und eine langsame Funktion
Der Dieb aus Lektion 1 hatte zwei Vorteile. Ein Versuch diente jedem Benutzer: 300 Digests wurden einmal berechnet und mit der ganzen Tabelle verglichen. Und jeder Versuch kostete fast nichts, weil
Das sind zwei getrennte Probleme, und sie haben zwei getrennte Reparaturen. Diese Lektion hält sie auseinander, weil jede Reparatur das andere Problem unberührt lässt.
Ein Salt
Ein
Die ersten zwei Zeilen sind die Tabelle aus Lektion 1: Dasselbe Passwort ergibt beide Male denselben Digest, a353b0deccba3f4e. Die letzten zwei Zeilen sind wieder dana und gus, mit demselben Passwort und je einem Salt. Ihre Digests, 335dd0afc19d7c76 und 52e28c68e4587e5e, haben nichts gemeinsam.
Ein Salt ist kein Geheimnis, und es ist kein Schlüssel. Es steht im Klartext neben dem Hash, weil der Server es wieder braucht, um ein Passwort zu prüfen. Es muss nur für jeden Datensatz anders und unvorhersagbar sein, also kommt es aus secrets, aus dem Grund, den Kapitel 2 genannt hat.
Dieser Block soll zeigen, was ein Salt tut. So werden Passwörter nicht gespeichert: Die
Wo lebt das Salt eines Datensatzes?
Was ein Salt für den Dieb ändert
Denk an das letmein hängt davon ab, gegen welchen Datensatz er ausprobiert wird, also gibt es keinen einzelnen Digest, den man dafür speichern könnte.
Der Dieb muss für jeden Datensatz neu anfangen: das Salt dieses Datensatzes nehmen, alle 300 Wörter damit hashen, vergleichen. Für 8 Benutzer sind das 8 mal 300, also 2.400 Digests. Für 8 Millionen Benutzer sind es 2.400 Millionen. Die Arbeit wächst jetzt mit der Anzahl der Konten.
Das zweite Leck ist auch geschlossen. Zwei Benutzer mit demselben Passwort bekommen verschiedene Salts und damit verschiedene Digests. Niemand kann an der Tabelle sehen, dass dana und gus gleich gewählt haben.
Jeder Datensatz hat jetzt sein eigenes Salt. 8 Benutzer, 300 Wörter: Wie viele Digests braucht es, um jedes Wort gegen jeden Benutzer auszuprobieren?
Was ein Salt nicht ändert
Nimm jetzt den Dieb, der nicht alle will. Er will ana.
Anas Salt steht in der Tabelle, neben ihrem Hash. Der Dieb nimmt es, hasht damit 300 Wörter und ist fertig. Eines hat das Salt ihm schon genommen: Digests, die jemand vor dem Datenleck vorbereitet hat, nützen gegen ihren Datensatz nichts. Aber frische Versuche gegen einen Datensatz kosten so viel wie vorher. Jeder Versuch ist immer noch ein schneller SHA-256-Aufruf, und eine Grafikkarte schafft davon immer noch eine enorme Anzahl pro Sekunde.
Ein Salt beantwortet also den ersten Vorteil, einen Versuch für alle, und lässt den zweiten in Ruhe.
Eine langsame Funktion
Die zweite Reparatur ist, jeden Versuch teuer zu machen. Ein Passwort-Hash ist eine Funktion, die absichtlich so gebaut ist, dass ein Aufruf spürbar Zeit und Speicher kostet.
Der Server zahlt diese Kosten einmal pro Anmeldung, wo ein paar Hundertstelsekunden keine Rolle spielen. Der Dieb zahlt sie einmal pro Versuch, gegen jeden Datensatz. Millionen Versuche zu je ein paar Hundertstelsekunden sind ein anderes Geschäft als Millionen Versuche zu fast nichts.
Pythons Standardbibliothek hat eine solche Funktion, hashlib.scrypt. Das ist ein Aufruf, als Fragment, weil er auf dieser Seite nicht läuft:
digest = hashlib.scrypt(
b"sunshine2024", salt=dana_salt, n=2**14, r=8, p=1, dklen=32
)
print(digest.hex())
Es gibt 3c0f35b38363436da5b163be671680e2337f6a9ac47bdd4b21504e6c2c0be613 aus. Das Salt ist ein eigenes n, r und p legen fest, wie viel Arbeit ein Aufruf leistet. Mit diesen Einstellungen dauert ein Aufruf auf dieser Website etwa zwei Hundertstelsekunden und braucht während der Ausführung etwa 16
Die zwei Reparaturen nebeneinander:
| Der Vorteil des Diebs | Die Reparatur | Was sie ändert |
|---|---|---|
| Ein Versuch wird gegen jeden Datensatz zugleich getestet, und gleiche Passwörter sind sichtbar | Ein zufälliges Salt für jeden Datensatz | Jeder Datensatz muss einzeln angegriffen werden |
| Jeder Versuch kostet fast nichts | Eine langsame Funktion | Jeder Versuch kostet Zeit und Speicher |
Ein Passwort ist nur mit beiden sicher gespeichert.
Ein Dieb will das Passwort eines bestimmten Benutzers und hat dessen gesalzenen SHA-256-Datensatz. Welche Reparatur macht das schwerer?
In der nächsten Lektion rufst du die langsame Funktion selbst auf.