BTCRECOVER / TESTED LABORATORY
BTCRecover candidate lab: 10 reproducible exercises
Download synthetic tokenlists and passwordlists, inspect expected candidates, and reproduce ten checks against a pinned BTCRecover revision.
What we tested
Ten small candidate-generation exercises were run with BTCRecover using invented inputs. All ten produced exactly the expected candidate sets. No wallet file, real password, seed phrase or private key was used. These results validate these examples only; they are not wallet-recovery, GPU or performance benchmarks.
Pinned upstream commit: 1457088acf17630eb12a5b53989982ac34e55f2a. The tool reported 1.13.0-Cryptoguide. Optional native secp256k1 libraries were absent; that warning is not a wallet-speed measurement.
| Experiment | Candidates | Result |
|---|---|---|
| Required lines and fixed ends | 2 | Pass |
| An optional suffix | 4 | Pass |
| Removing the ordering anchors | 12 | Pass |
| One unknown decimal digit | 10 | Pass |
| Two unknown decimal digits | 100 | Pass |
| A restricted character set | 2 | Pass |
| A literal space within one token | 1 | Pass |
| Whole passwords preserve spaces | 2 | Pass |
| At most one letter-case change | 12 | Pass |
| A token-count limit excludes combinations | 3 | Pass |
Download and reproduce
Install the maintained BTCRecover project in an appropriate local environment. For matching revision results, use the commit linked above. Extract the practice ZIP, then copy the ten input .txt files into your BTCRecover directory and run the commands below from there. Files ending in -expected.txt contain sorted expected candidates, not input rules.
The ZIP also includes verify.py and results.json. To run all checks automatically from the extracted candidate-lab folder, pass the path to your BTCRecover checkout:
python verify.py "PATH/TO/btcrecover"The verification script runs only --listpass, checks the checkout commit, and compares candidate sets rather than their order. It stops if the pinned tool’s output format changes. BTCRecover may print warning and file-loading messages around the candidate stream; those diagnostic messages are not candidates.
Required lines and fixed ends
Three required lines; two year choices; fixed beginning and end. Two candidates are included.
+ ^River
+ 2021 2022
+ !$python btcrecover.py --listpass --tokenlist anchored.txtObserved: 2 candidates; exact expected set matched.
River2021!
River2022!An optional suffix
Only the suffix becomes optional. Each of the two years appears both with and without the exclamation mark.
+ ^River
+ 2021 2022
!$python btcrecover.py --listpass --tokenlist optional.txtObserved: 4 candidates; exact expected set matched.
River2021
River2021!
River2022
River2022!Removing the ordering anchors
All lines remain required, but the three pieces can occupy six different orders for each year choice.
+ River
+ 2021 2022
+ !python btcrecover.py --listpass --tokenlist order.txtObserved: 12 candidates; exact expected set matched.
!2021River
!2022River
!River2021
!River2022
2021!River
2021River!
2022!River
2022River!
River!2021
River!2022
River2021!
River2022!One unknown decimal digit
One decimal position provides ten choices. The letter prefix is fixed.
+ ^River
+ %d$python btcrecover.py --listpass --tokenlist digit.txtObserved: 10 candidates; exact expected set matched.
River0
River1
River2
River3
River4
River5
River6
River7
River8
River9Two unknown decimal digits
Two decimal positions provide 10 × 10 choices, including leading zeros.
+ ^River
+ %2d$python btcrecover.py --listpass --tokenlist two-digits.txtObserved: 100 candidates; exact expected set matched.
River00
River01
River02
River03
River04
…
River99A restricted character set
Restricting the character set to 2 or 7 leaves only two choices.
+ ^River
+ %[27]$python btcrecover.py --listpass --tokenlist narrow.txtObserved: 2 candidates; exact expected set matched.
River2
River7A literal space within one token
The %s wildcard inserts a space within one required token. The token has no beginning or ending anchor.
+ River%sStonepython btcrecover.py --listpass --tokenlist space.txtObserved: 1 candidates; exact expected set matched.
River StoneWhole passwords preserve spaces
Each passwordlist line is a complete guess; the internal space stays part of the first guess.
River Stone!
River2022!python btcrecover.py --listpass --passwordlist literal.txtObserved: 2 candidates; exact expected set matched.
River Stone!
River2022!At most one letter-case change
Each original remains included, plus five variants with exactly one alphabetic character’s case flipped.
River2021!
River2022!python btcrecover.py --listpass --passwordlist case-typo.txt --typos 1 --typos-caseObserved: 12 candidates; exact expected set matched.
RIver2021!
RIver2022!
RiVer2021!
RiVer2022!
RivEr2021!
RivEr2022!
RiveR2021!
RiveR2022!
River2021!
River2022!
river2021!
river2022!A token-count limit excludes combinations
Three optional one-token lines are restricted to exactly one token per candidate. Multi-token combinations are excluded.
River
Stone
2022python btcrecover.py --listpass --tokenlist token-limit.txt --min-tokens 1 --max-tokens 1Observed: 3 candidates; exact expected set matched.
2022
River
StoneInterpret the results carefully
A larger candidate count is not automatically a better search. The optional-suffix fixture covers more possibilities because it relaxes a specific assumption. The unanchored fixture covers more orders, but that matters only if order is actually uncertain. None of these results estimates the probability that an unknown wallet password is among the candidates.
The downloadable results manifest records input hashes and sorted candidate-set hashes. Candidate hashes use UTF-8, LF line endings and a final newline. These hashes identify reproducible test artifacts; they are not an independent security audit.
Sources and evidence
How this material was prepared and tested. Upstream instructions can change; check your installed revision.