key: validate BIP32 seed length in CExtKey::SetSeed #35320

pull muhahahmad68 wants to merge 1 commits into bitcoin:master from muhahahmad68:bip32-setseed-length-validation changing 1 files +1 −0
  1. muhahahmad68 commented at 10:17 AM on May 19, 2026: none

    BIP32 specifies that the seed must be between 128 and 512 bits (16 to 64 bytes). CExtKey::SetSeed currently accepts any length, which could result in weak master keys being generated. Add an Assert at the start of SetSeed to enforce the valid seed length range as a programming invariant. The existing BIP32 test vectors already provide sufficient coverage of valid seed lengths.

    To test:

    cmake --build build -j --target test_bitcoin ./build/bin/test_bitcoin --run_test=bip32_tests

    Fixes #35308

  2. DrahtBot commented at 10:17 AM on May 19, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--006a51241073e994b41acfe9ec718e94-->

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/35320.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline for information on the review process. A summary of reviews will appear here.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  3. ViniciusCestarii commented at 3:09 PM on May 21, 2026: contributor

    Two things:

    1. I believe return is the wrong failure handling. Silently returning leaves the CExtKey in an uninitialized/partial state with no way for the caller to detect the rejection. Since passing an out-of-spec seed is a programming error with no safe recovery, Assert(seed.size() >= 16 && seed.size() <= 64) is more appropriate because it makes the contract explicit and terminates loudly on violation rather than silently producing a broken object.

    2. The tests belongs in src/test/bip32_tests.cpp. That file already exercises CExtKey::SetSeed directly and is the natural home for BIP32 seed validation tests.

  4. muhahahmad68 commented at 5:41 PM on May 21, 2026: none

    Two things:

    1. I believe return is the wrong failure handling. Silently returning leaves the CExtKey in an uninitialized/partial state with no way for the caller to detect the rejection. Since passing an out-of-spec seed is a programming error with no safe recovery, Assert(seed.size() >= 16 && seed.size() <= 64) is more appropriate because it makes the contract explicit and terminates loudly on violation rather than silently producing a broken object.
    2. The tests belongs in src/test/bip32_tests.cpp. That file already exercises CExtKey::SetSeed directly and is the natural home for BIP32 seed validation tests.

    Yeah, very much agree!.

    Checked it out - I'll move the tests.

  5. muhahahmad68 force-pushed on May 21, 2026
  6. quapka commented at 10:26 AM on May 22, 2026: none
    1. nit: I believe that swapping the ordering would improve readability, Assert(16 <= seed.size() && seed.size() <= 64)

    2. The commit message needs to be updated as well to match the proposed functionality, it still mentions the early return.

    3. The tests are lacking, especially since they do not test arguably the most problematic part which are short seeds. The BOOST_CHECK_THROW (or its variants, I am not familiar with Boost) could be used to test too short and too long seeds.

  7. in src/test/bip32_tests.cpp:205 in d46735f248
     201 | @@ -202,4 +202,17 @@ BOOST_AUTO_TEST_CASE(bip32_max_depth) {
     202 |      BOOST_CHECK(!pubkey_parent.Derive(pubkey_child, 0));
     203 |  }
     204 |  
     205 | +BOOST_AUTO_TEST_CASE(extkey_setseed_bip32_length)
    


    achow101 commented at 9:54 PM on May 27, 2026:

    What is the purpose of this test? The fixed test vectors already handle these cases.

  8. muhahahmad68 commented at 3:01 PM on May 28, 2026: none

    Thanks for the feedback @quapka, @achow101 The added test cases were handled already with the test vectors. For invalid test cases, Assert calls assertion_fail which aborts, seems BOOST_CHECK_THROW and its variant can't catch it. I don't know if adding a fuzz test seem like a good option

  9. achow101 commented at 5:35 PM on May 28, 2026: member

    Assertions enforce invariants and are there to reveal programming bugs outside of tests. This does not need any new tests.

  10. muhahahmad68 commented at 9:21 PM on May 28, 2026: none

    Assertions enforce invariants and are there to reveal programming bugs outside of tests. This does not need any new tests.

    Got it

  11. key: validate BIP32 seed length in CExtKey::SetSeed
    BIP32 specifies that seed must be between 128 and 512 bits
    (16 to 64 bytes). CExtKey::SetSeed currently accepts any length,
    including empty seeds, which could lead to weak master keys.
    
    Add an Assert at the start of SetSeed to enforce the valid seed
    length range.
    
    Fixes #35308
    2cf9d79d84
  12. muhahahmad68 force-pushed on May 28, 2026
  13. muhahahmad68 commented at 9:52 PM on May 28, 2026: none

    Removed the test case per @achow101 feedback, the existing BIP32 test vectors provide sufficient coverage and Assert is there to enforce the invariant, not to be tested directly. Updated the commit to only include the Assert in key.cpp.

  14. DrahtBot added the label CI failed on Jun 5, 2026
  15. DrahtBot closed this on Jun 10, 2026

  16. DrahtBot reopened this on Jun 10, 2026

  17. DrahtBot removed the label CI failed on Jun 10, 2026

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-06-11 10:51 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me