Repository navigation
mcf: validate the field pushed by PasswordHash::push_base64 - #2498
Open
choksi2212 wants to merge 1 commit into
Open
choksi2212 wants to merge 1 commit into
choksi2212 wants to merge 1 commit into
Conversation
`PasswordHash` is documented to always hold a valid MCF hash, but `push_base64` was the one push taking unvalidated input that neither validated nor reported: it appended the `$` delimiter plus the base64-encoding of its input unconditionally, so empty input produced a hash string that no longer parses (the `$6$` shapes from RustCrypto#2471). Make `push_base64` validate the encoded field and return `Result`, mirroring the adjacent `push_displayable`: the pre-push length is cached and on validation failure the hash is rolled back to its prior contents, so a rejected push leaves the hash exactly as it was. Empty input now fails with the same `FieldInvalid` error `push_str` and `push_displayable` already return for empty fields. Fixes RustCrypto#2471 Signed-off-by: choksi2212 <choksi2212@users.noreply.github.com>
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.
PasswordHashis documented to always hold a valid MCF hash, butpush_base64was the one push taking unvalidated input that neither validated nor reported: it appended the$delimiter plus the base64-encoding of its input unconditionally. Empty input therefore produced a hash string that no longer parses, exactly as diagnosed in #2471 (credit to @yuxi-liu-wired for the analysis and the reproduced scenarios — this implements their option 1):reproduced empirically on pristine master, while
push_str("")andpush_displayable("")already reject empty withErr(FieldInvalid)— so the infalliblepush_base64was the one remaining unvalidated push.Change
push_base64now validates the encoded field and returnsResult, mirroring the adjacentpush_displayable(#2115/#2118): the pre-push length is cached, and on validation failure the delimiter is rolled back and theFielderror is returned, so a rejected push leaves the hash exactly as it was — subsequent pushes still build a valid hash (pinned by the second regression test via the salt-then-hash push sequence thepbkdf2/scryptMCF hashers use).Non-empty input is unaffected: every
Base64alphabet encodes into the[A-Za-z0-9./+=,\-]field charset, so the only newly-rejected input is empty.Breaking-change note
The signature changes
() -> Result<()>, i.e. a breaking change for the next mcf release (0.7.0). No other crate in this repo calls it; the known downstream callers are the MCF hashers inRustCrypto/password-hashes, all inside functions that already returnResult:pbkdf2/src/mcf.rs:56,57scrypt/src/mcf.rs:69sha-crypt/src/mcf.rs:79,83yescrypt/src/mcf.rs:54,57each a mechanical
.unwrap()/?addition once mcf 0.7 is published. I'm happy to prep those PRs once this lands. If you'd rather avoid the break, the alternatives considered in #2471 were a fallibletry_push_base64alongside the current method (leaves the invariant breakable viapush_base64in release builds) or panicking (counter to the direction #2118 took forpush_displayable); happy to rework if you prefer a different shape.Verification
rustc 1.99.0, Windows/MSVC:
push_base64_empty+push_base64_empty_leaves_hash_usable: green with the fix; negative control — with the validation removed but theResultsignature kept, both fail withOk(()) != Err(FieldInvalid)cargo test -p mcf --all-features --lib --tests: 9/9 (default features 9/9,--no-default-features --features alloc6/6)cargo build --workspace: cleancargo clippy -p mcf --all-features --all-targets: 0 warningscargo fmt -p mcf -- --check: cleanmcf/CHANGELOG.md: Unreleased entry addedFixes #2471