Regression-first BIP39 wallet-entry audit
Baseline main: 0473c3e. Before product changes, 68 new audit regressions produced 42 failures, 26 passes and zero skips. A separate run confirms all 24 official English seed vectors pass: PBKDF2-HMAC-SHA512/2048 and 64-byte output are already correct.
Findings:
- The advertised BIP39 wordlist is a generated placeholder list (word0005, etc.) with only a few official words. It fails complete-wordlist digest and entropy/mnemonic interoperability fixtures.
- MnemonicToSeed lowercases/collapses mnemonic text and omits NFKD normalization for mnemonic/passphrase. Unicode passphrases and Japanese seed vectors diverge from BIP39; raw standard seed conversion must preserve text except NFKD.
- MnemonicToEntropy accepts bad checksums and null inputs dereference. ValidateMnemonic reconstructs sensitive entropy without clearing it and duplicates decoding/checksum logic.
- HdWalletBuilder accepts invalid checksums and unknown/legacy placeholder words, returning a wallet. Accepted case/spacing formatting is not canonicalized in the returned phrase.
- GetWordCountFromEntropyBytes can accept unsupported signed integer sizes after multiplication overflow.
- Source review: captured instance policy is unused; Pbkdf2Core is created from ambient policy. Temporary bit/checksum/entropy buffers need clear ownership, including exceptional paths. Runtime-wide zeroization is not implied.
Resolution scope
Use the official 2048-word English list with attribution and digest regression. Normalize raw seed password/salt with NFKD only; retain its independent text-to-seed semantics without claiming non-English wordlist validation. Validate checksum in the shared entropy decoder; make Builder reject invalid English mnemonics and canonicalize supported case/spacing formatting before seed derivation. Propagate captured policy, guard entropy sizes before multiplication, and clear owned temporary buffers.
Migration must explain that old placeholder mnemonics are nonstandard and changing the wordlist or normalization can change the wallet. Preserve trusted existing seed/private material; do not silently translate placeholder words into a new standard mnemonic or substitute a different seed.
Reproduction:
dotnet test --project tests/HeroCrypt.Tests/HeroCrypt.Tests.csproj -c Release -f net10.0 -- --filter-class '*Bip39MnemonicTests+AuditRegressions*' --no-progress
Sources: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki ; https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt ; https://github.com/trezor/python-mnemonic/blob/master/vectors.json
Regression-first BIP39 wallet-entry audit
Baseline main: 0473c3e. Before product changes, 68 new audit regressions produced 42 failures, 26 passes and zero skips. A separate run confirms all 24 official English seed vectors pass: PBKDF2-HMAC-SHA512/2048 and 64-byte output are already correct.
Findings:
Resolution scope
Use the official 2048-word English list with attribution and digest regression. Normalize raw seed password/salt with NFKD only; retain its independent text-to-seed semantics without claiming non-English wordlist validation. Validate checksum in the shared entropy decoder; make Builder reject invalid English mnemonics and canonicalize supported case/spacing formatting before seed derivation. Propagate captured policy, guard entropy sizes before multiplication, and clear owned temporary buffers.
Migration must explain that old placeholder mnemonics are nonstandard and changing the wordlist or normalization can change the wallet. Preserve trusted existing seed/private material; do not silently translate placeholder words into a new standard mnemonic or substitute a different seed.
Reproduction:
Sources: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki ; https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt ; https://github.com/trezor/python-mnemonic/blob/master/vectors.json