Rotation Chain
Immutable audit trail for key lifecycle events.
Overview
Section titled “Overview”The Rotation Chain is an append-only log that records every key rotation, revocation, and recovery event. It provides:
- Auditability — Complete history of key changes
- Verifiability — Third parties can validate the chain
- Continuity — Proves identity through key transitions
- Non-repudiation — Actions are cryptographically signed
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐│ Entry 1 │───▶│ Entry 2 │───▶│ Entry 3 │───▶│ Entry 4 ││ │ │ │ │ │ │ ││ OK₁ gen │ │ OK₁→OK₂ │ │ OK₂ rev │ │ OK₃ gen │└─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │ │ │ └──────────────┴──────────────┴──────────────┘ │ RIK signaturesEntry Types
Section titled “Entry Types”Key Generation
Section titled “Key Generation”Records the creation of a new key.
{ "sequence": 1, "type": "key_generation", "timestamp": "2026-01-15T00:00:00Z", "keyId": "ok-001", "keyType": "Ed25519", "publicKey": "z6Nk...", "purposes": ["authentication", "signing"], "validFrom": "2026-01-15T00:00:00Z", "validUntil": "2026-02-15T00:00:00Z", "rikSignature": "..."}Key Rotation
Section titled “Key Rotation”Records the transition from one key to another.
{ "sequence": 2, "type": "key_rotation", "timestamp": "2026-02-01T00:00:00Z", "oldKeyId": "ok-001", "newKeyId": "ok-002", "reason": "scheduled", "previousEntryHash": "sha256:...", "rikSignature": "..."}Rotation Reasons:
| Reason | Description |
|---|---|
scheduled | Regular rotation per policy |
compromise_suspected | Precautionary rotation |
compromise_confirmed | Emergency rotation |
upgrade | Algorithm/protocol upgrade |
manual | Operator-initiated |
Key Revocation
Section titled “Key Revocation”Records the invalidation of a key before expiry.
{ "sequence": 3, "type": "key_revocation", "timestamp": "2026-02-03T12:00:00Z", "keyId": "ok-002", "reason": "compromise_confirmed", "effectiveImmediately": true, "previousEntryHash": "sha256:...", "rikSignature": "..."}RIK Rotation
Section titled “RIK Rotation”Records the rare event of rotating the Root Identity Key.
{ "sequence": 10, "type": "rik_rotation", "timestamp": "2026-06-01T00:00:00Z", "oldRikId": "rik-001", "oldRikDid": "did:key:z6MkOLD...", "newRikId": "rik-002", "newRikDid": "did:key:z6MkNEW...", "reason": "scheduled", "continuityProof": { "type": "dual_signature", "oldRikSignature": "...", "newRikSignature": "..." }, "previousEntryHash": "sha256:..."}Recovery Event
Section titled “Recovery Event”Records identity recovery using the Recovery Key.
{ "sequence": 11, "type": "recovery", "timestamp": "2026-07-15T00:00:00Z", "recoveryType": "rik_restoration", "newRikId": "rik-003", "newRikDid": "did:key:z6MkREC...", "authorizingShards": 2, "totalShards": 3, "previousEntryHash": "sha256:...", "rkSignature": "..."}Chain Structure
Section titled “Chain Structure”Hash Linking
Section titled “Hash Linking”Each entry includes a hash of the previous entry, forming an immutable chain:
Entry 1├── data: {...}├── hash: H1 = sha256(data)└── rikSignature: sign(RIK, H1)
Entry 2├── data: {..., previousEntryHash: H1}├── hash: H2 = sha256(data)└── rikSignature: sign(RIK, H2)
Entry 3├── data: {..., previousEntryHash: H2}├── hash: H3 = sha256(data)└── rikSignature: sign(RIK, H3)Full Chain Format
Section titled “Full Chain Format”{ "format": "SAP/RotationChain", "version": 1, "chainId": "sha256:...", "rootRik": "did:key:z6Mk...", "created": "2026-01-15T00:00:00Z", "entries": [ { "sequence": 1, "type": "key_generation", ... }, { "sequence": 2, "type": "key_rotation", ... }, { "sequence": 3, "type": "key_revocation", ... } ], "tip": { "sequence": 3, "hash": "sha256:...", "timestamp": "2026-02-03T12:00:00Z" }}Verification Process
Section titled “Verification Process”Full Chain Verification
Section titled “Full Chain Verification”1. Parse chain structure │ ▼2. Verify genesis entry (sequence 1) │ ▼3. For each subsequent entry: ├── Verify sequence is sequential ├── Verify previousEntryHash matches ├── Verify timestamp is monotonic └── Verify RIK signature │ ▼4. Verify tip matches last entry │ ▼5. Return validation resultIncremental Verification
Section titled “Incremental Verification”When you have a previously verified chain tip:
1. Compare stored tip hash with received │ ├── Match → Chain unchanged │ └── Mismatch → Verify new entries only │ ▼ 2. Verify entries from (stored_tip + 1) to new_tip │ ▼ 3. Update stored tipContinuity Across RIK Changes
Section titled “Continuity Across RIK Changes”When RIK rotates, continuity is proven through dual signatures:
┌─────────────────────────────────────────────────────────┐│ RIK Rotation Continuity Proof │├─────────────────────────────────────────────────────────┤│ ││ Old Identity: did:key:z6MkOLD... ││ New Identity: did:key:z6MkNEW... ││ ││ Proof Statement: ││ "I (old) am transitioning to (new)" ││ ││ Signatures: ││ ├── oldRikSignature: sign(OLD_RIK, statement) ││ └── newRikSignature: sign(NEW_RIK, statement) ││ ││ Verifiers: ││ 1. Verify old signature with old RIK ✓ ││ 2. Verify new signature with new RIK ✓ ││ 3. Accept continuity claim ✓ ││ │└─────────────────────────────────────────────────────────┘Storage & Distribution
Section titled “Storage & Distribution”Local Storage
Section titled “Local Storage”~/.sap/├── rotation_chain.json # Full chain├── rotation_chain.sealed # Encrypted backup└── chain_tip.json # Quick tip referencePublished Tip
Section titled “Published Tip”The PID includes the chain tip for quick verification:
{ "sentinel": { "rotationTip": "sha256:a1b2c3d4...", "rotationCount": 15, "policyHash": "sha256:e5f6g7h8..." }}Full Chain Distribution
Section titled “Full Chain Distribution”Options for sharing the complete chain:
- On-demand fetch: API endpoint returns full chain
- Content-addressed: IPFS/Arweave for immutability
- Gossip protocol: P2P distribution among agents
Security Properties
Section titled “Security Properties”Tamper Evidence
Section titled “Tamper Evidence”Any modification to a historical entry invalidates all subsequent hashes:
Original: E1 → E2 → E3 → E4 ↓Modified: E1 → E2' → ??? (hash mismatch)Non-Repudiation
Section titled “Non-Repudiation”Each entry is signed by RIK, proving:
- The identity holder authorized the change
- The change occurred after the previous entry
- No entries have been removed or reordered
Forward Security
Section titled “Forward Security”Compromise of an OK doesn’t expose:
- RIK (used only for signing)
- Historical chain entries
- Future rotation plans
Implementation
Section titled “Implementation”Adding an Entry
Section titled “Adding an Entry”function addRotationEntry(chain, entry, rik) { // 1. Set sequence entry.sequence = chain.entries.length + 1;
// 2. Link to previous if (chain.entries.length > 0) { const lastEntry = chain.entries[chain.entries.length - 1]; entry.previousEntryHash = hashEntry(lastEntry); }
// 3. Set timestamp entry.timestamp = new Date().toISOString();
// 4. Sign with RIK entry.rikSignature = sign(rik, entry);
// 5. Append to chain chain.entries.push(entry);
// 6. Update tip chain.tip = { sequence: entry.sequence, hash: hashEntry(entry), timestamp: entry.timestamp };
return chain;}Verifying the Chain
Section titled “Verifying the Chain”function verifyChain(chain, trustedRik) { let previousHash = null;
for (const entry of chain.entries) { // Verify sequence if (entry.sequence !== chain.entries.indexOf(entry) + 1) { return { valid: false, error: "Invalid sequence" }; }
// Verify hash link if (previousHash && entry.previousEntryHash !== previousHash) { return { valid: false, error: "Hash chain broken" }; }
// Verify signature if (!verify(trustedRik, entry, entry.rikSignature)) { return { valid: false, error: "Invalid signature" }; }
previousHash = hashEntry(entry); }
return { valid: true };}Related
Section titled “Related”- Key Hierarchy — RIK/OK/RK architecture
- PID Structure — Public Identity Document
- Identity Sentinel — Sealed backups
- Key Management Guide — Operational best practices