# Key rotation How an identity changes its key without losing the trust built around the old one — and why two objects are needed to do it honestly. Wire objects: `KeyRotationRequest` (tag `0x08`) and `KeyRotationConfirm` (tag `0x09`), PROTOCOL.md §8.8–8.9. --- ## 1. Why two objects A rotation needs evidence that **both** keys agreed: - The **successor** signs a request: "I succeed predecessor." Alone it is worthless — anyone can name any predecessor, including a victim's. - The **predecessor** signs a confirm bound to that exact request by content ID (`rotation_hash = SHA-256(request TCE)`, the INV-4 pattern). Alone it is unintelligible. Together they are cryptographic evidence of mutual consent. A stolen predecessor key can still rotate silently — cryptography cannot detect theft — but it can never *point* the identity at a key whose owner never consented, and the freshness bound below caps how long a silent thief keeps working. ## 2. Wire rules - The request lives at most **60 seconds**, the same format bound as approval requests. Rotation intent is short-lived; long-horizon freshness is policy, not wire. - The confirm must sit inside the request window with the usual ±120 s skew allowance, exactly like an approval response. - One relay stores at most one confirm per request; competing confirms make a link unusable rather than letting a verifier pick a winner. ## 3. Resolution With `Policy.TrustedIssuers` set and a claim's issuer not a root, the verifier walks confirmed successions backwards: ``` trusted root (old) ◀──confirm── new ◀──confirm── newer ──claim──▶ subject ``` - Every link must fully verify: both signatures plus the hash binding, checked against stored bytes via `VerifyKeyRotationConfirm`. - Hops are bounded by `Policy.MaxDepth` (default for rotations: 4). - **Freshness**: with `Policy.RotationMaxAge > 0`, a link's confirm must be no older than that many seconds at the evaluation instant. Zero disables the check — history stays valid forever, which suits long-lived roots whose rotation ceremony was audited once. - The accepted result reports the path in `Result.RotationChain` (`issuer → … → root`) as audit evidence. Rotation composes independently of delegation: an issuer may reach a trusted root either by being granted voice or by *being* the root's newer key. If both paths exist, delegation wins as the more specific statement; both chains are reported when applicable. ## 4. What rotation does not mean - It does not transfer revocations: claims signed by the old key keep their own lifecycle; only the *authority to be believed going forward* moves. - It does not heal compromise retroactively: anything signed before the confirm stands as signed.