316 lines
28 KiB
Markdown
316 lines
28 KiB
Markdown
# Report: the statistical distinguisher and the round margin of M_r
|
|
|
|
Internal adversarial pass, not an independent review. Every sentence here that could be quoted in public carries
|
|
that label. Lane adv-mixer-3, branch adv-mixer-3. First results 7 October 2026, 19:0x UTC; rows are appended as
|
|
they land.
|
|
|
|
## Header
|
|
|
|
| Field | Value |
|
|
|---|---|
|
|
| Target commit | 017e70376489251e18564c0abce7e466e606c8b3 (class v4 sub-version 3, object byte 7) |
|
|
| Target | the mixer M_r (spec 01 section 1.8.4), class v4 (`V4_CLASS` = `MX8`): 72 applications per item, 8 between dependent cache reads |
|
|
| Base commit | build/master 7a7caa34, merged 04c4d9bc; `git diff --quiet 017e7037 HEAD -- igneum-pow && echo IDENTICAL` prints IDENTICAL |
|
|
| Harness | tools/attack/adv-mixer-3 (igneum-pow by path); binary sha256 bdd8432f6181bcc9e77885cf840c83e2a6ffe5ae027182a1d9181710bbb06e70 (commands index, sac, diff, lin, lin0, rx, cnf), identical on both boxes; v2 8153dbafa4540c796ae5a76e31258dbb1323724465aa4709d9cecd050dea5c40 adds sac0 |
|
|
| SAT solver | CaDiCaL 3.0.1, built from the GitHub source into ~/adv-mixer-3-tools on each box (user directory, nothing system-wide) |
|
|
| Boxes | igneum-build-1 (queue 01, 03, 05, 09) and igneum-build-2 (queue 02, 04, 06, 08), nice 10, cores 8 to 95, 64 threads per sweep; the boxes ran at load 160 to 460 on 96 cores throughout, so every wall time here is a loaded-box time |
|
|
| Logs | /srv/builds/_adv-mixer-3/logs/ on each box (outside the worktree mirror); copies under docs/analysis/cryptanalysis/logs/adv-mixer-3/ on this branch |
|
|
| Days | 20729 (genesis, 3 October 2026), 20733 (Devnet 3 epoch 0), plus 8 fixed day indices in queue 07 |
|
|
| Band | 6 sigma at the sample count of each row; a cell beyond it is a distinguisher, a cell inside it is invisible to that row |
|
|
|
|
Plant rule: a tool is trusted once it has fired on a known-failed shape. Which shape fired is in each row.
|
|
|
|
## Status board
|
|
|
|
| Q | Method | Known-failed shape | Gate | Result (numbers) | Status |
|
|
|---|---|---|---|---|---|
|
|
| Q1 | exhaustive round-0 line-index census, all 2^32 t, k = 0..8 | k = 0 (the init: one bin holds 2^32, fired on both days) | chi-square z within 6, no empty bin | day 20729: uniform at k = 1 (z -1.13), 2 (-0.68), 3 (-0.39), 4 (-0.47), 5 (-1.47), 6 (-0.30), 7 (-1.04), 8 (1.13, the real first read); day 20733 uniform at k = 1 (z -0.71), its k = 2..8 running under the lock; day 20730 (queue 07) uniform at k = 2, 3, 4, 8 | PASS to k = 8 on day 20729 (BOUND: the index histogram is uniform from k = 1), RUNNING |
|
|
| Q2 | single-bit avalanche, random states, 2^24 (and 2^27) states | `one` at k = 8 (fired: 1959 holes); `weak` fires at k = 1 only, not at k = 8 (see Q2) | no cell beyond 6 sigma | day 20729 k = 1: 354 holes, 129,726 cells beyond 6 sigma, worst p = 1.000; day 20733 k = 1: 266 holes, 136,797 cells; day 20729 k = 2 at 2^24: 0 holes, 0 cells beyond 6 sigma, worst z -4.74 (band 0.0015); k = 3: 0 and 0, worst z -5.28; k = 4: 0 and 0, worst z 5.28; day 20733 k = 2: 0 and 0, worst z -4.59; k = 3: 0 and 0, worst z 4.61; k = 4: 0 and 0, worst z 4.67; k = 5..8 and the 2^27 rows running | FINDING at k = 1, PASS from k = 2 on both days (margin: 1 of 8 on random states) |
|
|
| Q2b | t-bit avalanche on the round-0 input (32 bits in), 2^24 (and 2^28) states | k = 0 (the init alone, fired: 12,439 holes) | no cell beyond 6 sigma | k = 1: 0 holes, 218 cells beyond 6 sigma, worst p = 0.7427 (t bit 31 to state bit 53), 18 line-index cells beyond 6 sigma. k = 2..8 at 2^24: 0 cells beyond 6 sigma, worst z 3.7 to 4.7 (the maximum of 16,384 normals is about 4.1); k = 2, 3, 4 at 2^28 states: 0 cells beyond 6 sigma, worst z -4.30, 4.76, -4.64, band 0.00018. Day 20733: k = 1 has 502 cells beyond 6 sigma, worst p = 0.7595 (t bit 31 to state bit 127); k = 2..8 at 2^24: 0 cells, worst z 3.9 to 4.6; its 2^28 rows running | FINDING at k = 1 on both days, PASS from k = 2 on both days (margin: 1 of 8) |
|
|
| Q3 | differential multiplicity, 576 low-weight input differences, 2^20 pairs each | `nomul` at k = 1 (fired: 17,289 deterministic output bits at 4,096 pairs) | no multiplicity 4 or more, no deterministic bit | k = 1: 695 deterministic output bits over the 576 differences (max 35 in one difference) on day 20729, 537 (max 40) on 20733; k = 2..7: 0 deterministic bits, max multiplicity 1, no pair with 2 zero words, both days; k = 8 running | FINDING at k = 1 (deterministic bits), PASS from k = 2 |
|
|
| Q4 | single-bit linear correlations, random states, 2^26 samples | k = 0 (the identity, fired: c = 1.0 on the diagonal) | no cell beyond 6 sigma (band 0.00073) | day 20729 k = 1..7 and day 20733 k = 1..8: worst c between 0.00055 and 0.00062 (z 4.5 to 5.1; the expected maximum of 262,144 normals is 4.8), 0 cells beyond 6 sigma on every row; day 20729 k = 8 running | PASS from k = 1 (BOUND) |
|
|
| Q4b | t-bit linear correlations on the round-0 input, 2^26 samples | k = 0 (fired: c = 1.0, t bit 0 to s[8] bit 0) | no cell beyond 6 sigma | both days, k = 1..8: worst c 0.00046 to 0.00059 (z 3.7 to 4.9 over 16,384 cells), 0 cells beyond 6 sigma | PASS from k = 1 (BOUND) |
|
|
| Q5 | rotational-XOR, rotations 1, 8, 16, 2^22 samples | `weak0` at k = 1 (fired: 740 zero-difference words of 2^20 at r = 1, 245 at r = 16) | no zero-difference word above 2 of N, no repeated difference above 3 | both days, k = 1, 2, 3, 4 at 2^22 samples: 0 zero-difference words at every rotation (random expects about 0.001), most frequent per-word difference multiplicity 3 (the birthday expectation at 2^22 draws of 32 bits) | PASS from k = 1 (BOUND: the XOR constants and the odd multiply kill the rotational property inside one application) |
|
|
| Q6 | SAT (CaDiCaL) on the round-0 input: find t with a given 22-bit index after k applications | k = 1 solved and verified | solve inside one hour per k, time against the honest 2^10 x k x 130 ops | k = 1: SATISFIABLE in 137 s wall on build-1 (load about 160) and 1,593 s on build-2 (load about 500), the same model t = 0x49880000 both times, verified to the target 0x20eb79 through the real code. Honest: 2^10 trials of one application is under a millisecond. The solver is five orders slower than brute force at k = 1 | PASS at k = 1 (BOUND); k = 2..4 RUNNING (one-hour cap each) |
|
|
| Q7 | days: 20733 on every row, 8 fixed day indices on Q1 and Q2 (queue 07, run by the sibling adv-mixer from the shared queue) | as above | as above | day 20733: every row above; day 20730: index uniform at k = 2, 3, 4, 8, sac clean at k = 2, 3; the other seven days pending in queue 07 | RUNNING |
|
|
| GPU | any GPU row | n/a | n/a | no GPU on either box | BLOCKED |
|
|
|
|
The round margin so far (internal adversarial pass, not an independent review): every single-bit statistic that
|
|
reaches beyond k = 1 is listed with its k in the rows below. Where the table says "pending" the row is not yet in.
|
|
|
|
## Q1: the round-0 line-index census (exhaustive)
|
|
|
|
The input to round 0 is 8 fixed words K and 8 words affine in one 32-bit t, so the first line index is a map of
|
|
32 bits to 22 bits and can be censused over its whole domain. For k applications with keys round_key(0..k-1):
|
|
|
|
Command (build-1), per k: `adv-mixer-3 index --day 20729 --apps k --threads 64`. Logs: index-20729-k<k>.log.
|
|
|
|
| Day | k | chi-square z (df 2^22 - 1) | empty bins | min | max | segment z | line z | s[0] bit balance worst z | verdict |
|
|
|---|---|---|---|---|---|---|---|---|---|
|
|
| 20729 | 0 | 6.2e12 | 4194303 | 0 | 2^32 | 7.8e11 | 2.4e10 | n/a | NON-UNIFORM (the plant: one bin) |
|
|
| 20729 | 1 | -1.13 | 0 | 871 | 1191 | -2.00 | -0.26 | pending | uniform within the band |
|
|
| 20729 | 2 | -0.68 | 0 | 874 | 1191 | 0.56 | -0.14 | pending | uniform |
|
|
| 20729 | 3 | -0.39 | 0 | 853 | 1187 | -0.03 | -1.15 | pending | uniform |
|
|
| 20729 | 4 | -0.47 | 0 | 857 | 1190 | 1.07 | -0.25 | pending | uniform |
|
|
| 20729 | 5 | -1.47 | 0 | 872 | 1202 | 0.99 | -0.11 | pending | uniform |
|
|
| 20729 | 6 | -0.30 | 0 | 867 | 1185 | 0.01 | -1.62 | pending | uniform |
|
|
| 20729 | 7 | -1.04 | 0 | 862 | 1191 | -0.45 | -0.88 | pending | uniform |
|
|
| 20729 | 8 | 1.13 | 0 | 863 | 1202 | 1.46 | -0.63 | pending | uniform (the real first read) |
|
|
| 20730 | 2 | -0.53 | 0 | 864 | 1217 | -0.36 | -0.19 | pending | uniform (queue 07, run by adv-mixer) |
|
|
| 20730 | 3 | -0.78 | 0 | 866 | 1189 | -0.26 | 1.05 | pending | uniform |
|
|
| 20730 | 4 | 0.25 | 0 | 865 | 1187 | -0.01 | -0.30 | pending | uniform |
|
|
| 20730 | 8 | -1.29 | 0 | 867 | 1188 | 0.73 | 1.00 | pending | uniform |
|
|
| 20733 | 0 | 6.2e12 | 4194303 | 0 | 2^32 | 7.8e11 | 2.4e10 | n/a | NON-UNIFORM (plant) |
|
|
| 20733 | 1 | -0.71 | 0 | 863 | 1202 | 0.11 | -0.60 | pending | uniform |
|
|
|
|
Reading: after one application the 2^32 round-0 inputs already spread over the 2^22 lines as a uniform draw
|
|
would (Poisson 1024 per bin: min 871, max 1191 are the expected extremes over 4 million bins). The multiply layer
|
|
on the 8 affine words and one double round are enough for the line index as a histogram. This is a histogram
|
|
test, not an independence test: Q2b measures whether individual t bits still leak into individual index bits.
|
|
|
|
## Q2: single-bit avalanche on random states (the regime of rounds 1 to 8)
|
|
|
|
Command (build-1), per k: `adv-mixer-3 sac --day 20729 --apps k --start 8 --states 2^24 --threads 64`.
|
|
Keys round_key(8..8+k-1) (round 1's keys). Logs: sac-20729-k<k>.log.
|
|
|
|
Plants: `--plant one --apps 8` (one application in place of eight) fired with 1,959 holes and 89,129 cells
|
|
beyond 6 sigma at 65,536 states. `--plant weak --apps 8` (MUL 1, RC 0, ROT 16) did NOT fire at k = 8: 0 holes,
|
|
worst z 4.88. Eight double rounds of a constant-free ARX permutation on random 512-bit inputs diffuse fully, so
|
|
"weak" is a known-failed shape at k = 1 only (a sibling's census fired it there; this lane's 4,096-state smoke
|
|
run at k = 1 fired it too: 14,364 holes). The `one` plant is the firing check of this row.
|
|
|
|
| Day | k | states | holes | cells beyond 6 sigma | worst cell | worst p | line-index cells beyond 6 sigma (of 11,264) | verdict |
|
|
|---|---|---|---|---|---|---|---|---|
|
|
| 20729 | 1 | 2^24 | 354 | 129,726 | in 279 (word 8) to out 64 (word 2) | 1.0000 | 7,930 | DISTINGUISHED |
|
|
| 20729 | 2 | 2^24 | 0 | 0 | in 322 (word 10) to out 373 (word 11) | 0.49942 (z -4.74) | 0 | inside the band |
|
|
| 20729 | 3 | 2^24 | 0 | 0 | in 370 (word 11) to out 88 (word 2) | 0.49936 (z -5.28) | 0 | inside |
|
|
| 20733 | 1 | 2^24 | 266 | 136,797 | in 30 (word 0) to out 32 (word 1) | 1.0000 | pending | DISTINGUISHED |
|
|
| 20729 | 4 | 2^24 | 0 | 0 | in 295 (word 9) to out 346 (word 10) | 0.50064 (z 5.28) | 0 | inside |
|
|
| 20733 | 2 | 2^24 | 0 | 0 | in 260 (word 8) to out 450 (word 14) | 0.49944 (z -4.59) | 0 | inside |
|
|
| 20733 | 3 | 2^24 | 0 | 0 | in 61 (word 1) to out 495 (word 15) | 0.50056 (z 4.61) | 0 | inside |
|
|
| 20733 | 4 | 2^24 | 0 | 0 | in 350 (word 10) to out 23 (word 0) | 0.50057 (z 4.67) | 0 | inside |
|
|
| 20730 | 2 | 2^24 | 0 | 0 | queue 07, run by adv-mixer | mean flip 0.50000 | pending | inside |
|
|
| 20730 | 3 | 2^24 | 0 | 0 | queue 07, run by adv-mixer | mean flip 0.50000 | pending | inside |
|
|
|
|
Reading: one application on a random 512-bit state leaves 354 deterministic cells (an input bit that always
|
|
or never flips a given output bit) and 129,726 of 262,144 cells beyond 6 sigma; 7,930 of the 11,264 cells that
|
|
feed the line index are among them. Two applications leave no cell beyond 6 sigma at 2^24 states (band 0.0015).
|
|
The worst z of -4.74 is the expected extreme of 262,144 standard normals. The margin on this statistic is 1 of
|
|
the 8 applications between reads, the same as on the round-0 input (Q2b).
|
|
|
|
## Q2b: t-bit avalanche on the round-0 input
|
|
|
|
Command (build-1), per k: `adv-mixer-3 sac0 --day 20729 --apps k --states 2^24 --threads 64` (v2 binary).
|
|
Logs: sac0-20729-k<k>.log. Plant k = 0 (the init alone) fired: 12,439 holes of 16,384 cells.
|
|
|
|
| Day | k | states | holes | cells beyond 6 sigma (of 16,384) | worst cell | worst p | line-index cells beyond 6 sigma (of 704) | verdict |
|
|
|---|---|---|---|---|---|---|---|---|
|
|
| 20729 | 1 | 2^24 | 0 | 218 | t bit 31 to state bit 53 (word 1) | 0.7427 | 18 | DISTINGUISHED |
|
|
| 20729 | 2 | 2^24 | 0 | 0 | t bit 23 to bit 147 | 0.49949 (z -4.19) | 0 | inside the band |
|
|
| 20729 | 3 | 2^24 | 0 | 0 | t bit 26 to bit 219 | 0.49955 (z -3.73) | 0 | inside |
|
|
| 20729 | 4 | 2^24 | 0 | 0 | t bit 30 to bit 329 | 0.50051 (z 4.15) | 0 | inside |
|
|
| 20729 | 5 | 2^24 | 0 | 0 | t bit 31 to bit 162 | 0.49947 (z -4.32) | 0 | inside |
|
|
| 20729 | 6 | 2^24 | 0 | 0 | t bit 26 to bit 194 | 0.50050 (z 4.08) | 0 | inside |
|
|
| 20729 | 7 | 2^24 | 0 | 0 | t bit 6 to bit 390 | 0.49943 (z -4.69) | 0 | inside |
|
|
| 20729 | 8 | 2^24 | 0 | 0 | t bit 13 to bit 9 | 0.49947 (z -4.33) | 0 | inside |
|
|
| 20729 | 2 | 2^28 | 0 | 0 | t bit 8 to bit 352 | 0.49987 (z -4.30) | 0 | inside (band 0.00018) |
|
|
| 20729 | 3 | 2^28 | 0 | 0 | t bit 26 to bit 97 | 0.50015 (z 4.76) | 0 | inside (band 0.00018) |
|
|
| 20729 | 4 | 2^28 | 0 | 0 | t bit 17 to bit 8 | 0.49986 (z -4.64) | 0 | inside (band 0.00018) |
|
|
| 20733 | 0 | 65,536 | 12,448 | 16,094 | t bit 0 to bit 0 | 0.0000 | 704 of 704 | DISTINGUISHED (plant) |
|
|
| 20733 | 1 | 2^24 | 0 | 502 | t bit 31 to state bit 127 (word 3) | 0.7595 | pending | DISTINGUISHED |
|
|
| 20733 | 2 | 2^24 | 0 | 0 | t bit 11 to bit 337 | 0.49946 (z -4.45) | 0 | inside |
|
|
| 20733 | 3 | 2^24 | 0 | 0 | t bit 23 to bit 219 | 0.49952 (z -3.97) | 0 | inside |
|
|
| 20733 | 4 | 2^24 | 0 | 0 | t bit 23 to bit 220 | 0.50051 (z 4.19) | 0 | inside |
|
|
| 20733 | 5 | 2^24 | 0 | 0 | t bit 29 to bit 48 | 0.49948 (z -4.25) | 0 | inside |
|
|
| 20733 | 6 | 2^24 | 0 | 0 | t bit 20 to bit 404 | 0.49950 (z -4.13) | 0 | inside |
|
|
| 20733 | 7 | 2^24 | 0 | 0 | t bit 29 to bit 239 | 0.49953 (z -3.86) | 0 | inside |
|
|
| 20733 | 8 | 2^24 | 0 | 0 | t bit 2 to bit 370 | 0.50056 (z 4.62) | 0 | inside |
|
|
|
|
Why k = 1 has deterministic cells and k = 2 has none (read from the code, `memhard::qr` and `mixer`): a
|
|
difference whose lowest set bit is at position j keeps that lowest bit through an XOR with a constant, through a
|
|
multiply by an odd constant (the product difference is odd times the difference, so its lowest set bit stays at
|
|
j) and through an addition (the lowest changed bit of a sum is the lowest changed bit of the addends when only
|
|
one addend changes). So a single flipped bit walks one application as a deterministic lowest-bit trail: a += b
|
|
fixes bit j of a, d ^= a fixes bit j of d, the rotation moves it to j + r1, and so on through the 8 quarter
|
|
rounds (the 35 to 40 fixed bits per difference that Q3 counts). After one application the difference sits in
|
|
every word with several set bits, both addends of every add now carry a difference, and the lowest-bit rule no
|
|
longer applies: the trail ends. That is the mechanism behind the margin of 1 in every avalanche row.
|
|
|
|
Reading: on the real input of round 0 (one 32-bit t), one application leaves a 24 percent bias on 218 of the
|
|
16,384 (t bit, state bit) cells and on 18 of the 704 cells that feed the first line index. Two applications leave
|
|
nothing at 2^24 states (band 0.0015). The margin on this statistic is 1 of the 8 applications before the first
|
|
read: the first read's address is not predictable from t after 2 of its 8 applications, at this band.
|
|
|
|
## Q3: differential multiplicity
|
|
|
|
Command (build-1), per k: `adv-mixer-3 diff --day 20729 --apps k --start 8 --samples 2^20 --threads 64`.
|
|
576 input differences (512 single bits, 64 random two-bit), 2^20 random pairs each, the 512-bit output difference
|
|
hashed to 64 bits; the band for one output difference is 2^-19 (multiplicity 2 or more). Plant `nomul` at k = 1
|
|
fired: 7,992 deterministic output bits (day 20729), 7,189 (day 20733). Logs: diff-<day>-k<k>.log.
|
|
|
|
| Day | k | max multiplicity of one output difference | deterministic output bits (all 576 differences) | max in one difference | pairs with 2 or more zero output words | verdict |
|
|
|---|---|---|---|---|---|---|
|
|
| 20729 | 1 | 1 | 695 | 35 of 512 | 0 | DISTINGUISHED (deterministic bits) |
|
|
| 20729 | 2 | 1 | 0 | 0 | 0 | inside the band |
|
|
| 20729 | 3 to 7 | 1 | 0 | 0 | 0 | inside |
|
|
| 20733 | 1 | 1 | 537 | 40 of 512 | 0 | DISTINGUISHED (deterministic bits) |
|
|
| 20733 | 2 to 7 | 1 | 0 | 0 | 0 | inside |
|
|
|
|
Reading: at k = 1 a single-bit input difference fixes 35 to 40 output bits (the quarter-round structure: the
|
|
first add and XOR of a column pass a flipped bit on deterministically before the rotations spread it), but no
|
|
full output difference repeats even once in 2^20 pairs, because the other 470 bits of the difference are
|
|
spread. At k = 2 no output bit is fixed by any of the 576 input differences. Differentials of probability above
|
|
2^-19 do not exist for these input differences past k = 1. The truncated form (whole output words unchanged)
|
|
never beats the random rate at any k.
|
|
|
|
## Q4: single-bit linear correlations
|
|
|
|
Command (build-1), per k: `adv-mixer-3 lin --day 20729 --apps k --start 8 --samples 2^26 --threads 64`.
|
|
Band: 6 sigma = 0.00073. Plant k = 0 fired (c = 1.0 on the 512 diagonal cells).
|
|
|
|
| Day | k | samples | worst c | worst z | cells beyond 6 sigma (of 262,144) | line-index worst z | output balance worst z | verdict |
|
|
|---|---|---|---|---|---|---|---|---|
|
|
| 20729 | 1 | 2^26 | -0.00056 | -4.61 | 0 | -3.72 | 3.82 | inside the band |
|
|
| 20729 | 2 | 2^26 | 0.00058 | 4.73 | 0 | 4.09 | 3.47 | inside |
|
|
| 20729 | 3 | 2^26 | 0.00056 | 4.61 | 0 | -3.95 | 3.17 | inside |
|
|
| 20729 | 4 | 2^26 | -0.00056 | -4.61 | 0 | 4.18 | 3.08 | inside |
|
|
| 20729 | 5 | 2^26 | 0.00057 | 4.64 | 0 | 4.14 | 3.27 | inside |
|
|
| 20729 | 6 | 2^26 | -0.00055 | -4.54 | 0 | pending | pending | inside |
|
|
| 20729 | 7 | 2^26 | -0.00055 | -4.51 | 0 | pending | pending | inside |
|
|
| 20733 | 1 | 2^26 | -0.00056 | -4.60 | 0 | pending | pending | inside |
|
|
| 20733 | 2 | 2^26 | -0.00056 | -4.60 | 0 | pending | pending | inside |
|
|
| 20733 | 3 | 2^26 | -0.00062 | -5.10 | 0 | pending | pending | inside |
|
|
| 20733 | 4 | 2^26 | 0.00060 | 4.95 | 0 | pending | pending | inside |
|
|
| 20733 | 5 | 2^26 | -0.00060 | -4.94 | 0 | pending | pending | inside |
|
|
| 20733 | 6 | 2^26 | -0.00056 | -4.58 | 0 | pending | pending | inside |
|
|
| 20733 | 7 | 2^26 | 0.00059 | 4.83 | 0 | pending | pending | inside |
|
|
| 20733 | 8 | 2^26 | -0.00060 | -4.95 | 0 | pending | pending | inside |
|
|
|
|
Reading: a single input bit and a single output bit have no measurable linear correlation after one application
|
|
on random states. The worst z of 4.6 to 4.7 over 262,144 cells is what 262,144 draws of a standard normal give
|
|
(expected maximum about 4.8). This is the single-bit mask family only; multi-bit masks are owed work.
|
|
|
|
## Q4b: t-bit linear correlations on the round-0 input
|
|
|
|
Command (build-1), per k: `adv-mixer-3 lin0 --day 20729 --apps k --samples 2^26 --threads 64` (x = the 32 bits
|
|
of t, y = the state after the init and k applications). Plant k = 0 fired: c = 1.0 between t bit 0 and s[8] bit 0
|
|
(the init's `t * MUL[0] + RC[0]` has bit 0 = t bit 0 XOR RC bit 0), 65 cells beyond 6 sigma.
|
|
|
|
| Day | k | worst c | worst z | cells beyond 6 sigma (of 16,384) |
|
|
|---|---|---|---|---|
|
|
| 20729 | 1 | 0.00048 | 3.93 | 0 |
|
|
| 20729 | 2 | 0.00059 | 4.85 | 0 |
|
|
| 20729 | 3 | 0.00051 | 4.14 | 0 |
|
|
| 20729 | 4 | 0.00049 | 4.04 | 0 |
|
|
| 20729 | 5 | -0.00057 | -4.67 | 0 |
|
|
| 20729 | 6 | -0.00048 | -3.97 | 0 |
|
|
| 20729 | 7 | 0.00058 | 4.76 | 0 |
|
|
| 20729 | 8 | -0.00051 | -4.15 | 0 |
|
|
| 20733 | 1 | 0.00047 | 3.82 | 0 |
|
|
| 20733 | 2 | 0.00056 | 4.60 | 0 |
|
|
| 20733 | 3 | 0.00051 | 4.19 | 0 |
|
|
| 20733 | 4 | 0.00052 | 4.25 | 0 |
|
|
| 20733 | 5 | 0.00049 | 4.02 | 0 |
|
|
| 20733 | 6 | -0.00050 | -4.08 | 0 |
|
|
| 20733 | 7 | -0.00046 | -3.74 | 0 |
|
|
| 20733 | 8 | -0.00058 | -4.75 | 0 |
|
|
|
|
Reading: no t bit has a linear correlation with any state bit after one application, at a band of 0.00073. The
|
|
24 percent avalanche bias of Q2b at k = 1 is a differential effect (a flipped t bit flips a state bit with
|
|
probability 0.74), not a linear one.
|
|
|
|
## Q5: rotational-XOR
|
|
|
|
Command (build-1): `adv-mixer-3 rx --day 20729 --apps k --start 8 --samples 2^22`. Plant `weak0` (MUL 1, RC 0,
|
|
ROT 16, round key 0: a constant-free ARX round) at k = 1 fired on both days (day 20733: 739, 222): at r = 1, 740 of 2^20 samples had a zero
|
|
rotational-XOR difference in one word and the difference 0x00000001 repeated 784 times; at r = 16, 245 zero
|
|
differences. Real day:
|
|
|
|
| Day | k | samples | zero-difference words, max over 16 words, at r = 1 / 8 / 16 | most frequent per-word difference, multiplicity | verdict |
|
|
|---|---|---|---|---|---|
|
|
| 20729 | 1 | 2^22 | 0 / 0 / 0 (random expects 0.001) | 3 / 3 / 3 (birthday expectation at 2^22 draws of 32 bits: 3) | no RX property |
|
|
| 20729 | 2 | 2^22 | 0 / 0 / 0 | 3 / 3 / 3 | no RX property |
|
|
| 20729 | 3 | 2^22 | 0 / 0 / 0 | 3 / 3 / 3 | no RX property |
|
|
| 20729 | 4 | 2^22 | 0 / 0 / 0 | 3 / 3 / 3 | no RX property |
|
|
| 20733 | 1 to 4 | 2^22 | 0 / 0 / 0 on every row | 3 / 3 / 3 on every row | no RX property |
|
|
|
|
Reading: rotational-XOR cryptanalysis needs the constants to be rotation-friendly; here every word is XORed with
|
|
a drawn 32-bit constant plus the round key and then multiplied by a drawn odd constant before the ARX layer, so
|
|
the rotational pair (x, x <<< r) loses its relation inside the first layer. No RX property reaches k = 1.
|
|
|
|
## Q6: SAT on the round-0 input
|
|
|
|
Command (build-1, smoke run): `adv-mixer-3 cnf --day 20729 --apps 1 --t0 0x12345678 --out k1.cnf` then
|
|
`cadical -q k1.cnf`. CNF: 33,873 variables, 112,328 clauses (Tseitin: t is 32 variables; each constant multiply
|
|
is a shift-add chain of 32-bit ripple adders over the set bits of MUL; each quarter round four adders; rotations
|
|
are wires; constants are folded). Result: `s SATISFIABLE`, 137.06 s wall on the loaded box; the model gives
|
|
t = 0x49880000; `adv-mixer-3 verify --day 20729 --apps 1 --t 0x49880000` prints index 0x20eb79, the target.
|
|
|
|
Honest cost of the same task: about 2^10 random t each through one application, under 2^18 integer operations,
|
|
under a millisecond on one core. The solver at k = 1 is five orders slower than the honest search.
|
|
|
|
| Day | k | CNF variables | CNF clauses | result | wall | model verified |
|
|
|---|---|---|---|---|---|---|
|
|
| 20729 | 1 (smoke, build-1) | 33,873 | 112,328 | SATISFIABLE | 137 s | t = 0x49880000, index 0x20eb79 = target |
|
|
| 20729 | 1 (queue 08, build-2) | 33,873 | 112,328 | SATISFIABLE | 1,593 s (box at load 500) | the same t |
|
|
| 20729 | 2 | 68,624 | 227,767 | not run (the lease was withdrawn before it was granted) | | |
|
|
|
|
Reading: the one-application model is a 32-variable problem with 112 k clauses of ripple-carry adders (16
|
|
constant multiplies of up to 32 adders each dominate). CaDiCaL needs minutes on it where the honest search needs
|
|
a millisecond, and the k = 2 model doubles the clause count. The SAT route to the first read's address is not a
|
|
shortcut at k = 1; the rows for k = 2 to 4 say how fast it gets worse.
|
|
|
|
## Box-hours
|
|
|
|
Rule changes during the pass (so the hours stay honest): 18:4x UTC the build-server lane dropped the SIGSTOP
|
|
yield-to-builds rule and set every sweep to nice 10 on cores 8 to 95; the same lane moved every log, pid file and
|
|
CNF out of the worktree mirror into /srv/builds/_adv-mixer-3/. Both applied before the first sweep started. 18:56 UTC the same lane set one bounded sweep per box across all lanes (`flock /srv/builds/_adv/locks/sweep.lock`, 88 threads): queue 01 (index 20729, k = 5..8 left) and 02 (index 20733, k = 2..8 left) were killed by pid file at 18:57 and 18:58 UTC as the lowest-value runs and re-queued as queue 10 under the lock; the six other sweeps that had started were left to finish; nothing new starts outside the lock.
|
|
|
|
| Step | Box | Start (UTC) | Wall | Note |
|
|
|---|---|---|---|---|
|
|
| Build harness (two builds, one fix) | build-1 | 18:36 | 29 s | |
|
|
| Build harness | build-2 | 18:44 | 14 s | |
|
|
| CaDiCaL from source | build-1, build-2 | 18:42, 18:44 | about 1 min each | |
|
|
| Smoke plants and k = 1 SAT | build-1 | 18:38 | 3 min | |
|
|
| Queue 01, 03, 05 | build-1 | 18:42 | running | |
|
|
| Queue 02, 04, 06, 08 | build-2 | 18:47 | running | |
|
|
| Queue 09 (sac0) | build-1 | 18:50 | running | |
|
|
| Queue 01 and 02 killed | build-1, build-2 | 18:57, 18:58 | 15 min, 11 min | the one-sweep-per-box rule; re-queued as 10 |
|
|
| Queue 10 (index 20729 k = 5..8, 20733 k = 5..8) under the sweep lock | build-1 | 19:00 | 21 min | 20729 k = 5..8 done; 20733 k = 5 was running when killed |
|
|
| Queue 16 (index 20733 k = 2..4) under the sweep lock | build-2 | 19:13 | 7 min | k = 2 was running when killed |
|
|
| Every adv-mixer-3 process killed | build-1, build-2 | 19:20:51 to 19:21:01 | | main's rule (relayed by the coordinator at 19:20 UTC): no sweep starts except through the build-server lane's `lease pool`; everything hand-started is killed now. Killed by pid file, process group: 03 (sac 20729: k = 5 at 2^24 and the 2^27 rows lost), 09 (sac0: the day 20733 2^28 rows lost), 10 (index 20733 k = 5..8 lost), 04 (sac 20733 k = 5..8 lost), 08 (CaDiCaL on k = 2 for 20729, about 7 min in, lost; k = 3, 4 and day 20733 not started), 16 (index 20733 k = 2..4 lost). Zero processes of this lane remained on either box at 19:21:01 UTC. Nothing of this lane ran until `lease pool` existed |
|
|
| Re-queue through `lease pool` | build-1 (queue 17: sac 20729 k = 5..8 and 2^27 rows, sac 20733 k = 5..8, index 20733 k = 2..8, sac0 20733 2^28 rows), build-2 (queue 18: CaDiCaL k = 2..4, both days) | 19:24 UTC (relaunched 19:2x after a guard line refused on the first start) | running | `lease pool 48 --min 16` per census (the lease sizes the harness threads to the cores it took), `lease pool 1 --min 1` per CaDiCaL; waits behind the release builds and the class v5 suites, which outrank every sweep tonight |
|
|
| v5 yield | both | 19:26, widened 19:31 | | before every lease the driver sleeps while any waiter in `lease status` is owned by class-v5 or labelled v5; both drivers restarted with the rule before their first lease was granted; refined 19:32 to yield by owner (class-v5, or attack-pass with v5), never to another adv- lane |
|
|
| Queue 18 withdrawn from build-2 | build-2 | 19:35 | 0 (no lease was ever granted) | main's order: every adv-* waiter leaves box 2 until the class v5 census runs; the SAT rows k = 2..4 re-queue there afterwards |
|
|
| Priority classes in the lease (release > v5 > measure > adv) | build-1 | 19:42 | | queue 17 killed and re-submitted once under the ranked tool as `lease pool 32 --min 16` (an adv holder at 32 threads or fewer is never pre-empted); waiting on free cores at 19:43 UTC |
|
|
| Queue 07 (8 random days) | build-1 | 18:5x | running | claimed and run by the sibling lane adv-mixer from the shared queue; its logs are index-<day>-k<k>.log and sac-<day>-k<k>.log under /srv/builds/_adv-mixer-3/logs/ on build-1, read by this lane |
|
|
|
|
## The round margin, stated
|
|
|
|
Internal adversarial pass, not an independent review. Against the 8 applications between dependent cache reads
|
|
and the 72 per item, on the two real days 20729 and 20733:
|
|
|
|
| Statistic | Reaches k = 1 | Reaches k = 2 | Margin between reads | Margin per item |
|
|
|---|---|---|---|---|
|
|
| Single-bit avalanche on random 512-bit states (Q2), 2^24 states | yes (354 and 266 deterministic cells, 130 k cells beyond 6 sigma) | no (0 cells at band 0.0015) | 8 - 1 = 7 | 71 |
|
|
| t-bit avalanche on the round-0 input (Q2b), 2^24 and 2^28 states | yes (24 to 26 percent bias on 218 and 502 cells) | no (0 cells at band 0.00018) | 7 | 71 |
|
|
| Deterministic output bits of a low-weight input difference (Q3), 2^20 pairs | yes (35 to 40 bits fixed per single-bit difference) | no | 7 | 71 |
|
|
| Any repeating full output difference (Q3), band 2^-19 | no | no | 8 | 72 |
|
|
| Single-bit linear correlation (Q4, Q4b), band 0.00073 | no | no | 8 | 72 |
|
|
| Rotational-XOR (Q5), 2^22 samples | no | no | 8 | 72 |
|
|
| Round-0 line-index histogram over all 2^32 t (Q1) | no (uniform from k = 1, through k = 8) | no | 8 | 72 |
|
|
| SAT preimage of the round-0 line index (Q6) | k = 1 solved, 137 s, five orders slower than the honest 2^10 trials | not run (killed at 19:20 UTC) | not a shortcut at k = 1 | |
|
|
|
|
Every statistic that reaches k = 1 is the lowest-set-bit trail through one application (the mechanism in Q2);
|
|
none reaches k = 2 at the bands above. The bound: no distinguisher in this pass survives 2 of the 8 keyed
|
|
applications between reads, so 6 of the 8 are margin on every measured statistic, and 70 of the 72 per item. A
|
|
shortcut was not found: no method here saves even one application against the honest 9,360 ops per item of
|
|
chip-model-v3.md. What the bands do not cover: biases below 0.00018 (Q2b) or 0.0015 (Q2), correlations below
|
|
0.00073 with multi-bit masks, differentials below 2^-19, and any structure a SAT model of 2 or more applications
|
|
would expose. Unknown: whether the sibling lanes' censuses over random days change any row.
|
|
|
|
## What a longer pass would add
|
|
|
|
Multi-bit linear masks and a MILP trail bound; the SAT model on the full 512-bit state with a cache-line XOR
|
|
between applications; 2^30 states on the k that sits at the band. None of these is a reason to wait on the
|
|
numbers above.
|