Skip to content

BIP93: Fix checksum selection boundaries - #2258

Open
BenWestgate wants to merge 3 commits into
bitcoin:masterfrom
BenWestgate:bip93-checksum-boundary
Open

BIP93: Fix checksum selection boundaries#2258
BenWestgate wants to merge 3 commits into
bitcoin:masterfrom
BenWestgate:bip93-checksum-boundary

Conversation

@BenWestgate

@BenWestgate BenWestgate commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Motivation

BIP93 currently admits expanded codewords beyond the checksum’s stated period, so its detection guarantee no longer applies to the complete codeword. This cause problems for a generic codex32_decode function in later PRs. 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, 95 and > 1023.

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.
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 issue: BlockstreamResearch/codex32#75
rust-codex32 PR: BlockstreamResearch/codex32#76

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: BlockstreamResearch/codex32#75
@vitrixLab

This comment was marked as low quality.

@murchandamus murchandamus added Proposed BIP modification PR by non-owner to update BIP content Pending acceptance This BIP modification requires sign-off by the champion of the BIP being modified labels Aug 17, 2026
@murchandamus

Copy link
Copy Markdown
Member

cc: @roconnor-blockstream, @apoelstra

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.
@BenWestgate

BenWestgate commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

Remaining gate: reproducible boundary vectors.

I added "reproducible boundary vectors."

Edit: Unsure if I should have done this to satisfy a review comment that was later marked "low quality".

For vectors, we need at minimum:

  • add regular checksum 44-, 45-, and 46-byte seeds to These examples use the wrong checksum for their given data sizes
  • add Expanded values 94, 95 and > 1023 to These examples have improper lengths
  • remove any vectors that are now accepted

Willing to revert the "reproducible" vectors added in a9d8246 if reviews also find it overkill or open to another suggestion.

What I would keep:
Separated checksum verification into regular/long primitives that check expanded length is within the checksum period and residue is valid. While ms32_verify_checksum owns the switch to long primitive at 96 expanded symbol codewords and calls the above.

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.

BenWestgate added a commit to BenWestgate/codex32 that referenced this pull request Aug 20, 2026
Account for the HRP expansion when selecting and slicing regular and long
checksums. Enforce the invalid 94–95 value gap and update the affected test
vectors.

Aligns the reference implementation with bitcoin/bips#2258.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Pending acceptance This BIP modification requires sign-off by the champion of the BIP being modified Proposed BIP modification PR by non-owner to update BIP content

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants