
Bcrypt-Passwort-Hashing: Warum es wichtig ist und wie man es verwendet
📷 Pixabay / PexelsBcrypt-Passwort-Hashing: Warum es wichtig ist und wie man es verwendet
Als SHA-256-Hashes gespeicherte Passwörter können in Minuten geknackt werden. Bcrypt ist absichtlich langsam entworfen -- und genau das ist der Punkt. Lernen Sie, wie Bcrypt funktioniert, wie man einen Kostenfaktor wählt und wie man es in Node.js, Python und PHP implementiert.
Das Passwort-Speicherproblem
Stellen Sie sich vor, Sie bauen ein Login-System. Ein Benutzer erstellt ein Konto mit dem Passwort hunter2. Sie müssen etwas in Ihrer Datenbank speichern, damit Sie nächste Woche bei der Anmeldung überprüfen können, ob er das Richtige eingegeben hat.
Die naive Lösung ist, hunter2 direkt zu speichern. Das ist katastrophal. Jedes Datenbankbreach, jede SQL-Injection, jedes Backup auf einem falsch konfigurierten S3-Bucket -- der Angreifer hat jetzt das tatsächliche Passwort jedes Benutzers.
Der nächste Schritt ist das Hashen. SHA-256("hunter2") ergibt einen fixen String, den Sie nicht umkehren können. Speichern Sie das stattdessen. Besser, oder?
Besser -- aber nicht gut genug.
Das Problem ist, dass SHA-256 darauf ausgelegt ist, schnell zu sein. Moderne GPUs können Milliarden von SHA-256-Hashes pro Sekunde berechnen. Ein Angreifer mit einer Datenbank von SHA-256-gehashten Passwörtern und einer guten GPU kann mithilfe vorberechneter Tabellen (Rainbow-Tables) oder Wörterbuchangriffen in Stunden, manchmal Minuten, einen erheblichen Teil der gängigen Passwörter knacken.
Bcrypt wurde speziell dafür entwickelt, das zu lösen. Es ist absichtlich langsam, und die Geschwindigkeit ist konfigurierbar.
Experimentieren Sie direkt mit Bcrypt-Hashes mit unserem Bcrypt Hash Generator -- kein Setup erforderlich.
Was Bcrypt eigentlich ist
Bcrypt ist eine Passwort-Hashfunktion, die 1999 von Niels Provos und David Mazieres auf Basis des Blowfish-Verschlüsselungsalgorithmus entworfen wurde. Im Gegensatz zu SHA-256 oder MD5 (allgemeinen kryptografischen Hash-Funktionen) wurde bcrypt von Grund auf speziell für die Passwort-Speicherung gebaut.
Drei Eigenschaften machen es dafür geeignet:
1. Es ist absichtlich langsam
Bcrypt enthält einen konfigurierbaren Kostenfaktor (auch Arbeitsfaktor oder Salt-Runden genannt). Die Funktion führt intern 2^Kosten Iterationen durch. Das Erhöhen des Kostenfaktors um 1 verdoppelt die Rechenzeit. Das bedeutet, Sie können die Geschwindigkeit an Ihre Hardware anpassen -- und wenn Hardware schneller wird, können Sie den Kostenfaktor erhöhen, um voraus zu bleiben.
Ein SHA-256-Hash dauert Mikrosekunden. Ein Bcrypt-Hash bei Kostenfaktor 12 dauert etwa 200-300 Millisekunden. Der Unterschied klingt gering, ändert aber die Wirtschaftlichkeit für Angreifer dramatisch.
2. Es behandelt Salting automatisch
Ein Salt ist ein Zufallswert, der dem Passwort vor dem Hashen hinzugefügt wird. Salting stellt sicher, dass zwei Benutzer mit demselben Passwort unterschiedliche Hashes erhalten, und vereitelt vorberechnete Rainbow-Table-Angriffe.
Bcrypt generiert automatisch einen kryptografisch zufälligen 128-Bit-Salt und bettet ihn in den Ausgabe-Hash ein. Sie müssen Salts nicht selbst verwalten.
3. Der Hash ist in sich geschlossen
Die Ausgabe von Bcrypt enthält die Algorithmusversion, den Kostenfaktor, den Salt und den Hash -- alles in einem String. Das bedeutet, Sie müssen nur einen einzigen String pro Benutzer speichern und können ein Passwort verifizieren, ohne den Salt separat abzurufen.
Ein typischer Bcrypt-Hash sieht so aus:
$2b$12$LJ3m6gEwO/fSFqCVXWLwOeR/dYtTVkRDCwoGLBE0Fg6voFEOB5viy
Aufschlüsselung:
$2b$ -- Algorithmusversion (2b ist der aktuelle Standard)
12$ -- Kostenfaktor (2^12 = 4.096 Iterationen des Schlüsselplans)
LJ3m6gEwO/fSFqCVXWLwOe -- 22-stelliger base64-kodierter Salt (128 Bit)
R/dYtTVkRDCwoGLBE0Fg6voFEOB5viy -- 31-stelliger base64-kodierter Hash
Hashing vs. Verschlüsselung: Der entscheidende Unterschied
Dieser Unterschied ist wichtig genug, um ihn klar zu formulieren.
Hashing ist eine Einwegfunktion. Sie geben ein Passwort ein und erhalten einen Hash. Es gibt keinen Schlüssel, keine Umkehroperation. Die einzige Möglichkeit zu prüfen, ob ein Passwort mit einem Hash übereinstimmt, ist das Hashen des Kandidatenpassworts und der Vergleich des Ergebnisses.
Verschlüsselung ist eine bidirektionale Funktion. Sie verschlüsseln Daten mit einem Schlüssel und können sie mit demselben (oder einem verwandten) Schlüssel in das Original zurück entschlüsseln.
Passwörter sollten immer gehasht, nicht verschlüsselt werden. Wenn Sie Passwörter verschlüsseln, enthält Ihr System irgendwo einen Entschlüsselungsschlüssel, und wer diesen Schlüssel bekommt, hat alle Passwörter Ihrer Benutzer. Mit Hashing zeigt ein Datenbankbreach Hashes, keine Passwörter -- und mit Bcrypt sind diese Hashes langsam zu knacken.
Der Kostenfaktor: Die richtige Langsamkeit wählen
Der Kostenfaktor steuert direkt, wie viel Berechnungsaufwand Bcrypt betreibt. Jedes Inkrement verdoppelt die Arbeit.
| Kostenfaktor | Iterationen | Ungefähre Zeit (typischer Server) |
|---|---|---|
| 10 | 1.024 | ~65ms |
| 11 | 2.048 | ~130ms |
| 12 | 4.096 | ~250ms |
| 13 | 8.192 | ~500ms |
| 14 | 16.384 | ~1.000ms |
Die obigen Zeiten variieren je nach Hardware erheblich. Führen Sie Benchmarks auf Ihrer eigentlichen Produktionshardware durch, bevor Sie sich entscheiden.
OWASPs aktuelle Empfehlung ist ein Kostenfaktor von mindestens 10 mit einer Hash-Zeit von 100ms oder mehr. Die meisten Praktiker verwenden heute 12 als vernünftigen Standard.
Der Kompromiss:
- Zu niedrig (8 oder darunter): Hashes sind schnell genug, dass ein Angreifer mit einer guten GPU schnell Fortschritte gegen eine geleakte Datenbank erzielen kann.
- Zu hoch (15+): Legitime Login-Anfragen dauern über eine Sekunde, was Benutzer bemerken und bei Angriffen auf Ihren Login-Endpunkt Denial-of-Service-Potenzial schafft.
- Goldilocks-Zone (~12): ~250ms pro Hash ist langsam genug, um Angreifer bedeutend zu behindern, schnell genug, dass Benutzer es nicht bemerken.
Bcrypt implementieren: Code-Beispiele
Node.js
import bcrypt from 'bcrypt';
const COST_FACTOR = 12;
// Passwort hashen
async function hashPassword(plaintext) {
const hash = await bcrypt.hash(plaintext, COST_FACTOR);
return hash;
// "$2b$12$..." -- diesen String in Ihrer Datenbank speichern
}
// Passwort beim Login verifizieren
async function verifyPassword(plaintext, storedHash) {
const match = await bcrypt.compare(plaintext, storedHash);
return match; // true oder false
}
// Verwendungsbeispiel
const hash = await hashPassword('hunter2');
console.log(hash); // $2b$12$...
const valid = await verifyPassword('hunter2', hash);
console.log(valid); // true
const invalid = await verifyPassword('wrongpassword', hash);
console.log(invalid); // false
Python (mit bcrypt-Paket)
import bcrypt
COST_FACTOR = 12
def hash_password(plaintext: str) -> str:
"""Passwort hashen und bcrypt-Hash-String zurückgeben."""
password_bytes = plaintext.encode('utf-8')
salt = bcrypt.gensalt(rounds=COST_FACTOR)
hashed = bcrypt.hashpw(password_bytes, salt)
return hashed.decode('utf-8')
def verify_password(plaintext: str, stored_hash: str) -> bool:
"""Klartext-Passwort gegen gespeicherten bcrypt-Hash verifizieren."""
password_bytes = plaintext.encode('utf-8')
hash_bytes = stored_hash.encode('utf-8')
return bcrypt.checkpw(password_bytes, hash_bytes)
# Verwendung
hash_value = hash_password('hunter2')
print(hash_value) # $2b$12$...
print(verify_password('hunter2', hash_value)) # True
print(verify_password('wrongpassword', hash_value)) # False
PHP
<?php
// Passwort hashen
function hashPassword(string $plaintext): string {
return password_hash($plaintext, PASSWORD_BCRYPT, ['cost' => 12]);
}
// Passwort verifizieren
function verifyPassword(string $plaintext, string $storedHash): bool {
return password_verify($plaintext, $storedHash);
}
// Verwendung
$hash = hashPassword('hunter2');
echo $hash; // $2y$12$...
var_dump(verifyPassword('hunter2', $hash)); // bool(true)
var_dump(verifyPassword('wrongpassword', $hash)); // bool(false)
?>
Häufige Fehler und wie man sie vermeidet
Passwörter im Klartext oder mit reversibler Kodierung speichern
Base64 ist Kodierung, kein Hashing. base64("hunter2") ist aHVudGVyMg==. Jeder Angreifer, der das sieht, kann es in einer Zeile dekodieren.
Schnelle Hash-Funktionen für Passwörter verwenden
SHA-256, SHA-512, MD5, SHA-1 -- alle sind darauf ausgelegt, schnell zu sein. Schnelligkeit ist die falsche Eigenschaft für das Passwort-Hashing.
Das 72-Byte-Abschneideproblem
Die ursprüngliche Bcrypt-Spezifikation verarbeitet nur die ersten 72 Bytes der Eingabe. Die Standard-Gegenmaßnahme ist, die Eingabe zunächst mit SHA-256 zu hashen und dann den Hash mit bcrypt zu hashen:
import crypto from 'crypto';
import bcrypt from 'bcrypt';
async function hashLongPassword(plaintext) {
const prehashed = crypto
.createHash('sha256')
.update(plaintext)
.digest('base64');
return bcrypt.hash(prehashed, 12);
}
Bcrypt-Hashes testen
Unser Bcrypt Hash Generator ist nützlich für:
- Test-Hashes während der Entwicklung ohne Projektsetup generieren
- Verifizieren, dass Ihre Implementierung gültige Bcrypt-Ausgaben erzeugt
- Hash-zu-Passwort-Verifizierung in Ihrem Code schnell testen
Das Tool läuft vollständig in Ihrem Browser und sendet keine Daten an einen Server.
Bcrypt vs. Alternativen
| Algorithmus | Speicherintensiv | GPU-resistent | OWASP-Status | Hinweise |
|---|---|---|---|---|
| Bcrypt | Nein | Teilweise | Empfohlen | Bewährt, 72-Byte-Limit |
| Argon2id | Ja | Ja | Bevorzugt | PHC-Gewinner, neuer |
| scrypt | Ja | Ja | Akzeptabel | Speicherintensiv, komplexe Parameter |
| PBKDF2 | Nein | Nein | Akzeptabel | NIST-genehmigt, FIPS-konform |
| SHA-256 (einfach) | Nein | Nein | Nicht verwenden | Kein Passwort-Hash |
Fazit
Passwort-Hashing ist einer jener Bereiche, wo der Unterschied zwischen "funktioniert" und "funktioniert korrekt" sehr wichtig ist. Bcrypt bietet drei wichtige Dinge: absichtliche Langsamkeit, automatisches Salting und ein in sich geschlossenes Ausgabeformat.
Verwenden Sie Kostenfaktor 12 als Ausgangspunkt. Führen Sie Benchmarks auf Ihrer eigentlichen Hardware durch. Erhöhen Sie ihn, wenn Ihr Server deutlich schneller als 200ms hashen kann. Wenn Sie von Grund auf neu starten, werfen Sie einen Blick auf Argon2id.
Verwandte Tools und Ressourcen
- Bcrypt Hash Generator -- Bcrypt-Hashes im Browser generieren und verifizieren
- Password Generator -- Starke Zufallspasswörter generieren
- Password Strength Checker -- Passwortstärke bewerten
- Hash Generator -- MD5, SHA-1, SHA-256 und SHA-512 Hashes generieren
- Hash Functions Explained -- Tiefgehende Analyse von SHA-256, MD5 und kryptografischem Hashing