keccak: document that an unconstrained len_bytes admits prefix hashes; add negative tests#1758
Open
pauldelucia wants to merge 2 commits into
Open
keccak: document that an unconstrained len_bytes admits prefix hashes; add negative tests#1758pauldelucia wants to merge 2 commits into
pauldelucia wants to merge 2 commits into
Conversation
f61f849 to
119e5f4
Compare
gopikannappan
added a commit
to gopikannappan/binius64
that referenced
this pull request
Jul 10, 2026
… + add negative tests blake3_variable hashes the prover-claimed length: it enforces digest == blake3(message[..len_bytes]) and len_bytes <= max_len_bytes, but does not constrain the len_bytes value itself. With a free len_bytes and an internally-consumed digest, a prover can substitute the digest of any prefix. This mirrors the keccak len_bytes contract documented in binius-zk#1758. - document the len_bytes caller obligation on blake3_variable (safe patterns: pin to a public input / derived wire, or use blake3_fixed for constant length) - add variable_unconstrained_len_admits_prefix_hash: honest-length control, the prefix-hash characterization, and a positive-binding control showing message[..len_bytes] is bound (full-message digest rejected under a short len) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Keccak256's variable-length gadget proves digest == keccak256(message[..len_bytes]) for a prover-chosen len_bytes, constraining only len_bytes <= max_len_bytes. When a caller leaves len_bytes a free witness and consumes the digest internally, the constraint system is satisfiable for any prefix of the message. Document the caller obligation on Keccak256::new and the len_bytes field, note the safe ethsign pattern, point constant-length callers at fixed_length::keccak256, fix the stale doc argument list, and add negative tests (prefix acceptance under a free len wire, over-capacity rejection, and a pinned-length control that rejects the same payload).
119e5f4 to
ecbd9f2
Compare
Contributor
Author
|
While writing this up I noticed the same |
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.
Keccak256::newtakeslen_bytesas an arbitraryWireand provesdigest == keccak256(message[..len_bytes])for a prover-chosen length — notdigest == keccak256(message). The only constraint on the wire islen_bytes <= max_len_bytes.If a caller leaves
len_bytesa free witness and the digest is a prover-influenced / internally-consumed value (rather than a verifier-fixed public input), the constraint system is satisfiable for any prefix. Concretely: for a 100-byte message, a prover can claimlen = 50, supplydigest = keccak256(message[..50])with hand-built padding, and it verifies.If the digest is a public input, a free
len_bytesis harmless. But a circuit that consumes the digest internally has no such protection — which is exactly the shape the in-treeethsigncircuit has, and it stays sound only because it pins the length (a public input for the message hash,add_constant_64for the address hash). So this is a caller obligation rather than a gadget bug — but it was undocumented, and the gadget had no negative tests.This PR:
len_bytescontract onKeccak256::newand the field, notes the safeethsignpattern, and points constant-length callers atfixed_length::keccak256;newdoc's stale argument list; andlen_bytes, over-capacity rejection, and a pinned-length control that rejects the same payload.Happy to adjust the framing or add an explicit API guard if you'd prefer. New tests pass via
cargo test -p binius-circuits --lib keccak::tests.