Dynamic analysis: run 4, native seed-to-seed gap

Question

How far apart are a file’s four Yarrow seeds (key1 → iv1 → key2 → iv2) in an undebugged run? Every earlier capture used breakpoints on each seed, which inflated the gaps to 10–500 ms. recover’s cost scales with the gap window, so this is the parameter that matters most.

Method: in-process QPC logger, no seed breakpoints

What actually happened during the run

Results

129 QPC reads in total. Each caller appears in its own role:

Caller (static) Role Count
0x14004d505 / 0x14004e06f main start / end timer 1 / 1
0x14007bc49 RSA padding Yarrow seed (FUN_14007bbe0) 1
0x1400aff57 per-file coroutine start (FUN_1400ae840) 21
0x14007b237 per-value Yarrow seed (FUN_14007b1f0) 84 = 21 × 4
0x1400b1c99 per-file coroutine end 21

All 84 seeds are in increasing order. Two encryptor threads (TID 0x1F9C, 0x1B38) interleave. Gap sizes are in 100 ns ticks:

Gap n Min Median Mean Max
file start → key1 21 1 2 3.1 18
key1 → iv1 21 3,916 4,119 4,205 4,692
iv1 → key2 21 3,887 4,047 4,894 14,397
key2 → iv2 21 3,889 4,121 5,424 27,109
key1 → iv2 (whole file) 21 11,773 12,539 14,522 36,268
same thread: iv2 → next file’s key1 19 15,024 16,513 17,809 32,634
file start → file end 21 25,644 27,619 31,842 66,591

Sorted key2 → iv2 gaps: 3,889 3,892 3,904 3,911 3,913 3,922 3,925 3,945 4,040 4,094 4,121 4,231 4,244 4,255 4,296 4,308 4,344 5,073 5,078 7,404 27,109.

Interpretation

Effect on recover

Pairs = key2 window (ticks) × gap span (ticks), at ~150,000 pairs/s on the 20-thread analysis host.

key2 uncertainty Gap 3,800–5,200 (span 1,400, covers 18/21) Gap 3,800–8,000 (span 4,200, covers 20/21) Gap 3,800–28,000 (span 24,200, covers 21/21)
±0.5 ms (10,000 ticks) 1.4·10⁷ pairs, ~1.6 min 4.2·10⁷, ~4.7 min 2.4·10⁸, ~27 min
±5 ms (100,000) 1.4·10⁸, ~16 min 4.2·10⁸, ~47 min 2.4·10⁹, ~4.5 h
±50 ms (10⁶) 1.4·10⁹, ~2.6 h 4.2·10⁹, ~7.8 h 2.4·10¹⁰, ~45 h

Practical recipe:

  1. Search the narrow gap window first.
  2. Widen only if nothing is found.
  3. After the first hit, use the solved file’s seeds to bracket the next file to a few milliseconds, with the measured inter-file spacing.

The uptime estimate (boot time vs. file timestamps) remains the dominant cost; the gap no longer is.

Checked on the native outputs (artifacts/seed-gap-recover-demo-2026-10-11.txt). Both runs used a key2 window of ±2,500 ticks, a gap window of 3,800–8,000 and 16 known zero bytes:

File Candidate pairs Result
gap_00.txt.akira (Spot; its gap is the 7,404-tick outlier) 21,009,201 true key2/iv2 pair found in 70 s; decrypted all zero
gap_db_0.sqlite.akira (Full; one chunk under 0xFFFF, so KCipher-2 only) 21,009,201 found in 85 s; decrypted all zero

recover now defaults to --gap 3800:8000, and the default ChaCha-stage windows are widened to at least that range. test_real_outputs.py includes both native files (12/12 pass).

Artifacts

VM state