base32ct: reject non-zero trailing bits in the last symbol - #2460
Open
yuxi-liu-wired wants to merge 1 commit into
Open
yuxi-liu-wired wants to merge 1 commit into
yuxi-liu-wired wants to merge 1 commit into
Conversation
RFC 4648 3.5 requires the unused low bits of the last symbol of a partial
block to be zero. `decode` ignored them, so several strings decoded to the
same bytes: "me", "mf" and "mh" all decode to "a" ("me" is the canonical
encoding). base64ct rejects the equivalent Base64 inputs since RustCrypto#680 (RustCrypto#679).
A remainder of 2/4/5/7 symbols leaves 2/4/1/3 unused bits in its last
symbol; reject the input when any of them is set.
Tests: a proptest that every accepted input is the canonical encoding of
its output (decode then encode gives the input back), and a regression
test for "mf" / "mh" / "mf======".
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
RFC 4648 3.5 requires the unused low bits of the last symbol of a partial block to be zero ("canonical encoding").
Encoding::decodeignores them, so several strings decode to the same bytes:base64ct rejects the equivalent Base64 inputs since #680 (for #679).
A remainder of 2, 4, 5 or 7 symbols leaves 2, 4, 1 or 3 unused bits in its last symbol. This PR rejects the input when any of those bits is set. The check is folded into the existing
erraccumulator, which keeps the decoder free of input-dependent branches.Tests in
tests/proptests.rs:decode_is_canonical: a proptest that every accepted input decodes and re-encodes to itself.reject_non_zero_trailing_bits: a regression test for"mf","mh"and"mf======", and a check that"me"still decodes.Both fail on master.
This PR was produced by AI agents (Claude) while fuzzing the RustCrypto encoding crates. The same bug class showed up in base64ct's
decode_in_place.