Sicherheit · 9. September 2026

Passwortsicherheit für Entwickler — was speichern, was hashen und was niemals, niemals tun

Klartext-Passwörter in einer Datenbank sind ein Sicherheitsverstoß, der nur darauf wartet, zu passieren. Hier erfahren Sie, wie moderne Passwortspeicherung aussieht, warum 'einfach mit SHA-256 hashen' nicht ausreicht und was Sie stattdessen tun sollten.

Jede Offenlegung eines Datenschutzverstoßes folgt dem gleichen Bogen: “Wir nehmen Sicherheit ernst.” Dann lesen Sie die Details und stellen fest, dass Passwörter im Klartext gespeichert wurden, mit MD5 gehasht oder mit einem Schlüssel verschlüsselt wurden, der sich in derselben Datenbank befand. Das Problem der Passwortspeicherung ist gelöst — die Algorithmen existieren, die Bibliotheken existieren, die Dokumentation existiert — und doch machen Entwickler es immer noch falsch.

Dieser Beitrag behandelt, was gespeichert werden sollte, was nicht gespeichert werden sollte, den Unterschied zwischen Hashing und Verschlüsselung und warum SHA-256(password) kein Passwort-Hash ist.

Die Regel: niemals Klartext speichern

Wenn Ihre Datenbank kompromittiert wird und Sie Klartext-Passwörter haben, ist jeder Benutzer, der dieses Passwort auf anderen Seiten wiederverwendet, jetzt kompromittiert. Nicht nur Ihre Seite — ihre E-Mail, ihre Bank, ihre sozialen Medien. Klartext-Passwortspeicherung ist kein Sicherheitsproblem. Es ist ein moralisches Problem.

Speichern Sie immer einen Hash.

Hashing vs. Verschlüsselung

Hashing ist eine Einwegtransformation. Sie können es nicht umkehren. Bei hash(password) können Sie password nicht wiederherstellen. Sie können nur verifizieren: Eingabe hashen und vergleichen.

Verschlüsselung ist eine Zwei-Wege-Transformation. Bei encrypt(password, key) können Sie password mit dem Schlüssel wiederherstellen. Wenn der Schlüssel kompromittiert wird, sind alle Passwörter kompromittiert.

Hashen Sie Passwörter. Verschlüsseln Sie sie niemals. Wenn Sie den Klartext wiederherstellen müssen (was Sie nicht müssen), lösen Sie das falsche Problem.

Warum SHA-256 nicht ausreicht

Ein häufiger Fehler: hash = SHA-256(password). Es ist schnell, es ist bekannt und es ist falsch für Passwörter.

Das Problem ist die Geschwindigkeit. SHA-256 auf einer modernen GPU verarbeitet Milliarden von Hashes pro Sekunde. Ein Angreifer mit einer Datenbank von SHA-256-Passwort-Hashes kann jedes gängige Passwort, jedes Wörterbuchwort, jede Permutation in Minuten ausprobieren.

Passwort-Hashing-Algorithmen sind absichtlich langsam. Sie verwenden Schlüsseldehnung — Tausende von Iterationen einer Hash-Funktion — um Brute-Force-Angriffe unpraktikabel zu machen:

  • bcrypt — der Standard seit 1999. Anpassbarer Kostenfaktor. Passwort + Salt → Hash. Jede bedeutende Sprache hat eine Bibliothek.
  • scrypt — speicherhart. Benötigt große Mengen an RAM zur Berechnung, was GPU-Angriffe erschwert.
  • Argon2 — Gewinner des Passwort-Hashing-Wettbewerbs (2015). Speicherhart, konfigurierbare Zeit- und Speicherkosten. Die aktuelle Best Practice.
  • PBKDF2 — von NIST empfohlen, weit verbreitet, verwendet HMAC-Iterationen. Weniger speicherhart als Argon2, aber gut getestet.

Verwenden Sie bcrypt, scrypt oder Argon2. Erfinden Sie nicht Ihr eigenes Schema. Hashen Sie nicht einmal mit SHA-256 und nennen Sie es erledigt.

Salz: warum jedes Passwort ein einzigartiges braucht

Ein Salz sind zufällige Daten, die dem Passwort vor dem Hashing hinzugefügt werden. Ohne Salz erzeugen zwei Benutzer mit demselben Passwort denselben Hash. Ein Angreifer kann Hashes für gängige Passwörter vorberechnen (eine Rainbow-Tabelle) und sie mit Ihrer Datenbank abgleichen.

Mit einem einzigartigen Salz pro Benutzer ist jeder Hash anders, selbst wenn die Passwörter identisch sind. Rainbow-Tabellen funktionieren nicht. Der Angreifer muss jedes Passwort einzeln mit Brute-Force angreifen.

Moderne Passwort-Hashing-Funktionen (bcrypt, Argon2) generieren automatisch ein zufälliges Salz. Sie müssen Salze nicht separat verwalten. Übergeben Sie das Passwort an die Hash-Funktion, und sie erledigt den Rest.

Was gespeichert werden sollte

Für jeden Benutzer speichern Sie:

  • Den Passwort-Hash (bcrypt/Argon2-Ausgabe, die das Salz und die Kostenparameter enthält)
  • Den Hash-Algorithmus (bcrypt, argon2 usw.)
  • Die Kostenparameter (bcrypt-Runden, Argon2-Speicher/Zeit)

Speichern Sie NICHT:

  • Das Klartext-Passwort
  • Das Salz separat (die Hash-Funktion-Ausgabe enthält es)
  • Einen “Verschlüsselungsschlüssel”, der das Passwort entschlüsseln könnte
  • Passwort-Hinweise (sie geben Informationen preis)

Die Hash-Ausgabe von bcrypt sieht so aus: $2b$12$LJ3m4ys3GzF4VQ.YOUR.HASH.HERE. Das $2b$ identifiziert den Algorithmus, 12 ist der Kostenfaktor, und der Rest ist Salt + Hash. Um einen Login-Versuch zu überprüfen, hashen Sie das eingegebene Passwort mit denselben Parametern und vergleichen es.

Kostenfaktoren

Der Kostenfaktor von bcrypt bestimmt, wie langsam der Hash ist. Jede Erhöhung verdoppelt die Berechnungszeit:

  • Kosten 10: ~10ms pro Hash (schnell für Benutzer, schnell für Angreifer)
  • Kosten 12: ~40ms pro Hash (angemessen)
  • Kosten 14: ~160ms pro Hash (langsam für Angreifer, merkbar für Benutzer)
  • Kosten 16: ~640ms pro Hash (zu langsam für die meisten Login-Abläufe)

Der Sweet Spot in 2026: bcrypt Kosten 12-14, Argon2 mit 64MB+ Speicher und 3+ Iterationen. Das Ziel ist es, jeden Hash-Versuch so langsam zu machen, dass das Brute-Forcen von Milliarden von Passwörtern Jahre dauert, aber so schnell, dass ein Benutzer bei der Anmeldung keine Verzögerung bemerkt.

Rate-Limiting

Hashing allein reicht nicht aus. Wenn ein Angreifer Millionen von Passwörtern pro Sekunde gegen Ihren Login-Endpunkt ausprobieren kann, wird selbst bcrypt Sie nicht retten.

Begrenzen Sie Login-Versuche. Nach 5-10 fehlgeschlagenen Versuchen von derselben IP oder demselben Konto sperren Sie das Konto vorübergehend oder erfordern ein CAPTCHA. Dies begrenzt Brute-Force-Angriffe auf ein Minimum.

Enthüllen Sie nicht, ob Benutzername oder Passwort falsch waren. “Ungültiger Benutzername oder Passwort” ist sicherer als “Kein Konto mit dieser E-Mail gefunden.” Letzteres sagt einem Angreifer, welche Benutzernamen existieren.

Kontosperrung nach anhaltenden Fehlern hinzufügen. Nach 10-20 fehlgeschlagenen Versuchen das Konto für 15 Minuten sperren oder eine E-Mail-Verifizierung zum Entsperren erfordern.

Passwortgenerierung

Bei der Generierung von Passwörtern (für Benutzer, API-Schlüssel, Tokens):

  • Minimum 12 Zeichen. 8 reicht nicht mehr gegen moderne Hardware aus.
  • Großbuchstaben, Kleinbuchstaben, Ziffern und Symbole einbeziehen. Aber Länge ist wichtiger als Komplexität.
  • Verwenden Sie einen CSPRNG (kryptographisch sicheren Pseudo-Zufallszahlengenerator). Math.random() ist nicht sicher.
  • Generieren Sie niemals vorhersagbare Muster. Password1! sieht komplex aus, ist aber ratenfach erratbar.

Das beste Passwort ist eine zufällig generierte Zeichenkette von einem CSPRNG. Verwassen Sie einen Passwort-Manager zur Speicherung. Bitten Sie Benutzer nicht, komplexe Passwörter zu merken — geben Sie ihnen ein generiertes und lassen Sie den Manager es verwalten.

Häufige Fehler

  • Einmaliges Hashing mit SHA-256 oder MD5 — zu schnell, kein Salz, trivial brute-forcebar.
  • Verwendung eines statischen Salzes — wenn alle Benutzer denselben Salz teilen, funktionieren Rainbow-Tabellen.
  • Separate Salzspeicherung — wenn das Salz in einer anderen Tabelle ist, erhält ein Angreifer, der die Datenbank kompromittiert, beides.
  • Verschlüsseln statt Hashen — wenn Sie das Passwort entschlüsseln können, kann es ein Angreifer mit dem Schlüssel auch.
  • Kein Rate-Limiting — selbst bcrypt ist anfällig für unbegrenzte Login-Versuche.
  • Offenlegung, ob ein Benutzername existiert — hilft Angreifern, gültige Konten zu enumerieren.
  • Verwendung von Math.random() zur Passwortgenerierung — vorhersagbar, nicht kryptographisch sicher.

Schnellreferenz

Tun Nicht tun
bcrypt, Argon2 oder scrypt verwenden SHA-256 oder MD5 verwenden
Bibliothek das Salz-Handling überlassen Salze selbst verwalten
Login-Versuche begrenzen Unbegrenzte Passwortversuche erlauben
Passwörter mit CSPRNG generieren Math.random() verwenden
Nur den Hash speichern Klartext- oder verschlüsselte Passwörter speichern
“Ungültige Anmeldeinformationen” sagen “Falsches Passwort” sagen

Ausprobieren

Wenn Sie ein sicheres zufälliges Passwort generieren oder eine Zeichenkette für Tests hashen müssen, verwenden Sie ein browserbasiertes Tool, damit die Operation lokal bleibt. Ihr Passwort sollte niemals für eine einfache Generierungsaufgabe einen Server berühren.