Kryptografische Algorithmen
Passwork verwendet unterschiedliche kryptografische Algorithmen auf dem Server und dem Client.
Algorithmenübersicht
| Zweck | Algorithmus | Einsatzort |
|---|---|---|
| Schlüsselableitung aus Passwort | PBKDF2 | Masterschlüssel-Generierung |
| Symmetrische Verschlüsselung (Server) | AES-256-CFB | Server-seitige Datenbankverschlüsselung |
| Symmetrische Verschlüsselung (Client) | CryptoJS AES-256-CBC | Alle Client-Daten |
| Asymmetrische Verschlüsselung | RSA-OAEP | Schlüsselaustausch |
| Hashing | SHA-256, SHA-512 | Passwortüberprüfung, Integrität |
| Zufallszahlengenerierung | WebCrypto API | Schlüsselgenerierung, IV, Salt |
PBKDF2 (Password-Based Key Derivation Function 2)
PBKDF2 wird verwendet, um einen kryptografischen Schlüssel aus dem Masterpasswort des Benutzers abzuleiten.
Client-Parameter
| Parameter | Wert |
|---|---|
| Algorithmus | PBKDF2 |
| Hashfunktion | SHA-256 |
| Iterationen | 300.000 |
| Ausgabeschlüssellänge | 512 Bit |
| Salt | 20 Zeichen, einzigartig pro Benutzer |
| Bibliothek | pbkdf2 (npm) |
Server-Parameter
| Parameter | Wert |
|---|---|
| Algorithmus | PBKDF2 |
| Hashfunktion | SHA-512 |
| Iterationen | 600.000 |
| Ausgabeschlüssellänge | 512 Bit |
| Bibliothek | PHP hash_pbkdf2() |
SHA-256 mit 300.000 Iterationen wird auf dem Client verwendet, um ein Gleichgewicht zwischen Sicherheit und Browser-Performance zu gewährleisten. Strengere Parameter (SHA-512, 600.000 Iterationen) werden auf dem Server für das Authentifizierungspasswort-Hashing angewendet.
Salt
| Parameter | Wert |
|---|---|
| Länge | 20 Zeichen |
| Alphabet | A-Z, a-z, 0-9, @, ! (64 Zeichen) |
| Entropie | ~120 Bit |
| Generierung | Server, kryptografisch sicher |
| Speicherung | Server, im Benutzerprofil |
| Einzigartigkeit | Einzigartig pro Benutzer |
Das Salt wird immer auf dem Server generiert und an den Client übermittelt. Der Client generiert kein Salt eigenständig, wodurch die Verwendung eines kryptografisch sicheren Generators sichergestellt wird.
Ergebnisformat
Das PBKDF2-Ergebnis auf dem Client wird als Zeichenfolge kodiert:
pbkdf:sha256:300000:64:{salt}
Zweck der hohen Iterationsanzahl
Eine hohe Iterationsanzahl (300.000+) verlangsamt Brute-Force-Angriffe erheblich:
- Jeder Versuch benötigt erhebliche Zeit
- Paralleles GPU-Brute-Forcing wird erschwert
- Vorberechnete Tabellen sind aufgrund des einzigartigen Salts unmöglich
Automatische Hash-Migration
Das System unterstützt die automatische Migration von PBKDF2-Hashes bei Parameteränderungen.
Server-Hash-Format:
pbkdf:{base64_hash}:{algorithm}:{iterations}:{length}:{salt}
Beispiel: pbkdf:Abc123...==:sha512:600000:64:xY3zKmN9qR2w...
Migrationsmechanismus:
- Benutzer meldet sich am System an
- System prüft die vorhandenen Hash-Parameter
- Falls die Parameter von den aktuellen Einstellungen abweichen → Neuhashing erforderlich
- Das Passwort wird automatisch mit neuen Parametern gehasht
- Der neue Hash wird in der Datenbank gespeichert
Was aktualisiert werden kann:
| Parameter | Aktueller Wert | Beispiel neuer Werte |
|---|---|---|
| Hash-Algorithmus | SHA-512 | SHA3-512, BLAKE2b512 |
| Iterationsanzahl | 600.000 | 1.000.000, 2.000.000 |
| Schlüssellänge | 512 Bit | 256, 1024 Bit |
Bei Parameteraktualisierungen:
- Neue Benutzer → erhalten sofort Hashes mit neuen Parametern
- Bestehende Benutzer → Migration erfolgt bei der nächsten Anmeldung
- Benutzer ohne Anmeldung → alte Hashes funktionieren weiterhin
Die Migration ist für Benutzer transparent — sie geben einfach ihr Passwort wie gewohnt ein.
AES (Advanced Encryption Standard)
Passwork verwendet unterschiedliche AES-Modi auf Server und Client.
Server-Verschlüsselung: AES-256-CFB
AES-256 im CFB-Modus (Cipher Feedback) über OpenSSL wird auf dem Server verwendet.
| Parameter | Wert |
|---|---|
| Algorithmus | AES-256-CFB |
| Schlüssellänge | 256 Bit |
| Blockgröße | 128 Bit |
| Initialisierungsvektor (IV) | 128 Bit, zufällig pro Verschlüsselung |
| Bibliothek | OpenSSL (über PHP) |
Eigenschaften des CFB-Modus:
- Stromchiffre-Modus
- Kein Padding erforderlich
- IV wird zusammen mit dem Chiffretext gespeichert
Verwendung: Verschlüsselung von Daten in der Datenbank (externe Links, Einstellungen, LDAP/SMTP-Passwörter).
Server-IV-Generierung:
| Parameter | Wert |
|---|---|
| Länge | 128 Bit |
| Generator | Kryptografisch sicher (OS CSPRNG) |
| Einzigartigkeit | Neuer IV für jede Verschlüsselungsoperation |
| Speicherung | Am Anfang der verschlüsselten Daten |
Struktur der verschlüsselten Daten: [128 Bit IV][Chiffretext]
Client-Verschlüsselung: CryptoJS AES-256-CBC
Die CryptoJS-Bibliothek wird auf dem Client für alle symmetrischen Verschlüsselungsoperationen verwendet.
| Parameter | Wert |
|---|---|
| Bibliothek | CryptoJS |
| Modus | CBC (Cipher Block Chaining) |
| Schlüssellänge | 256 Bit |
| Padding | PKCS#7 |
| IV | Automatisch (128 Bit) |
| KDF | Integrierte Schlüsselableitungsfunktion |
| Ausgabekodierung | Base32 |
Schlüsseltransformation zu AES-256:
Symmetrische Schlüssel in Passwork sind 100 Zeichen (~596 Bit Entropie), aber AES-256 benötigt exakt einen 256-Bit-Schlüssel. CryptoJS führt die Transformation automatisch über eine Schlüsselableitungsfunktion (KDF) durch:
- Ein zufälliges 64-Bit-Salt wird generiert
- Der ursprüngliche 100-Zeichen-Schlüssel wird in einen 256-Bit-AES-Schlüssel umgewandelt
- Das Salt wird zusammen mit dem Chiffretext zur Entschlüsselung gespeichert
Die Eingabe von 596 Bit garantiert maximale Stärke des 256-Bit-Ausgabeschlüssels. Dies gewährleistet auch Vereinheitlichung — alle symmetrischen Schlüssel (Tresor, Eintrag, Anhang) werden identisch generiert.
Client-IV-Generierung:
CryptoJS generiert automatisch einen IV für jede Verschlüsselung:
| Parameter | Wert |
|---|---|
| Länge | 128 Bit |
| Generator | window.crypto.getRandomValues() |
| Einzigartigkeit | Neuer IV für jede Verschlüsselungsoperation |
| Speicherformat | Im OpenSSL-kompatiblen Format enthalten |
CryptoJS-Ausgabeformat: "Salted__" + [64 Bit Salt] + [Chiffretext mit IV] → Base64
Warum unterschiedliche Modi?
| Kriterium | Server (CFB) | Client (CBC) |
|---|---|---|
| Bibliothek | OpenSSL | CryptoJS |
| Auswahlgrund | PHP-Standard | Abwärtskompatibilität |
| Vorteile | Strommodus | Breite Unterstützung |
CryptoJS vs. WebCrypto API
Die CryptoJS-Bibliothek wird für die symmetrische Verschlüsselung auf dem Client verwendet, nicht die native WebCrypto API. Hier ein Vergleich.
Vergleich:
| Aspekt | CryptoJS | WebCrypto API |
|---|---|---|
| Implementierung | Reines JavaScript | Nativer Browser-Code |
| Performance | Langsamer | Deutlich schneller |
| Schutz vor Timing-Angriffen | Keine Garantien | Schutz auf Implementierungsebene |
| Speicherverwaltung | Schlüssel im JS-Heap | Schlüssel können nicht-extrahierbar sein |
| API | Synchron | Asynchron (Promise) |
| Kompatibilität | Jede JS-Umgebung | Nur moderne Browser |
Warum CryptoJS verwendet wird:
- Abwärtskompatibilität — vorhandene verschlüsselte Daten verwenden das CryptoJS-Format
- Synchrone API — einfachere Integration mit bestehendem Codebase
- Universalität — funktioniert in jeder JavaScript-Umgebung
Sicherheitsmaßnahmen in der aktuellen Implementierung:
- PBKDF2 über separate Bibliothek — Masterschlüssel wird über kryptografisch starkes PBKDF2 abgeleitet
- WebCrypto für RSA — kritische asymmetrische Operationen werden über die native API durchgeführt
- Kryptografisch sichere IV-Generierung — über
crypto.getRandomValues(), nichtMath.random() - Daten werden einmal verschlüsselt — Timing-Angriffe erfordern mehrere Operationen mit demselben Schlüssel
Risikobewertung:
| Bedrohung | Risikostufe | Begründung |
|---|---|---|
| Timing-Angriffe | Niedrig | Erfordert lokalen Browser-Zugriff |
| Speicher-Exposition | Niedrig | Mit solchem Zugriff ist es einfacher, das Passwort bei der Eingabe abzufangen |
| Bekannte CVE | Minimal | Die verwendete CryptoJS-Version hat keine kritischen Schwachstellen |
Zukünftige Versionen planen den schrittweisen Übergang zur WebCrypto API für symmetrische Verschlüsselung. Dies wird ermöglichen:
- Verwendung von AES-GCM (authentifizierte Verschlüsselung) anstelle von AES-CBC
- 10-100-fache Performance-Verbesserung
- Schlüsselschutz auf Browser-Ebene
Die Migration wird mit Abwärtskompatibilität für vorhandene Daten durchgeführt.
RSA (Rivest–Shamir–Adleman)
RSA wird für asymmetrische Verschlüsselung verwendet — sicherer Austausch symmetrischer Schlüssel zwischen Benutzern.
Parameter
| Parameter | Wert |
|---|---|
| Algorithmus | RSA-OAEP |
| Moduluslänge | 2048 Bit |
| Öffentlicher Exponent | 65537 (0x010001) |
| Hashfunktion | SHA-256 |
| Bibliothek | WebCrypto API (crypto.subtle) |
Schlüsselgenerierung
RSA-Schlüssel werden auf dem Client mit der WebCrypto API generiert:
crypto.subtle.generateKey({
name: 'RSA-OAEP',
modulusLength: 2048,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: 'SHA-256'
}, true, ['encrypt', 'decrypt'])
Speicherformate
| Schlüssel | Format | Beschreibung |
|---|---|---|
| Öffentlich | SPKI (PEM) | SubjectPublicKeyInfo |
| Privat | PKCS#8 (PEM) | Verschlüsselt mit Masterschlüssel |
Unterstützte Formate
Das System unterstützt den Schlüsselimport in folgenden Formaten:
- PKCS#1 —
-----BEGIN RSA PRIVATE KEY----- - PKCS#8 —
-----BEGIN PRIVATE KEY----- - SPKI —
-----BEGIN PUBLIC KEY----- - JWK — JSON Web Key (zur Konvertierung)
Abwärtskompatibilität
Für ältere 1024-Bit-Schlüssel wird ein JSEncrypt-Bibliotheks-Fallback verwendet, da die WebCrypto API RSA-1024 nicht unterstützt.
Warum RSA-2048?
| Aspekt | Beschreibung |
|---|---|
| Sicherheit | Äquivalent zu 112 Bit symmetrischer Verschlüsselung |
| Performance | Akzeptable Geschwindigkeit im Browser |
| Kompatibilität | Breite Unterstützung in allen Browsern |
Hashing
SHA-256
| Parameter | Wert |
|---|---|
| Hash-Länge | 256 Bit |
| Bibliothek (Client) | js-sha256 |
| Verwendung | Masterschlüssel-Hash, PBKDF2, RSA-OAEP |
SHA-512
| Parameter | Wert |
|---|---|
| Hash-Länge | 512 Bit |
| Bibliothek (Client) | js-sha512 |
| Bibliothek (Server) | PHP hash() |
| Verwendung | Server-PBKDF2, Serverschlüssel-Hash, Suchindizes |
Zufallszahlengenerierung
Alle kryptografischen Parameter werden mit kryptografisch sicheren Zufallszahlengeneratoren (CSPRNG) generiert.
Entropiequellen
Server (PHP)
| Generator | Entropiequelle | Verwendung |
|---|---|---|
random_bytes() | OS CSPRNG | Binärdaten (Schlüssel, Token) |
random_int() | OS CSPRNG | Zeichenfolgen (Salts, Codes) |
OS-Entropiequellen:
- Linux:
/dev/urandom,getrandom()-Systemaufruf - Windows:
CryptGenRandom()(CryptoAPI) - macOS:
arc4random_buf()
Client (JavaScript)
| Generator | Entropiequelle | Verwendung |
|---|---|---|
window.crypto.getRandomValues() | Browser/OS CSPRNG | Zahlen, Arrays |
CryptoJS.lib.WordArray.random() | crypto.getRandomValues() | IV für AES |
Browser-Entropiequellen:
- Chromium/Electron: BoringSSL CSPRNG
- Firefox: NSS (Network Security Services)
- Safari: CommonCrypto (Apple)
Kryptografische Stärkegarantien
| Eigenschaft | Garantie |
|---|---|
| Unvorhersagbarkeit | Nächster Wert nicht vorhersagbar |
| Gleichverteilung | Alle Werte gleich wahrscheinlich |
| Unverzerrt | Rejection Sampling wird verwendet |
| Verfügbarkeit | Generatoren blockieren nicht |
Generierte Schlüssel und Token
| Was generiert wird | Länge | Alphabet | Entropie |
|---|---|---|---|
| Symmetrische Schlüssel | |||
| Tresorschlüssel | 100 Zeichen | A-Z, a-z, 0-9, @, ! | ~596 Bit |
| Eintragschlüssel | 100 Zeichen | A-Z, a-z, 0-9, @, ! | ~596 Bit |
| Anhangsschlüssel | 100 Zeichen | A-Z, a-z, 0-9, @, ! | ~596 Bit |
| Link-Schlüssel | 100 Zeichen → 256 Bit | A-Z, a-z, 0-9, @, ! | ~596 Bit Eingabe |
| Serververschlüsselungsschlüssel | 256 Bit | Binär | 256 Bit |
| Salts | |||
| PBKDF2-Salt | 20 Zeichen | A-Z, a-z, 0-9, @, ! | ~120 Bit |
| Tresor-Salt | 32 Zeichen | A-Z, a-z, 0-9, @, ! | ~190 Bit |
| Token und Geheimnisse | |||
| Secret Code (localStorage) | 100 Zeichen | A-Z, a-z, 0-9 | ~596 Bit |
| Extension Secret | 60 Zeichen | A-Z, a-z, 0-9 | ~357 Bit |
| Auth Token (Erweiterung) | 400 Bit | Hex | 400 Bit |
| Externer Link-Token | 43 Zeichen | A-Z, a-z, 0-9 | ~256 Bit |
| Sitzungstoken | |||
| Access Token | 256 Bit | Base64 | 256 Bit |
| Refresh Token | 256 Bit | Base64 | 256 Bit |
| Initialisierungsvektoren | |||
| IV (Server, AES-CFB) | 128 Bit | Binär | 128 Bit |
| IV (Client, AES-CBC) | 128 Bit | Binär | 128 Bit |
Token-Einzigartigkeitsüberprüfung
Für Token, die garantierte Einzigartigkeit erfordern (Link-Token, Einladungscodes), wird eine Datenbankprüfung durchgeführt:
- Zufälliges Token wird generiert
- Einzigartigkeit wird in der Datenbank geprüft
- Bei Kollision — Neugenerierung
- Garantiert einzigartiges Token wird zurückgegeben
Kollisionswahrscheinlichkeit:
- 43 Zeichen aus 62: ~10^77 Kombinationen
- Bei einer Milliarde Token: Kollisionswahrscheinlichkeit ≈ 10^-59
- Praktisch unmöglich
Kryptografische Bibliotheken
Client (JavaScript/TypeScript)
| Bibliothek | Zweck |
|---|---|
| WebCrypto API | RSA-Operationen, Zufallszahlen |
| CryptoJS | AES-Verschlüsselung (alle Daten) |
| js-sha256 | SHA-256-Hashing |
| js-sha512 | SHA-512-Hashing |
| pbkdf2 | PBKDF2-Schlüsselableitung |
| node-jsencrypt | RSA-Fallback (1024 Bit) |
| pem-jwk | PEM ↔ JWK-Konvertierung |
| totp-generator | TOTP-Code-Generierung |
Server (PHP)
| Komponente | Zweck |
|---|---|
| OpenSSL | AES-256-CFB-Verschlüsselung |
| hash() | SHA-256, SHA-512-Hashing |
| hash_pbkdf2() | PBKDF2-Schlüsselableitung |
| random_bytes() | Zufallsdatengenerierung |
Vergleich mit Industriestandards
| Parameter | Passwork | NIST-Empfehlungen (2024) | Status |
|---|---|---|---|
| Symmetrische Verschlüsselung | AES-256 | AES-128/192/256 | ✓ |
| Asymmetrische Verschlüsselung | RSA-2048 | RSA-2048+ | ✓ |
| Hashing | SHA-256/512 | SHA-2-Familie | ✓ |
| PBKDF2-Iterationen | 300K/600K | ≥310K (SHA-256) | ✓ |
| Zufallszahlengenerator | CSPRNG | CSPRNG | ✓ |