BIP93: Fix checksum selection boundaries #2258

pull BenWestgate wants to merge 2 commits into bitcoin:master from BenWestgate:bip93-checksum-boundary changing 1 files +118 −27
  1. BenWestgate commented at 4:49 AM on August 17, 2026: contributor

    Motivation

    BIP93 currently chooses checksum type by data-part length but the checksum’s error detection boundary applies to the expanded codeword, including the five-value expansion of "ms". This will cause problems for a generic codex32_decode function in later PRs and at worst allow an HRP error to go undetected at the boundary. Both regular and long checksums permitted codewords in excess of their period.

    Changes

    • ms32_verify_checksum and ms32_create_checksum now include the expanded "ms" HRP length when selecting regular vs. long checksums.
    • ms32_create_checksum uses if 5 + len(data) > 80: as the switch to ms32_create_long_checksum.
    • added ms32_create_regular_checksum and ms32_verify_regular_checksum.
    • The Python reference code, specification, rationale, and vectors are updated.

    Valid lengths:

    • Regular codewords will now be <= 93 expanded values
    • Long codewords will now be >= 96 and <= 1023 expanded values

    Invalid lengths:

    • Expanded values 94 and 95
    • Long codewords >1023 expanded values

    Compatibility

    This is a breaking change for old regular codex32 strings encoding 44-, 45-, and 46-byte seeds. However the authors do not see this is a problem due to the exceedingly rare possibility these have ever been created and used. The underlying seed lengths remain supported so users must migrate by reencoding their data with the Long codex32 checksum for modern decoders to accept them. The 43-byte regular encoding and existing 47-byte long encoding remain valid.

    Testing

    Thoroughly reviewed the complete diff. Ran git diff --check. Checked the new 43–47-byte boundary vectors. Checked that expanded length 1023 verifies and 1024 fails. Checked that the legacy short-checksum vectors should fail.

    Discussion

    Proposal: #2040 (comment) cACK #2040 (comment) Reference impl: https://github.com/BlockstreamResearch/codex32/issues/75

  2. BIP93: Correct checksum selection boundaries
    The checksum correction guarantees apply to the expanded codeword,
    which includes the five-value expansion of the "ms" human-readable
    part. The reference code instead selected the checksum using only the
    data-part length, allowing regular checksums beyond their 93-value
    correction boundary.
    
    Select regular and long checksums using expanded codeword length.
    Reject expanded lengths 94 and 95, and reject long checksums above
    1023 values. Keep checksum creation permissive while enforcing these
    limits during verification.
    
    This invalidates legacy short-checksum encodings for 44-, 45-, and
    46-byte master seeds. The underlying seed lengths remain supported
    using the long checksum.
    
    Update the specification, Python reference code, compatibility
    discussion, and boundary vectors accordingly.
    
    Refs: https://github.com/BlockstreamResearch/codex32/issues/75
    3531824ed9
  3. vitrixLab commented at 5:05 AM on August 17, 2026: none

    LGTM!

    — specification-consistent correction of the boundary issue discussed in "PR #2040" (https://github.com/bitcoin/bips/pull/2040).

    Checksum selection must use the expanded codeword length, including the fixed "ms" HRP’s five-value expansion.

    · Regular: ≤93 · Invalid: 94–95 · Long: 96–1023

    This matches the 43-byte regular / 44–46-byte long boundary.

    Intentional consequence: legacy regular-checksum encodings of 44–46-byte seeds become invalid and must use the long checksum.

    Remaining gate: reproducible boundary vectors.

  4. murchandamus added the label Proposed BIP modification on Aug 17, 2026
  5. murchandamus added the label Pending acceptance on Aug 17, 2026
  6. murchandamus commented at 9:54 PM on August 17, 2026: member
  7. Update bip-0093.mediawiki
    BIP93: Separate checksum primitives from format selection  Distinguish the regular and long checksum primitives from the codex32 format selector. Each primitive verifier enforces its stated maximum period, while ms32_verify_checksum selects the checksum required by BIP93 and rejects expanded lengths 94 and 95.  Keep ms32_create_checksum as the format-selection helper and add the corresponding regular-checksum creator.  Add reproducible 43- through 47-byte vectors and direct assertions for the 93/94/95/96 and 1023/1024 expanded-length boundaries.
    a9d8246244
  8. BenWestgate commented at 2:03 AM on August 20, 2026: contributor

    Remaining gate: reproducible boundary vectors.

    I added "reproducible boundary vectors."

    I also separated checksum verification into two regular/long primitives that check the length is within the checksum period and residue is valid. While ms32_verify_checksum enforces the 94, 95 gap and selects the proper primitive above and below that.

    Similarly ms32_create_regular_checksum creates the short checksum for data, while ms32_create_checksum selects the required checksum by expanded codewode length and creates it.

    It should be easier to generate test vectors and test them now, as well as to reuse our checksums for non-codex32 data.


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bips. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-08-20 04:10 UTC

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