Summary
The currently-documented v0.1 architecture stores credential ciphertext on chain (pallet-secrets-vault, encrypted to the TEE shielding key). This creates an unbounded retroactive-confidentiality risk — public + immutable + permanent ciphertext means any future TEE-key compromise (years, decades) leaks all credentials ever stored. This is the harvest-now-decrypt-later threat applied to our own ledger, and it is not addressed by the current spec.
The fix requires two architectural moves that compose. Splitting the TEE into two enclaves does not address the consequence axis on its own.
Where this is currently asserted (the wrong direction)
The Stage 6 email pipeline (docs/spec/ses-email-architecture.md) already does the right thing for raw MIME (S3 for blobs, chain for metadata). That pattern was not generalized to credentials.
Threat in detail
Three properties of an immutable public ledger combine into the worst-case substrate for encrypted secrets:
- Public — every node, every block explorer, every archival service has the ciphertext.
- Immutable — "delete" is a marker; bytes remain in every archival node.
- Forever — block N's ciphertext is bit-identical at block N + 10M.
Combined with a single long-lived shielding key (derived from master seed at `shielding/v1`, never rotated in current spec):
An attacker who copies the chain today and waits — for 1 year, 10 years, 30 years — wins everything if the shielding key ever leaks. Including credentials that have long since been "revoked" or "deleted" at the application layer.
This does not require breaking AES, breaking the curve, or quantum cryptography. It only requires that the master seed eventually leaves the TEE — once, ever, in any future timeframe. Vectors include:
- Side-channel extraction of the sealed master seed (real risk on commodity TEEs over decade timescales)
- Vendor-side compromise (SGX has had several published microarchitectural breaks)
- A successor enclave operator who is curious about the past
- A single insider with sealed-storage extraction capability
Severity
High. The blast radius on compromise is all credential data ever stored. The threat is not theoretical for long timescales (the spec targets v0.1 production, not a short-lived demo). Discovery of the gap is pre-implementation, so remediation is doc + design only — no users to migrate. Cost of fixing now is small; cost of fixing later (after on-chain encrypted vault ships and accumulates ciphertext) is unbounded.
Why "split the TEE into two enclaves" doesn't fix this
Splitting addresses joint-compromise probability. The retroactive-confidentiality consequence is unchanged because the ciphertext is still public and still permanent on chain. Same-platform splits are the worst case (single SGX vulnerability takes both). Heterogeneous threshold (SGX + TDX + Nitro) reduces probability but is expensive and v0.2+. The fix has to be on the consequence axis, not the probability axis.
Proposed remediation (two moves, both required, both delivered together)
Move 1 — off-chain ciphertext, on-chain hash + audit
- Ciphertext lives in S3 under `s3://agentkeys-vault-/<user_wallet>///<blob_id>.enc`
- Chain holds new pallet `pallet-vault-pointers` with `(user_wallet, service, agent_wallet, epoch, blob_id, ciphertext_hash, created_at)`
- The deprecated `pallet-secrets-vault` design is no longer a target
- Bucket access gated by Stage 7 PrincipalTag-from-JWT (already specified)
- Tamper-evident: read-time hash check rejects S3 mutation
Move 2 — forward-secret per-epoch DEK rotation
- Per-user-per-epoch DEK; default cadence weekly + on-revocation
- DEK wrapped under TEE shielding key, published on chain as `EpochDek { epoch, wrapped_dek }`
- Rotation re-encrypts active blobs (lazy variant: at next read, default for v0.1)
- Old DEKs destroyed on `EpochDestroyed` extrinsic; old S3 blobs lifecycle-deleted
- After K epochs of rotation: total TEE compromise leaks at most one epoch, not all history
The two moves multiply, they do not add. Rotation alone (with on-chain ciphertext) is cosmetic — the old blobs are still public forever. Off-chain alone (without rotation) is better but still leaks everything captured during the vulnerable window. Together they deliver bounded forward secrecy.
Encryption-center responsibility
A separate "rotation enclave" (TEE-B) handles DEK generation, re-encryption, and DEK destruction. Smaller code surface than the auth/decrypt enclave (TEE-A); no network I/O; no untrusted-input parsing; no host shared memory beyond sealed master seed + in-flight DEK. Forward-secrecy guarantees rest on TEE-B's small attack surface, not on platform-diversity (which is v0.2+).
For v0.1 the two roles can run in the same enclave with attested code-module separation; for v0.2+ they split into separate processes (and eventually heterogeneous-platform threshold).
Doc work landed in this branch
Follow-ups not yet covered
- Heima-side review of `pallet-vault-pointers` shape (Kai conversation)
- New gap entry in `docs/spec/heima-gaps-vs-desired-architecture.md` §5 (suggested): "Off-chain ciphertext + on-chain pointers, not on-chain encrypted state"
- Decision on epoch cadence (default proposal: weekly + on-revocation)
- Decision on lifecycle TTL for old epochs (default proposal: 14 days)
- Threshold-rotation across heterogeneous TEE platforms — v0.2+
- TEE-A / TEE-B split: merged for v0.1, split for v0.2; protocol shape needed so the same code works in both deployments
Related
Summary
The currently-documented v0.1 architecture stores credential ciphertext on chain (
pallet-secrets-vault, encrypted to the TEE shielding key). This creates an unbounded retroactive-confidentiality risk — public + immutable + permanent ciphertext means any future TEE-key compromise (years, decades) leaks all credentials ever stored. This is the harvest-now-decrypt-later threat applied to our own ledger, and it is not addressed by the current spec.The fix requires two architectural moves that compose. Splitting the TEE into two enclaves does not address the consequence axis on its own.
Where this is currently asserted (the wrong direction)
wiki/blockchain-tee-architecture.md§1, table row "Credential blobs" → "encrypted ciphertext, on chain inpallet-secrets-vault"wiki/data-classification.md§1, row "Credential blobs" → "On chain: encrypted ciphertext"wiki/key-security.md§1, v0.1 column → "Encrypted blob in Heima TEE (pallet-secrets-vault)"docs/spec/credential-backend-interface.md"Mapping to Heima Primitives" →store_credential→pallet-secrets-vault::write_secretThe Stage 6 email pipeline (
docs/spec/ses-email-architecture.md) already does the right thing for raw MIME (S3 for blobs, chain for metadata). That pattern was not generalized to credentials.Threat in detail
Three properties of an immutable public ledger combine into the worst-case substrate for encrypted secrets:
Combined with a single long-lived shielding key (derived from master seed at `shielding/v1`, never rotated in current spec):
This does not require breaking AES, breaking the curve, or quantum cryptography. It only requires that the master seed eventually leaves the TEE — once, ever, in any future timeframe. Vectors include:
Severity
High. The blast radius on compromise is all credential data ever stored. The threat is not theoretical for long timescales (the spec targets v0.1 production, not a short-lived demo). Discovery of the gap is pre-implementation, so remediation is doc + design only — no users to migrate. Cost of fixing now is small; cost of fixing later (after on-chain encrypted vault ships and accumulates ciphertext) is unbounded.
Why "split the TEE into two enclaves" doesn't fix this
Splitting addresses joint-compromise probability. The retroactive-confidentiality consequence is unchanged because the ciphertext is still public and still permanent on chain. Same-platform splits are the worst case (single SGX vulnerability takes both). Heterogeneous threshold (SGX + TDX + Nitro) reduces probability but is expensive and v0.2+. The fix has to be on the consequence axis, not the probability axis.
Proposed remediation (two moves, both required, both delivered together)
Move 1 — off-chain ciphertext, on-chain hash + audit
Move 2 — forward-secret per-epoch DEK rotation
The two moves multiply, they do not add. Rotation alone (with on-chain ciphertext) is cosmetic — the old blobs are still public forever. Off-chain alone (without rotation) is better but still leaks everything captured during the vulnerable window. Together they deliver bounded forward secrecy.
Encryption-center responsibility
A separate "rotation enclave" (TEE-B) handles DEK generation, re-encryption, and DEK destruction. Smaller code surface than the auth/decrypt enclave (TEE-A); no network I/O; no untrusted-input parsing; no host shared memory beyond sealed master seed + in-flight DEK. Forward-secrecy guarantees rest on TEE-B's small attack surface, not on platform-diversity (which is v0.2+).
For v0.1 the two roles can run in the same enclave with attested code-module separation; for v0.2+ they split into separate processes (and eventually heterogeneous-platform threshold).
Doc work landed in this branch
Follow-ups not yet covered
Related