FlowingDev

Bcrypt & Argon2: Warum deine Passwörter ein Workout brauchen

Erfahre, wie moderne Passwort-Hashing-Algorithmen wie bcrypt und Argon2 deine Daten schützen, indem sie das Knacken von Passwörtern rechenintensiv und langsam machen.

Tool ausprobieren: Bcrypt & Argon2 Hash

In einem Satz

Passwort-Hashing-Algorithmen wie bcrypt und Argon2 wandeln das Passwort eines Nutzers in eine lange, unumkehrbare Zeichenkette um. Sie sind absichtlich so konzipiert, dass ihre Berechnung langsam und teuer ist, was es für Angreifer quälend schwierig macht, sie zu knacken – selbst wenn sie deine gesamte Benutzerdatenbank stehlen.

Welches Problem es löst

Im finsteren digitalen Mittelalter speicherten Entwickler User-Passwörter im Plaintext. Wenn ein Hacker in die Datenbank einbrach, bekam er eine Datei mit allen Benutzernamen und den dazugehörigen Passwörtern. Game over. Du kannst dir das Gemetzel vorstellen.

Der erste Fortschritt war das „Hashing“. Statt P@sswort123 zu speichern, speicherte man dessen Hash – eine Zeichenkette mit fester Länge, die von einem Algorithmus wie MD5 oder SHA-1 erzeugt wurde. Wenn sich der User einloggte, wurde das eingegebene Passwort gehasht und mit dem gespeicherten Hash verglichen. Das war schon besser, hatte aber eine fatale Schwäche: Rainbow Tables. Da eine Hash-Funktion für dieselbe Eingabe immer dieselbe Ausgabe erzeugt (z. B. wird password mit MD5 immer zu 5f4dcc3b5aa765d61d8327deb882cf99), berechneten Angreifer die Hashes für Milliarden gängiger Passwörter vor und speicherten sie in einer riesigen Nachschlagetabelle. Ein gestohlener Hash konnte so in Millisekunden in sein ursprüngliches Passwort zurückverwandelt werden.

Die nächste Evolutionsstufe war das „Salting“. Bevor das Passwort gehasht wird, fügt man ihm eine einzigartige, zufällige Zeichenkette hinzu, einen sogenannten „Salt“. Statt also P@ssword123 zu hashen, hasht man P@ssword123 + aBcDeFg12345. Der Salt wird dann zusammen mit dem Hash in der Datenbank gespeichert. Das macht Rainbow Tables komplett unbrauchbar, denn nun ist der Hash jedes Nutzers einzigartig, selbst wenn alle das Passwort „password“ gewählt haben. Ein Angreifer müsste für jeden einzelnen, einzigartigen Salt eines jeden Nutzers eine neue Rainbow Table erstellen, was rechnerisch undurchführbar ist.

Aber dann betrat ein neuer Bösewicht die Bühne: schiere Rechenleistung. Moderne GPUs und spezielle Hardware (ASICs) können pro Sekunde Milliarden von gesalzenen Passwortkombinationen gegen einen einzigen gestohlenen Hash ausprobieren. Hashing-Algorithmen wie SHA-256 sind von Haus aus schnell, was super ist, um die Integrität von Dateien zu prüfen, aber schrecklich, um Passwörter zu schützen.

Das ist das Problem, zu dessen Lösung bcrypt und Argon2 geschaffen wurden. Sie sind Passwort-Hashing-Funktionen (PHFs), eine spezielle Klasse von Hash-Algorithmen, die absichtlich, quälend langsam und ressourcenintensiv sind. Sie machen die Überprüfung auch nur eines einzigen Passworts so teuer, dass das Brute-Forcing einer gestohlenen Datenbank für den Angreifer zu einem wirtschaftlichen und zeitlichen Albtraum wird.

Wie es unter der Haube funktioniert

Die Magie hinter modernem Passwort-Hashing liegt nicht nur im Algorithmus selbst, sondern darin, den Algorithmus zu einer konfigurierbaren Menge an „Arbeit“ zu zwingen. Das wird oft als „Key Stretching“ bezeichnet.

Die Kernidee: Adaptiver Aufwand

Sowohl bcrypt als auch Argon2 haben einstellbare „Kosten“- oder „Arbeits“-Faktoren. Das ist ihre Superkraft. Es ist eine Zahl, die du festlegst und die bestimmt, wie langsam und ressourcenhungrig der Hashing-Prozess sein wird. Die Idee ist, diesen Aufwand so einzustellen, dass das Hashen eines Passworts auf deinem Server eine angemessene Zeit in Anspruch nimmt (sagen wir, 100-500 Millisekunden) – langsam genug, um einen Angreifer zu frustrieren, aber schnell genug, um deine Nutzer nicht zu nerven.

Da Computer gemäß dem Mooreschen Gesetz immer schneller werden, kannst du einfach alle paar Jahre den Kostenfaktor erhöhen, um das gleiche Sicherheitsniveau beizubehalten. Dein Hashing-„Workout“ wird härter, während die Hardware des Angreifers stärker wird.

Bcrypt: Der treue Veteran

Bcrypt, 1999 eingeführt, basiert auf der Blowfish-Verschlüsselungschiffre. Seine primäre Verteidigung gegen Brute-Force-Angriffe besteht darin, dass es nicht nur rechen-, sondern auch speicherintensiv ist.

Der Algorithmus verarbeitet Passwort und Salt wiederholt, aber ein wichtiger Teil seines internen Zustands wird so gespeichert, dass häufiger Zugriff auf einen Batzen RAM erforderlich ist. Während CPUs darin gut sind, leben GPUs – die bevorzugte Waffe von Angreifern – von einfachen, parallelisierbaren Berechnungen mit minimalem Speicherzugriff. Indem bcrypt den Prozess zwingt, ständig auf den Speicher zuzugreifen, wirft es den GPU-basierten Knack-Maschinen einen Knüppel ins Getriebe.

Ein typischer bcrypt-Hash-String sieht so aus:

$2b$12$J9yLsf9dTOZiCEpT1zO97uF2Yp3uG/yG4Q6V.C1rCg8u6d5qO5GqS

Schauen wir uns die einzelnen Teile an:

Teil Beispiel Bedeutung
Algorithmus $2b Identifiziert den bcrypt-Algorithmus und seine Version.
Kostenfaktor 12 Der Arbeitsfaktor. Die Anzahl der Iterationen ist 212. Eine Erhöhung um 1 verdoppelt die Zeit.
Salt & Hash J9yLsf...d5qO5GqS Die ersten 22 Zeichen sind der Base64-kodierte Salt. Der Rest ist der eigentliche Hash des Passworts.

Entscheidend ist, dass alle Informationen, die zur Überprüfung eines Passworts benötigt werden – der Algorithmus, der Aufwand und der Salt – direkt in diesem einen praktischen String gespeichert sind.

Argon2: Der moderne Champion

Argon2 war 2015 der Gewinner der Password Hashing Competition (PHC), einer mehrjährigen Anstrengung, einen neuen, standardisierten Passwort-Hashing-Algorithmus zu finden. Er ist so konzipiert, dass er noch widerstandsfähiger gegen moderne Hardware-Angriffe ist als bcrypt.

Er bietet drei verschiedene Hebel zur Feinabstimmung seines Aufwands:

  1. Speicheraufwand (m): Die Menge an Speicher (in KiB), die der Algorithmus verwenden wird. Dies ist seine Hauptverteidigung gegen Hardware-Beschleunigung, da er so eingestellt werden kann, dass er mehr Speicher benötigt, als auf einem einzelnen GPU-Kern verfügbar ist.
  2. Zeitaufwand (t): Die Anzahl der Iterationen oder Durchläufe, die der Algorithmus über den Speicher macht. Dies erhöht die gesamte Berechnungszeit.
  3. Parallelitätsgrad (p): Die Anzahl der Threads oder „Lanes“, die verwendet werden können. Dies ermöglicht es dem Algorithmus, Multi-Core-CPUs für das Hashing zu nutzen, bedeutet aber auch, dass ein Angreifer dieselbe Parallelität nutzen kann. Es ist ein Trade-off-Parameter.

Die empfohlene Variante ist Argon2id, eine Hybridversion aus zwei anderen Varianten. Sie bietet eine ausgewogene Resistenz sowohl gegen Seitenkanalangriffe (bei denen ein Angreifer Systemeffekte wie den Stromverbrauch analysiert) als auch gegen GPU-Cracking-Angriffe.

Ein Argon2id-Hash-String ist ähnlich eigenständig:

$argon2id$v=19$m=65536,t=3,p=4$c29tZXNhbHQ$RdescudvJCsgt3ub+b+dWRWJTIT0T7cKLfgflAIk124

Teil Beispiel Bedeutung
Algorithmus $argon2id Identifiziert den Argon2id-Algorithmus.
Version v=19 Die Versionsnummer des Algorithmus.
Parameter m=65536,t=3,p=4 Der Speicher-, Zeit- und Parallelitätsaufwand.
Salt c29tZXNhbHQ Der Base64-kodierte zufällige Salt. (Dies dekodiert zu „somesalt“).
Hash Rdescudv...flAIk124 Der Base64-kodierte Hash des Passworts.

Der Verifizierungsprozess

Und jetzt kommt der schöne Teil. Man entschlüsselt niemals einen Hash. Die Verifizierung ist eine Einbahnstraße.

  1. Ein User versucht, sich mit P@ssword123 einzuloggen.
  2. Deine Anwendung holt den vollständigen Hash-String aus der Datenbank (z.B. den Argon2id-String aus der obigen Tabelle).
  3. Dein Code parst diesen String und extrahiert den Algorithmus (argon2id), die Version (19), die Kostenfaktoren (m=65536, t=3, p=4) und den Salt (c29tZXNhbHQ).
  4. Dann nimmt er das gerade vom User eingegebene Passwort (P@ssword123) und hasht es mit exakt denselben Parametern.
  5. Schließlich vergleicht er den neu erzeugten Hash mit dem Hash-Teil des Strings aus der Datenbank. Wenn sie identisch sind, ist das Passwort korrekt. Wenn nicht, wird der Zugriff verweigert.

Beispiele aus der echten Welt

Der LinkedIn-Hack von 2012: Eine Lektion in Geschwindigkeit

2012 erlitt LinkedIn einen massiven Hack, bei dem über 6,5 Millionen Hashes von Nutzerpasswörtern in einem russischen Hackerforum landeten. Das Problem? Es waren ungesalzene SHA-1-Hashes. Innerhalb von Stunden begannen Sicherheitsexperten und Black Hats gleichermaßen ein Wettrennen, um sie zu knacken. Die Listen der erfolgreich geknackten Passwörter wuchsen von Minute zu Minute. Da die Hashes „schnell“ und ungesalzen waren, reichte eine einzige, riesige Rainbow Table aus. Der Imageschaden war immens.

Lektion: Ein schneller, ungesalzener Hash ist kaum besser als Plaintext. Der LinkedIn-Hack war ein gewaltiger Weckruf für die Branche, der unzählige Unternehmen dazu brachte, endlich auf langsames, gesalzenes Hashing wie bcrypt umzusteigen.

Die E-Commerce-Seite, die sich Zeit kaufte

Ein cleverer Entwickler bei einem Startup namens „CircuitCraze“ bestand darauf, Argon2id für die neue Kundendatenbank zu verwenden, und stellte die Parameter so ein, dass jeder Login etwa 300 ms dauerte. Ein Jahr später legte ein falsch konfigurierter Cloud Storage Bucket ein Datenbank-Backup frei. Die users-Tabelle mit all ihren Argon2id-Hashes wurde von einem Angreifer heruntergeladen. Das Team erzwang sofort einen globalen Passwort-Reset. Der Angreifer, der vor der Aussicht stand, Tausende von Dollar für Cloud-Computing ausgeben zu müssen, nur um eine Handvoll Passwörter aus einem nun nutzlosen Datensatz zu knacken, gab einfach auf und wandte sich einfacheren Zielen zu.

Lektion: Starkes Passwort-Hashing ist deine primäre Verteidigungslinie nach einem Hack. Es verhindert nicht den Einbruch, aber es verwandelt ein katastrophales Datenleck in einen handhabbaren Vorfall, indem es dir entscheidende Zeit zum Reagieren verschafft.

Der schleichende Kostenfaktor

Ein Team startete 2015 eine neue Web-App und entschied sich klugerweise für bcrypt mit einem Kostenfaktor von 10. Das funktionierte super. Spulen wir vor bis heute. Das Mooresche Gesetz hat seinen Job gemacht, und ein Kostenfaktor von 10 gilt heute als schwach. Ein Security Audit stuft dies als hohes Risiko ein. Das Team steht nun vor einem Dilemma: Wie können sie die Sicherheit für Millionen von Nutzern verbessern, ohne einen Massen-Passwort-Reset zu erzwingen? Die elegante Lösung: Wenn sich ein Nutzer das nächste Mal anmeldet, überprüft das System sein Passwort mit dem alten Kostenfaktor-10-Hash. Wenn es korrekt ist, hasht es dasselbe Passwort sofort mit einem neuen Kostenfaktor von 13 neu und ersetzt den alten Hash in der Datenbank.

Lektion: Passwortsicherheit ist kein Fall von „einmal einstellen und vergessen“. Kostenfaktoren sind eine lebendige Einstellung, die regelmäßig überprüft und erhöht werden muss, um mit den Fähigkeiten der Angreifer Schritt zu halten.

Häufige Fehler und Fallstricke

  • Einen schnellen Hash verwenden. Lass es. MD5, SHA-1, SHA-256, SHA-512... die sind für Prüfsummen, nicht für Passwörter. Sie sind darauf ausgelegt, schnell zu sein, was genau das ist, was du nicht willst.
  • Dein eigenes Krypto-Süppchen kochen. Versuche niemals, dein eigenes Hashing-Schema zu erfinden, wie sha512(password + salt). Verwende eine standardisierte, von Experten geprüfte, kampferprobte Bibliothek für bcrypt oder Argon2, die es richtig macht.
  • Einen statischen oder wiederverwendeten Salt verwenden. Ein Salt muss kryptografisch zufällig und für jedes einzelne Passwort, das du speicherst, einzigartig sein. Einen einzigartigen Salt neben jedem Hash zu speichern, ist die korrekte und standardmäßige Vorgehensweise.
  • Den Aufwand zu niedrig ansetzen. Ein bcrypt-Kostenfaktor unter 12 (im Jahr 2024) oder schwache Argon2-Parameter machen den ganzen Zweck zunichte. Damit bescherst du dem Angreifer nur einen leichten Tag. Stelle ihn so langsam ein, wie du es tolerieren kannst.
  • Den Aufwand zu hoch ansetzen. Wenn das Hashing 10 Sekunden dauert, wird dein Login-Formular einen Timeout haben und sich kaputt anfühlen. Schlimmer noch, du machst deinen Server anfällig für einen Denial-of-Service (DoS)-Angriff, bei dem jemand deine CPUs zum Stillstand bringen kann, indem er einfach wiederholt Anfragen an das Login-Formular sendet.
  • Nur den Hash-Digest speichern. Die von bcrypt und Argon2 erzeugten Strings enthalten den Algorithmus, die Kosten und den Salt aus gutem Grund. Du musst den gesamten String speichern (z.B. in einer VARCHAR(255)-Spalte), um Passwörter in Zukunft verifizieren zu können.

Warum du das auf dem Schirm haben solltest

Wenn dein Job darin besteht, irgendetwas zu bauen, das ein Login-Formular hat, musst du das verstehen.

  • Backend- & Full-Stack-Entwickler: Das liegt in deiner direkten Verantwortung. Wenn du hier Mist baust, bringst du jeden einzelnen deiner Nutzer in Gefahr.
  • Security Engineers & DevOps: Ihr seid diejenigen, die Richtlinien festlegen, Audits durchführen und die Infrastruktur verwalten. Ihr müsst wissen, wie „gut“ aussieht und wie man das testet.
  • Frontend-Entwickler: Wenn du verstehst, dass ein sicherer Login einige hundert Millisekunden dauern kann, erklärt das, warum du dem Nutzer Feedback geben musst (wie einen Loading Spinner), um zu verhindern, dass er wütend auf den „Anmelden“-Button hämmert.

Kurz gesagt, wenn die Worte „User“, „Account“ oder „Passwort“ irgendwo in deinen Projektanforderungen auftauchen, ist Passwort-Hashing ein fundamentales Konzept, das du dir nicht leisten kannst zu ignorieren.

Tauche tiefer ein

Theorie erledigt. Zeit, loszulegen — 100 % in deinem Browser.

Tool ausprobieren: Bcrypt & Argon2 Hash