Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/codex32/bip93.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ def _checksum_for_encoded_length(hrp: str, encoded_length: int) -> _Checksum:

def _decode_codex32(text: str) -> tuple[str, _ProfileRules | None, tuple[int, ...], _Checksum]:
hrp, encoded = bech32_decode(text)
if len(hrp) > 83:
raise InvalidLength(f"human-readable part exceeds 83 characters ({len(hrp)})")
if len(hrp) + 1 + len(encoded) < 21:
raise InvalidLength("codex32 string must contain at least 21 characters")
checksum = _checksum_for_encoded_length(hrp, len(encoded))
Expand Down
2 changes: 2 additions & 0 deletions src/codex32/correction.py
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,8 @@ def _validate_context(context: CorrectionContext) -> None:
_validate_single_case_ascii(context.hrp)
if context.hrp.lower() != context.hrp:
raise ValueError("hrp must be a normalized application prefix")
if len(context.hrp) > 83:
raise ValueError(f"human-readable part exceeds 83 characters ({len(context.hrp)})")
length = context.expected_length
if length is not None:
if isinstance(length, bool) or not isinstance(length, int):
Expand Down
1 change: 1 addition & 0 deletions tests/test_correction_bch.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ def test_public_context_constrains_length_prefix_and_used_indices() -> None:
CorrectionContext(Profile.MS, excluded_indices=["a"]), # type: ignore[arg-type]
CorrectionContext(Profile.MS, excluded_indices=("s",)),
CorrectionContext(Profile.MS, excluded_indices=("a", "A")),
CorrectionContext("z" * 84, expected_length=106),
),
)
def test_malformed_public_context_is_rejected(context: CorrectionContext) -> None:
Expand Down
10 changes: 9 additions & 1 deletion tests/test_generic_hrp.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
recover_secret,
)
from codex32.cli import main, ms_main
from codex32.errors import MismatchedHrp, MismatchedProfile
from codex32.errors import InvalidLength, MismatchedHrp, MismatchedProfile

UNKNOWN = {
"short": {
Expand Down Expand Up @@ -50,6 +50,14 @@ def test_opaque_hrp_parse_complete_recover_and_derive(vector: dict[str, str]) ->
assert derive_share([secret, a], "d").text == vector["D"].upper()


def test_hrp_over_83_characters_is_rejected_at_the_bip173_limit() -> None:
within_limit = oracle_encode("z" * 83, "0testsq")
over_limit = oracle_encode("z" * 84, "0testsq")
assert parse_codex32(within_limit).hrp == "z" * 83
with pytest.raises(InvalidLength):
parse_codex32(over_limit)


def test_sharing_compares_normalized_hrp_and_keeps_compatibility_error_name() -> None:
assert MismatchedProfile is MismatchedHrp
zz = parse_codex32(UNKNOWN["short"]["S"])
Expand Down
Loading