# LATTICE attack log ## Scoreboard Cost to recover the 256-bit key (brute force = 2^256; lower = more broken). Best attack per cell, after the C-accelerated tools (which use 10-100x more data than the JavaScript ones and found more cracks). | | LATTICE-1 | LATTICE-2 | LATTICE-3 | **LATTICE-4 (current)** | |---|---|---|---|---| | Rounds | 12 | 20 | 20 | 20 | | Round-3 cracks at 1M pairs/bit | hundreds | 69 | 108 | **0 (even at 8M)** | | 4 rounds | 2^77 | 2^129 | 2^98 | 2^145 | | 5 rounds | 2^136 | 2^135 | 2^135 | **2^175** | | 6 rounds | 2^247 | 2^250 | 2^235 | **held** | | 7 rounds | — | held | held | held | | Rounds broken / margin | 6 of 12 · 2x | 6 of 20 · 3.3x | 6 of 20 · 3.3x | **5 of 20 · 4x** | | Speed (C reference) | — | 198 MB/s | 166 MB/s | ~150-180 MB/s | **Correction:** earlier JavaScript runs reported LATTICE-3 round 4 at ≈ 2^225. With 20x more data the C tools find 27-108 round-3 cracks instead of 4, and round 4 falls for ≈ 2^98-2^134. Lesson: more attack effort keeps finding more. ## LATTICE-4 (current design) Built from a C-accelerated design search. Changes vs LATTICE-3: a multiply term in step 5 of the mixing function, and rotation amounts [15, 16, 8, 3]. Full specification: SPEC.md. | # | Attack | Result | |---|--------|--------| | 42 | C research harness | Matches JS bit for bit; 24x faster scans | | 43 | Design search: 3 mixing variants x 150 rotation sets, 3 rounds, 20k pairs/bit | Many candidates clean at that precision | | 44 | 15 finalists at 1M pairs/bit | LATTICE-3: 108 cracks. 8-step [20,23,4,2]: 0. All 12-step: 0. 4 of 5 multiply: 0 | | 45 | 3 finalists at 8M pairs/bit (~1 billion pairs each) | 8-step: **30 cracks (fails)**. 12-step: 0. Multiply [15,16,8,3]: 0 | | 46 | C key-recovery tool validated | Reproduces LATTICE-2 round 5 (2^135.5 vs JS 2^137) | | 47 | Finalists, key recovery from 2-round cracks | 12-step: 4 rounds 2^195, 5 held (14 rounds total). Multiply: 4 rounds 2^145, 5 rounds 2^175, 6 held | | 48 | Equal-cost comparison | Multiply design: margin 4x at 20 rounds; 12-step: 3.5x; LATTICE-3: 3.3x. **Multiply chosen as LATTICE-4** | | 49 | LATTICE-4 round 6, heavy (48 cracks, 1M scan, 400k pairs) | Held | | 50 | LATTICE-3 round 7, heavy | Held | | 51 | Differential-linear, 3 rounds, 600k pairs, 393k output masks | Held (4.8 sd vs 5.1 sd noise ceiling). Also held on LATTICE-3 at 60k | | 52 | Two-bit input differences, all 1,984 pairs, 150k pairs each | Held (4.9 sd vs 5.3 ceiling) | | 53 | Related-key, 256 key bits, 3 rounds, 200k pairs | Held. Round 2 broken (expected) | | 54 | Rotational / cube / slide / statistics | Rotational broken at 1 round only; cube at 2 rounds finds 2-3 constant bits (LATTICE-3: 65); slide none; stats pass | | 55 | Implementation checks | Poly1305 passes RFC 8439 vector (JS and C); 26 KAT vectors identical in JS and C; tamper detection 100% | | 56 | Conditional differential, aimed at round 6 (research/cond.c). Step 1: for all 128 attacker-controlled input bits, 1M pairs each, find the most likely one-round difference. Step 2: keep only pairs that hit it (the attacker pays 1/p for this) and measure bias further on, 100k conforming pairs (~6.6 billion tries) per test | Best entry: nonce word 13 bit 16 gives a 4-12 bit one-round difference with p = 2^-15.2 to 2^-16. Control at round 2: 114 output bits above 6 sd (tool works). **Round 3: held** (strongest 3.2 sd vs 3.9 noise ceiling). **Round 4: held** (3.1 sd). Conditioning buys round 1 for 2^16 work but the multiply step spreads the difference fully by round 3, so the distinguisher still reaches only 2 rounds. **Round 6: held** | ### Not yet attempted on LATTICE-4 Conditional differentials with two or more rounds of conditions (costs more than 2^32 per pair at the probabilities seen in #56), multiplicative / algebraic attacks on the multiply step, multi-bit related-key differences, invariant subspaces, and the one that counts most: outside cryptanalysis. --- ## LATTICE-3 (previous design, 20 rounds) LATTICE-2 plus: the key is XORed back into the state after every 2nd round, and a round-dependent constant enters every round. | # | Attack | Result | |---|--------|--------| | 34 | Combined cracks re-run on LATTICE-1 (improved greedy method) | 4 rounds **≈ 2^77** using 18 cracks / 179 key bits. 5 rounds 2^136, 6 rounds 2^247 | | 35 | Combined cracks on LATTICE-2 | 4 rounds 2^129 (9 cracks, 127 bits), 5 rounds 2^137, 6 rounds 2^250 | | 36 | LATTICE-3 crack scan, 120k pairs/bit | Only 4 cracks (counter/nonce bit 3 -> bit 8), 1.1-1.5% | | 37 | LATTICE-3 combined, 4 rounds | **≈ 2^225**: the 4 cracks pin down only 31 key bits | | 38 | LATTICE-3 combined, 5 rounds | ≈ 2^136: no improvement | | 39 | LATTICE-3b (key injected after EVERY round) | 5 rounds ≈ 2^125: **worse**. Hypothesis disproved; variant rejected | | 40 | LATTICE-3 combined, 6 rounds, 2 runs | ≈ 2^245 both runs (marginal) | | 41 | LATTICE-3 rotational / cube / slide / stats / related-key | Same as LATTICE-2: broken only at rounds 1-2 | --- ## LATTICE-2 (previous design, 20 rounds) **Current standing: 5 of 20 rounds broken (key recovery ≈ 2^138). Round 6 held (best ≈ 2^254, within estimation error of brute force). Safety margin: 4x** (ChaCha's best published: 7 of 20, 2.9x; same caveat: ChaCha's attackers are professionals with years, ours had one night). What changed from LATTICE-1 and why: 1. **Layout**: constants top row, key rows 2-3, counter + nonce bottom row (the ChaCha layout). With our Latin-square groups, every column and every group holds 2 key words, so undoing one round means guessing 64 key bits, not 32. 2. **Rotation amounts [28, 25, 8, 13]**, picked by attacking 40 candidates at round 3 and keeping the one that leaked least. LATTICE-1's amounts ranked 31st of 40 on the new layout. 3. **20 rounds** instead of 12. | # | Attack | Result | Rounds broken | |---|--------|--------|---------------| | 21 | Rotation-amount search | 40 candidates, then top 8 with 7,500 pairs per bit. Winner shows no 3-round leak at that precision | n/a | | 22 | Full differential scan, 2 rounds | Broken (expected for any design) | 2 | | 23 | Full differential scan, 3 rounds, 40k pairs | Crack: counter/nonce bit 3 -> bit 8 of same word | 3 | | 24 | Confirmation, 400k pairs | **1.6% bias** (20 sd), stable across keys (1-3%). LATTICE-1's equivalent: 4.8%, swinging 1-10% by key | 3 | | 25 | Key recovery + neutral bits, 4 rounds | Crack survives with 20 key bits guessed. Single-crack cost ≈ 2^236 | **4** | | 26 | Same attack on LATTICE-1 for comparison | LATTICE-1 4 rounds: held for that particular key (its crack is key-dependent). 5 rounds: ≈ 2^138 | — | | 27 | Key recovery + neutral bits, 5 rounds | Crack visible with 104-131 key bits guessed. **≈ 2^138, same as LATTICE-1**: the fixes didn't add broken-round depth | **5** | | 28 | Key recovery + neutral bits, 6 rounds | Needs 234+ key bits guessed. Best ≈ 2^254.4 on one crack, 2^255+ on another: effectively brute force | 5 (held) | | 29 | Related-key scan, 3 rounds | Flip each of 256 key bits too: nothing beyond the known crack | 3 (no change) | | 30 | Rotational | Round 1 broken, rounds 2-4 held | 1 | | 31 | Cube attacks 2^8-2^16 on counter and nonce | Round 2 broken, rounds 3-4 held | 2 | | 32 | Slide precondition | Never | 0 | | 33 | Keystream statistics, weak keys, round trip | Pass | 0 | Speed: 28 MB/s in plain JavaScript (LATTICE-1: 35 MB/s at 12 rounds). ### Not yet attempted on LATTICE-2 - Combining many cracks (the trick that took LATTICE-1's 4-round cost from 2^236-style to 2^144) - Multi-round differential trails, differential-linear attacks - Outside review --- ## LATTICE-1 (broken design, kept for reference) Every attack attempted against the cipher, newest at the bottom. "Rounds broken" means the attack can tell the reduced-round cipher apart from random. The full cipher runs 12 rounds. **Current standing: 5 of 12 rounds broken (key recovery ≈ 2^140), round 6 marginal (≈ 2^248). Safety margin: 2.4x, below ChaCha's 2.9x.** **Recommendation: raise the round count from 12 to 20** (margin 20/6 = 3.3x), or fix the bit-24 weakness in the mixing function, then rerun every attack. For comparison, the best published attacks on ChaCha20 reach about 7 of its 20 rounds (2.9x margin). That comparison flatters us: ChaCha has had 15+ years of attacks by professional cryptanalysts. LATTICE-1 has had one evening of attacks by its own designers. | # | Date | Attack | What it tries | Result | Rounds broken | |---|------|--------|---------------|--------|---------------| | 1 | 2026-11-14 | Round trip | Encrypt then decrypt 200 random messages | Correct | n/a | | 2 | 2026-11-14 | Avalanche (basic differential) | Flip 1 input bit, 1,500 pairs x 48 bit positions, watch all 512 output bits | Full diffusion from round 3 at this precision | 2 | | 3 | 2026-11-14 | Keystream statistics | 4 MB: bit balance, byte frequency, byte-pair frequency | Indistinguishable from random | 0 | | 4 | 2026-11-14 | Weak keys | All-zero / all-ones key and nonce, adjacent counters | Output still random-looking | 0 | | 5 | 2026-11-14 | Nonce reuse | Same key + nonce on two messages, attacker guesses one message | **Second message fully recovered.** Expected: this breaks every stream cipher. Rule for the app: never reuse a nonce. | n/a (usage rule) | | 6 | 2026-11-14 | High-precision differential | 120,000 pairs per input bit, 4 input bits | **Round 3 broken** (bias 1.56% vs 0.87% threshold). Missed by attack 2. | **3** | | 7 | 2026-11-14 | Targeted 4-round differential | 1.5 million pairs on the 3 most suspicious input bits | Held. Worst bias 2.9 standard deviations, i.e. noise | 3 (no change) | | 8 | 2026-11-14 | Linear correlation | 60 input bits x 512 output bits, 40,000 samples | Held at every round tested, even round 1 | 0 | | 9 | 2026-11-14 | Rotational | Rotate all attacker-controlled words by 1 bit | Round 1 broken, round 2 held. The diagonal constants do their job | 1 | | 10 | 2026-11-14 | Cube attack (algebraic) | XOR outputs over 2^8 and 2^12 counter values, 48 keys | Rounds 1-2 broken (1 constant bit at round 2), round 3 held | 2 | | 11 | 2026-11-14 | Bigger cube attacks | 2^16 counter cube at round 3; 2^12 nonce cubes at rounds 2-3 | Held | 2 (no change) | | 12 | 2026-11-14 | Slide / self-similarity | 400,000 states: does a round ever map back onto the constant pattern? | Never | 0 | | 13 | 2026-11-14 | Full differential scan | All 384 attacker-controlled input bits x 20,000 pairs at round 3 | **Bit 24 of any nonce/counter word causes ~6% biases (17 sd)**, 4x stronger than attack 6 found | 3 | | 14 | 2026-11-14 | 4-round direct differential | Top 5 input bits x 400,000 pairs | Held: worst 3.8 sd, which is noise | 3 (no change) | | 15 | 2026-11-14 | 4-round key recovery (undo last round) | Guess the one key word in a round-4 group, undo round 4, look for the round-3 crack | **True key ranked #1 of 65,536**; specific key bits always correct in the top 64 guesses | **4** | | 16 | 2026-11-14 | Probabilistic neutral bits, 4 rounds | Which key bits matter for each of 14 cracks | Each crack needs only 3-19 key bits. 112 key bits recoverable at ~2^32 work each; rest brute force. **Total ≈ 2^144** | **4** | | 17 | 2026-11-14 | Neutral bits, 5 rounds (loose) | Undo 2 rounds, guess 49-53 significant bits | Failed: 203 wrong neutral bits drown the crack | 4 (no change) | | 18 | 2026-11-14 | Neutral bits, 5 rounds (tight) | Guess 77-116 bits instead | **Crack survives: 2.5%-8.7% bias (19-67 sd). Total ≈ 2^140.** Needs a key where the chosen crack is strong | **5** | | 19 | 2026-11-14 | Key-dependence check | Same crack, fixed keys | Crack strength varies by key: ~0% for some, 9% for others. Attacker tries several cracks | n/a | | 20 | 2026-11-14 | Neutral bits, 6 rounds | Undo 3 rounds | Needs 233 key bits guessed; crack visible at 2.2%. Total ≈ 2^248, only 2^8 below brute force | **6 (marginal)** | ## Lessons so far - **More data finds more rounds.** The basic test said round 3 was safe. 80x more data broke it. A well-funded attacker has far more data and time than this laptop. That's why the margin matters. - **The design choices that worked:** the diagonal constants killed the rotational attack after one round; the Latin-square mixing spreads a change across the whole state by round 3. - **The real weak spot: bit 24 of the nonce and counter words.** A flip there survives three rounds with a ~6% bias. The attacker controls those words, so they can trigger it freely. - **Undoing rounds is cheap because round 4 only mixes within groups of four.** Two of the four Latin-square groups contain just one key word each, so an attacker guesses 32 bits, not 256. - **What stopped round 6:** after undoing three rounds, almost every key bit matters again. - **Fix options:** more rounds (simplest), different rotation amounts in M (to kill the bit-24 trail), or a state layout where every Latin-square group holds at least two key words. ## Attacks not yet attempted - Multi-round differential characteristics (chaining a 2-round trail with a 2-round bias) - How common strong-crack keys are (affects the 5- and 6-round results) - Multiple target bits combined (could push round 6 further below brute force) - Differential-linear attacks - Related-key attacks with multi-bit key differences - Side channels (timing, power): ARX is constant-time by design, but the JavaScript engine is not guaranteed to be - Outside review: publish the spec and invite people to break it. This is the only test that really counts.