Post-quantum encryption: hybrid ML-KEM-768 identities with upgrade-on-touch (#28) #107
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/pq-encryption"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implements #28, unblocked by Nikola's research: age v1.3.0+ natively supports hybrid post-quantum recipients, and because age wraps ONE file key into an independent header stanza per recipient, multi-recipient encryption (user+recovery, group spaces #18) carries over unchanged. We already pin age v1.3.1 — zero new dependencies.
Config:
storage.encryption.postQuantum: true(orCAIRN_ENC_POST_QUANTUM=true) switches ALL custody backends (keycloak-profile, openbao, deployment) to minting hybrid ML-KEM-768+X25519 identities (AGE-SECRET-KEY-PQ-1…).The constraint, enforced: hybrid recipients emit a
postquantumlabel and refuse to mix with classical recipients. Startup validation therefore requires the recovery identity (and deployment identity) to match the flavor, withrecoveryIdentityLegacy/deploymentIdentityLegacyas decrypt-only slots for the pre-migration keys. A test proves age rejects a mixed set.Migration — upgrade-on-touch: existing principals hold classical identities. On first encrypted operation under PQ, a hybrid identity is minted and stored FIRST; the classical identity is RETAINED (multi-value Keycloak attribute /
legacyIdentitiesin OpenBao) so every pre-PQ file still decrypts. Rollback (postQuantum: false) selects the retained classical identity again — nothing minted, nothing orphaned. OpenBao upgrades use versioned check-and-set so racing replicas can't clobber keys.Internals: new flavor-aware keyset layer (
pq.go:ParseIdentity,IsHybrid,resolveKeyset); Keycloak user+group custody, OpenBao, and StaticKeys all rewritten on it;Recoveryfields widened toage.Identity.instanceSeed(#31) with a PQ deployment identity is refused at startup (HKDF derivation is X25519-only — documented follow-up).Tests: flavor parsing, hybrid StaticKeys roundtrip + recovery, the mixing guard, Keycloak PQ lazy provision, full upgrade-on-touch matrix (legacy decrypt / attribute retention / classical-cannot-read-new-content / hybrid recovery works), rollback, OpenBao upgrade with legacy retention. Full suite green.
Costs (from #28): ~2000-char identities (bigger attribute values), ~2× keygen, negligible enc/dec.