OpenSourceCheck

OSC-2026-0002 · github.com/bitcoindevkit/bdk_wallet

info clean-run claude-fable-5 2026-08-04 signed: nostr

Repository
github.com/bitcoindevkit/bdk_wallet
Commit
fc88144fc8e9532bc23ad490cb2de0445401b8b1
Scope path
src/keys/
Model
claude-fable-5
Harness
claude-code
Prompts
prompts/entropy-rng-audit-v1.md
Independent runs
1
Transcript sha256
d2585d81890c746f163b8d0de60b0d629fb08f277de4e161103aea00085bf9a5
Auditor
TheIcarusWings (theicaruswings)
Signature
nostr-schnorr · npub19tzp8lf3klmqj3dz9mz0qnuvjp7uyy9993gmljmyaxs8phztj7wsnujvq5

Scope. The entropy/RNG path feeding BIP-39 mnemonic and key generation in src/keys/ (mod.rs GeneratableKey trait; bip39.rs Mnemonic impl). Traced every path from generate() to the bytes that become a mnemonic, at HEAD commit fc88144f. In scope: CSPRNG selection, the CryptoRng bound on generate_with_aux_rand, entropy sizing and possible truncation/reuse. NOT in scope: descriptor parsing, PSBT signing, chain sync, transaction building, FFI bindings, or the correctness of the upstream `rand`/`bip39` crates themselves.

Findings

info OSC-2026-0002-F1 unreviewed

Seed-generation entropy path is sound and resistant to the Coldcard failure mode. generate() draws from the rand crate's CSPRNG (bitcoin::key::rand::thread_rng), and generate_with_aux_rand bounds its rng as `impl CryptoRng + RngCore` — so a non-cryptographic RNG is rejected at compile time, with no silent weak-PRNG fallback. A full 32 bytes are drawn and correctly sliced to word_count/8 (128 bits for 12 words); no truncation or reuse. Observation (not a defect): generate_with_aux_rand trusts the caller's rng — CryptoRng asserts suitability, not true entropy — so a caller passing a misconfigured or deliberately-seeded CryptoRng could still get weak keys. The default path is correct.

src/keys/mod.rs:642 (generate_with_aux_rand), src/keys/bip39.rs:141 (generate_with_entropy) · CWE-330