xxh3-128 under the random-secret model: independent verification (2026-09-19)

Verification lane, separate from the searcher’s ../rs128.c harness: a fresh sampler (verify_rs128.c), a different RNG family (128-bit Lehmer MCG instead of xoshiro256**), own pair constructions (gen_pairs.py, seed 91919), and the upstream header fetched directly from GitHub on the compute host rather than the searcher’s vendored copy.

Source and self-checks

Key model sampled

Per trial: 24 uniform 64-bit words -> 192-byte secret (little-endian), plus an independent uniform 64-bit seed. secret mode calls XXH3_128bits_withSecret(m, len, secret, 192) (public API, seed 0); secretseed mode calls XXH3_128bits_internal with the random seed AND the random secret; seed mode is the row’s current model (XXH3_128bits_withSeed, default kSecret). A hit is equality of BOTH low64 and high64 for the pair under the same key.

Results

Current row pair F (32 B, L = 4 words) – full 128-bit collisions

leg (log) key model count / N rate 95% CI (log2) cap bits, 95% CI
F_secret_2p34_r1001 uniform 192-B secret, XXH3_128bits_withSecret (seed 0) 156 / 2^34 2^-26.71 [-26.95, -26.49] 28.71 [28.49, 28.95]
F_secretseed_2p33_r1002 uniform secret AND uniform seed (XXH3_128bits_internal) 84 / 2^33 2^-26.61 [-26.93, -26.30] 28.61 [28.30, 28.93]
F_seed_2p32_r1003 (control) default kSecret, uniform 64-bit seed (row’s current model) 44 / 2^32 2^-26.54 [-27.00, -26.12] 28.54 [28.12, 29.00]
family_secret_2p32_r1004 (F_row line) uniform secret, second stream 60 / 2^32 2^-26.09 [-26.48, -25.73] 28.09 [27.73, 28.48]
pooled, uniform secret (156+60+84) secret and secret+seed 300 / (234+232+2^33) 2^-26.58 [-26.75, -26.42] 28.58 [28.42, 28.75]

Searcher’s own leg for the same model (../logs/F_secret_2p34_s11.txt, xoshiro stream 11): 179 / 2^34 = 2^-26.52 [-26.74, -26.30]; overlaps with every row above. Combined with my withSecret legs (156+60+179 over 234+232+2^34): 395 / 2^35.32 = 2^-26.60.

Conclusion for (a): the random-secret rate of pair F equals the default-secret row figure (165 / 2^34 = 2^-26.63, 95% [-26.86, -26.41]) within noise; the seed adds nothing on top of a uniform secret (secretseed leg indistinguishable from the secret leg). Row score under the random-secret model: bits ~28.6, direction estimated upper bound (sampled cap at L = 4).

Proposed best pair / family (uniform 192-B secret, 2^32 keys each, log family_secret_2p32_r1004)

pair (own construction unless noted) len count rate 95% CI (log2)
own_sum_-1_block0 (w1 = ~w0, both complemented) 32 40 2^-26.68 [-27.16, -26.23]
own_sum_-1_block0_b 32 48 2^-26.42 [-26.85, -26.01]
own_sum_2^63-1_block0 (w1 = ~w0 ^ 2^63) 32 49 2^-26.39 [-26.82, -25.98]
own_sum_-1_block1 (same on words 2,3) 32 40 2^-26.68 [-27.16, -26.23]
own_twin_sum_2^62-1_block0 32 8 2^-29.00 [-30.21, -28.02]
own_twin_sum_263+262-1_block0 32 5 2^-29.68 [-31.30, -28.46]
own_complement_random_sum_control (both words complemented, sum not preserved) 32 0 < 2^-30.12 (97.5%)
own_random_pair_control 32 0 < 2^-30.12
xxh3-64 memo NAF pair (default-secret trick) 32 0 < 2^-30.12
own_64B_sum_-1_block0 64 43 2^-26.57 [-27.04, -26.14] (L = 8: cap 29.6)
own_160B_sum_-1_block0 160 34 2^-26.91 [-27.44, -26.43] (L = 20: cap 31.2)

Conclusion for (b): every member of the sum -1 / sum 2^63-1 complement class sits at the same ~2^-26.6 regardless of the words, the block, or the length, so the rate is pair-independent and no member beats pair F; the best cap is the 32-byte one (L = 4), ~28.6 bits. The TWIN classes (sum 2^62-1, 263+262-1) are NOT at the class rate: pooled 13 / 2^33 = 2^-29.3 [-30.21, -28.53], i.e. about 6x rarer, matching the fold ‘differ by exactly 2^63’ event (35 / 2^34 = 2^-28.9 in fold_check). The controls (random pair, sum-breaking complement, the xxh3-64 NAF pair) give zero hits in 2^32, so the NAF trick does not transfer to a uniform secret.

Hash-independent check of the prediction

fold_check 34 5 4 (logs/fold_check_2p34.txt): Pr[fold(A,B) = fold(A,B)] for independent uniform A, B, fold(a,b) = lo64(ab) ^ hi64(ab): 165 / 2^34 = 2^-26.63 (twin-by-2^63 events: 35). This is the event that decides pair F once the two 16-byte-block words are XORed with uniform secret words, and it is the same number as the default-secret row figure (165 / 2^34).

Reproduction (compute host: Xeon, nice -n 10 taskset -c 24-31, 8 threads)

curl -sSL -o xxhash.h https://raw.githubusercontent.com/Cyan4973/xxHash/v0.8.3/xxhash.h
curl -sSL -o xxhash.c https://raw.githubusercontent.com/Cyan4973/xxHash/v0.8.3/xxhash.c
sha256sum xxhash.h xxhash.c
cc -O2 -std=gnu11 -pthread -o verify_rs128 verify_rs128.c -lm
cc -O2 -o witness_check witness_check.c xxhash.c
cc -O2 -pthread -o fold_check fold_check.c -lm
python3 gen_pairs.py                      # row.txt, family.txt
./run_verify.sh                           # selftest + the four legs below, logs in logs/
./verify_rs128 secret     34 1001 8 row.txt
./verify_rs128 secretseed 33 1002 8 row.txt
./verify_rs128 seed       32 1003 8 row.txt
./verify_rs128 secret     32 1004 8 family.txt
./fold_check 34 5 4
python3 ci_check.py <count> <N> 4         # exact Poisson 95% CI, cap bits for L = 4 words

All counts are deterministic given (mode, log2N, rngseed, threads).