Schluesselbund: ein Hauptschluessel, mehrfach verpackt (#190)
SecretKeyStore.Wrap band den Hauptschluessel unter Windows per DPAPI ans Benutzerkonto und gab ihn sonst ungewrappt zurueck - eine Zeile, die man beim Lesen ueberspringt und die auf dem Zielsystem "im Klartext" bedeutet. Dahinter steht jetzt ein SecretKeyRing: derselbe Hauptschluessel, mehrfach verpackt, je Fach ein ISecretProvider (dpapi, passphrase, file). Fuer Aufrufer aendert sich nichts - GetOrCreateKey gibt weiterhin 32 Byte zurueck. Genau dafuer war die Naht da. WARUM MEHRERE FAECHER UND NICHT EIN BESSERES Ein Schluessel an der Maschine ueberlebt keinen Umzug; einer an einer Passphrase verlangt bei jedem Start jemanden, der tippt - und Dauerbetrieb ohne Menschen ist der Zweck (#214). Der Bund entscheidet sich nicht: Im Alltag oeffnet das Maschinenfach ohne Rueckfrage, nach einem Umzug die Passphrase, und beide fuehren zu DEMSELBEN Schluessel. Alle enc:v2-Werte bleiben lesbar. Und deshalb darf die Schluesseldatei jetzt ueberhaupt in eine Sicherung: Sobald ein Wiederherstellungsfach da ist, steht der Hauptschluessel in keiner Fassung im Klartext darin. Nicht zu verwechseln mit der Sicherung mit Passphrase: Die schluesselt jeden WERT einzeln ins Archiv um, fuer den Transport einer Instanz. Das Wiederherstellungs- fach schluesselt den HAUPTSCHLUESSEL um, damit eine bestehende Installation weiterlaeuft - unbeaufsichtigt ueber CLAWD_SECRET_PASSPHRASE. Die Unterscheidung steht in docs/Roadmap.md bei #190. Beide Altformate werden uebernommen: 32 rohe Byte werden zum Fach file, ein DPAPI-Block zum Fach dpapi. Derselbe Schluessel, nur anders verpackt. Zwei Zusagen, mit Tests festgehalten: - Geht KEIN Fach auf, wird abgebrochen statt ein neuer Schluessel erzeugt. Ein neuer Hauptschluessel machte jeden bestehenden Wert wortlos unlesbar. - Ein Umzug legt den Schluessel NICHT im Klartext ab, nur damit der naechste Start bequemer wird. Beim automatischen Weg wird nur hinzugefuegt, nie weggenommen; weggenommen wird nur in SetRecoveryPassphrase, wo ein Mensch gerade getippt hat. #190 bleibt offen: Unter Linux greift weiterhin das Fach file. Neu ist, dass es beim Start als Warnung im Protokoll steht statt unsichtbar zu sein. Womit das Maschinenfach dort gefuellt wird, ist Entscheidung #180 - diese Schnittstelle ist die Stelle, an der die Antwort eingesetzt wird. 834 Tests gruen, 0 Warnungen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -373,6 +373,41 @@ Steht vor #190, weil die Antwort das Backend bestimmt, das dort gebaut wird.
|
||||
|
||||
### [SEC] #190 — L1: Der Hauptschlüssel liegt unter Linux im Klartext
|
||||
|
||||
> **Stand 2026-09-10: Die Naht ist gebaut, die Linux-Antwort steht noch aus.**
|
||||
>
|
||||
> `SecretKeyStore` hält nicht mehr einen verpackten Schlüssel, sondern einen
|
||||
> **Schlüsselbund** (`SecretKeyRing`): denselben Hauptschlüssel, mehrfach verpackt.
|
||||
> Jedes Fach gehört einem `ISecretProvider` — `dpapi` (Windows), `passphrase`
|
||||
> (Wiederherstellung), `file` (nur Dateirechte, der Zustand *dieses* Befunds, jetzt
|
||||
> beim Namen genannt).
|
||||
>
|
||||
> **Warum mehrere Fächer und nicht ein besseres.** Ein Schlüssel an der Maschine
|
||||
> überlebt keinen Umzug; einer an einer Passphrase verlangt bei jedem Start jemanden,
|
||||
> der tippt — und der Dauerbetrieb ohne Menschen ist der Zweck (#214). Der Bund
|
||||
> entscheidet sich nicht: Im Alltag öffnet das Maschinenfach ohne Rückfrage, nach
|
||||
> einem Umzug die Passphrase, und beide führen zu **demselben** Schlüssel. Alle
|
||||
> `enc:v2`-Werte bleiben lesbar, nichts muss neu eingetragen werden.
|
||||
>
|
||||
> **Zwei Wege, die sich ähneln und nicht dasselbe sind** — das ist die Stelle, an der
|
||||
> man beim Lesen falsch abbiegt:
|
||||
>
|
||||
> | | Sicherung mit Passphrase (`BackupService`) | Wiederherstellungsfach (`SecretKeyRing`) |
|
||||
> |---|---|---|
|
||||
> | Was umgeschlüsselt wird | jeder **Wert** einzeln, in das Archiv hinein | der **Hauptschlüssel**, in der Schlüsseldatei |
|
||||
> | Wofür | eine Instanz auf eine andere Maschine bringen | eine bestehende Installation weiterbenutzen, wenn das Maschinenfach nicht mehr aufgeht |
|
||||
> | Wann entschieden | beim Ziehen der Sicherung | einmal, vorher |
|
||||
> | Ohne Menschen | nein, die Passphrase gehört zur Sicherung | ja, über `CLAWD_SECRET_PASSPHRASE` |
|
||||
>
|
||||
> **Was noch fehlt, ist genau #180:** Womit das Maschinenfach unter Linux gefüllt wird.
|
||||
> Bis dahin greift dort `file` — dieselbe Schutzstufe wie vorher, aber sie steht jetzt
|
||||
> als Warnung im Protokoll und in `SecretKeyStore.Problems`, statt eine stille Zeile
|
||||
> `: key` zu sein. Der Befund bleibt deshalb offen.
|
||||
>
|
||||
> Zwei Zusagen sind mit Tests festgehalten: Geht **kein** Fach auf, wird abgebrochen
|
||||
> statt ein neuer Schlüssel erzeugt (der machte jeden bestehenden Wert wortlos
|
||||
> unlesbar). Und ein Umzug legt den Schlüssel **nicht** im Klartext ab, nur damit der
|
||||
> nächste Start bequemer wird.
|
||||
|
||||
`SecretKeyStore.Wrap` bindet den Schlüssel unter Windows per DPAPI ans Benutzerkonto
|
||||
und gibt ihn sonst ungewrappt zurück; der einzige Schutz ist dann `0600` aus
|
||||
`AppPaths.RestrictToOwner`. Auf einer dauerhaft laufenden, netzgebundenen Maschine ist
|
||||
|
||||
Reference in New Issue
Block a user