Skip to content

Commit

Permalink
Merge pull request #248 from dalek-cryptography/add-identity-check
Browse files Browse the repository at this point in the history
Add a transcript protocol function that checks for identity points.
  • Loading branch information
hdevalence committed May 7, 2019
2 parents 880bd99 + 5dbbd2b commit c27c852
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 83 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ keywords = ["cryptography", "ristretto", "zero-knowledge", "bulletproofs"]
description = "A pure-Rust implementation of Bulletproofs using Ristretto"

[dependencies]
curve25519-dalek = { version = "1", features = ["serde"] }
curve25519-dalek = { version = "1.0.3", features = ["serde"] }
subtle = "2"
sha3 = "0.8"
digest = "0.8"
Expand All @@ -21,7 +21,7 @@ byteorder = "1"
serde = "1"
serde_derive = "1"
failure = "0.1"
merlin = "1"
merlin = "1.1"
clear_on_drop = "0.2"

[dev-dependencies]
Expand Down
12 changes: 6 additions & 6 deletions src/inner_product_proof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ impl InnerProductProof {
L_vec.push(L);
R_vec.push(R);

transcript.commit_point(b"L", &L);
transcript.commit_point(b"R", &R);
transcript.append_point(b"L", &L);
transcript.append_point(b"R", &R);

let u = transcript.challenge_scalar(b"u");
let u_inv = u.invert();
Expand Down Expand Up @@ -154,8 +154,8 @@ impl InnerProductProof {
L_vec.push(L);
R_vec.push(R);

transcript.commit_point(b"L", &L);
transcript.commit_point(b"R", &R);
transcript.append_point(b"L", &L);
transcript.append_point(b"R", &R);

let u = transcript.challenge_scalar(b"u");
let u_inv = u.invert();
Expand Down Expand Up @@ -205,8 +205,8 @@ impl InnerProductProof {

let mut challenges = Vec::with_capacity(lg_n);
for (L, R) in self.L_vec.iter().zip(self.R_vec.iter()) {
transcript.commit_point(b"L", L);
transcript.commit_point(b"R", R);
transcript.validate_and_append_point(b"L", L)?;
transcript.validate_and_append_point(b"R", R)?;
challenges.push(transcript.challenge_scalar(b"u"));
}

Expand Down
28 changes: 14 additions & 14 deletions src/r1cs/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ impl<'a, 'b> Prover<'a, 'b> {

// Add the commitment to the transcript.
let V = self.cs.pc_gens.commit(v, v_blinding).compress();
self.cs.transcript.commit_point(b"V", &V);
self.cs.transcript.append_point(b"V", &V);

(V, Variable::Committed(i))
}
Expand All @@ -216,7 +216,7 @@ impl<'a, 'b> Prover<'a, 'b> {
// We cannot do this in advance because user can commit variables one-by-one,
// but this suffix provides safe disambiguation because each variable
// is prefixed with a separate label.
self.cs.transcript.commit_u64(b"m", self.m);
self.cs.transcript.append_u64(b"m", self.m);
self.cs
}
}
Expand Down Expand Up @@ -325,7 +325,7 @@ impl<'a, 'b> ProverCS<'a, 'b> {

// Commit the blinding factors for the input wires
for v_b in &self.v_blinding {
builder = builder.commit_witness_bytes(b"v_blinding", v_b.as_bytes());
builder = builder.rekey_with_witness_bytes(b"v_blinding", v_b.as_bytes());
}

use rand::thread_rng;
Expand Down Expand Up @@ -368,9 +368,9 @@ impl<'a, 'b> ProverCS<'a, 'b> {
)
.compress();

self.transcript.commit_point(b"A_I", &A_I);
self.transcript.commit_point(b"A_O", &A_O);
self.transcript.commit_point(b"S", &S);
self.transcript.append_point(b"A_I", &A_I);
self.transcript.append_point(b"A_O", &A_O);
self.transcript.append_point(b"S", &S);

// 4. Compute blinded vector polynomials l(x) and r(x)

Expand Down Expand Up @@ -419,11 +419,11 @@ impl<'a, 'b> ProverCS<'a, 'b> {
let T_5 = self.pc_gens.commit(t_poly.t5, t_5_blinding).compress();
let T_6 = self.pc_gens.commit(t_poly.t6, t_6_blinding).compress();

self.transcript.commit_point(b"T_1", &T_1);
self.transcript.commit_point(b"T_3", &T_3);
self.transcript.commit_point(b"T_4", &T_4);
self.transcript.commit_point(b"T_5", &T_5);
self.transcript.commit_point(b"T_6", &T_6);
self.transcript.append_point(b"T_1", &T_1);
self.transcript.append_point(b"T_3", &T_3);
self.transcript.append_point(b"T_4", &T_4);
self.transcript.append_point(b"T_5", &T_5);
self.transcript.append_point(b"T_6", &T_6);

let x = self.transcript.challenge_scalar(b"x");

Expand Down Expand Up @@ -460,10 +460,10 @@ impl<'a, 'b> ProverCS<'a, 'b> {

let e_blinding = x * (i_blinding + x * (o_blinding + x * s_blinding));

self.transcript.commit_scalar(b"t_x", &t_x);
self.transcript.append_scalar(b"t_x", &t_x);
self.transcript
.commit_scalar(b"t_x_blinding", &t_x_blinding);
self.transcript.commit_scalar(b"e_blinding", &e_blinding);
.append_scalar(b"t_x_blinding", &t_x_blinding);
self.transcript.append_scalar(b"e_blinding", &e_blinding);

// Get a challenge value to combine statements for the IPP
let w = self.transcript.challenge_scalar(b"w");
Expand Down
26 changes: 13 additions & 13 deletions src/r1cs/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ impl<'a, 'b> Verifier<'a, 'b> {
self.cs.V.push(commitment);

// Add the commitment to the transcript.
self.cs.transcript.commit_point(b"V", &commitment);
self.cs.transcript.append_point(b"V", &commitment);

Variable::Committed(i)
}
Expand All @@ -183,7 +183,7 @@ impl<'a, 'b> Verifier<'a, 'b> {
// We cannot do this in advance because user can commit variables one-by-one,
// but this suffix provides safe disambiguation because each variable
// is prefixed with a separate label.
self.cs.transcript.commit_u64(b"m", self.m);
self.cs.transcript.append_u64(b"m", self.m);
self.cs
}
}
Expand Down Expand Up @@ -261,26 +261,26 @@ impl<'a, 'b> VerifierCS<'a, 'b> {
// We are performing a single-party circuit proof, so party index is 0.
let gens = self.bp_gens.share(0);

self.transcript.commit_point(b"A_I", &proof.A_I);
self.transcript.commit_point(b"A_O", &proof.A_O);
self.transcript.commit_point(b"S", &proof.S);
self.transcript.append_point(b"A_I", &proof.A_I);
self.transcript.append_point(b"A_O", &proof.A_O);
self.transcript.append_point(b"S", &proof.S);

let y = self.transcript.challenge_scalar(b"y");
let z = self.transcript.challenge_scalar(b"z");

self.transcript.commit_point(b"T_1", &proof.T_1);
self.transcript.commit_point(b"T_3", &proof.T_3);
self.transcript.commit_point(b"T_4", &proof.T_4);
self.transcript.commit_point(b"T_5", &proof.T_5);
self.transcript.commit_point(b"T_6", &proof.T_6);
self.transcript.append_point(b"T_1", &proof.T_1);
self.transcript.append_point(b"T_3", &proof.T_3);
self.transcript.append_point(b"T_4", &proof.T_4);
self.transcript.append_point(b"T_5", &proof.T_5);
self.transcript.append_point(b"T_6", &proof.T_6);

let x = self.transcript.challenge_scalar(b"x");

self.transcript.commit_scalar(b"t_x", &proof.t_x);
self.transcript.append_scalar(b"t_x", &proof.t_x);
self.transcript
.commit_scalar(b"t_x_blinding", &proof.t_x_blinding);
.append_scalar(b"t_x_blinding", &proof.t_x_blinding);
self.transcript
.commit_scalar(b"e_blinding", &proof.e_blinding);
.append_scalar(b"e_blinding", &proof.e_blinding);

let w = self.transcript.challenge_scalar(b"w");

Expand Down
16 changes: 8 additions & 8 deletions src/range_proof/dealer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,15 @@ impl<'a, 'b> DealerAwaitingBitCommitments<'a, 'b> {

// Commit each V_j individually
for vc in bit_commitments.iter() {
self.transcript.commit_point(b"V", &vc.V_j);
self.transcript.append_point(b"V", &vc.V_j);
}

// Commit aggregated A_j, S_j
let A: RistrettoPoint = bit_commitments.iter().map(|vc| vc.A_j).sum();
self.transcript.commit_point(b"A", &A.compress());
self.transcript.append_point(b"A", &A.compress());

let S: RistrettoPoint = bit_commitments.iter().map(|vc| vc.S_j).sum();
self.transcript.commit_point(b"S", &S.compress());
self.transcript.append_point(b"S", &S.compress());

let y = self.transcript.challenge_scalar(b"y");
let z = self.transcript.challenge_scalar(b"z");
Expand Down Expand Up @@ -158,8 +158,8 @@ impl<'a, 'b> DealerAwaitingPolyCommitments<'a, 'b> {
let T_1: RistrettoPoint = poly_commitments.iter().map(|pc| pc.T_1_j).sum();
let T_2: RistrettoPoint = poly_commitments.iter().map(|pc| pc.T_2_j).sum();

self.transcript.commit_point(b"T_1", &T_1.compress());
self.transcript.commit_point(b"T_2", &T_2.compress());
self.transcript.append_point(b"T_1", &T_1.compress());
self.transcript.append_point(b"T_2", &T_2.compress());

let x = self.transcript.challenge_scalar(b"x");
let poly_challenge = PolyChallenge { x };
Expand Down Expand Up @@ -221,10 +221,10 @@ impl<'a, 'b> DealerAwaitingProofShares<'a, 'b> {
let t_x_blinding: Scalar = proof_shares.iter().map(|ps| ps.t_x_blinding).sum();
let e_blinding: Scalar = proof_shares.iter().map(|ps| ps.e_blinding).sum();

self.transcript.commit_scalar(b"t_x", &t_x);
self.transcript.append_scalar(b"t_x", &t_x);
self.transcript
.commit_scalar(b"t_x_blinding", &t_x_blinding);
self.transcript.commit_scalar(b"e_blinding", &e_blinding);
.append_scalar(b"t_x_blinding", &t_x_blinding);
self.transcript.append_scalar(b"e_blinding", &e_blinding);

// Get a challenge value to combine statements for the IPP
let w = self.transcript.challenge_scalar(b"w");
Expand Down
19 changes: 11 additions & 8 deletions src/range_proof/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,24 +287,27 @@ impl RangeProof {
transcript.rangeproof_domain_sep(n as u64, m as u64);

for V in value_commitments.iter() {
transcript.commit_point(b"V", V);
// Allow the commitments to be zero (0 value, 0 blinding)
// See https://github.com/dalek-cryptography/bulletproofs/pull/248#discussion_r255167177
transcript.append_point(b"V", V);
}
transcript.commit_point(b"A", &self.A);
transcript.commit_point(b"S", &self.S);

transcript.validate_and_append_point(b"A", &self.A)?;
transcript.validate_and_append_point(b"S", &self.S)?;

let y = transcript.challenge_scalar(b"y");
let z = transcript.challenge_scalar(b"z");
let zz = z * z;
let minus_z = -z;

transcript.commit_point(b"T_1", &self.T_1);
transcript.commit_point(b"T_2", &self.T_2);
transcript.validate_and_append_point(b"T_1", &self.T_1)?;
transcript.validate_and_append_point(b"T_2", &self.T_2)?;

let x = transcript.challenge_scalar(b"x");

transcript.commit_scalar(b"t_x", &self.t_x);
transcript.commit_scalar(b"t_x_blinding", &self.t_x_blinding);
transcript.commit_scalar(b"e_blinding", &self.e_blinding);
transcript.append_scalar(b"t_x", &self.t_x);
transcript.append_scalar(b"t_x_blinding", &self.t_x_blinding);
transcript.append_scalar(b"e_blinding", &self.e_blinding);

let w = transcript.challenge_scalar(b"w");

Expand Down
72 changes: 44 additions & 28 deletions src/transcript.rs
Original file line number Diff line number Diff line change
@@ -1,59 +1,75 @@
//! Defines a `TranscriptProtocol` trait for using a Merlin transcript.

use byteorder::{ByteOrder, LittleEndian};
use curve25519_dalek::ristretto::CompressedRistretto;
use curve25519_dalek::scalar::Scalar;
use merlin::Transcript;

use errors::ProofError;

pub trait TranscriptProtocol {
/// Commit a domain separator for an `n`-bit, `m`-party range proof.
/// Append a domain separator for an `n`-bit, `m`-party range proof.
fn rangeproof_domain_sep(&mut self, n: u64, m: u64);
/// Commit a domain separator for a length-`n` inner product proof.

/// Append a domain separator for a length-`n` inner product proof.
fn innerproduct_domain_sep(&mut self, n: u64);
/// Commit a domain separator for a constraint system.

/// Append a domain separator for a constraint system.
fn r1cs_domain_sep(&mut self);
/// Commit a 64-bit integer.
fn commit_u64(&mut self, label: &'static [u8], n: u64);
/// Commit a `scalar` with the given `label`.
fn commit_scalar(&mut self, label: &'static [u8], scalar: &Scalar);
/// Commit a `point` with the given `label`.
fn commit_point(&mut self, label: &'static [u8], point: &CompressedRistretto);

/// Append a `scalar` with the given `label`.
fn append_scalar(&mut self, label: &'static [u8], scalar: &Scalar);

/// Append a `point` with the given `label`.
fn append_point(&mut self, label: &'static [u8], point: &CompressedRistretto);

/// Check that a point is not the identity, then append it to the
/// transcript. Otherwise, return an error.
fn validate_and_append_point(
&mut self,
label: &'static [u8],
point: &CompressedRistretto,
) -> Result<(), ProofError>;

/// Compute a `label`ed challenge variable.
fn challenge_scalar(&mut self, label: &'static [u8]) -> Scalar;
}

fn le_u64(value: u64) -> [u8; 8] {
let mut value_bytes = [0u8; 8];
LittleEndian::write_u64(&mut value_bytes, value);
value_bytes
}

impl TranscriptProtocol for Transcript {
fn rangeproof_domain_sep(&mut self, n: u64, m: u64) {
self.commit_bytes(b"dom-sep", b"rangeproof v1");
self.commit_bytes(b"n", &le_u64(n));
self.commit_bytes(b"m", &le_u64(m));
self.append_message(b"dom-sep", b"rangeproof v1");
self.append_u64(b"n", n);
self.append_u64(b"m", m);
}

fn innerproduct_domain_sep(&mut self, n: u64) {
self.commit_bytes(b"dom-sep", b"ipp v1");
self.commit_bytes(b"n", &le_u64(n));
self.append_message(b"dom-sep", b"ipp v1");
self.append_u64(b"n", n);
}

fn r1cs_domain_sep(&mut self) {
self.commit_bytes(b"dom-sep", b"r1cs v1");
self.append_message(b"dom-sep", b"r1cs v1");
}

fn commit_u64(&mut self, label: &'static [u8], n: u64) {
self.commit_bytes(label, &le_u64(n));
fn append_scalar(&mut self, label: &'static [u8], scalar: &Scalar) {
self.append_message(label, scalar.as_bytes());
}

fn commit_scalar(&mut self, label: &'static [u8], scalar: &Scalar) {
self.commit_bytes(label, scalar.as_bytes());
fn append_point(&mut self, label: &'static [u8], point: &CompressedRistretto) {
self.append_message(label, point.as_bytes());
}

fn commit_point(&mut self, label: &'static [u8], point: &CompressedRistretto) {
self.commit_bytes(label, point.as_bytes());
fn validate_and_append_point(
&mut self,
label: &'static [u8],
point: &CompressedRistretto,
) -> Result<(), ProofError> {
use curve25519_dalek::traits::IsIdentity;

if point.is_identity() {
Err(ProofError::VerificationError)
} else {
Ok(self.append_message(label, point.as_bytes()))
}
}

fn challenge_scalar(&mut self, label: &'static [u8]) -> Scalar {
Expand Down
10 changes: 6 additions & 4 deletions tests/r1cs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,10 @@ impl ShuffleProof {
R1CSError,
> {
// Apply a domain separator with the shuffle parameters to the transcript
// XXX should this be part of the gadget?
let k = input.len();
transcript.commit_bytes(b"dom-sep", b"ShuffleProof");
transcript.commit_bytes(b"k", Scalar::from(k as u64).as_bytes());
transcript.append_message(b"dom-sep", b"ShuffleProof");
transcript.append_u64(b"k", k as u64);

let mut prover = Prover::new(&bp_gens, &pc_gens, transcript);

Expand Down Expand Up @@ -111,9 +112,10 @@ impl ShuffleProof {
output_commitments: &Vec<CompressedRistretto>,
) -> Result<(), R1CSError> {
// Apply a domain separator with the shuffle parameters to the transcript
// XXX should this be part of the gadget?
let k = input_commitments.len();
transcript.commit_bytes(b"dom-sep", b"ShuffleProof");
transcript.commit_bytes(b"k", Scalar::from(k as u64).as_bytes());
transcript.append_message(b"dom-sep", b"ShuffleProof");
transcript.append_u64(b"k", k as u64);

let mut verifier = Verifier::new(&bp_gens, &pc_gens, transcript);

Expand Down

0 comments on commit c27c852

Please sign in to comment.