mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-11-14 09:38:50 +00:00
Nested and static nested recovery ran lfsr_recovery32 once per nonce and intersected two ~2^16 candidate lists. The cipher state is linear while the nonce is fed in, so the states for one nonce are those for the other xored with a known difference. Checking both keystreams inside a single recovery leaves about one candidate instead of two large lists. lfsr_recovery32_dual() does that: it skips the early bit times where the difference prunes little (start chosen per call from an exact per bit match probability, falling back to 0 on overflow), scans the first pass 64 states at a time through a bit packed filter table, extends the tables branch free in cache sized chunks, and replaces the 512 scattered sort buckets with one contiguous counting sort. lfsr_recovery32() is rebuilt on the same machinery, so hf mf sen, mfkey32, mfkey64 and the nested tools all gain. It stays single threaded because nested_util.c already calls it from four threads. recover() takes the second keystream as optional extra state; the plain path is unchanged. Both return the same key sets as before, verified against the old code under ASan/UBSan over random and degenerate nonce pairs. nested per key: ~390 ms -> ~4 ms lfsr_recovery32 per call: ~270 ms -> ~165 ms peak RSS, single nonce: 47.6 MB -> 27.6 MB tools/mfc/protocol links pthread now, as the other two mfc tool dirs do. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>