# 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% |

### Not yet attempted on LATTICE-4
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.
