BIP93: Fix checksum selection boundaries - #2258
Conversation
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
This comment was marked as low quality.
This comment was marked as low quality.
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.
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:
Willing to revert the "reproducible" vectors added in a9d8246 if reviews also find it overkill or open to another suggestion. What I would keep: 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. |
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.
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_decodefunction in later PRs. Both regular and long checksums permitted codewords in excess of their period.Changes
ms32_verify_checksumandms32_create_checksumnow include the expanded "ms" HRP length when selecting regular vs. long checksums.ms32_create_checksumusesif 5 + len(data) > 80:as the switch toms32_create_long_checksum.ms32_create_regular_checksumandms32_verify_regular_checksum.Valid lengths:
Invalid lengths:
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