Firefox-Passwörter entschlüsseln: NSS, key4.db und logins.json
2026-06-17 · 3 min
Chrome stützt sich auf den Schlüsselspeicher des Betriebssystems — DPAPI unter Windows, den Keychain unter macOS. Firefox geht seinen eigenen Weg: gespeicherte Passwörter werden durch NSS (Network Security Services) geschützt, dieselbe Krypto-Bibliothek, die Firefox auch für TLS verwendet. Nichts ist an Ihr Windows-Konto gebunden, was Firefox-Passwörter offline besser wiederherstellbar macht als die von Chrome — Sie brauchen nur zwei Dateien und (manchmal) das Master-Passwort.
Die zwei Dateien
| Datei | Inhalt | Format |
|---|---|---|
logins.json | die verschlüsselten Benutzernamen & Passwörter | JSON |
key4.db | der Schlüssel, der sie entschlüsselt | SQLite |
Beide liegen im Profilstamm (siehe Speicherorte der
Firefox-Dateien). Cookies sind eine
eigene Geschichte — cookies.sqlite liegt im Klartext und braucht überhaupt
keinen Schlüssel (anders als Chrome-Cookies).
logins.json ist ein Array von Einträgen:
{
"logins": [
{
"hostname": "https://example.com",
"encryptedUsername": "MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECC4...",
"encryptedPassword": "MEIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECF...",
"timeCreated": 1700000000000,
"timeLastUsed": 1701234567890
}
]
}
Jeder encrypted*-Wert ist Base64 einer ASN.1-Struktur: eine Schlüssel-ID,
eine Chiffre + IV und der Chiffretext. Die Chiffre für die Einträge selbst ist
immer 3DES-CBC — der Schlüssel dazu stammt aber aus key4.db.
Im Inneren von key4.db
key4.db (SQLite; es löste etwa 2018 die alte Berkeley-DB-key3.db ab) hat
zwei relevante Tabellen:
metadata— die Zeileid = 'password'trägtitem1(das globale Salt) unditem2(ein password-check-Blob).nssPrivate— die Zeile, derena102der bekannten IDf8000000000000000000000000000001entspricht, trägta11, den verschlüsselten Schlüssel.
item2 und a11 sind beide auf dieselbe Weise gekapselt, durch einen
Schlüssel, der aus dem globalen Salt und Ihrem Master-Passwort (standardmäßig
leer) abgeleitet wird. Welche Kapselung verwendet wird, gibt der Algorithmus-OID
in der ASN.1-Struktur an:
| OID | Schema |
|---|---|
1.2.840.113549.1.12.5.1.3 | pbeWithSha1And3KeyTripleDES-CBC (Legacy 3DES) |
1.2.840.113549.1.5.13 | PBES2 → PBKDF2-HMAC-SHA256 + AES-256-CBC (modern) |
Schlüsselableitung
Legacy 3DES PBE. Eine SHA-1/HMAC-SHA1-Kaskade über die Salts:
hp = SHA1(globalSalt || primaryPassword)
chp = SHA1(hp || entrySalt)
k1 = HMAC-SHA1(chp, pes || entrySalt) # pes = entrySalt padded to 20 bytes
tk = HMAC-SHA1(chp, pes)
k2 = HMAC-SHA1(chp, tk || entrySalt)
k = k1 || k2 ; key = k[:24] ; iv = k[-8:]
Modernes PBES2. Sauberer und heute der Regelfall:
k = SHA1(globalSalt || primaryPassword)
key = PBKDF2-HMAC-SHA256(k, entrySalt, iterations, 32)
iv = 0x04 0x0e || <14-byte stored IV> # an NSS quirk: real IV is 16 bytes
So oder so fließt das Master-Passwort nur über das erste
SHA1(globalSalt || password) ein. Kein Passwort gesetzt → das Passwort ist
die leere Zeichenkette, und alles entschlüsselt sich ganz ohne Geheimnis.
Die Selbstprüfung, die es vertrauenswürdig macht
Sie müssen nie raten, ob die Ableitung funktioniert hat. Entschlüsseln Sie
item2, und der Klartext muss exakt lauten:
password-check\x02\x02
(die literale Zeichenkette password-check plus ihre zwei
PKCS#7-Padding-Bytes). Stimmt das überein, sind das Master-Passwort und die
gesamte Ableitung korrekt — ein falsches Passwort scheitert also lautstark,
statt stillschweigend Müll zu erzeugen. Das ist dieselbe
"Entschlüsselung-beweist-sich-selbst"-Eigenschaft wie beim
DPAPI-Masterkey-HMAC.
Nach erfolgter Prüfung entschlüsseln Sie a11, um den 24-Byte-3DES-Schlüssel
wiederherzustellen, und entschlüsseln dann jeden logins.json-Eintrag damit
(3DES-CBC, PKCS#7 entfernen), um den Klartext-Benutzernamen und das
-Passwort zu erhalten.
Warum es in einem Browser-Tab läuft
Die gesamte Kette besteht aus SHA-1, HMAC-SHA1, PBKDF2, 3DES und AES — keine
Betriebssystemaufrufe, kein Schlüsselspeicher. Das macht sie zu einem sauberen
Kandidaten für ein WebAssembly-Modul: Unser Entschlüsseler ist ein kleines
Rust-Crate (RustCrypto + ein winziger ASN.1-Reader), zu WASM kompiliert. Die
Seite liest key4.db und logins.json, übergibt die rohen Blobs an das WASM
und zeigt die entschlüsselten Anmeldedaten — ohne dass etwas hochgeladen wird.
Legen Sie beide Dateien in den
In-Browser-Parser, geben
Sie das Master-Passwort ein (oder lassen Sie es leer) und entschlüsseln Sie.
Fallstricke
- Master-Passwort. Hat der Benutzer eines gesetzt und Sie haben es nicht,
scheitert die
password-check, und es gibt keine Abkürzung — es schützt alles. - key3.db. Sehr alte Profile verwenden die Berkeley-DB-
key3.dbstattkey4.db; das Schema ist ähnlich, aber der Container unterscheidet sich. - Vergessen Sie die Salt-Quelle nicht. Das globale Salt steht in
key4.db, nicht inlogins.json— Sie brauchen jedes Mal beide Dateien.