# Security analysis — attack vectors and hardening This document is the deliberate adversary's view of AES512. It enumerates the attack surface layer by layer, states what each vector can and cannot do against this design, names the concrete mitigation in the code, and — most importantly — is honest about the residual risk. It is the reasoning behind the "v3" hardening. Read this together with [DESIGN.md](DESIGN.md) (cipher spec), [PROTOCOL.md](PROTOCOL.md) (wire spec) and [../SECURITY.md](../SECURITY.md) (guarantees and non-goals). ## 0. The honest headline Is this "stronger than AES-256"? That collapses two questions that must be kept separate: - **Target security level and margins — larger, by construction.** 512-bit key (≈2²⁵⁶ work even under Grover, vs AES-256's ≈2¹²⁸), 512-bit block (birthday bound at 2²⁵⁶ blocks, so no practical data limit), a proven-MDS diffusion layer with an 18-round margin, a key schedule with *no* related-key structure, a *constant-time* core, and a protocol with post-quantum confidentiality **and** post-quantum authentication. Every one of these is a larger margin than, or a known weakness removed relative to, AES-256 used naively. - **Assurance — far lower, and no design choice can fix that.** AES-256 has withstood 25 years of the world's best public cryptanalysis. This construction has had essentially none. Bigger numbers and cleaner structure reduce the *known* attack surface; they do not confer the *confidence* that only sustained third-party cryptanalysis produces. A design can be simultaneously more conservative and less trustworthy, and this one is. So: **more margin, less pedigree.** For research and for a hardened messenger among people who understand that caveat, it is a legitimately strong stack. For anything whose compromise you cannot tolerate, use AES-256-GCM / TLS 1.3. ## 1. Block-cipher attack vectors | Vector | Assessment | Mitigation in this design | Residual risk | |---|---|---|---| | **Differential cryptanalysis** | The classic chosen-plaintext statistical attack. | MDS MixColumns (branch number 9, proven exhaustively in `mds_test.go`) + diffusion-optimal ShiftRows ⇒ ≥81 active S-boxes per 4 rounds; AES S-box max diff. prob. 2⁻⁶. An 8-round trail is already bounded ≈2⁻⁹⁷², far under the 2⁻⁵¹² block floor. 18 rounds ⇒ ~4.5× that margin. | Trail bounds ≠ differential (clustering) bounds; unproven against multi-trail differentials. Margin is large but not a proof. | | **Linear cryptanalysis** | Known-plaintext correlation attack. | Same wide-trail bound: ≥81 active S-boxes/4 rounds, S-box max correlation 2⁻³ ⇒ 4-round hull ≤2⁻²⁴³. | Same caveat (linear hulls vs single trails). | | **Related-key attacks** | Broke *full* AES-256 (Biryukov–Khovratovich, 2⁹⁹·⁵) via its slow, linear key schedule. **This was v1/v2's worst inherited weakness.** | **v3 replaces the key schedule with SHAKE-256(domain‖key).** Round keys are independent and pseudorandom — there is no algebraic relation for an attacker to exploit. Finding useful related keys now requires finding SHAKE relations (infeasible). | Essentially eliminated for this attack class. Cost: round keys are non-derivable and must be stored (they already were). | | **Weak keys / key-schedule structure** | Key classes with exploitable structure. | SHAKE expansion has no key structure ⇒ no weak-key classes; any 64-byte key is as good as any other. | None known. | | **Integral / square / saturation** | Reaches furthest on reduced-round AES (7–8 rounds). | 512-bit state ⇒ saturation structures need up to 2⁶⁴ texts per column; 18 rounds vs the ~4-round incomplete-diffusion window these exploit. | Not analyzed for this exact cipher; margin argument only. | | **Impossible-differential / boomerang / rectangle** | Middle-round distinguishers. | Wide-trail margin + 18 rounds; boomerang needs two short high-prob. differentials, both bounded away here. | Unproven; margin only. | | **Algebraic (XSL, Gröbner)** | Never threatened AES; more variables with larger state. | Larger state ⇒ larger, harder systems; SHAKE schedule destroys clean round-key algebra. | Considered non-threat, consistent with AES experience. | | **Cache-timing / software side channel** | **The most practical real-world break of table-based AES** (Bernstein 2005; Osvik–Shamir–Tromer). Recovers keys across cache boundaries on shared hardware. | **v3 uses NO S-box table.** The S-box is computed algebraically (GF(2⁸) inverse via a fixed 11-multiply addition chain + affine map), all branchless. Every memory index in the cipher is a public loop counter; `gfMult`/`xtime` are data-independent. Verified against the AES table on all 256 inputs (`sbox_test.go`); grep confirms no table lookup in shipping code. | Constant-time in software (best effort vs compiler transforms). Does **not** cover power/EM analysis (needs masking — out of scope). ~30× slower than table AES (see §5). | | **Fault attacks** | Inject faults to leak keys. | Out of scope (physical). The KAT/roundtrip self-consistency would catch gross corruption but this is not a countermeasure. | Present, as for most software ciphers. | | **Brute force / Grover** | Exhaustive key search. | 512-bit key ⇒ 2⁵¹² classical, ≈2²⁵⁶ under Grover (NIST cat. 5 and beyond). | None meaningful. | ## 2. AEAD / mode attack vectors | Vector | Assessment | Mitigation | Residual risk | |---|---|---|---| | **Nonce reuse (streaming AEAD)** | Repeating a nonce under one key in CTR mode is catastrophic (keystream reuse). | `NewAEAD` uses 32-byte nonces (accidental-collision-safe). For code where nonce discipline is hard, **`NewSIV` provides misuse resistance**: the IV is synthesized from the message, so reuse leaks only whether two full (nonce, AD, plaintext) triples are identical (`siv_test.go` proves keystream is not reused). | With `NewAEAD`, a *deterministic* nonce bug is still fatal — use `NewSIV` or the `securechannel` (which derives nonces from sequence numbers). | | **Forgery / ciphertext integrity** | Forge a valid ciphertext. | Encrypt-then-MAC (Bellare–Namprempre), HMAC-SHA-512 tag truncated to 256 bits, constant-time compare, decrypt only after verify. Forgery ≈2⁻²⁵⁶. Fuzzed (`FuzzAEADOpen`). | Standard EtM assurances. | | **Key-commitment / partitioning oracle** | A non-committing AEAD (e.g. AES-GCM) lets one ciphertext open under two keys — enables partitioning-oracle attacks in multi-key/password settings. | Both AEAD and SIV are **key-committing for free**: the tag is HMAC over (nonce, AD, ciphertext) under a MAC key derived from the AEAD key. Matching under two keys needs an HMAC collision across keys. Tested (`TestAEADCrossKey`, `TestSIVCrossKey`). | None known. | | **Length / truncation manipulation** | Splice or truncate to change meaning. | 64-bit length prefixes make the MAC input injective; truncation changes the tag. | None known. | | **Padding oracle** | Classic CBC break. | No CBC, no padding-based mode in the public API; AEAD/SIV reject before any plaintext use. | N/A. | ## 3. Protocol (securechannel) attack vectors | Vector | Assessment | Mitigation | Residual risk | |---|---|---|---| | **Passive record-then-decrypt (quantum "harvest now")** | Record today, decrypt when a quantum computer exists. | **Hybrid X25519 + ML-KEM-1024** ephemeral key agreement: recovering keys needs breaking *both* ECDH and ML-KEM. | Relies on ML-KEM-1024 (NIST-standardized, FIPS 203) holding. | | **Active MITM / impersonation (classical)** | Sit between the parties. | Mutual auth: Ed25519 signatures over the full transcript, role-separated domains (no reflection), transcript binds both identities+ephemerals+KEM ciphertexts (no unknown-key-share). | Standard SIGMA-family assurances. | | **Impersonation by a *quantum* adversary** | Ed25519 is quantum-forgeable ⇒ a quantum attacker could impersonate in **new** handshakes (it cannot retro-decrypt — §row 1). **v2's authentication was classical-only.** | **v3 adds post-quantum authentication:** each identity has a *static* ML-KEM-1024 key. Both parties prove possession by having to decapsulate an encapsulation to their static key, whose result is mixed into the session keys (KEMTLS-style implicit auth). Auth now survives if **either** signatures **or** the lattice assumption holds. | Full break needs both a quantum computer *and* theft of a static ML-KEM key — a much higher bar. Ed25519 remains as belt-and-suspenders. | | **Identity exposure (passive)** | v2 sent both identity keys in cleartext ⇒ an eavesdropper enumerates who talks to whom. | **v3 encrypts identities and signatures** under a key derived from the *ephemeral* hybrid secret (Noise-XX-style). A passive observer sees only ephemeral public keys. | Protects against **passive** observers only. An **active** MITM that completes its own ephemeral exchange can still learn identities (documented). Full protection needs a pre-known server key (IK-style); out of scope. | | **Replay / reorder / drop / truncation** | Re-inject or shuffle frames. | Per-message key from a **hash ratchet** advanced in lockstep + implicit direction/sequence nonce: any out-of-lockstep frame derives the wrong key, fails auth, and **permanently kills the channel** (`TestReplayed/Reordered/TamperedFrameKillsChannel`). No "warn and continue". | A dropped frame is fatal (by design) — reconnect. | | **In-session key compromise** | Steal live session state. | The **hash ratchet** gives per-message forward secrecy: the chain key is advanced one-way after each message, so compromising the current state cannot recover the keys of already-sent messages. | No *future* secrecy (no DH ratchet): a compromise reveals messages from the compromise point until reconnect. A full double ratchet is future work. | | **Downgrade** | Force a weaker version/parameter set. | Single protocol version, hard-fail on mismatch; version is folded into the signed transcript. | N/A (no negotiation to attack). | | **Key-compromise impersonation (KCI)** | Steal A's key ⇒ impersonate others *to* A. | Inherent to signature auth, but v3's static-KEM mutual auth *raises* the bar: impersonating a party also needs its static ML-KEM key, not just its signing key. | Reduced vs signature-only, not eliminated. | | **First-contact MITM (TOFU)** | The very first connection to a name has nothing to compare against. | TOFU pins the whole identity thereafter; **`ExpectedServerFingerprint` removes the window entirely** — pin out of band and first contact is as safe as the rest. Fingerprint covers *both* keys. | If you rely on TOFU and don't verify the first fingerprint, first contact is exposed. | | **Traffic analysis (metadata)** | Sizes/timing/volume leak. | Frames padded to `PadTo`-byte buckets (`TestFramePadding` shows equal-length frames for unequal messages); handshake messages are fixed-size (fixed-length keys). | Padding only *coarsens* length; timing/volume/relationship metadata still leak. Not an anonymity system. | | **Malformed-input DoS / parser exploits** | Crash or hang the peer with bad bytes. | Every field length-checked before any crypto call (no panic reachable), strict JSON (unknown fields rejected), 16 KB handshake cap, frame length bounds, whole-handshake deadline. Fuzzed (`FuzzUnmarshalPublicIdentity`, `FuzzSplitFields`) and hammered (`TestMalformedHandshake`). | Computational DoS (forcing KEM/signature work) is possible; rate-limiting is an app-layer concern (noted). | | **Bad randomness** | Predictable ephemerals ⇒ break. | Hybrid design needs *both* X25519 and ML-KEM ephemeral randomness to fail; all from `crypto/rand`. | A totally broken RNG still breaks it (as it does everything). No hedged/derandomized signing. | | **Endpoint compromise** | Malware on the device. | Out of scope — no cryptosystem survives this. | Present. | ## 4. What changed from v2 → v3 (and why) | Change | Vector it closes | |---|---| | Key schedule → SHAKE-256 | Related-key (AES-256's signature weakness) | | Table-free algebraic S-box | Cache-timing key recovery (the top practical AES break) | | 14 → 18 rounds | Extra margin vs all structural attacks | | Static ML-KEM identity + KEMTLS mutual auth | Quantum impersonation | | Encrypted identities in handshake | Passive identity exposure | | Per-message hash ratchet | In-session forward secrecy | | Frame + handshake padding | Traffic-analysis length leakage | | SIV misuse-resistant mode | Catastrophic nonce reuse | | `ExpectedServerFingerprint` | TOFU first-contact MITM | | Committing AEAD (documented + tested) | Partitioning-oracle / multi-key ambiguity | ## 5. Cost of the hardening The constant-time S-box is ~30× slower than a table (≈0.4 MB/s block throughput; a 1 KB message ≈2.5 ms of cipher work). The v3 handshake is ~44 ms of CPU (four ML-KEM operations + two Ed25519 sign/verify + X25519 + encrypting the identity blobs with the constant-time cipher), and a 1 KB message round trip is ~15 ms. **This is imperceptible for chat** — the stated use case — but the design is not a bulk-data cipher; a bitsliced constant-time core (same security property, far faster) is the natural performance follow-up and is called out as future work. Security bought with that cost: elimination of the single most practical real-world AES attack (cache timing) and of AES-256's most-cited weakness (related-key), plus post-quantum authentication and per-message forward secrecy. For this project's goals that is the right trade. ## 6. What would raise assurance further (future work) 1. **Third-party cryptanalysis** — the only thing that converts "large margin" into "trustworthy". Everything else is secondary to this. 2. Bitsliced constant-time core (perf + keeps the side-channel property). 3. Hybrid PQ **signatures** (ML-DSA) for fully post-quantum authentication. 4. A DH/KEM ratchet for post-compromise (future) secrecy, not just forward. 5. Formal analysis of the handshake (Tamarin/ProVerif). 6. Length-hiding beyond bucketing; padding-defense against timing. ## 7. An open invitation to break it Cryptanalytic results on this stack — positive or negative — are the entire point of publishing it. If you are looking for a place to start: - **Reduced-round distinguishers.** The bounds in §1 are single-trail bounds; clustering (multi-trail differentials, linear hulls) on this 8×8 geometry with the Grøstl matrix is unstudied for the *keyed* setting. Anything at 8+ rounds that beats the trail bounds would be a real result; anything on the full 18 rounds beating generic search falsifies the design claim. - **The key-schedule model.** Round keys are a SHAKE-256 image of the master key ([DESIGN.md](DESIGN.md) §2.6). The related-key claim reduces to SHAKE; attacks in *chosen-round-key* models are out of scope by construction, but a gap between "XOF-derived" and "truly independent" round keys that matters here would be interesting. - **The modes.** Encrypt-then-MAC and SIV over a 512-bit-block CTR with HMAC-SHA-512 — the compositions are textbook, the instantiation is not. Key-commitment, nonce-misuse and multi-key behaviour are tested (`aead_test.go`, `siv_test.go`) but not proven. - **The handshake.** A SIGMA/KEMTLS hybrid with encrypted identities ([PROTOCOL.md](PROTOCOL.md)). A machine-checked model (Tamarin/ProVerif) confirming — or refuting — the claimed properties (mutual auth, forward secrecy, identity hiding against passive observers, downgrade absence) would be a welcome contribution. - **The constant-time property.** The claim is source-level; a compiler is free to betray it. Tooling runs (dudect, ctgrind/valgrind, binary analysis of the wasm build) that confirm or refute data-independence of the emitted code close a real gap. Reproduce everything: `go test ./...` runs the MDS proof, KATs, Monte-Carlo chain and fuzz seeds; `cmd/genkat` regenerates vectors for an independent implementation. Report findings via the repository issue tracker (or the contact on the project page) — credit is yours, and negative results are publishable here too: this document will link any serious analysis, whatever its conclusion.