Files
sshkeyvault/docs/issues/006-geheimnisse-schluesselformat.md
T
florian.wildeandClaude Opus 5.5 6cdc49df49 docs: Stand und Entscheidungen zu #006 festhalten (#006)
Der framework-freie Kern ist fertig; Deployment-Key, Master-Key im Worker
und der Nachweis am Datenbank-Dump haengen an Datenbank und Worker und
kommen mit #007. Die Entscheidungen (16 bcrypt-Runden, Fehlercodes,
RSA-Mindestlaenge abschaltbar fuers Beobachten, Umschlag-Format,
Dateirechte des Master-Keys) stehen im Issue, damit die Anbindung nicht
raten muss.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 09:17:46 +02:00

3.6 KiB
Raw Blame History

#006 Verschlüsselte Ablage und OpenSSH-Schlüsselformat

Status: in Arbeit Meilenstein: v0.1.0 Labels: sicherheit Geschätzt: 4 h Tatsächlich: –

Ziel

Envelope Encryption für Private Keys mit Master-Key aus Datei; eigene Erzeugung und Serialisierung von OpenSSH-Schlüsseln ohne temporäre Dateien; Deployment-Key der Instanz.

Aufgaben

  • Master-Key aus Datei laden (32 Byte roh, Base64 oder Hex; Rechteprüfung) – masterKeyLaden
  • Master-Key aus SSHKV_MASTER_KEY_FILE nur im Worker anbinden
  • AES-256-GCM, DEK je Schlüssel, AAD = Schlüssel-ID + Fingerprint, Master-Key-Version
  • ed25519 und RSA-4096 erzeugen (Node crypto), OpenSSH-Format schreiben und lesen (optional Passphrase: bcrypt-pbkdf + aes256-ctr)
  • Fingerprint SHA256 wie ssh-keygen -l
  • Deployment-Key beim ersten Start erzeugen
  • Log-Redaction (schwaerzen; Einbau in Logger/Protokoll folgt)

Akzeptanzkriterien

  • ssh-keygen -y -f liest erzeugte Schlüssel (mit und ohne Passphrase)
  • Fingerprints identisch zu ssh-keygen -lf
  • Datenbank-Dump enthält keinen Klartext-Schlüssel

Abhängigkeiten

#003

Notizen / Entscheidungen

  • Kern fertig; Anbindung an Datenbank/Worker folgt mit #007. Offen sind Deployment-Key beim ersten Start, Master-Key nur im Worker laden und der Nachweis „Datenbank-Dump enthält keinen Klartext“.
  • Module: src/lib/ssh/openssh.ts (Erzeugen/Schreiben/Lesen, Fingerprint, Public-Key-Zeilen), src/lib/krypto/umschlag.ts (Envelope Encryption, Master-Key laden), src/lib/protokoll-schwaerzen.ts (Redaction). Alle framework-frei.
  • Eigener Serializer für openssh-key-v1 statt ssh-keygen: keine Private Keys als Temp-Dateien. Die Tests prüfen gegen das echte ssh-keygen (beide Richtungen, mit/ohne Passphrase).
  • Passphrase: aes256-ctr + bcrypt mit 16 Runden (ssh-keygen nimmt heute 24). bcrypt-pbkdf ist reines JavaScript; 16 Runden halten das im Worker unter einer Sekunde. Beim Lesen gilt die Rundenzahl aus der Datei (Obergrenze 1000 gegen absichtlich teure Importe). Andere Cipher (z. B. aes256-gcm@openssh.com via ssh-keygen -Z) werden mit klarer Meldung abgelehnt. Private-Key-Import nur für ed25519 und RSA.
  • SchluesselFormatFehler trägt einen code (ungueltig, nicht_unterstuetzt, passphrase_fehlt, passphrase_falsch, zu_schwach); Meldungen sind feste Sätze ohne Eingabe.
  • RSA-Mindestlänge 2048 Bit standardmäßig in publicKeyZeileLesen und privateKeyLesen; { rsaMindestBits: 0 } für das reine Beobachten vorhandener authorized_keys (Drift).
  • Kommentare mit Steuerzeichen werden abgelehnt, sonst ließe sich über einen Kommentar eine zweite Zeile in authorized_keys einschleusen.
  • Umschlag-Format je Puffer: Version (1) | IV (12) | Tag (16) | Daten. AAD Klartext = zusatz (vorgesehen: schluessel:<id>:<fingerprint>), AAD DEK = sshkv-dek:v<masterKeyVersion>. versiegeln(..., masterKeyVersion = 1); beim Öffnen muss der Aufrufer den Master-Key passend zur Version wählen.
  • Master-Key-Datei mit Gruppe/Welt-Leserecht → Abbruch, außer SSHKV_MASTER_KEY_UNSICHER_ERLAUBT=1 (dann Warnung). Achtung Docker: Secrets ohne Swarm sind Bind-Mounts mit den Rechten der Host-Datei – dort chmod 400 und passenden Eigentümer setzen.
  • Schwärzen greift auf Feldnamen, die einen der Wortstämme privat, passwort, password, passphrase, secret, geheimnis, token, masterkey, authorization, cookie enthalten (nicht nur als Präfix), sowie auf PEM-Private-Keys in jeder Zeichenkette (auch abgeschnitten, auch in message/stack von Fehlern). Rohe Bytes werden zu [Binärdaten].