ToolPal
Ein Vorhängeschloss auf einer Laptop-Tastatur als Symbol für digitale Sicherheit und Passwortschutz.

Bcrypt-Passwort-Hashing: Warum es wichtig ist und wie man es verwendet

📷 Pixabay / Pexels

Bcrypt-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.

7. April 20267 Min. Lesezeit

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.

KostenfaktorIterationenUngefähre Zeit (typischer Server)
101.024~65ms
112.048~130ms
124.096~250ms
138.192~500ms
1416.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

AlgorithmusSpeicherintensivGPU-resistentOWASP-StatusHinweise
BcryptNeinTeilweiseEmpfohlenBewährt, 72-Byte-Limit
Argon2idJaJaBevorzugtPHC-Gewinner, neuer
scryptJaJaAkzeptabelSpeicherintensiv, komplexe Parameter
PBKDF2NeinNeinAkzeptabelNIST-genehmigt, FIPS-konform
SHA-256 (einfach)NeinNeinNicht verwendenKein 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

Häufig gestellte Fragen

Artikel teilen

XLinkedIn

Verwandte Beiträge