QTL v2: anti-lockout (QTLO) design

Revision: 1, 6 October 2026 Code: qtl_v2_guarded.py (lock), qtl_v2_tamper_test.py (test) Evidence: qtl-v2-runs/anti-lockout-20261006-193624.json

Safety rule (read first)

QTL is a research prototype for protecting test data. It must never control physical access: doors, bunkers, safe rooms, vaults, vehicles, medical devices, or anything else where a failed or delayed unlock could trap or endanger a person. Physical access systems need a mechanical override that works with no software, and people inside must always be able to get out. The lock prints this notice and stores it in every sealed header.

The problem: QTL lockout (QTLO)

In QTL v1, tampering was only detected at the very end, by AES-GCM. Test Two raised the stored Argon2 passes from 8,113 to 10,142, and the owner sat through 393.5 s of work before rejection. An attacker who can edit the file can make every unlock attempt cost as much as the code permits. A mistyped password (the fifth unlock) also cost a full 320 s.

The fix: cheapest check first

Order

Check

Catches

Cost

1

Fingerprint: SHA-256 over the whole envelope, kept by the owner outside the file

Any change to header or ciphertext

microseconds

2

Allow-list: costs, modulus size and checkpoint layout must equal a built-in profile exactly

Inflated costs, even if the attacker also replaced the stored fingerprint

microseconds

3

Password check value: HKDF of the Argon2 key

Wrong password, before the puzzle starts

one Argon2 run

4

Puzzle checkpoints: sealer-made commitments at every 1/C of the squarings. Progress is saved at each one

Damaged puzzle data, at the first checkpoint. Crashes resume instead of restarting

≤ 1/C of the puzzle

5

AES-256-GCM decrypt

Anything left

full unlock

Why the password check doesn’t weaken the lock. The puzzle result does not depend on the password. An attacker solves the puzzle once, then guesses passwords at Argon2 cost, with or without the check value. The check value only saves the honest owner time.

Test results (toy profile: 64 MiB Argon2, 150,000 squarings, 10 checkpoints)

Case

Stopped at

Time

v1 equivalent

Correct key

recovered

2.07 s

—

Test Two attack (passes → 10,142)

fingerprint

< 1 ms

393.5 s

Same, attacker also replaced the fingerprint

allow-list

< 1 ms

393.5 s

Squarings ×100, fingerprint replaced

allow-list

< 1 ms

—

Profile label swapped, fingerprint replaced

allow-list

< 1 ms

—

One ciphertext bit flipped

fingerprint

< 1 ms

full unlock

No fingerprint supplied

fingerprint (refused)

< 1 ms

—

Wrong password

password

0.05 s

320 s (fifth unlock)

Puzzle base damaged, fingerprint replaced

checkpoint 1

0.24 s (≈ 1/10)

full unlock

Interrupted at checkpoint 4, then resumed

recovered

0.82 + 1.22 s (no repeated work)

restart from zero

Tampered progress file

progress

0.04 s

—

All 12 cases passed. A 13th case, a machine too small for the Argon2 memory, was added later and is refused instantly (anti-lockout-20261006-195710.json). Keys were random, held in memory, and never written.

Remaining limits

  1. Keep the fingerprint somewhere else. If the attacker controls both the file and the place the fingerprint is kept, checks 2 and 4 still cap the damage: the worst case is one Argon2 run plus 1/C of the puzzle.

  2. Destruction can’t be undone by cryptography. Deleting every copy loses the data. Keep 2–3 copies in different places; the fingerprint finds the good one instantly. Reed-Solomon self-repair and a recovery envelope (ideas 5 and 6) are not built yet.

  3. Saved progress lets whoever holds it skip that much work. Store it owner-only (0600) and delete it after a successful unlock.

  4. mac-m1-312s (1 GiB/p=4 Argon2 × 8 passes; 23.5 M squarings). Sized from the timed run of 6 Oct 2026, in which the earlier 23.0 M version unlocked in 305.2 s (qtl-v2-runs/live-mac-m1-312s-proposed-20261006-194804.json). 23.5 M targets about 312 s on that M1 in this Python code. Faster single cores or optimized squaring software shorten the wait. This is a work lock, not a clock.

  5. RAM check. Before Argon2 starts, unlock reads this machine’s physical RAM from the OS and refuses instantly if Argon2 would need more than 50% of it. Nothing needs to be saved for this check.