Skip to content

Add DST to bulletproofs, DDH and key consistency proofs#967

Open
jonas-lj wants to merge 1 commit into
mainfrom
jonas/bp_dst
Open

Add DST to bulletproofs, DDH and key consistency proofs#967
jonas-lj wants to merge 1 commit into
mainfrom
jonas/bp_dst

Conversation

@jonas-lj

@jonas-lj jonas-lj commented May 22, 2026

Copy link
Copy Markdown
Contributor

Adds a domain-separation-tag (dst) to the bulletproof range proofs and the Twisted ElGamal / DDH sigma proofs (DdhTupleNizk, ZeroProof, ConsistencyProof, KeyConsistencyProof).

The sigma-proof challenges are made byte-for-byte compatible with Contra's Move/TS implementations: blake2b256(dst || canonical-element-bytes…), top byte zeroed, canonical LE scalar (RistrettoScalar::fiat_shamir_challenge). Breaking change: prove/verify call sites now require a dst.

This changes range proof verification, so Sui must be updated.

Test plan

  • cargo test -p fastcrypto --lib (nizk, twisted_elgamal, bulletproofs)
  • cargo fmt --check + cargo xclippy -D warnings

@jonas-lj jonas-lj changed the title Add DST to bulletproofs Add DST to DDH and key consistency proofs May 24, 2026
@jonas-lj jonas-lj changed the title Add DST to DDH and key consistency proofs Add DST to bulletproofs May 26, 2026
@jonas-lj jonas-lj force-pushed the jonas/bp_dst branch 2 times, most recently from fa1d158 to b519d32 Compare May 29, 2026 06:59
@jonas-lj jonas-lj changed the title Add DST to bulletproofs Add DST to bulletproofs, DDH and key consistency proofs May 29, 2026
@jonas-lj jonas-lj force-pushed the jonas/bp_dst branch 18 times, most recently from 69cb481 to 9ced462 Compare May 29, 2026 10:29
@jonas-lj jonas-lj marked this pull request as ready for review May 29, 2026 10:31
@jonas-lj jonas-lj requested review from Daeinar and benr-ml May 29, 2026 10:32
@jonas-lj jonas-lj force-pushed the jonas/bp_dst branch 22 times, most recently from a930d31 to 11a526e Compare June 2, 2026 06:38
@jonas-lj jonas-lj requested a review from benr-ml June 2, 2026 06:43
Adds a domain-separation-tag (DST) parameter to the range proofs (bulletproofs)
and the sigma-protocol proofs used by Contra:
- RangeProof prove/verify bind the DST into the Merlin transcript.
- DdhTupleNizk (nizk.rs) and ZeroProof / ConsistencyProof / KeyConsistencyProof
  (twisted_elgamal.rs) bind the DST into their Fiat-Shamir challenge.

The DDH, ElGamal and key-consistency challenge constructions are made
byte-for-byte compatible with the Move and TypeScript implementations in Contra:
blake2b256(dst || canonical-element-bytes... in Move's order) with the top byte
zeroed and reduced to a canonical little-endian scalar, exposed as
RistrettoScalar::fiat_shamir_challenge.

The DDH challenge reduction is abstracted behind a FiatShamirChallenge strategy
trait (default Blake2bCanonicalChallenge) so alternative reductions can be
plugged in; ZeroProof and KeyConsistencyProof reuse the same strategy.
Comment thread fastcrypto/src/nizk.rs
Comment on lines +73 to +80
fn challenge(x_g: &G, x_h: &G, a: &G, b: &G, dst: &[u8]) -> G::ScalarType {
let chunks: Vec<Vec<u8>> = vec![
dst.to_vec(),
bcs::to_bytes(x_g).expect("Serialization succeeds"),
bcs::to_bytes(x_h).expect("Serialization succeeds"),
bcs::to_bytes(a).expect("Serialization succeeds"),
bcs::to_bytes(b).expect("Serialization succeeds"),
];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Should we pass parameters to challenge in the same order as they are processed, i.e., move dst to the front?

let mut digest = Blake2b256::digest(bcs::to_bytes(msg).unwrap()).digest;
digest[31] = 0;
RistrettoScalar::from_byte_array(&digest).expect("Always in field")
/// Derive an internal batching coefficient labelled `label` from the challenge `c` and (optional)

@Daeinar Daeinar Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be derived from the challenge c but from a fresh random value. I know that this will be fixed in another PR (right?) but I'm wondering if it would make sense to write here already that the batching coefficient will be derived from randomness r instead of challenge c (i.e. update the name of the input parameter etc)?

@Daeinar Daeinar left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jonas-lj Looks good overall. Just some smaller nits. Feel free to ignore if they don't make sense in the context of this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants