Aegis sessions now ratchet: compromising one message key does
not compromise past or future messages, and a peer's DH key
rotates on every direction-flip.
What shipped:
- Symmetric ratchet (ChainKey, MessageKey, DerivedMessageKeys)
— HMAC-SHA-256 chain advancement with 0x01/0x02 domain
separators, HKDF-SHA-256 expansion to AES-256-GCM material.
- Outer ratchet (RootKey) — HKDF-on-RK with the X25519 DH
output as IKM, the old RK as salt, AEGIS_RATCHET_RK_v1
info string. Produces the next root key plus the new
chain key in a single HKDF step.
- RatchetSession — bidirectional state, mutating
encrypt/decrypt, DH-ratchet step orchestration. Header
is JSON with .sortedKeys and AAD-bound to the AEAD tag.
- Out-of-order delivery + bounded skipped-keys cache.
Two limits, both pinned at 1000 (matching libsignal):
maxSkippedKeysCache — LRU eviction
maxSkipPerInboundMessage — CPU DoS guard
- PQXDHRatchetIntegrationTests — the Sprint 4 → Sprint 5
seam: PrekeyBundle → PQXDH → RatchetSession →
bidirectional Double Ratchet messages exchanged across
DH rotations and out-of-order arrivals.
Test status: 191 tests, 3 skipped (issue #1), 0 failures.
Open follow-ups:
- #6 — Sprint 6 (iOS app shell + Keychain) — first visible
Aegis. Sprint 5 was the last big crypto layer before the
UI lights up.
- #10 — optional libsignal byte-level interop. The
pinned-input PQXDH KAT (1ae88af) handles the drift-
detection rationale; libsignal interop stays as a
polish-window item.
pre-council-approval (Maintainer @DemigodDSK, 2026-04-28)