key: validate BIP32 seed length in CExtKey::SetSeed
What changed, and why it matters
This commit adds a safety check to Bitcoin Core's code that creates master cryptographic keys from a seed. The BIP32 standard says seeds must be 16 to 64 bytes long, but the function previously accepted any length, including empty seeds. The fix rejects out-of-range seeds with an internal assertion. It is a hardening change rather than a fix for an active exploit path, because callers in the current codebase already supply valid-length seeds.
Review all callers of SetSeed to confirm they already enforce 16-64 byte seeds and cannot pass attacker-controlled lengths. Consider whether Assert (which aborts) is the right failure mode for production wallet code, or whether a recoverable error return would be safer. No urgent patch deployment is indicated unless a caller path with untrusted input is identified.
Security signals we found
Input validation added to cryptographic key derivation
Non-compliant BIP32 seed lengths now rejected
Defense-in-depth hardening against weak master keys
Fixes public issue #35308
Evidence from the diff
CExtKey::SetSeed() in src/key.cpp now asserts that the supplied seed is between 16 and 64 bytes inclusive, matching BIP32. Previously it accepted arbitrary spans, including zero-length seeds, and hashed them into a master key. The change uses Assert() so out-of-range lengths trigger a non-recoverable failure in debug builds and are still rejected in release builds (Assert is mapped to a non-continuing check). This prevents accidental creation of weak or non-compliant master keys if future callers pass invalid input.
Changed components
src/key.cppCExtKey::SetSeedBIP32 hierarchical deterministic wallet key derivationInspect captured patch +1 / −0
diff --git a/src/key.cpp b/src/key.cpp
index cc03df1c..7b2df88f 100644
--- a/src/key.cpp
+++ b/src/key.cpp
@@ -367,6 +367,7 @@ bool CExtKey::Derive(CExtKey &out, unsigned int _nChild) const {
void CExtKey::SetSeed(std::span<const std::byte> seed)
{
+ Assert(16 <= seed.size() && seed.size() <= 64);
static const unsigned char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'};
std::vector<unsigned char, secure_allocator<unsigned char>> vout(64);
CHMAC_SHA512{hashkey, sizeof(hashkey)}.Write(UCharCast(seed.data()), seed.size()).Finalize(vout.data());
Why this scored 42/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.