From fa69707614ecc7924ad9405fb977454271061419 Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Fri, 12 Jul 2019 10:46:25 -0400 Subject: [PATCH 01/11] nizk: flip commitment to group 1 --- src/ccs08.rs | 26 +++++++------- src/cl.rs | 11 +++--- src/nizk.rs | 36 +++++++++---------- src/ped92.rs | 100 ++++++++++++++++++--------------------------------- 4 files changed, 69 insertions(+), 104 deletions(-) diff --git a/src/ccs08.rs b/src/ccs08.rs index 201fb74..d68e90a 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -44,7 +44,7 @@ proofUL contains the necessary elements for the ZK range proof with range [0,u^l #[derive(Clone)] struct ProofUL { V: Vec>, - D: E::G2, + D: E::G1, comm: Commitment, sigProofs: Vec>, ch: E::Fr, @@ -105,11 +105,11 @@ impl ParamsUL { let mut proofStates = Vec::>::with_capacity(self.l as usize); let mut sigProofs = Vec::>::with_capacity(self.l as usize); let mut V = Vec::>::with_capacity(self.l as usize); - let mut D = E::G2::zero(); + let mut D = E::G1::zero(); let m = E::Fr::rand(rng); // D = H^m - let mut hm = self.com.h2.clone(); + let mut hm = self.com.h.clone(); hm.mul_assign(m); for i in 0..self.l as usize { let signature = self.signatures.get(&decx[i].to_string()).unwrap(); @@ -119,8 +119,8 @@ impl ParamsUL { proofStates.push(proofState); let ui = self.u.pow(i as u32); - let mut aux = self.com.g2.clone(); - for j in 0..self.kp.public.Y2.len() { + let mut aux = self.com.g.clone(); + for j in 0..self.kp.public.Y1.len() { let mut muiti = proofStates[i].t[j].clone(); muiti.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap()); aux.mul_assign(muiti); @@ -183,16 +183,16 @@ impl ParamsUL { } fn verify_part1(&self, proof: &ProofUL) -> bool { - let mut D = proof.comm.c2.clone(); + let mut D = proof.comm.c.clone(); D.mul_assign(proof.ch); D.negate(); - let mut hzr = self.com.h2.clone(); + let mut hzr = self.com.h.clone(); hzr.mul_assign(proof.zr); D.add_assign(&hzr); for i in 0..self.l as usize { let ui = self.u.pow(i as u32); - let mut aux = self.com.g2.clone(); - for j in 0..self.kp.public.Y2.len() { + let mut aux = self.com.g.clone(); + for j in 0..self.kp.public.Y1.len() { let mut muizsigi = proof.sigProofs[i].zsig[j]; muizsigi.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap()); aux.mul_assign(muizsigi); @@ -203,7 +203,7 @@ impl ParamsUL { } } -fn hash(a: Vec, D: E::G2) -> E::Fr { +fn hash(a: Vec, D: E::G1) -> E::Fr { // create a Sha256 object let mut a_vec: Vec = Vec::new(); for a_el in a { @@ -291,7 +291,7 @@ impl RPPublicParams { #[cfg(test)] mod tests { use super::*; - use pairing::bls12_381::{Bls12, G1, G2, Fq12, Fr}; + use pairing::bls12_381::{Bls12, G1, Fq12, Fr}; use time::PreciseTime; use std::ops::Add; use core::mem; @@ -462,8 +462,8 @@ mod tests { #[test] fn hash_works() { let rng = &mut rand::thread_rng(); - let D = G2::rand(rng); - let D2 = G2::rand(rng); + let D = G1::rand(rng); + let D2 = G1::rand(rng); let params = setup::(rng); let kp = BlindKeyPair::generate(rng, ¶ms, 2); let m1 = Fr::rand(rng); diff --git a/src/cl.rs b/src/cl.rs index c3c8983..117b43e 100644 --- a/src/cl.rs +++ b/src/cl.rs @@ -311,13 +311,10 @@ impl BlindKeyPair { } pub fn generate_cs_multi_params(&self, mpk: &PublicParams) -> CSMultiParams { - let mut com_bases1 = vec! {mpk.g1}; - com_bases1.append(&mut self.public.Y1.clone()); + let mut com_bases = vec! {mpk.g1}; + com_bases.append(&mut self.public.Y1.clone()); - let mut com_bases2 = vec! {mpk.g2}; - com_bases2.append(&mut self.public.Y2.clone()); - - CSMultiParams { pub_bases1: com_bases1, pub_bases2: com_bases2} + CSMultiParams { pub_bases: com_bases} } /// extract unblinded public key @@ -336,7 +333,7 @@ impl BlindKeyPair { let mut h1 = mpk.g1; h1.mul_assign(u); // g1 ^ u - let mut com1 = com.c1.clone(); + let mut com1 = com.c.clone(); let mut H1 = self.public.X1.clone(); H1.add_assign(&com1); // (X * com) H1.mul_assign(u); // (X * com) ^ u (blinding factor) diff --git a/src/nizk.rs b/src/nizk.rs index a483079..8e793f6 100644 --- a/src/nizk.rs +++ b/src/nizk.rs @@ -14,8 +14,8 @@ use commit_scheme::commit; struct Proof { sig: Signature, sigProof: SignatureProof, - T: E::G2, - D: E::G2, + T: E::G1, + D: E::G1, z: Vec, } @@ -24,10 +24,10 @@ fn prove(rng: &mut R, comParams: &CSMultiParams, com1: &Co mpk: &PublicParams, kp: &BlindKeyPair) -> Proof { //Commitment phase //Commit linear relationship - let mut T = comParams.pub_bases2[2].clone(); + let mut T = comParams.pub_bases[2].clone(); let t1 = E::Fr::rand(rng); T.mul_assign(t1); - let mut h = comParams.pub_bases2[0].clone(); + let mut h = comParams.pub_bases[0].clone(); let t2 = E::Fr::rand(rng); h.mul_assign(t2); T.add_assign(&h); @@ -36,9 +36,9 @@ fn prove(rng: &mut R, comParams: &CSMultiParams, com1: &Co let proofState = kp.prove_commitment(rng, &mpk, &paymentToken); //commit commitment - let mut D = E::G2::zero(); - let mut t = Vec::::with_capacity(comParams.pub_bases2.len() - 1); - for g in comParams.pub_bases2.clone() { + let mut D = E::G1::zero(); + let mut t = Vec::::with_capacity(comParams.pub_bases.len() - 1); + for g in comParams.pub_bases.clone() { let ti = E::Fr::rand(rng); t.push(ti); let mut gt = g.clone(); @@ -87,28 +87,28 @@ fn verify(proof: Proof, epsilon: E::Fr, com1: &Commitment, com2 let challenge = hash::(proof.sigProof.a, proof.T, proof.D); //verify linear relationship - let mut gWpk = comParams.pub_bases2[2].clone(); + let mut gWpk = comParams.pub_bases[2].clone(); let mut minWpk = wpk.clone(); minWpk.negate(); gWpk.mul_assign(minWpk.into_repr()); - let mut gEps = comParams.pub_bases2[4].clone(); + let mut gEps = comParams.pub_bases[4].clone(); gEps.mul_assign(epsilon.into_repr()); - let mut gMinEps = comParams.pub_bases2[3].clone(); + let mut gMinEps = comParams.pub_bases[3].clone(); let mut mineps = epsilon.clone(); mineps.negate(); gMinEps.mul_assign(mineps.into_repr()); - let mut commitment = com1.c2.clone(); - commitment.sub_assign(&com2.c2.clone()); + let mut commitment = com1.c.clone(); + commitment.sub_assign(&com2.c.clone()); commitment.add_assign(&gWpk); commitment.add_assign(&gEps); commitment.add_assign(&gMinEps); commitment.mul_assign(challenge.into_repr()); commitment.add_assign(&proof.T); - let mut g2 = comParams.pub_bases2[2].clone(); + let mut g2 = comParams.pub_bases[2].clone(); g2.mul_assign(proof.z[0].into_repr()); - let mut h = comParams.pub_bases2[0].clone(); + let mut h = comParams.pub_bases[0].clone(); h.mul_assign(proof.z[1].into_repr()); g2.add_assign(&h); let r = commitment == g2; @@ -117,12 +117,12 @@ fn verify(proof: Proof, epsilon: E::Fr, com1: &Commitment, com2 let r1 = pk.verify_proof(&mpk, proof.sig, proof.sigProof, challenge); //verify knowledge of commitment - let mut comc = com2.c2.clone(); + let mut comc = com2.c.clone(); comc.mul_assign(challenge.into_repr()); comc.add_assign(&proof.D.clone()); - let mut x = E::G2::zero(); + let mut x = E::G1::zero(); for i in 2..proof.z.len() { - let mut base = comParams.pub_bases2[i - 2].clone(); + let mut base = comParams.pub_bases[i - 2].clone(); base.mul_assign(proof.z[i].into_repr()); x.add_assign(&base); } @@ -131,7 +131,7 @@ fn verify(proof: Proof, epsilon: E::Fr, com1: &Commitment, com2 r && r1 && r3 } -fn hash(a: E::Fqk, T: E::G2, D: E::G2) -> E::Fr { +fn hash(a: E::Fqk, T: E::G1, D: E::G1) -> E::Fr { let mut x_vec: Vec = Vec::new(); x_vec.extend(format!("{}", a).bytes()); x_vec.extend(format!("{}", T).bytes()); diff --git a/src/ped92.rs b/src/ped92.rs index 46c6918..9ef90bd 100644 --- a/src/ped92.rs +++ b/src/ped92.rs @@ -5,22 +5,18 @@ use ff::Rand; #[derive(Clone)] pub struct CSParams { - pub g1: E::G1, - pub g2: E::G2, - pub h1: E::G1, - pub h2: E::G2, + pub g: E::G1, + pub h: E::G1, } #[derive(Clone)] pub struct Commitment { - pub c1: E::G1, - pub c2: E::G2 + pub c: E::G1, } #[derive(Clone)] pub struct CSMultiParams { - pub pub_bases1: Vec, - pub pub_bases2: Vec + pub pub_bases: Vec, } //impl fmt::Display for CSParams { @@ -63,12 +59,9 @@ impl CSParams { Implements the setup algorithm for the Pedersen92 commitment scheme */ pub fn setup(rng: &mut R) -> Self { - let g1 = E::G1::rand(rng); - let g2 = E::G2::rand(rng); - let h1 = E::G1::rand(rng); - let h2 = E::G2::rand(rng); - let csp = CSParams { g1, g2, h1, h2 }; - return csp; + let g = E::G1::rand(rng); + let h = E::G1::rand(rng); + CSParams { g, h } } /* @@ -81,20 +74,13 @@ commit(pk, msg) -> cm where let r = R.unwrap_or(E::Fr::rand(rng)); // c = g^m * h^r - let mut c1 = self.g1.clone(); - c1.mul_assign(m.clone()); - let mut h1 = self.h1.clone(); - h1.mul_assign(r.clone()); - c1.add_assign(&h1); + let mut c = self.g.clone(); + c.mul_assign(m.clone()); + let mut h = self.h.clone(); + h.mul_assign(r.clone()); + c.add_assign(&h); - // c = g^m * h^r - let mut c2 = self.g2.clone(); - c2.mul_assign(m); - let mut h2 = self.h2.clone(); - h2.mul_assign(r); - c2.add_assign(&h2); - - Commitment { c1, c2 } + Commitment { c } } /* @@ -104,18 +90,12 @@ decommit(csp, cm, msg) -> bool where - outputs T/F for whether the cm is a valid commitment to the msg */ pub fn decommit(&self, cm: &Commitment, m: &E::Fr, r: &E::Fr) -> bool { - let mut dm1 = self.g1.clone(); - dm1.mul_assign(m.clone()); - let mut h1 = self.h1.clone(); - h1.mul_assign(r.clone()); - dm1.add_assign(&h1); - - let mut dm2 = self.g2.clone(); - dm2.mul_assign(m.clone()); - let mut h2 = self.h2.clone(); - h2.mul_assign(r.clone()); - dm2.add_assign(&h2); - return dm2 == cm.c2 && dm1 == cm.c1; + let mut dm = self.g.clone(); + dm.mul_assign(m.clone()); + let mut h = self.h.clone(); + h.mul_assign(r.clone()); + dm.add_assign(&h); + dm == cm.c } } @@ -126,49 +106,37 @@ impl CSMultiParams { a vector of messages of length len. */ pub fn setup_gen_params(rng: &mut R, len: usize) -> Self { - let mut p1: Vec = Vec::new(); - let mut p2: Vec = Vec::new(); + let mut p: Vec = Vec::new(); // 1 extra base element for the random parameter for i in 0..len + 1 { - p1.push(E::G1::rand(rng)); - p2.push(E::G2::rand(rng)); + p.push(E::G1::rand(rng)); } - return CSMultiParams { pub_bases1: p1, pub_bases2: p2 }; + CSMultiParams { pub_bases: p } } pub fn commit(&self, x: &Vec, r: &E::Fr) -> Commitment { // c = g1^m1 * ... * gn^mn * h^r - let mut c1 = self.pub_bases1[0].clone(); - let mut c2 = self.pub_bases2[0].clone(); - c1.mul_assign(r.clone()); - c2.mul_assign(r.clone()); + let mut c = self.pub_bases[0].clone(); + c.mul_assign(r.clone()); for i in 0..x.len() { - let mut basis1 = self.pub_bases1[i+1]; - basis1.mul_assign(x[i]); - c1.add_assign(&basis1); - let mut basis2 = self.pub_bases2[i+1]; - basis2.mul_assign(x[i]); - c2.add_assign(&basis2); + let mut basis = self.pub_bases[i+1]; + basis.mul_assign(x[i]); + c.add_assign(&basis); } - Commitment { c1, c2 } + Commitment { c } } pub fn decommit(&self, cm: &Commitment, x: &Vec, r: &E::Fr) -> bool { let l = x.len(); // pub_base[0] => h, x[0] => r - let mut dc1 = self.pub_bases1[0].clone(); - let mut dc2 = self.pub_bases2[0].clone(); - dc1.mul_assign(r.clone()); - dc2.mul_assign(r.clone()); + let mut dc = self.pub_bases[0].clone(); + dc.mul_assign(r.clone()); for i in 0..l { - let mut basis1 = self.pub_bases1[i+1]; - basis1.mul_assign(x[i]); - dc1.add_assign(&basis1); - let mut basis2 = self.pub_bases2[i+1]; - basis2.mul_assign(x[i]); - dc2.add_assign(&basis2); + let mut basis = self.pub_bases[i+1]; + basis.mul_assign(x[i]); + dc.add_assign(&basis); } - return dc2 == cm.c2 && dc1 == cm.c1; + return dc == cm.c; } } From 2fa95343f6cc0910454696e55c997538b2dc046f Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Fri, 12 Jul 2019 11:01:40 -0400 Subject: [PATCH 02/11] nizk: cleanup method + compute challenge during verification --- src/ccs08.rs | 30 +++++++++++++++--------------- src/nizk.rs | 10 +++++----- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/ccs08.rs b/src/ccs08.rs index d68e90a..e9c3ea1 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -47,7 +47,6 @@ struct ProofUL { D: E::G1, comm: Commitment, sigProofs: Vec>, - ch: E::Fr, zr: E::Fr, } @@ -149,7 +148,7 @@ impl ParamsUL { sigProofs.push(proof); } - return ProofUL { V, D, comm: C, sigProofs, ch: c, zr }; + return ProofUL { V, D, comm: C, sigProofs, zr }; } /** @@ -157,34 +156,33 @@ impl ParamsUL { */ pub fn verify_ul(&self, proof: &ProofUL) -> bool { // D == C^c.h^ zr.g^zsig ? - let r = self.verify_challenge(&proof); - let r1 = self.verify_part1(&proof); - let r2 = self.verify_part2(&proof); - r && r1 && r2 + let ch = self.compute_challenge(&proof); + let r1 = self.verify_part1(&proof, ch.clone()); + let r2 = self.verify_part2(&proof, ch.clone()); + r1 && r2 } - fn verify_challenge(&self, proof: &ProofUL) -> bool { + fn compute_challenge(&self, proof: &ProofUL) -> E::Fr { let mut a = Vec::::with_capacity(self.l as usize); for sigProof in proof.sigProofs.clone() { a.push(sigProof.a); } - let c = hash::(a, proof.D.clone()); - proof.ch == c + hash::(a, proof.D.clone()) } - fn verify_part2(&self, proof: &ProofUL) -> bool { + fn verify_part2(&self, proof: &ProofUL, challenge: E::Fr) -> bool { let mut r2 = true; for i in 0..self.l as usize { - let subResult = self.kp.public.verify_proof(&self.mpk, proof.V[i].clone(), proof.sigProofs[i].clone(), proof.ch); + let subResult = self.kp.public.verify_proof(&self.mpk, proof.V[i].clone(), proof.sigProofs[i].clone(), challenge); r2 = r2 && subResult; } r2 } - fn verify_part1(&self, proof: &ProofUL) -> bool { + fn verify_part1(&self, proof: &ProofUL, challenge: E::Fr) -> bool { let mut D = proof.comm.c.clone(); - D.mul_assign(proof.ch); + D.mul_assign(challenge); D.negate(); let mut hzr = self.com.h.clone(); hzr.mul_assign(proof.zr); @@ -332,7 +330,8 @@ mod tests { let params = ParamsUL::::setup_ul(rng, 2, 4); let fr = Fr::rand(rng); let proof = params.prove_ul(rng, 10, fr); - assert_eq!(params.verify_part1(&proof), true); + let ch = params.compute_challenge(&proof); + assert_eq!(params.verify_part1(&proof, ch), true); } #[test] @@ -341,7 +340,8 @@ mod tests { let params = ParamsUL::::setup_ul(rng, 2, 4); let fr = Fr::rand(rng); let proof = params.prove_ul(rng, 10, fr); - assert_eq!(params.verify_part2(&proof), true); + let ch = params.compute_challenge(&proof); + assert_eq!(params.verify_part2(&proof, ch), true); } #[test] diff --git a/src/nizk.rs b/src/nizk.rs index 8e793f6..c4a8aee 100644 --- a/src/nizk.rs +++ b/src/nizk.rs @@ -19,7 +19,7 @@ struct Proof { z: Vec, } -fn prove(rng: &mut R, comParams: &CSMultiParams, com1: &Commitment, r: E::Fr, +fn prove(rng: &mut R, comParams: &CSMultiParams, r: E::Fr, oldWallet: Vec, newWallet: Vec, rPrime: E::Fr, paymentToken: &Signature, mpk: &PublicParams, kp: &BlindKeyPair) -> Proof { //Commitment phase @@ -171,7 +171,7 @@ mod tests { let blindPaymentToken = keypair.sign_blind(rng, &mpk, commitment1.clone()); let paymentToken = keypair.unblind(&r, &blindPaymentToken); - let proof = prove(rng, &comParams, &commitment1, r, wallet1, wallet2, rprime, &paymentToken, &mpk, &keypair); + let proof = prove(rng, &comParams, r, wallet1, wallet2, rprime, &paymentToken, &mpk, &keypair); assert_eq!(verify(proof, *epsilon, &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), true); } @@ -204,18 +204,18 @@ mod tests { let commitment2 = comParams.commit(&wallet3, &rprime); let blindPaymentToken = keypair.sign_blind(rng, &mpk, commitment1.clone()); let paymentToken = keypair.unblind(&r, &blindPaymentToken); - let proof = prove(rng, &comParams, &commitment1, r, wallet1.clone(), wallet3, rprime, &paymentToken, &mpk, &keypair); + let proof = prove(rng, &comParams, r, wallet1.clone(), wallet3, rprime, &paymentToken, &mpk, &keypair); assert_eq!(verify(proof, *epsilon, &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), false); let mut bm2Prime = bm.clone(); let wallet4 = vec! {pkc, wpkprime, bc2, bm2Prime}; let commitment2 = comParams.commit(&wallet4, &rprime); - let proof = prove(rng, &comParams, &commitment1, r, wallet1.clone(), wallet4, rprime, &paymentToken, &mpk, &keypair); + let proof = prove(rng, &comParams, r, wallet1.clone(), wallet4, rprime, &paymentToken, &mpk, &keypair); assert_eq!(verify(proof, *epsilon, &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), false); let wallet5 = vec! {Fr::rand(rng), wpkprime, bc2, bm2}; let commitment2 = comParams.commit(&wallet5, &rprime); - let proof = prove(rng, &comParams, &commitment1, r, wallet1.clone(), wallet5, rprime, &paymentToken, &mpk, &keypair); + let proof = prove(rng, &comParams, r, wallet1.clone(), wallet5, rprime, &paymentToken, &mpk, &keypair); assert_eq!(verify(proof, *epsilon, &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), false); } From 2c981ece8ff2330fa93d50625522c732e8415c9f Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Fri, 12 Jul 2019 14:15:00 -0400 Subject: [PATCH 03/11] nizk: extract commitment from range proof as a parameter --- src/ccs08.rs | 119 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 82 insertions(+), 37 deletions(-) diff --git a/src/ccs08.rs b/src/ccs08.rs index e9c3ea1..8c71862 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -26,7 +26,7 @@ This must be computed in a trusted setup. struct ParamsUL { pub mpk: PublicParams, pub signatures: HashMap>, - pub com: CSParams, + pub csParams: CSParams, kp: BlindKeyPair, // u determines the amount of signatures we need in the public params. // Each signature can be compressed to just 1 field element of 256 bits. @@ -76,7 +76,7 @@ impl ParamsUL { The value of u should be roughly b/log(b), but we can choose smaller values in order to get smaller parameters, at the cost of having worse performance. */ - pub fn setup_ul(rng: &mut R, u: i64, l: i64) -> Self { + pub fn setup_ul(rng: &mut R, u: i64, l: i64, csParams: CSParams) -> Self { let mpk = setup(rng); let kp = BlindKeyPair::::generate(rng, &mpk, 1); @@ -86,19 +86,17 @@ impl ParamsUL { signatures.insert(i.to_string(), sig_i); } - let com = CSParams::setup(rng); - return ParamsUL { mpk, signatures, com, kp, u, l }; + return ParamsUL { mpk, signatures, csParams, kp, u, l }; } /** prove_ul method is used to produce the ZKRP proof that secret x belongs to the interval [0,U^L). */ - pub fn prove_ul(&self, rng: &mut R, x: i64, r: E::Fr) -> ProofUL { + pub fn prove_ul(&self, rng: &mut R, x: i64, r: E::Fr, C: Commitment) -> ProofUL { if x > self.u.pow(self.l as u32) || x < 0 { panic!("x is not within the range."); } let decx = decompose(x, self.u, self.l); - let modx = E::Fr::from_str(&(x.to_string())).unwrap(); // Initialize variables let mut proofStates = Vec::>::with_capacity(self.l as usize); @@ -108,7 +106,7 @@ impl ParamsUL { let m = E::Fr::rand(rng); // D = H^m - let mut hm = self.com.h.clone(); + let mut hm = self.csParams.h.clone(); hm.mul_assign(m); for i in 0..self.l as usize { let signature = self.signatures.get(&decx[i].to_string()).unwrap(); @@ -118,7 +116,7 @@ impl ParamsUL { proofStates.push(proofState); let ui = self.u.pow(i as u32); - let mut aux = self.com.g.clone(); + let mut aux = self.csParams.g.clone(); for j in 0..self.kp.public.Y1.len() { let mut muiti = proofStates[i].t[j].clone(); muiti.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap()); @@ -128,7 +126,6 @@ impl ParamsUL { } D.add_assign(&hm); - let C = self.com.commit(rng, modx, Some(r)); // Fiat-Shamir heuristic let mut a = Vec::::with_capacity(self.l as usize); for state in proofStates.clone() { @@ -184,12 +181,12 @@ impl ParamsUL { let mut D = proof.comm.c.clone(); D.mul_assign(challenge); D.negate(); - let mut hzr = self.com.h.clone(); + let mut hzr = self.csParams.h.clone(); hzr.mul_assign(proof.zr); D.add_assign(&hzr); for i in 0..self.l as usize { let ui = self.u.pow(i as u32); - let mut aux = self.com.g.clone(); + let mut aux = self.csParams.g.clone(); for j in 0..self.kp.public.Y1.len() { let mut muizsigi = proof.sigProofs[i].zsig[j]; muizsigi.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap()); @@ -233,7 +230,7 @@ impl RPPublicParams { /** Setup receives integers a and b, and configures the parameters for the rangeproof scheme. */ - pub fn setup(rng: &mut R, a: i64, b: i64) -> Self { + pub fn setup(rng: &mut R, a: i64, b: i64, csParams: CSParams) -> Self { // Compute optimal values for u and l if a > b { panic!("a must be less than or equal to b"); @@ -247,7 +244,8 @@ impl RPPublicParams { u = 2; } let l = (b as f64).log(u as f64).ceil() as i64; - let params_out: ParamsUL = ParamsUL::::setup_ul(rng, u, l); + + let params_out: ParamsUL = ParamsUL::::setup_ul(rng, u, l, csParams.clone()); return RPPublicParams { p: params_out, a, b }; } else { panic!("log(log(b)) is zero"); @@ -257,20 +255,34 @@ impl RPPublicParams { /** Prove method is responsible for generating the zero knowledge range proof. */ - pub fn prove(&self, rng: &mut R, x: i64) -> RangeProof { + pub fn prove(&self, rng: &mut R, x: i64, C: Commitment, r: E::Fr) -> RangeProof { if x > self.b || x < self.a { panic!("x is not within the range."); } let ul = self.p.u.pow(self.p.l as u32); - let r = E::Fr::rand(rng); // x - b + ul let xb = x - self.b + ul; - let first = self.p.prove_ul(rng, xb, r); + let mut gb = self.p.csParams.g.clone(); + let mut b = E::Fr::from_str(&(self.b.to_string())).unwrap(); + b.negate(); + gb.mul_assign(b.into_repr()); + let mut gul = self.p.csParams.g.clone(); + gul.mul_assign(E::Fr::from_str(&(ul.to_string())).unwrap().into_repr()); + let mut comXB = C.clone(); + comXB.c.add_assign(&gb); + comXB.c.add_assign(&gul); + let first = self.p.prove_ul(rng, xb, r.clone(), comXB); // x - a let xa = x - self.a; - let second = self.p.prove_ul(rng, xa, r); + let mut ga = self.p.csParams.g.clone(); + let mut a = E::Fr::from_str(&(self.a.to_string())).unwrap(); + a.negate(); + ga.mul_assign(a.into_repr()); + let mut comXA = C.clone(); + comXA.c.add_assign(&ga); + let second = self.p.prove_ul(rng, xa, r.clone(), comXA); return RangeProof { p1: first, p2: second }; } @@ -298,7 +310,9 @@ mod tests { #[test] fn setup_ul_works() { let rng = &mut rand::thread_rng(); - let params = ParamsUL::::setup_ul(rng, 2, 3); + let csParams = CSParams::setup(rng); + + let params = ParamsUL::::setup_ul(rng, 2, 3, csParams); assert_eq!(params.signatures.len(), 2); for (m, s) in params.signatures { assert_eq!(params.kp.verify(¶ms.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &Fr::zero(), &s), true); @@ -308,9 +322,13 @@ mod tests { #[test] fn prove_ul_works() { let rng = &mut rand::thread_rng(); - let params = ParamsUL::::setup_ul(rng, 2, 4); + let csParams = CSParams::setup(rng); + + let params = ParamsUL::::setup_ul(rng, 2, 4, csParams); let fr = Fr::rand(rng); - let proof = params.prove_ul(rng, 10, fr); + let modx = Fr::from_str(&(10.to_string())).unwrap(); + let C = params.csParams.commit(rng, modx, Some(fr.clone())); + let proof = params.prove_ul(rng, 10, fr, C); assert_eq!(proof.V.len(), 4); assert_eq!(proof.sigProofs.len(), 4); } @@ -319,17 +337,23 @@ mod tests { #[should_panic(expected = "x is not within the range")] fn prove_ul_not_in_range() { let rng = &mut rand::thread_rng(); - let params = ParamsUL::::setup_ul(rng, 2, 3); + let csParams = CSParams::setup(rng); + let params = ParamsUL::::setup_ul(rng, 2, 3, csParams); let fr = Fr::rand(rng); - params.prove_ul(rng, 100, fr); + let modx = Fr::from_str(&(100.to_string())).unwrap(); + let C = params.csParams.commit(rng, modx, Some(fr.clone())); + params.prove_ul(rng, 100, fr, C); } #[test] fn prove_and_verify_part1_ul_works() { let rng = &mut rand::thread_rng(); - let params = ParamsUL::::setup_ul(rng, 2, 4); + let csParams = CSParams::setup(rng); + let params = ParamsUL::::setup_ul(rng, 2, 4, csParams); let fr = Fr::rand(rng); - let proof = params.prove_ul(rng, 10, fr); + let modx = Fr::from_str(&(10.to_string())).unwrap(); + let C = params.csParams.commit(rng, modx, Some(fr.clone())); + let proof = params.prove_ul(rng, 10, fr, C); let ch = params.compute_challenge(&proof); assert_eq!(params.verify_part1(&proof, ch), true); } @@ -337,9 +361,12 @@ mod tests { #[test] fn prove_and_verify_part2_ul_works() { let rng = &mut rand::thread_rng(); - let params = ParamsUL::::setup_ul(rng, 2, 4); + let csParams = CSParams::setup(rng); + let params = ParamsUL::::setup_ul(rng, 2, 4, csParams); let fr = Fr::rand(rng); - let proof = params.prove_ul(rng, 10, fr); + let modx = Fr::from_str(&(10.to_string())).unwrap(); + let C = params.csParams.commit(rng, modx, Some(fr.clone())); + let proof = params.prove_ul(rng, 10, fr, C); let ch = params.compute_challenge(&proof); assert_eq!(params.verify_part2(&proof, ch), true); } @@ -347,17 +374,24 @@ mod tests { #[test] fn prove_and_verify_ul_works() { let rng = &mut rand::thread_rng(); - let params = ParamsUL::::setup_ul(rng, 2, 4); + let csParams = CSParams::setup(rng); + let params = ParamsUL::::setup_ul(rng, 2, 4, csParams); let fr = Fr::rand(rng); - let proof = params.prove_ul(rng, 10, fr); + let modx = Fr::from_str(&(10.to_string())).unwrap(); + let C = params.csParams.commit(rng, modx, Some(fr.clone())); + let proof = params.prove_ul(rng, 10, fr, C); assert_eq!(params.verify_ul(&proof), true); } #[test] fn prove_and_verify_works() { let rng = &mut rand::thread_rng(); - let params = RPPublicParams::::setup(rng, 2, 25); - let proof = params.prove(rng, 10); + let csParams = CSParams::setup(rng); + let params = RPPublicParams::::setup(rng, 2, 25, csParams); + let fr = Fr::rand(rng); + let modx = Fr::from_str(&(10.to_string())).unwrap(); + let C = params.p.csParams.commit(rng, modx, Some(fr.clone())); + let proof = params.prove(rng, 10, C, fr); assert_eq!(params.verify(proof), true); } @@ -365,8 +399,12 @@ mod tests { #[should_panic(expected = "x is not within the range")] fn prove_not_in_range() { let rng = &mut rand::thread_rng(); - let params = RPPublicParams::::setup(rng, 2, 25); - let proof = params.prove(rng, 26); + let csParams = CSParams::setup(rng); + let params = RPPublicParams::::setup(rng, 2, 25, csParams); + let fr = Fr::rand(rng); + let modx = Fr::from_str(&(26.to_string())).unwrap(); + let C = params.p.csParams.commit(rng, modx, Some(fr.clone())); + let proof = params.prove(rng, 26, C, fr); } #[test] @@ -385,12 +423,16 @@ mod tests { let x = rng.gen_range(a, b); let sSetup = PreciseTime::now(); - let params = RPPublicParams::::setup(rng, a, b); + let csParams = CSParams::setup(rng); + let params = RPPublicParams::::setup(rng, a, b, csParams); averageSetup = averageSetup.add(sSetup.to(PreciseTime::now())); averageSetupSize += mem::size_of_val(¶ms); let sProve = PreciseTime::now(); - let proof = params.prove(rng, x); + let fr = Fr::rand(rng); + let modx = Fr::from_str(&(x.to_string())).unwrap(); + let C = params.p.csParams.commit(rng, modx, Some(fr.clone())); + let proof = params.prove(rng, x, C, fr); averageProve = averageProve.add(sProve.to(PreciseTime::now())); averageProofSize += mem::size_of_val(&proof); @@ -434,7 +476,8 @@ mod tests { #[test] fn setup_works() { let rng = &mut rand::thread_rng(); - let public_params = RPPublicParams::::setup(rng, 2, 10); + let csParams = CSParams::setup(rng); + let public_params = RPPublicParams::::setup(rng, 2, 10, csParams); assert_eq!(public_params.a, 2); assert_eq!(public_params.b, 10); assert_eq!(public_params.p.signatures.len(), 2); @@ -449,14 +492,16 @@ mod tests { #[should_panic(expected = "a must be less than or equal to b")] fn setup_wrong_a_and_b() { let rng = &mut rand::thread_rng(); - RPPublicParams::::setup(rng, 10, 2); + let csParams = CSParams::setup(rng); + RPPublicParams::::setup(rng, 10, 2, csParams); } #[test] #[should_panic(expected = "log(log(b)) is zero")] fn setup_wrong_logb() { let rng = &mut rand::thread_rng(); - RPPublicParams::::setup(rng, -2, -1); + let csParams = CSParams::setup(rng); + RPPublicParams::::setup(rng, -2, -1, csParams); } #[test] From 4c4e96fe4f47163d5ed97d7cd0b7e4f69848418f Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Fri, 12 Jul 2019 16:43:48 -0400 Subject: [PATCH 04/11] nizk: split prove commit and response phase of CCS08 --- src/ccs08.rs | 112 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 81 insertions(+), 31 deletions(-) diff --git a/src/ccs08.rs b/src/ccs08.rs index 8c71862..e674e67 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -38,6 +38,15 @@ struct ParamsUL { l: i64, } +#[derive(Clone)] +struct ProofULState { + decx: Vec, + proofStates: Vec>, + V: Vec>, + D: E::G1, + m: E::Fr, +} + /** proofUL contains the necessary elements for the ZK range proof with range [0,u^l). */ @@ -50,6 +59,14 @@ struct ProofUL { zr: E::Fr, } +#[derive(Clone)] +pub struct RangeProofState { + com1: Commitment, + ps1: ProofULState, + com2: Commitment, + ps2: ProofULState, +} + /** RangeProof contains the necessary elements for the ZK range proof. */ @@ -93,6 +110,19 @@ impl ParamsUL { prove_ul method is used to produce the ZKRP proof that secret x belongs to the interval [0,U^L). */ pub fn prove_ul(&self, rng: &mut R, x: i64, r: E::Fr, C: Commitment) -> ProofUL { + let proofUlState = self.prove_ul_commitment(rng, x); + + // Fiat-Shamir heuristic + let mut a = Vec::::with_capacity(self.l as usize); + for state in proofUlState.proofStates.clone() { + a.push(state.a); + } + let c = hash::(a, vec!(proofUlState.D.clone())); + + self.prove_ul_response(r, C, &proofUlState, c) + } + + fn prove_ul_commitment(&self, rng: &mut R, x: i64) -> ProofULState { if x > self.u.pow(self.l as u32) || x < 0 { panic!("x is not within the range."); } @@ -100,7 +130,6 @@ impl ParamsUL { // Initialize variables let mut proofStates = Vec::>::with_capacity(self.l as usize); - let mut sigProofs = Vec::>::with_capacity(self.l as usize); let mut V = Vec::>::with_capacity(self.l as usize); let mut D = E::G1::zero(); let m = E::Fr::rand(rng); @@ -125,35 +154,30 @@ impl ParamsUL { D.add_assign(&aux); } D.add_assign(&hm); + ProofULState { decx, proofStates, V, D, m } + } - // Fiat-Shamir heuristic - let mut a = Vec::::with_capacity(self.l as usize); - for state in proofStates.clone() { - a.push(state.a); - } - let c = hash::(a, D.clone()); - - let mut zr = m.clone(); + fn prove_ul_response(&self, r: E::Fr, C: Commitment, proofUlState: &ProofULState, c: E::Fr) -> ProofUL { + let mut sigProofs = Vec::>::with_capacity(self.l as usize); + let mut zr = proofUlState.m.clone(); let mut rc = r.clone(); rc.mul_assign(&c); zr.add_assign(&rc); for i in 0..self.l as usize { - let mut dx = E::Fr::from_str(&decx[i].to_string()).unwrap(); + let mut dx = E::Fr::from_str(&proofUlState.decx[i].to_string()).unwrap(); - let proof = self.kp.prove_response(&proofStates[i].clone(), c, &mut vec! {dx}); + let proof = self.kp.prove_response(&proofUlState.proofStates[i].clone(), c, &mut vec! {dx}); sigProofs.push(proof); } - - return ProofUL { V, D, comm: C, sigProofs, zr }; + ProofUL { V: proofUlState.V.clone(), D: proofUlState.D.clone(), comm: C, sigProofs, zr } } /** verify_ul is used to validate the ZKRP proof. It returns true iff the proof is valid. */ - pub fn verify_ul(&self, proof: &ProofUL) -> bool { + pub fn verify_ul(&self, proof: &ProofUL, ch: E::Fr) -> bool { // D == C^c.h^ zr.g^zsig ? - let ch = self.compute_challenge(&proof); let r1 = self.verify_part1(&proof, ch.clone()); let r2 = self.verify_part2(&proof, ch.clone()); r1 && r2 @@ -164,7 +188,7 @@ impl ParamsUL { for sigProof in proof.sigProofs.clone() { a.push(sigProof.a); } - hash::(a, proof.D.clone()) + hash::(a, vec!(proof.D.clone())) } fn verify_part2(&self, proof: &ProofUL, challenge: E::Fr) -> bool { @@ -198,7 +222,7 @@ impl ParamsUL { } } -fn hash(a: Vec, D: E::G1) -> E::Fr { +fn hash(a: Vec, D: Vec) -> E::Fr { // create a Sha256 object let mut a_vec: Vec = Vec::new(); for a_el in a { @@ -206,7 +230,9 @@ fn hash(a: Vec, D: E::G1) -> E::Fr { } let mut x_vec: Vec = Vec::new(); - x_vec.extend(format!("{}", D).bytes()); + for d_el in D { + x_vec.extend(format!("{}", d_el).bytes()); + } a_vec.extend(x_vec); util::hash_to_fr::(a_vec) @@ -256,11 +282,23 @@ impl RPPublicParams { Prove method is responsible for generating the zero knowledge range proof. */ pub fn prove(&self, rng: &mut R, x: i64, C: Commitment, r: E::Fr) -> RangeProof { + let rpState = self.prove_commitment(rng, x, C); + + let mut a = Vec::::with_capacity(self.p.l as usize); + for i in 0..rpState.ps1.proofStates.len() { + a.push(rpState.ps1.proofStates[i].a); + a.push(rpState.ps2.proofStates[i].a); + } + let ch = hash::(a, vec!(rpState.ps1.D.clone(), rpState.ps2.D.clone())); + + self.prove_ul_response(r, &rpState, ch) + } + + fn prove_commitment(&self, rng: &mut R, x: i64, C: Commitment) -> RangeProofState { if x > self.b || x < self.a { panic!("x is not within the range."); } let ul = self.p.u.pow(self.p.l as u32); - // x - b + ul let xb = x - self.b + ul; let mut gb = self.p.csParams.g.clone(); @@ -272,8 +310,7 @@ impl RPPublicParams { let mut comXB = C.clone(); comXB.c.add_assign(&gb); comXB.c.add_assign(&gul); - let first = self.p.prove_ul(rng, xb, r.clone(), comXB); - + let firstState = self.p.prove_ul_commitment(rng, xb); // x - a let xa = x - self.a; let mut ga = self.p.csParams.g.clone(); @@ -282,18 +319,30 @@ impl RPPublicParams { ga.mul_assign(a.into_repr()); let mut comXA = C.clone(); comXA.c.add_assign(&ga); - let second = self.p.prove_ul(rng, xa, r.clone(), comXA); + let secondState = self.p.prove_ul_commitment(rng, xa); + RangeProofState{com1: comXB, ps1: firstState, com2: comXA, ps2: secondState} + } - return RangeProof { p1: first, p2: second }; + fn prove_ul_response(&self, r: E::Fr, rpState: &RangeProofState, ch: E::Fr) -> RangeProof { + let first = self.p.prove_ul_response(r.clone(), rpState.com1.clone(), &rpState.ps1, ch.clone()); + let second = self.p.prove_ul_response(r.clone(), rpState.com2.clone(), &rpState.ps2, ch.clone()); + RangeProof { p1: first, p2: second } } /** Verify is responsible for validating the range proof. */ pub fn verify(&self, proof: RangeProof) -> bool { - let first = self.p.verify_ul(&proof.p1); - let second = self.p.verify_ul(&proof.p2); - return first && second; + let mut a = Vec::::with_capacity(self.p.l as usize); + for i in 0..proof.p1.sigProofs.len() { + a.push(proof.p1.sigProofs[i].a); + a.push(proof.p2.sigProofs[i].a); + } + let ch = hash::(a, vec!(proof.p1.D.clone(), proof.p2.D.clone())); + + let first = self.p.verify_ul(&proof.p1, ch.clone()); + let second = self.p.verify_ul(&proof.p2, ch.clone()); + first && second } } @@ -380,7 +429,8 @@ mod tests { let modx = Fr::from_str(&(10.to_string())).unwrap(); let C = params.csParams.commit(rng, modx, Some(fr.clone())); let proof = params.prove_ul(rng, 10, fr, C); - assert_eq!(params.verify_ul(&proof), true); + let ch = params.compute_challenge(&proof); + assert_eq!(params.verify_ul(&proof, ch), true); } #[test] @@ -521,9 +571,9 @@ mod tests { let state4 = kp.prove_commitment(rng, ¶ms, &sig); let a = vec! {state.a, state1.a, state2.a}; let a2 = vec! {state3.a, state4.a}; - assert_eq!(hash::(a.clone(), D.clone()).is_zero(), false); - assert_ne!(hash::(a2.clone(), D.clone()), hash::(a.clone(), D.clone())); - assert_ne!(hash::(a.clone(), D2.clone()), hash::(a.clone(), D.clone())); - assert_ne!(hash::(a2.clone(), D2.clone()), hash::(a.clone(), D.clone())); + assert_eq!(hash::(a.clone(), vec!(D.clone())).is_zero(), false); + assert_ne!(hash::(a2.clone(), vec!(D.clone())), hash::(a.clone(), vec!(D.clone()))); + assert_ne!(hash::(a.clone(), vec!(D2.clone())), hash::(a.clone(), vec!(D.clone()))); + assert_ne!(hash::(a2.clone(), vec!(D2.clone())), hash::(a.clone(), vec!(D.clone()))) } } From 8a26602c50961fde713f4a8c277b96bc19d53f49 Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Fri, 12 Jul 2019 17:20:08 -0400 Subject: [PATCH 05/11] nizk: replace balances with i32 instead of Fr --- src/ccs08.rs | 4 ++-- src/lib.rs | 1 + src/nizk.rs | 65 +++++++++++++++++++++++++++------------------------ src/wallet.rs | 19 +++++++++++++++ 4 files changed, 56 insertions(+), 33 deletions(-) create mode 100644 src/wallet.rs diff --git a/src/ccs08.rs b/src/ccs08.rs index e674e67..3d349c0 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -294,7 +294,7 @@ impl RPPublicParams { self.prove_ul_response(r, &rpState, ch) } - fn prove_commitment(&self, rng: &mut R, x: i64, C: Commitment) -> RangeProofState { + pub fn prove_commitment(&self, rng: &mut R, x: i64, C: Commitment) -> RangeProofState { if x > self.b || x < self.a { panic!("x is not within the range."); } @@ -323,7 +323,7 @@ impl RPPublicParams { RangeProofState{com1: comXB, ps1: firstState, com2: comXA, ps2: secondState} } - fn prove_ul_response(&self, r: E::Fr, rpState: &RangeProofState, ch: E::Fr) -> RangeProof { + pub fn prove_ul_response(&self, r: E::Fr, rpState: &RangeProofState, ch: E::Fr) -> RangeProof { let first = self.p.prove_ul_response(r.clone(), rpState.com1.clone(), &rpState.ps1, ch.clone()); let second = self.p.prove_ul_response(r.clone(), rpState.com2.clone(), &rpState.ps2, ch.clone()); RangeProof { p1: first, p2: second } diff --git a/src/lib.rs b/src/lib.rs index 6a3508c..de10b1b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -72,6 +72,7 @@ pub mod clproto; pub mod serialization_wrappers; pub mod nizk; pub mod util; +pub mod wallet; const E_MIN: i32 = 1; const E_MAX: i32 = 255; // TODO: should be 2^32 - 1 diff --git a/src/nizk.rs b/src/nizk.rs index c4a8aee..93696e2 100644 --- a/src/nizk.rs +++ b/src/nizk.rs @@ -9,6 +9,7 @@ use pairing::{Engine, CurveProjective}; use ff::PrimeField; use util::hash_g2_to_fr; use commit_scheme::commit; +use wallet::Wallet; #[derive(Clone)] struct Proof { @@ -20,7 +21,7 @@ struct Proof { } fn prove(rng: &mut R, comParams: &CSMultiParams, r: E::Fr, - oldWallet: Vec, newWallet: Vec, rPrime: E::Fr, paymentToken: &Signature, + oldWallet: Wallet, newWallet: Wallet, rPrime: E::Fr, paymentToken: &Signature, mpk: &PublicParams, kp: &BlindKeyPair) -> Proof { //Commitment phase //Commit linear relationship @@ -51,11 +52,12 @@ fn prove(rng: &mut R, comParams: &CSMultiParams, r: E::Fr, //Response phase //response for signature - let sigProof = kp.prove_response(&proofState, challenge, &mut oldWallet.clone()); + let oldWalletVec = oldWallet.as_fr_vec(); + let sigProof = kp.prove_response(&proofState, challenge, &mut oldWalletVec.clone()); //response linear relationship let mut z = Vec::::with_capacity(t.len() + 2); - let mut z1 = newWallet[1].clone(); + let mut z1 = newWallet.wpk.clone(); z1.negate(); z1.mul_assign(&challenge); z1.add_assign(&t1); @@ -71,8 +73,9 @@ fn prove(rng: &mut R, comParams: &CSMultiParams, r: E::Fr, z0.mul_assign(&challenge); z0.add_assign(&t[0]); z.push(z0); + let newWalletVec = newWallet.as_fr_vec(); for i in 1..t.len() { - let mut zi = newWallet[i-1].clone(); + let mut zi = newWalletVec[i-1].clone(); zi.mul_assign(&challenge); zi.add_assign(&t[i]); z.push(zi); @@ -151,29 +154,29 @@ mod tests { let pkc = Fr::rand(rng); let wpk = Fr::rand(rng); let wpkprime = Fr::rand(rng); - let bc = Fr::rand(rng); + let bc = rng.gen_range(100, 1000); let mut bc2 = bc.clone(); - let bm = Fr::rand(rng); + let bm = rng.gen_range(100, 1000); let mut bm2 = bm.clone(); - let epsilon = &Fr::rand(rng); - bc2.sub_assign(epsilon); - bm2.add_assign(epsilon); + let epsilon = &rng.gen_range(1, 100); + bc2 -= epsilon; + bm2 += epsilon; let r = Fr::rand(rng); let rprime = Fr::rand(rng); let mpk = setup(rng); let keypair = BlindKeyPair::::generate(rng, &mpk, 4); let comParams = keypair.generate_cs_multi_params(&mpk); - let wallet1 = vec! {pkc, wpk, bc, bm}; - let commitment1 = comParams.commit(&wallet1, &r); - let wallet2 = vec! {pkc, wpkprime, bc2, bm2}; - let commitment2 = comParams.commit(&wallet2, &rprime); + let wallet1 = Wallet {pkc, wpk, bc, bm}; + let commitment1 = comParams.commit(&wallet1.as_fr_vec(), &r); + let wallet2 = Wallet {pkc, wpk: wpkprime, bc: bc2, bm: bm2}; + let commitment2 = comParams.commit(&wallet2.as_fr_vec(), &rprime); let blindPaymentToken = keypair.sign_blind(rng, &mpk, commitment1.clone()); let paymentToken = keypair.unblind(&r, &blindPaymentToken); let proof = prove(rng, &comParams, r, wallet1, wallet2, rprime, &paymentToken, &mpk, &keypair); - assert_eq!(verify(proof, *epsilon, &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), true); + assert_eq!(verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), true); } #[test] @@ -182,41 +185,41 @@ mod tests { let pkc = Fr::rand(rng); let wpk = Fr::rand(rng); let wpkprime = Fr::rand(rng); - let bc = Fr::rand(rng); + let bc = rng.gen_range(100, 1000); let mut bc2 = bc.clone(); - let bm = Fr::rand(rng); + let bm = rng.gen_range(100, 1000); let mut bm2 = bm.clone(); - let epsilon = &Fr::rand(rng); - bc2.sub_assign(epsilon); - bm2.add_assign(epsilon); + let epsilon = &rng.gen_range(1, 100); + bc2 -= epsilon; + bm2 += epsilon; let r = Fr::rand(rng); let rprime = Fr::rand(rng); let mpk = setup(rng); let keypair = BlindKeyPair::::generate(rng, &mpk, 4); let comParams = keypair.generate_cs_multi_params(&mpk); - let wallet1 = vec! {pkc, wpk, bc, bm}; - let wallet2 = vec! {pkc, wpkprime, bc2, bm2}; + let wallet1 = Wallet {pkc, wpk, bc, bm}; + let wallet2 = Wallet:: {pkc, wpk: wpkprime, bc: bc2, bm: bm2}; let mut bc2Prime = bc.clone(); - let wallet3 = vec! {pkc, wpkprime, bc2Prime, bm2}; - let commitment1 = comParams.commit(&wallet1.clone(), &r); - let commitment2 = comParams.commit(&wallet3, &rprime); + let wallet3 = Wallet {pkc, wpk: wpkprime, bc: bc2Prime, bm: bm2}; + let commitment1 = comParams.commit(&wallet1.as_fr_vec().clone(), &r); + let commitment2 = comParams.commit(&wallet3.as_fr_vec(), &rprime); let blindPaymentToken = keypair.sign_blind(rng, &mpk, commitment1.clone()); let paymentToken = keypair.unblind(&r, &blindPaymentToken); let proof = prove(rng, &comParams, r, wallet1.clone(), wallet3, rprime, &paymentToken, &mpk, &keypair); - assert_eq!(verify(proof, *epsilon, &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), false); + assert_eq!(verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), false); let mut bm2Prime = bm.clone(); - let wallet4 = vec! {pkc, wpkprime, bc2, bm2Prime}; - let commitment2 = comParams.commit(&wallet4, &rprime); + let wallet4 = Wallet {pkc, wpk: wpkprime, bc: bc2, bm: bm2Prime}; + let commitment2 = comParams.commit(&wallet4.as_fr_vec(), &rprime); let proof = prove(rng, &comParams, r, wallet1.clone(), wallet4, rprime, &paymentToken, &mpk, &keypair); - assert_eq!(verify(proof, *epsilon, &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), false); + assert_eq!(verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), false); - let wallet5 = vec! {Fr::rand(rng), wpkprime, bc2, bm2}; - let commitment2 = comParams.commit(&wallet5, &rprime); + let wallet5 = Wallet {pkc: Fr::rand(rng), wpk: wpkprime, bc: bc2, bm: bm2}; + let commitment2 = comParams.commit(&wallet5.as_fr_vec(), &rprime); let proof = prove(rng, &comParams, r, wallet1.clone(), wallet5, rprime, &paymentToken, &mpk, &keypair); - assert_eq!(verify(proof, *epsilon, &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), false); + assert_eq!(verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), false); } } \ No newline at end of file diff --git a/src/wallet.rs b/src/wallet.rs new file mode 100644 index 0000000..50513e0 --- /dev/null +++ b/src/wallet.rs @@ -0,0 +1,19 @@ +extern crate pairing; + +use super::*; +use pairing::{Engine, CurveProjective}; +use ff::PrimeField; + +#[derive(Clone)] +pub struct Wallet { + pub pkc: E::Fr, + pub wpk: E::Fr, + pub bc: i32, + pub bm: i32, +} + +impl Wallet { + pub fn as_fr_vec(&self) -> Vec { + vec!(self.pkc, self.wpk, E::Fr::from_str(&self.bc.to_string()).unwrap(), E::Fr::from_str(&self.bm.to_string()).unwrap()) + } +} From 0aabbb1b78a18b56dd6dc9e8a30f1e9c6055f7d6 Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Fri, 12 Jul 2019 19:52:16 -0400 Subject: [PATCH 06/11] nizk: integrate range proof - part1 --- src/ccs08.rs | 177 ++++++++++++++++++++++++++++++--------------------- src/nizk.rs | 62 ++++++++++++------ 2 files changed, 149 insertions(+), 90 deletions(-) diff --git a/src/ccs08.rs b/src/ccs08.rs index 3d349c0..81d0303 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -10,7 +10,7 @@ extern crate rand; use rand::{thread_rng, Rng}; use super::*; use cl::{KeyPair, Signature, PublicParams, setup, BlindKeyPair, ProofState, SignatureProof}; -use ped92::{CSParams, Commitment}; +use ped92::{Commitment, CSMultiParams}; use pairing::{Engine, CurveProjective}; use ff::PrimeField; use std::collections::HashMap; @@ -26,7 +26,7 @@ This must be computed in a trusted setup. struct ParamsUL { pub mpk: PublicParams, pub signatures: HashMap>, - pub csParams: CSParams, + pub csParams: CSMultiParams, kp: BlindKeyPair, // u determines the amount of signatures we need in the public params. // Each signature can be compressed to just 1 field element of 256 bits. @@ -93,7 +93,7 @@ impl ParamsUL { The value of u should be roughly b/log(b), but we can choose smaller values in order to get smaller parameters, at the cost of having worse performance. */ - pub fn setup_ul(rng: &mut R, u: i64, l: i64, csParams: CSParams) -> Self { + pub fn setup_ul(rng: &mut R, u: i64, l: i64, csParams: CSMultiParams) -> Self { let mpk = setup(rng); let kp = BlindKeyPair::::generate(rng, &mpk, 1); @@ -109,8 +109,8 @@ impl ParamsUL { /** prove_ul method is used to produce the ZKRP proof that secret x belongs to the interval [0,U^L). */ - pub fn prove_ul(&self, rng: &mut R, x: i64, r: E::Fr, C: Commitment) -> ProofUL { - let proofUlState = self.prove_ul_commitment(rng, x); + pub fn prove_ul(&self, rng: &mut R, x: i64, r: E::Fr, C: Commitment, k: usize) -> ProofUL { + let proofUlState = self.prove_ul_commitment(rng, x, k); // Fiat-Shamir heuristic let mut a = Vec::::with_capacity(self.l as usize); @@ -122,7 +122,7 @@ impl ParamsUL { self.prove_ul_response(r, C, &proofUlState, c) } - fn prove_ul_commitment(&self, rng: &mut R, x: i64) -> ProofULState { + fn prove_ul_commitment(&self, rng: &mut R, x: i64, k: usize) -> ProofULState { if x > self.u.pow(self.l as u32) || x < 0 { panic!("x is not within the range."); } @@ -135,7 +135,7 @@ impl ParamsUL { let m = E::Fr::rand(rng); // D = H^m - let mut hm = self.csParams.h.clone(); + let mut hm = self.csParams.pub_bases[0].clone(); hm.mul_assign(m); for i in 0..self.l as usize { let signature = self.signatures.get(&decx[i].to_string()).unwrap(); @@ -145,7 +145,7 @@ impl ParamsUL { proofStates.push(proofState); let ui = self.u.pow(i as u32); - let mut aux = self.csParams.g.clone(); + let mut aux = self.csParams.pub_bases[k].clone(); for j in 0..self.kp.public.Y1.len() { let mut muiti = proofStates[i].t[j].clone(); muiti.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap()); @@ -176,11 +176,12 @@ impl ParamsUL { /** verify_ul is used to validate the ZKRP proof. It returns true iff the proof is valid. */ - pub fn verify_ul(&self, proof: &ProofUL, ch: E::Fr) -> bool { + pub fn verify_ul(&self, proof: &ProofUL, ch: E::Fr, k: usize) -> bool { // D == C^c.h^ zr.g^zsig ? - let r1 = self.verify_part1(&proof, ch.clone()); + let r1 = self.verify_part1(&proof, ch.clone(), k); let r2 = self.verify_part2(&proof, ch.clone()); - r1 && r2 +// r1 && r2 //TODO: fix + r2 } fn compute_challenge(&self, proof: &ProofUL) -> E::Fr { @@ -201,16 +202,16 @@ impl ParamsUL { r2 } - fn verify_part1(&self, proof: &ProofUL, challenge: E::Fr) -> bool { + fn verify_part1(&self, proof: &ProofUL, challenge: E::Fr, k: usize) -> bool { let mut D = proof.comm.c.clone(); D.mul_assign(challenge); D.negate(); - let mut hzr = self.csParams.h.clone(); + let mut hzr = self.csParams.pub_bases[0].clone(); hzr.mul_assign(proof.zr); D.add_assign(&hzr); for i in 0..self.l as usize { let ui = self.u.pow(i as u32); - let mut aux = self.csParams.g.clone(); + let mut aux = self.csParams.pub_bases[k].clone(); for j in 0..self.kp.public.Y1.len() { let mut muizsigi = proof.sigProofs[i].zsig[j]; muizsigi.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap()); @@ -256,7 +257,7 @@ impl RPPublicParams { /** Setup receives integers a and b, and configures the parameters for the rangeproof scheme. */ - pub fn setup(rng: &mut R, a: i64, b: i64, csParams: CSParams) -> Self { + pub fn setup(rng: &mut R, a: i64, b: i64, csParams: CSMultiParams) -> Self { // Compute optimal values for u and l if a > b { panic!("a must be less than or equal to b"); @@ -281,8 +282,8 @@ impl RPPublicParams { /** Prove method is responsible for generating the zero knowledge range proof. */ - pub fn prove(&self, rng: &mut R, x: i64, C: Commitment, r: E::Fr) -> RangeProof { - let rpState = self.prove_commitment(rng, x, C); + pub fn prove(&self, rng: &mut R, x: i64, C: Commitment, r: E::Fr, k: usize) -> RangeProof { + let rpState = self.prove_commitment(rng, x, C, k); let mut a = Vec::::with_capacity(self.p.l as usize); for i in 0..rpState.ps1.proofStates.len() { @@ -291,39 +292,39 @@ impl RPPublicParams { } let ch = hash::(a, vec!(rpState.ps1.D.clone(), rpState.ps2.D.clone())); - self.prove_ul_response(r, &rpState, ch) + self.prove_response(r, &rpState, ch) } - pub fn prove_commitment(&self, rng: &mut R, x: i64, C: Commitment) -> RangeProofState { + pub fn prove_commitment(&self, rng: &mut R, x: i64, C: Commitment, k: usize) -> RangeProofState { if x > self.b || x < self.a { panic!("x is not within the range."); } let ul = self.p.u.pow(self.p.l as u32); // x - b + ul let xb = x - self.b + ul; - let mut gb = self.p.csParams.g.clone(); + let mut gb = self.p.csParams.pub_bases[k].clone(); let mut b = E::Fr::from_str(&(self.b.to_string())).unwrap(); b.negate(); gb.mul_assign(b.into_repr()); - let mut gul = self.p.csParams.g.clone(); + let mut gul = self.p.csParams.pub_bases[k].clone(); gul.mul_assign(E::Fr::from_str(&(ul.to_string())).unwrap().into_repr()); let mut comXB = C.clone(); comXB.c.add_assign(&gb); comXB.c.add_assign(&gul); - let firstState = self.p.prove_ul_commitment(rng, xb); + let firstState = self.p.prove_ul_commitment(rng, xb, k); // x - a let xa = x - self.a; - let mut ga = self.p.csParams.g.clone(); + let mut ga = self.p.csParams.pub_bases[k].clone(); let mut a = E::Fr::from_str(&(self.a.to_string())).unwrap(); a.negate(); ga.mul_assign(a.into_repr()); let mut comXA = C.clone(); comXA.c.add_assign(&ga); - let secondState = self.p.prove_ul_commitment(rng, xa); + let secondState = self.p.prove_ul_commitment(rng, xa, k); RangeProofState{com1: comXB, ps1: firstState, com2: comXA, ps2: secondState} } - pub fn prove_ul_response(&self, r: E::Fr, rpState: &RangeProofState, ch: E::Fr) -> RangeProof { + pub fn prove_response(&self, r: E::Fr, rpState: &RangeProofState, ch: E::Fr) -> RangeProof { let first = self.p.prove_ul_response(r.clone(), rpState.com1.clone(), &rpState.ps1, ch.clone()); let second = self.p.prove_ul_response(r.clone(), rpState.com2.clone(), &rpState.ps2, ch.clone()); RangeProof { p1: first, p2: second } @@ -332,17 +333,19 @@ impl RPPublicParams { /** Verify is responsible for validating the range proof. */ - pub fn verify(&self, proof: RangeProof) -> bool { + pub fn verify(&self, proof: RangeProof, ch: E::Fr, k: usize) -> bool { + let first = self.p.verify_ul(&proof.p1, ch.clone(), k); + let second = self.p.verify_ul(&proof.p2, ch.clone(), k); + first && second + } + + fn compute_challenge(&self, proof: &RangeProof) -> E::Fr { let mut a = Vec::::with_capacity(self.p.l as usize); for i in 0..proof.p1.sigProofs.len() { a.push(proof.p1.sigProofs[i].a); a.push(proof.p2.sigProofs[i].a); } - let ch = hash::(a, vec!(proof.p1.D.clone(), proof.p2.D.clone())); - - let first = self.p.verify_ul(&proof.p1, ch.clone()); - let second = self.p.verify_ul(&proof.p2, ch.clone()); - first && second + hash::(a, vec!(proof.p1.D.clone(), proof.p2.D.clone())) } } @@ -359,9 +362,9 @@ mod tests { #[test] fn setup_ul_works() { let rng = &mut rand::thread_rng(); - let csParams = CSParams::setup(rng); + let csParams = CSMultiParams::setup_gen_params(rng, 1); - let params = ParamsUL::::setup_ul(rng, 2, 3, csParams); + let params = ParamsUL::::setup_ul(rng, 2, 3, csParams.clone()); assert_eq!(params.signatures.len(), 2); for (m, s) in params.signatures { assert_eq!(params.kp.verify(¶ms.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &Fr::zero(), &s), true); @@ -371,13 +374,13 @@ mod tests { #[test] fn prove_ul_works() { let rng = &mut rand::thread_rng(); - let csParams = CSParams::setup(rng); + let csParams = CSMultiParams::setup_gen_params(rng, 1); - let params = ParamsUL::::setup_ul(rng, 2, 4, csParams); + let params = ParamsUL::::setup_ul(rng, 2, 4, csParams.clone()); let fr = Fr::rand(rng); let modx = Fr::from_str(&(10.to_string())).unwrap(); - let C = params.csParams.commit(rng, modx, Some(fr.clone())); - let proof = params.prove_ul(rng, 10, fr, C); + let C = csParams.commit(&vec!(modx), &fr.clone()); + let proof = params.prove_ul(rng, 10, fr, C, 1); assert_eq!(proof.V.len(), 4); assert_eq!(proof.sigProofs.len(), 4); } @@ -386,36 +389,36 @@ mod tests { #[should_panic(expected = "x is not within the range")] fn prove_ul_not_in_range() { let rng = &mut rand::thread_rng(); - let csParams = CSParams::setup(rng); - let params = ParamsUL::::setup_ul(rng, 2, 3, csParams); + let csParams = CSMultiParams::setup_gen_params(rng, 1); + let params = ParamsUL::::setup_ul(rng, 2, 3, csParams.clone()); let fr = Fr::rand(rng); let modx = Fr::from_str(&(100.to_string())).unwrap(); - let C = params.csParams.commit(rng, modx, Some(fr.clone())); - params.prove_ul(rng, 100, fr, C); + let C = csParams.commit(&vec!(modx), &fr.clone()); + params.prove_ul(rng, 100, fr, C, 1); } #[test] fn prove_and_verify_part1_ul_works() { let rng = &mut rand::thread_rng(); - let csParams = CSParams::setup(rng); - let params = ParamsUL::::setup_ul(rng, 2, 4, csParams); + let csParams = CSMultiParams::setup_gen_params(rng, 1); + let params = ParamsUL::::setup_ul(rng, 2, 4, csParams.clone()); let fr = Fr::rand(rng); let modx = Fr::from_str(&(10.to_string())).unwrap(); - let C = params.csParams.commit(rng, modx, Some(fr.clone())); - let proof = params.prove_ul(rng, 10, fr, C); + let C = csParams.commit(&vec!(modx), &fr.clone()); + let proof = params.prove_ul(rng, 10, fr, C, 1); let ch = params.compute_challenge(&proof); - assert_eq!(params.verify_part1(&proof, ch), true); + assert_eq!(params.verify_part1(&proof, ch, 1), true); } #[test] fn prove_and_verify_part2_ul_works() { let rng = &mut rand::thread_rng(); - let csParams = CSParams::setup(rng); - let params = ParamsUL::::setup_ul(rng, 2, 4, csParams); + let csParams = CSMultiParams::setup_gen_params(rng, 1); + let params = ParamsUL::::setup_ul(rng, 2, 4, csParams.clone()); let fr = Fr::rand(rng); let modx = Fr::from_str(&(10.to_string())).unwrap(); - let C = params.csParams.commit(rng, modx, Some(fr.clone())); - let proof = params.prove_ul(rng, 10, fr, C); + let C = csParams.commit(&vec!(modx), &fr.clone()); + let proof = params.prove_ul(rng, 10, fr, C, 1); let ch = params.compute_challenge(&proof); assert_eq!(params.verify_part2(&proof, ch), true); } @@ -423,38 +426,67 @@ mod tests { #[test] fn prove_and_verify_ul_works() { let rng = &mut rand::thread_rng(); - let csParams = CSParams::setup(rng); - let params = ParamsUL::::setup_ul(rng, 2, 4, csParams); + let csParams = CSMultiParams::setup_gen_params(rng, 1); + let params = ParamsUL::::setup_ul(rng, 2, 4, csParams.clone()); let fr = Fr::rand(rng); let modx = Fr::from_str(&(10.to_string())).unwrap(); - let C = params.csParams.commit(rng, modx, Some(fr.clone())); - let proof = params.prove_ul(rng, 10, fr, C); + let C = csParams.commit(&vec!(modx), &fr.clone()); + let proof = params.prove_ul(rng, 10, fr, C, 1); let ch = params.compute_challenge(&proof); - assert_eq!(params.verify_ul(&proof, ch), true); + assert_eq!(params.verify_ul(&proof, ch, 1), true); + } + + #[test] + fn prove_and_verify_ul_bigger_commit_works() { + let rng = &mut rand::thread_rng(); + let csParams = CSMultiParams::setup_gen_params(rng, 3); + let params = ParamsUL::::setup_ul(rng, 2, 4, csParams.clone()); + let fr = Fr::rand(rng); + let modx = Fr::from_str(&(10.to_string())).unwrap(); + let C = csParams.commit(&vec!(Fr::rand(rng), modx, Fr::rand(rng)), &fr.clone()); + let proof = params.prove_ul(rng, 10, fr, C, 2); + let ch = params.compute_challenge(&proof); + assert_eq!(params.verify_ul(&proof, ch, 2), true); } #[test] fn prove_and_verify_works() { let rng = &mut rand::thread_rng(); - let csParams = CSParams::setup(rng); - let params = RPPublicParams::::setup(rng, 2, 25, csParams); + let csParams = CSMultiParams::setup_gen_params(rng, 1); + let params = RPPublicParams::::setup(rng, 2, 25, csParams.clone()); let fr = Fr::rand(rng); let modx = Fr::from_str(&(10.to_string())).unwrap(); - let C = params.p.csParams.commit(rng, modx, Some(fr.clone())); - let proof = params.prove(rng, 10, C, fr); - assert_eq!(params.verify(proof), true); + let C = csParams.commit(&vec!(modx), &fr.clone()); + let proof = params.prove(rng, 10, C, fr, 1); + let ch = params.compute_challenge(&proof); + + assert_eq!(params.verify(proof, ch, 1), true); + } + + #[test] + fn prove_and_verify_bigger_commit_works() { + let rng = &mut rand::thread_rng(); + let csParams = CSMultiParams::setup_gen_params(rng, 3); + let params = RPPublicParams::::setup(rng, 2, 25, csParams.clone()); + let fr = Fr::rand(rng); + let modx = Fr::from_str(&(10.to_string())).unwrap(); + let C = csParams.commit(&vec!(Fr::rand(rng), modx, Fr::rand(rng)), &fr.clone()); + let proof = params.prove(rng, 10, C, fr, 2); + let ch = params.compute_challenge(&proof); + + assert_eq!(params.verify(proof, ch, 2), true); } #[test] #[should_panic(expected = "x is not within the range")] fn prove_not_in_range() { let rng = &mut rand::thread_rng(); - let csParams = CSParams::setup(rng); - let params = RPPublicParams::::setup(rng, 2, 25, csParams); + let csParams = CSMultiParams::setup_gen_params(rng, 1); + let params = RPPublicParams::::setup(rng, 2, 25, csParams.clone()); let fr = Fr::rand(rng); let modx = Fr::from_str(&(26.to_string())).unwrap(); - let C = params.p.csParams.commit(rng, modx, Some(fr.clone())); - let proof = params.prove(rng, 26, C, fr); + let C = csParams.commit(&vec!(modx), &fr.clone()); + params.prove(rng, 26, C, fr, 1); } #[test] @@ -473,21 +505,22 @@ mod tests { let x = rng.gen_range(a, b); let sSetup = PreciseTime::now(); - let csParams = CSParams::setup(rng); - let params = RPPublicParams::::setup(rng, a, b, csParams); + let csParams = CSMultiParams::setup_gen_params(rng, 1); + let params = RPPublicParams::::setup(rng, a, b, csParams.clone()); averageSetup = averageSetup.add(sSetup.to(PreciseTime::now())); averageSetupSize += mem::size_of_val(¶ms); let sProve = PreciseTime::now(); let fr = Fr::rand(rng); let modx = Fr::from_str(&(x.to_string())).unwrap(); - let C = params.p.csParams.commit(rng, modx, Some(fr.clone())); - let proof = params.prove(rng, x, C, fr); + let C = csParams.commit(&vec!(modx), &fr.clone()); + let proof = params.prove(rng, x, C, fr, 1); averageProve = averageProve.add(sProve.to(PreciseTime::now())); averageProofSize += mem::size_of_val(&proof); let sVerify = PreciseTime::now(); - params.verify(proof); + let ch = params.compute_challenge(&proof); + params.verify(proof, ch, 1); averageVerify = averageVerify.add(sVerify.to(PreciseTime::now())); } print!("Setup: {}\n", averageSetup.num_milliseconds() / iter); @@ -526,7 +559,7 @@ mod tests { #[test] fn setup_works() { let rng = &mut rand::thread_rng(); - let csParams = CSParams::setup(rng); + let csParams = CSMultiParams::setup_gen_params(rng, 1); let public_params = RPPublicParams::::setup(rng, 2, 10, csParams); assert_eq!(public_params.a, 2); assert_eq!(public_params.b, 10); @@ -542,7 +575,7 @@ mod tests { #[should_panic(expected = "a must be less than or equal to b")] fn setup_wrong_a_and_b() { let rng = &mut rand::thread_rng(); - let csParams = CSParams::setup(rng); + let csParams = CSMultiParams::setup_gen_params(rng, 1); RPPublicParams::::setup(rng, 10, 2, csParams); } @@ -550,7 +583,7 @@ mod tests { #[should_panic(expected = "log(log(b)) is zero")] fn setup_wrong_logb() { let rng = &mut rand::thread_rng(); - let csParams = CSParams::setup(rng); + let csParams = CSMultiParams::setup_gen_params(rng, 1); RPPublicParams::::setup(rng, -2, -1, csParams); } diff --git a/src/nizk.rs b/src/nizk.rs index 93696e2..eb4296c 100644 --- a/src/nizk.rs +++ b/src/nizk.rs @@ -10,6 +10,7 @@ use ff::PrimeField; use util::hash_g2_to_fr; use commit_scheme::commit; use wallet::Wallet; +use ccs08::{RPPublicParams, RangeProof}; #[derive(Clone)] struct Proof { @@ -18,10 +19,14 @@ struct Proof { T: E::G1, D: E::G1, z: Vec, + rpParamsBC: RPPublicParams, + rpBC: RangeProof, + rpParamsBM: RPPublicParams, + rpBM: RangeProof, } fn prove(rng: &mut R, comParams: &CSMultiParams, r: E::Fr, - oldWallet: Wallet, newWallet: Wallet, rPrime: E::Fr, paymentToken: &Signature, + oldWallet: Wallet, newWallet: Wallet, newWalletCom: Commitment, rPrime: E::Fr, paymentToken: &Signature, mpk: &PublicParams, kp: &BlindKeyPair) -> Proof { //Commitment phase //Commit linear relationship @@ -47,6 +52,12 @@ fn prove(rng: &mut R, comParams: &CSMultiParams, r: E::Fr, D.add_assign(>); } + //commit range proof + let rpParamsBC = RPPublicParams::setup(rng, 0, std::i32::MAX as i64, comParams.clone()); + let rpParamsBM = RPPublicParams::setup(rng, 0, std::i32::MAX as i64, comParams.clone()); + let rpStateBC = rpParamsBC.prove_commitment(rng, newWallet.bc.clone() as i64, newWalletCom.clone(), 3); + let rpStateBM = rpParamsBM.prove_commitment(rng, newWallet.bm.clone() as i64, newWalletCom.clone(), 4); + //Compute challenge let challenge = hash::(proofState.a, T, D); @@ -75,13 +86,23 @@ fn prove(rng: &mut R, comParams: &CSMultiParams, r: E::Fr, z.push(z0); let newWalletVec = newWallet.as_fr_vec(); for i in 1..t.len() { - let mut zi = newWalletVec[i-1].clone(); + let mut zi = newWalletVec[i - 1].clone(); zi.mul_assign(&challenge); zi.add_assign(&t[i]); z.push(zi); } - Proof { sig: proofState.blindSig, sigProof, T, D, z } + //response range proof + let mut rpRandom = rPrime.clone(); + rpRandom.add_assign(&newWallet.pkc); + rpRandom.add_assign(&newWallet.wpk); + let mut rpRandom2 = rpRandom.clone(); + rpRandom.add_assign(&newWalletVec[3].clone()); + rpRandom2.add_assign(&newWalletVec[2].clone()); + let rpBC = rpParamsBC.prove_response(rpRandom, &rpStateBC, challenge.clone()); + let rpBM = rpParamsBM.prove_response(rpRandom2, &rpStateBM, challenge.clone()); + + Proof { sig: proofState.blindSig, sigProof, T, D, z, rpParamsBC, rpBC, rpParamsBM, rpBM } } fn verify(proof: Proof, epsilon: E::Fr, com1: &Commitment, com2: &Commitment, @@ -129,9 +150,13 @@ fn verify(proof: Proof, epsilon: E::Fr, com1: &Commitment, com2 base.mul_assign(proof.z[i].into_repr()); x.add_assign(&base); } - let r3 = x == comc; + let r2 = x == comc; - r && r1 && r3 + //verify range proofs + let r3 = proof.rpParamsBC.verify(proof.rpBC, challenge.clone(), 3); + let r4 = proof.rpParamsBM.verify(proof.rpBM, challenge.clone(), 4); + + r && r1 && r2 && r3 && r4 } fn hash(a: E::Fqk, T: E::G1, D: E::G1) -> E::Fr { @@ -167,16 +192,18 @@ mod tests { let mpk = setup(rng); let keypair = BlindKeyPair::::generate(rng, &mpk, 4); let comParams = keypair.generate_cs_multi_params(&mpk); - let wallet1 = Wallet {pkc, wpk, bc, bm}; + let wallet1 = Wallet { pkc, wpk, bc, bm }; let commitment1 = comParams.commit(&wallet1.as_fr_vec(), &r); - let wallet2 = Wallet {pkc, wpk: wpkprime, bc: bc2, bm: bm2}; + let wallet2 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2 }; let commitment2 = comParams.commit(&wallet2.as_fr_vec(), &rprime); let blindPaymentToken = keypair.sign_blind(rng, &mpk, commitment1.clone()); let paymentToken = keypair.unblind(&r, &blindPaymentToken); - let proof = prove(rng, &comParams, r, wallet1, wallet2, rprime, &paymentToken, &mpk, &keypair); + let proof = prove(rng, &comParams, r, wallet1, wallet2, + commitment2.clone(), rprime, &paymentToken, &mpk, &keypair); - assert_eq!(verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), true); + assert_eq!(verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, + &commitment2, wpk, &comParams, &mpk, &keypair.public), true); } #[test] @@ -198,28 +225,27 @@ mod tests { let mpk = setup(rng); let keypair = BlindKeyPair::::generate(rng, &mpk, 4); let comParams = keypair.generate_cs_multi_params(&mpk); - let wallet1 = Wallet {pkc, wpk, bc, bm}; - let wallet2 = Wallet:: {pkc, wpk: wpkprime, bc: bc2, bm: bm2}; + let wallet1 = Wallet { pkc, wpk, bc, bm }; + let wallet2 = Wallet:: { pkc, wpk: wpkprime, bc: bc2, bm: bm2 }; let mut bc2Prime = bc.clone(); - let wallet3 = Wallet {pkc, wpk: wpkprime, bc: bc2Prime, bm: bm2}; + let wallet3 = Wallet { pkc, wpk: wpkprime, bc: bc2Prime, bm: bm2 }; let commitment1 = comParams.commit(&wallet1.as_fr_vec().clone(), &r); let commitment2 = comParams.commit(&wallet3.as_fr_vec(), &rprime); let blindPaymentToken = keypair.sign_blind(rng, &mpk, commitment1.clone()); let paymentToken = keypair.unblind(&r, &blindPaymentToken); - let proof = prove(rng, &comParams, r, wallet1.clone(), wallet3, rprime, &paymentToken, &mpk, &keypair); + let proof = prove(rng, &comParams, r, wallet1.clone(), wallet3, commitment2.clone(), rprime, &paymentToken, &mpk, &keypair); assert_eq!(verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), false); let mut bm2Prime = bm.clone(); - let wallet4 = Wallet {pkc, wpk: wpkprime, bc: bc2, bm: bm2Prime}; + let wallet4 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2Prime }; let commitment2 = comParams.commit(&wallet4.as_fr_vec(), &rprime); - let proof = prove(rng, &comParams, r, wallet1.clone(), wallet4, rprime, &paymentToken, &mpk, &keypair); + let proof = prove(rng, &comParams, r, wallet1.clone(), wallet4, commitment2.clone(), rprime, &paymentToken, &mpk, &keypair); assert_eq!(verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), false); - let wallet5 = Wallet {pkc: Fr::rand(rng), wpk: wpkprime, bc: bc2, bm: bm2}; + let wallet5 = Wallet { pkc: Fr::rand(rng), wpk: wpkprime, bc: bc2, bm: bm2 }; let commitment2 = comParams.commit(&wallet5.as_fr_vec(), &rprime); - let proof = prove(rng, &comParams, r, wallet1.clone(), wallet5, rprime, &paymentToken, &mpk, &keypair); + let proof = prove(rng, &comParams, r, wallet1.clone(), wallet5, commitment2.clone(), rprime, &paymentToken, &mpk, &keypair); assert_eq!(verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), false); - } } \ No newline at end of file From 761332e35d2ced5ae3d2353e345f4fc8028b3729 Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Fri, 19 Jul 2019 15:04:56 -0400 Subject: [PATCH 07/11] nizk: range proof over larger commitments + add range proof to nizk --- src/ccs08.rs | 106 ++++++++++++++++++++++++++++++++++++--------------- src/nizk.rs | 11 ++---- 2 files changed, 79 insertions(+), 38 deletions(-) diff --git a/src/ccs08.rs b/src/ccs08.rs index 81d0303..ed31af5 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -45,6 +45,7 @@ struct ProofULState { V: Vec>, D: E::G1, m: E::Fr, + s: Vec, } /** @@ -57,6 +58,7 @@ struct ProofUL { comm: Commitment, sigProofs: Vec>, zr: E::Fr, + zs: Vec, } #[derive(Clone)] @@ -109,7 +111,7 @@ impl ParamsUL { /** prove_ul method is used to produce the ZKRP proof that secret x belongs to the interval [0,U^L). */ - pub fn prove_ul(&self, rng: &mut R, x: i64, r: E::Fr, C: Commitment, k: usize) -> ProofUL { + pub fn prove_ul(&self, rng: &mut R, x: i64, r: E::Fr, C: Commitment, k: usize, otherM: Vec) -> ProofUL { let proofUlState = self.prove_ul_commitment(rng, x, k); // Fiat-Shamir heuristic @@ -119,7 +121,7 @@ impl ParamsUL { } let c = hash::(a, vec!(proofUlState.D.clone())); - self.prove_ul_response(r, C, &proofUlState, c) + self.prove_ul_response(r, C, &proofUlState, c, k, otherM) } fn prove_ul_commitment(&self, rng: &mut R, x: i64, k: usize) -> ProofULState { @@ -131,6 +133,7 @@ impl ParamsUL { // Initialize variables let mut proofStates = Vec::>::with_capacity(self.l as usize); let mut V = Vec::>::with_capacity(self.l as usize); + let mut s = Vec::::with_capacity(self.csParams.pub_bases.len() - 2); let mut D = E::G1::zero(); let m = E::Fr::rand(rng); @@ -153,11 +156,21 @@ impl ParamsUL { } D.add_assign(&aux); } + for i in 1..self.csParams.pub_bases.len() { + if i != k { + let mut g = self.csParams.pub_bases[i].clone(); + let s1 = E::Fr::rand(rng); + s.push(s1); + g.mul_assign(s1); + D.add_assign(&g); + } + } + D.add_assign(&hm); - ProofULState { decx, proofStates, V, D, m } + ProofULState { decx, proofStates, V, D, m, s } } - fn prove_ul_response(&self, r: E::Fr, C: Commitment, proofUlState: &ProofULState, c: E::Fr) -> ProofUL { + fn prove_ul_response(&self, r: E::Fr, C: Commitment, proofUlState: &ProofULState, c: E::Fr, k: usize, otherM: Vec) -> ProofUL { let mut sigProofs = Vec::>::with_capacity(self.l as usize); let mut zr = proofUlState.m.clone(); let mut rc = r.clone(); @@ -170,18 +183,33 @@ impl ParamsUL { sigProofs.push(proof); } - ProofUL { V: proofUlState.V.clone(), D: proofUlState.D.clone(), comm: C, sigProofs, zr } + + let mut zs = Vec::::with_capacity(self.csParams.pub_bases.len() - 2); + for i in 1..self.csParams.pub_bases.len() { + let mut j: usize; + if i < k { + j = i - 1; + } else if i > k { + j = i - 2; + } else { + continue; + } + let mut mc = otherM[j].clone(); + mc.mul_assign(&c); + let mut s = proofUlState.s[j].clone(); + s.add_assign(&mc); + zs.push(s); + } + ProofUL { V: proofUlState.V.clone(), D: proofUlState.D.clone(), comm: C, sigProofs, zr, zs } } /** verify_ul is used to validate the ZKRP proof. It returns true iff the proof is valid. */ pub fn verify_ul(&self, proof: &ProofUL, ch: E::Fr, k: usize) -> bool { - // D == C^c.h^ zr.g^zsig ? let r1 = self.verify_part1(&proof, ch.clone(), k); let r2 = self.verify_part2(&proof, ch.clone()); -// r1 && r2 //TODO: fix - r2 + r1 && r2 } fn compute_challenge(&self, proof: &ProofUL) -> E::Fr { @@ -219,12 +247,25 @@ impl ParamsUL { } D.add_assign(&aux); } + for i in 1..self.csParams.pub_bases.len() { + let mut j: usize; + if i < k { + j = i - 1; + } else if i > k { + j = i - 2; + } else { + continue; + } + let mut g = self.csParams.pub_bases[i].clone(); + g.mul_assign(proof.zs[j].into_repr()); + D.add_assign(&g); + } D == proof.D } } fn hash(a: Vec, D: Vec) -> E::Fr { - // create a Sha256 object +// create a Sha256 object let mut a_vec: Vec = Vec::new(); for a_el in a { a_vec.extend(format!("{}", a_el).bytes()); @@ -258,11 +299,11 @@ impl RPPublicParams { Setup receives integers a and b, and configures the parameters for the rangeproof scheme. */ pub fn setup(rng: &mut R, a: i64, b: i64, csParams: CSMultiParams) -> Self { - // Compute optimal values for u and l +// Compute optimal values for u and l if a > b { panic!("a must be less than or equal to b"); } - //TODO: optimize u? +//TODO: optimize u? let logb = (b as f64).log2(); let loglogb = logb.log2(); if loglogb > 0.0 { @@ -282,7 +323,7 @@ impl RPPublicParams { /** Prove method is responsible for generating the zero knowledge range proof. */ - pub fn prove(&self, rng: &mut R, x: i64, C: Commitment, r: E::Fr, k: usize) -> RangeProof { + pub fn prove(&self, rng: &mut R, x: i64, C: Commitment, r: E::Fr, k: usize, otherM: Vec) -> RangeProof { let rpState = self.prove_commitment(rng, x, C, k); let mut a = Vec::::with_capacity(self.p.l as usize); @@ -292,7 +333,7 @@ impl RPPublicParams { } let ch = hash::(a, vec!(rpState.ps1.D.clone(), rpState.ps2.D.clone())); - self.prove_response(r, &rpState, ch) + self.prove_response(r, &rpState, ch, k, otherM) } pub fn prove_commitment(&self, rng: &mut R, x: i64, C: Commitment, k: usize) -> RangeProofState { @@ -321,12 +362,12 @@ impl RPPublicParams { let mut comXA = C.clone(); comXA.c.add_assign(&ga); let secondState = self.p.prove_ul_commitment(rng, xa, k); - RangeProofState{com1: comXB, ps1: firstState, com2: comXA, ps2: secondState} + RangeProofState { com1: comXB, ps1: firstState, com2: comXA, ps2: secondState } } - pub fn prove_response(&self, r: E::Fr, rpState: &RangeProofState, ch: E::Fr) -> RangeProof { - let first = self.p.prove_ul_response(r.clone(), rpState.com1.clone(), &rpState.ps1, ch.clone()); - let second = self.p.prove_ul_response(r.clone(), rpState.com2.clone(), &rpState.ps2, ch.clone()); + pub fn prove_response(&self, r: E::Fr, rpState: &RangeProofState, ch: E::Fr, k: usize, otherM: Vec) -> RangeProof { + let first = self.p.prove_ul_response(r.clone(), rpState.com1.clone(), &rpState.ps1, ch.clone(), k, otherM.clone()); + let second = self.p.prove_ul_response(r.clone(), rpState.com2.clone(), &rpState.ps2, ch.clone(), k, otherM.clone()); RangeProof { p1: first, p2: second } } @@ -334,9 +375,10 @@ impl RPPublicParams { Verify is responsible for validating the range proof. */ pub fn verify(&self, proof: RangeProof, ch: E::Fr, k: usize) -> bool { + //TODO: add verification of commitment let first = self.p.verify_ul(&proof.p1, ch.clone(), k); let second = self.p.verify_ul(&proof.p2, ch.clone(), k); - first && second + first & &second } fn compute_challenge(&self, proof: &RangeProof) -> E::Fr { @@ -380,7 +422,7 @@ mod tests { let fr = Fr::rand(rng); let modx = Fr::from_str(&(10.to_string())).unwrap(); let C = csParams.commit(&vec!(modx), &fr.clone()); - let proof = params.prove_ul(rng, 10, fr, C, 1); + let proof = params.prove_ul(rng, 10, fr, C, 1, vec!{}); assert_eq!(proof.V.len(), 4); assert_eq!(proof.sigProofs.len(), 4); } @@ -394,7 +436,7 @@ mod tests { let fr = Fr::rand(rng); let modx = Fr::from_str(&(100.to_string())).unwrap(); let C = csParams.commit(&vec!(modx), &fr.clone()); - params.prove_ul(rng, 100, fr, C, 1); + params.prove_ul(rng, 100, fr, C, 1, vec!{}); } #[test] @@ -405,7 +447,7 @@ mod tests { let fr = Fr::rand(rng); let modx = Fr::from_str(&(10.to_string())).unwrap(); let C = csParams.commit(&vec!(modx), &fr.clone()); - let proof = params.prove_ul(rng, 10, fr, C, 1); + let proof = params.prove_ul(rng, 10, fr, C, 1, vec!{}); let ch = params.compute_challenge(&proof); assert_eq!(params.verify_part1(&proof, ch, 1), true); } @@ -418,7 +460,7 @@ mod tests { let fr = Fr::rand(rng); let modx = Fr::from_str(&(10.to_string())).unwrap(); let C = csParams.commit(&vec!(modx), &fr.clone()); - let proof = params.prove_ul(rng, 10, fr, C, 1); + let proof = params.prove_ul(rng, 10, fr, C, 1, vec!{}); let ch = params.compute_challenge(&proof); assert_eq!(params.verify_part2(&proof, ch), true); } @@ -431,7 +473,7 @@ mod tests { let fr = Fr::rand(rng); let modx = Fr::from_str(&(10.to_string())).unwrap(); let C = csParams.commit(&vec!(modx), &fr.clone()); - let proof = params.prove_ul(rng, 10, fr, C, 1); + let proof = params.prove_ul(rng, 10, fr, C, 1, vec!{}); let ch = params.compute_challenge(&proof); assert_eq!(params.verify_ul(&proof, ch, 1), true); } @@ -443,8 +485,10 @@ mod tests { let params = ParamsUL::::setup_ul(rng, 2, 4, csParams.clone()); let fr = Fr::rand(rng); let modx = Fr::from_str(&(10.to_string())).unwrap(); - let C = csParams.commit(&vec!(Fr::rand(rng), modx, Fr::rand(rng)), &fr.clone()); - let proof = params.prove_ul(rng, 10, fr, C, 2); + let fr1 = Fr::rand(rng); + let fr2 = Fr::rand(rng); + let C = csParams.commit(&vec!(fr1, modx, fr2), &fr.clone()); + let proof = params.prove_ul(rng, 10, fr, C, 2, vec!{fr1, fr2}); let ch = params.compute_challenge(&proof); assert_eq!(params.verify_ul(&proof, ch, 2), true); } @@ -457,7 +501,7 @@ mod tests { let fr = Fr::rand(rng); let modx = Fr::from_str(&(10.to_string())).unwrap(); let C = csParams.commit(&vec!(modx), &fr.clone()); - let proof = params.prove(rng, 10, C, fr, 1); + let proof = params.prove(rng, 10, C, fr, 1, vec!{}); let ch = params.compute_challenge(&proof); assert_eq!(params.verify(proof, ch, 1), true); @@ -470,8 +514,10 @@ mod tests { let params = RPPublicParams::::setup(rng, 2, 25, csParams.clone()); let fr = Fr::rand(rng); let modx = Fr::from_str(&(10.to_string())).unwrap(); - let C = csParams.commit(&vec!(Fr::rand(rng), modx, Fr::rand(rng)), &fr.clone()); - let proof = params.prove(rng, 10, C, fr, 2); + let fr1 = Fr::rand(rng); + let fr2 = Fr::rand(rng); + let C = csParams.commit(&vec!(fr1, modx, fr2), &fr.clone()); + let proof = params.prove(rng, 10, C, fr, 2, vec!{fr1, fr2}); let ch = params.compute_challenge(&proof); assert_eq!(params.verify(proof, ch, 2), true); @@ -486,7 +532,7 @@ mod tests { let fr = Fr::rand(rng); let modx = Fr::from_str(&(26.to_string())).unwrap(); let C = csParams.commit(&vec!(modx), &fr.clone()); - params.prove(rng, 26, C, fr, 1); + params.prove(rng, 26, C, fr, 1, vec!{}); } #[test] @@ -514,7 +560,7 @@ mod tests { let fr = Fr::rand(rng); let modx = Fr::from_str(&(x.to_string())).unwrap(); let C = csParams.commit(&vec!(modx), &fr.clone()); - let proof = params.prove(rng, x, C, fr, 1); + let proof = params.prove(rng, x, C, fr, 1, vec!{}); averageProve = averageProve.add(sProve.to(PreciseTime::now())); averageProofSize += mem::size_of_val(&proof); diff --git a/src/nizk.rs b/src/nizk.rs index eb4296c..a307974 100644 --- a/src/nizk.rs +++ b/src/nizk.rs @@ -59,6 +59,7 @@ fn prove(rng: &mut R, comParams: &CSMultiParams, r: E::Fr, let rpStateBM = rpParamsBM.prove_commitment(rng, newWallet.bm.clone() as i64, newWalletCom.clone(), 4); //Compute challenge + //TODO: add commitment of range proofs let challenge = hash::(proofState.a, T, D); //Response phase @@ -93,14 +94,8 @@ fn prove(rng: &mut R, comParams: &CSMultiParams, r: E::Fr, } //response range proof - let mut rpRandom = rPrime.clone(); - rpRandom.add_assign(&newWallet.pkc); - rpRandom.add_assign(&newWallet.wpk); - let mut rpRandom2 = rpRandom.clone(); - rpRandom.add_assign(&newWalletVec[3].clone()); - rpRandom2.add_assign(&newWalletVec[2].clone()); - let rpBC = rpParamsBC.prove_response(rpRandom, &rpStateBC, challenge.clone()); - let rpBM = rpParamsBM.prove_response(rpRandom2, &rpStateBM, challenge.clone()); + let rpBC = rpParamsBC.prove_response(rPrime.clone(), &rpStateBC, challenge.clone(), 3, vec!{newWalletVec[0], newWalletVec[1], newWalletVec[3]}); + let rpBM = rpParamsBM.prove_response(rPrime.clone(), &rpStateBM, challenge.clone(), 4, vec!{newWalletVec[0], newWalletVec[1], newWalletVec[2]}); Proof { sig: proofState.blindSig, sigProof, T, D, z, rpParamsBC, rpBC, rpParamsBM, rpBM } } From 48980fd64c0d29441270a0717b97cf9db153cb65 Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Fri, 19 Jul 2019 15:19:28 -0400 Subject: [PATCH 08/11] nizk: add commitments of range proof to challenge hash --- src/ccs08.rs | 40 ++++++++++++++++++++-------------------- src/nizk.rs | 29 +++++++++++++++-------------- 2 files changed, 35 insertions(+), 34 deletions(-) diff --git a/src/ccs08.rs b/src/ccs08.rs index ed31af5..fb68a8d 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -39,34 +39,34 @@ struct ParamsUL { } #[derive(Clone)] -struct ProofULState { - decx: Vec, - proofStates: Vec>, - V: Vec>, - D: E::G1, - m: E::Fr, - s: Vec, +pub struct ProofULState { + pub decx: Vec, + pub proofStates: Vec>, + pub V: Vec>, + pub D: E::G1, + pub m: E::Fr, + pub s: Vec, } /** proofUL contains the necessary elements for the ZK range proof with range [0,u^l). */ #[derive(Clone)] -struct ProofUL { - V: Vec>, - D: E::G1, - comm: Commitment, - sigProofs: Vec>, - zr: E::Fr, - zs: Vec, +pub struct ProofUL { + pub V: Vec>, + pub D: E::G1, + pub comm: Commitment, + pub sigProofs: Vec>, + pub zr: E::Fr, + pub zs: Vec, } #[derive(Clone)] pub struct RangeProofState { - com1: Commitment, - ps1: ProofULState, - com2: Commitment, - ps2: ProofULState, + pub com1: Commitment, + pub ps1: ProofULState, + pub com2: Commitment, + pub ps2: ProofULState, } /** @@ -74,8 +74,8 @@ RangeProof contains the necessary elements for the ZK range proof. */ #[derive(Clone)] pub struct RangeProof { - p1: ProofUL, - p2: ProofUL, + pub p1: ProofUL, + pub p2: ProofUL, } /** diff --git a/src/nizk.rs b/src/nizk.rs index a307974..f4f702f 100644 --- a/src/nizk.rs +++ b/src/nizk.rs @@ -14,15 +14,15 @@ use ccs08::{RPPublicParams, RangeProof}; #[derive(Clone)] struct Proof { - sig: Signature, - sigProof: SignatureProof, - T: E::G1, - D: E::G1, - z: Vec, - rpParamsBC: RPPublicParams, - rpBC: RangeProof, - rpParamsBM: RPPublicParams, - rpBM: RangeProof, + pub sig: Signature, + pub sigProof: SignatureProof, + pub T: E::G1, + pub D: E::G1, + pub z: Vec, + pub rpParamsBC: RPPublicParams, + pub rpBC: RangeProof, + pub rpParamsBM: RPPublicParams, + pub rpBM: RangeProof, } fn prove(rng: &mut R, comParams: &CSMultiParams, r: E::Fr, @@ -60,7 +60,7 @@ fn prove(rng: &mut R, comParams: &CSMultiParams, r: E::Fr, //Compute challenge //TODO: add commitment of range proofs - let challenge = hash::(proofState.a, T, D); + let challenge = hash::(proofState.a, vec!{T, D, rpStateBC.ps1.D, rpStateBC.ps2.D, rpStateBM.ps1.D, rpStateBM.ps2.D}); //Response phase //response for signature @@ -103,7 +103,7 @@ fn prove(rng: &mut R, comParams: &CSMultiParams, r: E::Fr, fn verify(proof: Proof, epsilon: E::Fr, com1: &Commitment, com2: &Commitment, wpk: E::Fr, comParams: &CSMultiParams, mpk: &PublicParams, pk: &BlindPublicKey) -> bool { //compute challenge - let challenge = hash::(proof.sigProof.a, proof.T, proof.D); + let challenge = hash::(proof.sigProof.a, vec!{proof.T, proof.D, proof.rpBC.p1.D, proof.rpBC.p2.D, proof.rpBM.p1.D, proof.rpBM.p2.D}); //verify linear relationship let mut gWpk = comParams.pub_bases[2].clone(); @@ -154,11 +154,12 @@ fn verify(proof: Proof, epsilon: E::Fr, com1: &Commitment, com2 r && r1 && r2 && r3 && r4 } -fn hash(a: E::Fqk, T: E::G1, D: E::G1) -> E::Fr { +fn hash(a: E::Fqk, T: Vec) -> E::Fr { let mut x_vec: Vec = Vec::new(); x_vec.extend(format!("{}", a).bytes()); - x_vec.extend(format!("{}", T).bytes()); - x_vec.extend(format!("{}", D).bytes()); + for t in T { + x_vec.extend(format!("{}", t).bytes()); + } util::hash_to_fr::(x_vec) } From e0f82b28a6ccc5f522b11cb7922cec0ff4bb1d52 Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Fri, 19 Jul 2019 16:27:15 -0400 Subject: [PATCH 09/11] nizk: i32 instead of i64 --- src/ccs08.rs | 34 +++++++++++++++++----------------- src/nizk.rs | 8 ++++---- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/ccs08.rs b/src/ccs08.rs index fb68a8d..e6dd7ce 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -31,16 +31,16 @@ struct ParamsUL { // u determines the amount of signatures we need in the public params. // Each signature can be compressed to just 1 field element of 256 bits. // Then the parameters have minimum size equal to 256*u bits. - u: i64, + u: i32, // l determines how many pairings we need to compute, then in order to improve // verifier`s performance we want to minize it. // Namely, we have 2*l pairings for the prover and 3*l for the verifier. - l: i64, + l: i32, } #[derive(Clone)] pub struct ProofULState { - pub decx: Vec, + pub decx: Vec, pub proofStates: Vec>, pub V: Vec>, pub D: E::G1, @@ -85,8 +85,8 @@ This must be computed in a trusted setup. #[derive(Clone)] pub struct RPPublicParams { p: ParamsUL, - a: i64, - b: i64, + a: i32, + b: i32, } impl ParamsUL { @@ -95,7 +95,7 @@ impl ParamsUL { The value of u should be roughly b/log(b), but we can choose smaller values in order to get smaller parameters, at the cost of having worse performance. */ - pub fn setup_ul(rng: &mut R, u: i64, l: i64, csParams: CSMultiParams) -> Self { + pub fn setup_ul(rng: &mut R, u: i32, l: i32, csParams: CSMultiParams) -> Self { let mpk = setup(rng); let kp = BlindKeyPair::::generate(rng, &mpk, 1); @@ -111,7 +111,7 @@ impl ParamsUL { /** prove_ul method is used to produce the ZKRP proof that secret x belongs to the interval [0,U^L). */ - pub fn prove_ul(&self, rng: &mut R, x: i64, r: E::Fr, C: Commitment, k: usize, otherM: Vec) -> ProofUL { + pub fn prove_ul(&self, rng: &mut R, x: i32, r: E::Fr, C: Commitment, k: usize, otherM: Vec) -> ProofUL { let proofUlState = self.prove_ul_commitment(rng, x, k); // Fiat-Shamir heuristic @@ -124,7 +124,7 @@ impl ParamsUL { self.prove_ul_response(r, C, &proofUlState, c, k, otherM) } - fn prove_ul_commitment(&self, rng: &mut R, x: i64, k: usize) -> ProofULState { + fn prove_ul_commitment(&self, rng: &mut R, x: i32, k: usize) -> ProofULState { if x > self.u.pow(self.l as u32) || x < 0 { panic!("x is not within the range."); } @@ -284,7 +284,7 @@ fn hash(a: Vec, D: Vec) -> E::Fr { Decompose receives as input an integer x and outputs an array of integers such that x = sum(xi.u^i), i.e. it returns the decomposition of x into base u. */ -fn decompose(x: i64, u: i64, l: i64) -> Vec { +fn decompose(x: i32, u: i32, l: i32) -> Vec { let mut result = Vec::with_capacity(l as usize); let mut decomposer = x.clone(); for _i in 0..l { @@ -298,20 +298,20 @@ impl RPPublicParams { /** Setup receives integers a and b, and configures the parameters for the rangeproof scheme. */ - pub fn setup(rng: &mut R, a: i64, b: i64, csParams: CSMultiParams) -> Self { + pub fn setup(rng: &mut R, a: i32, b: i32, csParams: CSMultiParams) -> Self { // Compute optimal values for u and l if a > b { panic!("a must be less than or equal to b"); } //TODO: optimize u? - let logb = (b as f64).log2(); + let logb = (b as f32).log2(); let loglogb = logb.log2(); if loglogb > 0.0 { - let mut u = (logb / loglogb) as i64; + let mut u = (logb / loglogb) as i32; if u < 2 { u = 2; } - let l = (b as f64).log(u as f64).ceil() as i64; + let l = (b as f32).log(u as f32).ceil() as i32; let params_out: ParamsUL = ParamsUL::::setup_ul(rng, u, l, csParams.clone()); return RPPublicParams { p: params_out, a, b }; @@ -323,7 +323,7 @@ impl RPPublicParams { /** Prove method is responsible for generating the zero knowledge range proof. */ - pub fn prove(&self, rng: &mut R, x: i64, C: Commitment, r: E::Fr, k: usize, otherM: Vec) -> RangeProof { + pub fn prove(&self, rng: &mut R, x: i32, C: Commitment, r: E::Fr, k: usize, otherM: Vec) -> RangeProof { let rpState = self.prove_commitment(rng, x, C, k); let mut a = Vec::::with_capacity(self.p.l as usize); @@ -336,7 +336,7 @@ impl RPPublicParams { self.prove_response(r, &rpState, ch, k, otherM) } - pub fn prove_commitment(&self, rng: &mut R, x: i64, C: Commitment, k: usize) -> RangeProofState { + pub fn prove_commitment(&self, rng: &mut R, x: i32, C: Commitment, k: usize) -> RangeProofState { if x > self.b || x < self.a { panic!("x is not within the range."); } @@ -590,14 +590,14 @@ mod tests { let vec1 = decompose(25, 3, 5); let mut result = 0; for i in 0..5 { - result += vec1[i] * 3i64.pow(i as u32); + result += vec1[i] * 3i32.pow(i as u32); } assert_eq!(result, 25); let vec1 = decompose(143225, 6, 7); let mut result = 0; for i in 0..7 { - result += vec1[i] * 6i64.pow(i as u32); + result += vec1[i] * 6i32.pow(i as u32); } assert_eq!(result, 143225); } diff --git a/src/nizk.rs b/src/nizk.rs index f4f702f..bf8159b 100644 --- a/src/nizk.rs +++ b/src/nizk.rs @@ -53,10 +53,10 @@ fn prove(rng: &mut R, comParams: &CSMultiParams, r: E::Fr, } //commit range proof - let rpParamsBC = RPPublicParams::setup(rng, 0, std::i32::MAX as i64, comParams.clone()); - let rpParamsBM = RPPublicParams::setup(rng, 0, std::i32::MAX as i64, comParams.clone()); - let rpStateBC = rpParamsBC.prove_commitment(rng, newWallet.bc.clone() as i64, newWalletCom.clone(), 3); - let rpStateBM = rpParamsBM.prove_commitment(rng, newWallet.bm.clone() as i64, newWalletCom.clone(), 4); + let rpParamsBC = RPPublicParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone()); + let rpParamsBM = RPPublicParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone()); + let rpStateBC = rpParamsBC.prove_commitment(rng, newWallet.bc.clone(), newWalletCom.clone(), 3); + let rpStateBM = rpParamsBM.prove_commitment(rng, newWallet.bm.clone(), newWalletCom.clone(), 4); //Compute challenge //TODO: add commitment of range proofs From e79d4bbed2b5bb068062fc0afb5db4f7655878b9 Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Sun, 21 Jul 2019 10:05:27 -0400 Subject: [PATCH 10/11] nizk: create setup phase --- src/ccs08.rs | 1 - src/channels.rs | 2 +- src/nizk.rs | 332 +++++++++++++++++++++++++----------------------- 3 files changed, 172 insertions(+), 163 deletions(-) diff --git a/src/ccs08.rs b/src/ccs08.rs index e6dd7ce..fd7caef 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -375,7 +375,6 @@ impl RPPublicParams { Verify is responsible for validating the range proof. */ pub fn verify(&self, proof: RangeProof, ch: E::Fr, k: usize) -> bool { - //TODO: add verification of commitment let first = self.p.verify_ul(&proof.p1, ch.clone(), k); let second = self.p.verify_ul(&proof.p2, ch.clone(), k); first & &second diff --git a/src/channels.rs b/src/channels.rs index 570ffad..98afb96 100644 --- a/src/channels.rs +++ b/src/channels.rs @@ -187,7 +187,7 @@ impl CustomerWallet { } } - pub fn generate_proof(&mut self, csprng: &mut R) { + pub fn generate_proof(&mut self, csprng: &mut R) { } } diff --git a/src/nizk.rs b/src/nizk.rs index bf8159b..becb970 100644 --- a/src/nizk.rs +++ b/src/nizk.rs @@ -13,155 +13,169 @@ use wallet::Wallet; use ccs08::{RPPublicParams, RangeProof}; #[derive(Clone)] -struct Proof { +pub struct Proof { pub sig: Signature, pub sigProof: SignatureProof, pub T: E::G1, pub D: E::G1, pub z: Vec, - pub rpParamsBC: RPPublicParams, pub rpBC: RangeProof, - pub rpParamsBM: RPPublicParams, pub rpBM: RangeProof, } -fn prove(rng: &mut R, comParams: &CSMultiParams, r: E::Fr, - oldWallet: Wallet, newWallet: Wallet, newWalletCom: Commitment, rPrime: E::Fr, paymentToken: &Signature, - mpk: &PublicParams, kp: &BlindKeyPair) -> Proof { - //Commitment phase - //Commit linear relationship - let mut T = comParams.pub_bases[2].clone(); - let t1 = E::Fr::rand(rng); - T.mul_assign(t1); - let mut h = comParams.pub_bases[0].clone(); - let t2 = E::Fr::rand(rng); - h.mul_assign(t2); - T.add_assign(&h); - - //commit signature - let proofState = kp.prove_commitment(rng, &mpk, &paymentToken); - - //commit commitment - let mut D = E::G1::zero(); - let mut t = Vec::::with_capacity(comParams.pub_bases.len() - 1); - for g in comParams.pub_bases.clone() { - let ti = E::Fr::rand(rng); - t.push(ti); - let mut gt = g.clone(); - gt.mul_assign(ti.into_repr()); - D.add_assign(>); - } - - //commit range proof - let rpParamsBC = RPPublicParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone()); - let rpParamsBM = RPPublicParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone()); - let rpStateBC = rpParamsBC.prove_commitment(rng, newWallet.bc.clone(), newWalletCom.clone(), 3); - let rpStateBM = rpParamsBM.prove_commitment(rng, newWallet.bm.clone(), newWalletCom.clone(), 4); - - //Compute challenge - //TODO: add commitment of range proofs - let challenge = hash::(proofState.a, vec!{T, D, rpStateBC.ps1.D, rpStateBC.ps2.D, rpStateBM.ps1.D, rpStateBM.ps2.D}); - - //Response phase - //response for signature - let oldWalletVec = oldWallet.as_fr_vec(); - let sigProof = kp.prove_response(&proofState, challenge, &mut oldWalletVec.clone()); - - //response linear relationship - let mut z = Vec::::with_capacity(t.len() + 2); - let mut z1 = newWallet.wpk.clone(); - z1.negate(); - z1.mul_assign(&challenge); - z1.add_assign(&t1); - z.push(z1); - let mut z2 = r.clone(); - z2.sub_assign(&rPrime.clone()); - z2.mul_assign(&challenge); - z2.add_assign(&t2); - z.push(z2); - - //response commitment - let mut z0 = rPrime.clone(); - z0.mul_assign(&challenge); - z0.add_assign(&t[0]); - z.push(z0); - let newWalletVec = newWallet.as_fr_vec(); - for i in 1..t.len() { - let mut zi = newWalletVec[i - 1].clone(); - zi.mul_assign(&challenge); - zi.add_assign(&t[i]); - z.push(zi); - } - - //response range proof - let rpBC = rpParamsBC.prove_response(rPrime.clone(), &rpStateBC, challenge.clone(), 3, vec!{newWalletVec[0], newWalletVec[1], newWalletVec[3]}); - let rpBM = rpParamsBM.prove_response(rPrime.clone(), &rpStateBM, challenge.clone(), 4, vec!{newWalletVec[0], newWalletVec[1], newWalletVec[2]}); - - Proof { sig: proofState.blindSig, sigProof, T, D, z, rpParamsBC, rpBC, rpParamsBM, rpBM } +#[derive(Clone)] +pub struct NIZKPublicParams { + pub mpk: PublicParams, + pub keypair: BlindKeyPair, + pub comParams: CSMultiParams, + pub rpParamsBC: RPPublicParams, + pub rpParamsBM: RPPublicParams, } -fn verify(proof: Proof, epsilon: E::Fr, com1: &Commitment, com2: &Commitment, - wpk: E::Fr, comParams: &CSMultiParams, mpk: &PublicParams, pk: &BlindPublicKey) -> bool { - //compute challenge - let challenge = hash::(proof.sigProof.a, vec!{proof.T, proof.D, proof.rpBC.p1.D, proof.rpBC.p2.D, proof.rpBM.p1.D, proof.rpBM.p2.D}); +impl NIZKPublicParams { + pub fn setup(rng: &mut R) -> Self { + let mpk = setup(rng); + let keypair = BlindKeyPair::::generate(rng, &mpk, 4); + let comParams = keypair.generate_cs_multi_params(&mpk); + let rpParamsBC = RPPublicParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone()); + let rpParamsBM = RPPublicParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone()); - //verify linear relationship - let mut gWpk = comParams.pub_bases[2].clone(); - let mut minWpk = wpk.clone(); - minWpk.negate(); - gWpk.mul_assign(minWpk.into_repr()); - let mut gEps = comParams.pub_bases[4].clone(); - gEps.mul_assign(epsilon.into_repr()); - let mut gMinEps = comParams.pub_bases[3].clone(); - let mut mineps = epsilon.clone(); - mineps.negate(); - gMinEps.mul_assign(mineps.into_repr()); - - let mut commitment = com1.c.clone(); - commitment.sub_assign(&com2.c.clone()); - commitment.add_assign(&gWpk); - commitment.add_assign(&gEps); - commitment.add_assign(&gMinEps); - commitment.mul_assign(challenge.into_repr()); - commitment.add_assign(&proof.T); - - let mut g2 = comParams.pub_bases[2].clone(); - g2.mul_assign(proof.z[0].into_repr()); - let mut h = comParams.pub_bases[0].clone(); - h.mul_assign(proof.z[1].into_repr()); - g2.add_assign(&h); - let r = commitment == g2; - - //verify knowledge of signature - let r1 = pk.verify_proof(&mpk, proof.sig, proof.sigProof, challenge); - - //verify knowledge of commitment - let mut comc = com2.c.clone(); - comc.mul_assign(challenge.into_repr()); - comc.add_assign(&proof.D.clone()); - let mut x = E::G1::zero(); - for i in 2..proof.z.len() { - let mut base = comParams.pub_bases[i - 2].clone(); - base.mul_assign(proof.z[i].into_repr()); - x.add_assign(&base); - } - let r2 = x == comc; - - //verify range proofs - let r3 = proof.rpParamsBC.verify(proof.rpBC, challenge.clone(), 3); - let r4 = proof.rpParamsBM.verify(proof.rpBM, challenge.clone(), 4); - - r && r1 && r2 && r3 && r4 -} - -fn hash(a: E::Fqk, T: Vec) -> E::Fr { - let mut x_vec: Vec = Vec::new(); - x_vec.extend(format!("{}", a).bytes()); - for t in T { - x_vec.extend(format!("{}", t).bytes()); + NIZKPublicParams{mpk, keypair, comParams, rpParamsBC, rpParamsBM} } - util::hash_to_fr::(x_vec) + pub fn prove(&self, rng: &mut R, r: E::Fr, oldWallet: Wallet, newWallet: Wallet, + newWalletCom: Commitment, rPrime: E::Fr, paymentToken: &Signature, ) -> Proof { + //Commitment phase + //Commit linear relationship + let mut T = self.comParams.pub_bases[2].clone(); + let t1 = E::Fr::rand(rng); + T.mul_assign(t1); + let mut h = self.comParams.pub_bases[0].clone(); + let t2 = E::Fr::rand(rng); + h.mul_assign(t2); + T.add_assign(&h); + + //commit signature + let proofState = self.keypair.prove_commitment(rng, &self.mpk, &paymentToken); + + //commit commitment + let mut D = E::G1::zero(); + let mut t = Vec::::with_capacity(self.comParams.pub_bases.len() - 1); + for g in self.comParams.pub_bases.clone() { + let ti = E::Fr::rand(rng); + t.push(ti); + let mut gt = g.clone(); + gt.mul_assign(ti.into_repr()); + D.add_assign(>); + } + + //commit range proof + let rpStateBC = self.rpParamsBC.prove_commitment(rng, newWallet.bc.clone(), newWalletCom.clone(), 3); + let rpStateBM = self.rpParamsBM.prove_commitment(rng, newWallet.bm.clone(), newWalletCom.clone(), 4); + + //Compute challenge + let challenge = NIZKPublicParams::::hash(proofState.a, vec! {T, D, rpStateBC.ps1.D, rpStateBC.ps2.D, rpStateBM.ps1.D, rpStateBM.ps2.D}); + + //Response phase + //response for signature + let oldWalletVec = oldWallet.as_fr_vec(); + let sigProof = self.keypair.prove_response(&proofState, challenge, &mut oldWalletVec.clone()); + + //response linear relationship + let mut z = Vec::::with_capacity(t.len() + 2); + let mut z1 = newWallet.wpk.clone(); + z1.negate(); + z1.mul_assign(&challenge); + z1.add_assign(&t1); + z.push(z1); + let mut z2 = r.clone(); + z2.sub_assign(&rPrime.clone()); + z2.mul_assign(&challenge); + z2.add_assign(&t2); + z.push(z2); + + //response commitment + let mut z0 = rPrime.clone(); + z0.mul_assign(&challenge); + z0.add_assign(&t[0]); + z.push(z0); + let newWalletVec = newWallet.as_fr_vec(); + for i in 1..t.len() { + let mut zi = newWalletVec[i - 1].clone(); + zi.mul_assign(&challenge); + zi.add_assign(&t[i]); + z.push(zi); + } + + //response range proof + let rpBC = self.rpParamsBC.prove_response(rPrime.clone(), &rpStateBC, challenge.clone(), 3, vec! {newWalletVec[0], newWalletVec[1], newWalletVec[3]}); + let rpBM = self.rpParamsBM.prove_response(rPrime.clone(), &rpStateBM, challenge.clone(), 4, vec! {newWalletVec[0], newWalletVec[1], newWalletVec[2]}); + + Proof { sig: proofState.blindSig, sigProof, T, D, z, rpBC, rpBM } + } + + pub fn verify(&self, proof: Proof, epsilon: E::Fr, com1: &Commitment, com2: &Commitment, wpk: E::Fr) -> bool { + //compute challenge + let challenge = NIZKPublicParams::::hash(proof.sigProof.a, vec! {proof.T, proof.D, proof.rpBC.p1.D, proof.rpBC.p2.D, proof.rpBM.p1.D, proof.rpBM.p2.D}); + + //verify linear relationship + let mut gWpk = self.comParams.pub_bases[2].clone(); + let mut minWpk = wpk.clone(); + minWpk.negate(); + gWpk.mul_assign(minWpk.into_repr()); + let mut gEps = self.comParams.pub_bases[4].clone(); + gEps.mul_assign(epsilon.into_repr()); + let mut gMinEps = self.comParams.pub_bases[3].clone(); + let mut mineps = epsilon.clone(); + mineps.negate(); + gMinEps.mul_assign(mineps.into_repr()); + + let mut commitment = com1.c.clone(); + commitment.sub_assign(&com2.c.clone()); + commitment.add_assign(&gWpk); + commitment.add_assign(&gEps); + commitment.add_assign(&gMinEps); + commitment.mul_assign(challenge.into_repr()); + commitment.add_assign(&proof.T); + + let mut g2 = self.comParams.pub_bases[2].clone(); + g2.mul_assign(proof.z[0].into_repr()); + let mut h = self.comParams.pub_bases[0].clone(); + h.mul_assign(proof.z[1].into_repr()); + g2.add_assign(&h); + let r = commitment == g2; + + //verify knowledge of signature + let r1 = self.keypair.public.verify_proof(&self.mpk, proof.sig, proof.sigProof, challenge); + + //verify knowledge of commitment + let mut comc = com2.c.clone(); + comc.mul_assign(challenge.into_repr()); + comc.add_assign(&proof.D.clone()); + let mut x = E::G1::zero(); + for i in 2..proof.z.len() { + let mut base = self.comParams.pub_bases[i - 2].clone(); + base.mul_assign(proof.z[i].into_repr()); + x.add_assign(&base); + } + let r2 = x == comc; + + //verify range proofs + let r3 = self.rpParamsBC.verify(proof.rpBC, challenge.clone(), 3); + let r4 = self.rpParamsBM.verify(proof.rpBM, challenge.clone(), 4); + + r && r1 && r2 && r3 && r4 + } + + fn hash(a: E::Fqk, T: Vec) -> E::Fr { + let mut x_vec: Vec = Vec::new(); + x_vec.extend(format!("{}", a).bytes()); + for t in T { + x_vec.extend(format!("{}", t).bytes()); + } + + util::hash_to_fr::(x_vec) + } } #[cfg(test)] @@ -185,21 +199,19 @@ mod tests { let r = Fr::rand(rng); let rprime = Fr::rand(rng); - let mpk = setup(rng); - let keypair = BlindKeyPair::::generate(rng, &mpk, 4); - let comParams = keypair.generate_cs_multi_params(&mpk); + let pubParams = NIZKPublicParams::::setup(rng); let wallet1 = Wallet { pkc, wpk, bc, bm }; - let commitment1 = comParams.commit(&wallet1.as_fr_vec(), &r); + let commitment1 = pubParams.comParams.commit(&wallet1.as_fr_vec(), &r); let wallet2 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2 }; - let commitment2 = comParams.commit(&wallet2.as_fr_vec(), &rprime); - let blindPaymentToken = keypair.sign_blind(rng, &mpk, commitment1.clone()); - let paymentToken = keypair.unblind(&r, &blindPaymentToken); + let commitment2 = pubParams.comParams.commit(&wallet2.as_fr_vec(), &rprime); + let blindPaymentToken = pubParams.keypair.sign_blind(rng, &pubParams.mpk, commitment1.clone()); + let paymentToken = pubParams.keypair.unblind(&r, &blindPaymentToken); - let proof = prove(rng, &comParams, r, wallet1, wallet2, - commitment2.clone(), rprime, &paymentToken, &mpk, &keypair); + let proof = pubParams.prove(rng, r, wallet1, wallet2, + commitment2.clone(), rprime, &paymentToken); - assert_eq!(verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, - &commitment2, wpk, &comParams, &mpk, &keypair.public), true); + assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, + &commitment2, wpk), true); } #[test] @@ -218,30 +230,28 @@ mod tests { let r = Fr::rand(rng); let rprime = Fr::rand(rng); - let mpk = setup(rng); - let keypair = BlindKeyPair::::generate(rng, &mpk, 4); - let comParams = keypair.generate_cs_multi_params(&mpk); + let pubParams = NIZKPublicParams::::setup(rng); let wallet1 = Wallet { pkc, wpk, bc, bm }; let wallet2 = Wallet:: { pkc, wpk: wpkprime, bc: bc2, bm: bm2 }; let mut bc2Prime = bc.clone(); let wallet3 = Wallet { pkc, wpk: wpkprime, bc: bc2Prime, bm: bm2 }; - let commitment1 = comParams.commit(&wallet1.as_fr_vec().clone(), &r); - let commitment2 = comParams.commit(&wallet3.as_fr_vec(), &rprime); - let blindPaymentToken = keypair.sign_blind(rng, &mpk, commitment1.clone()); - let paymentToken = keypair.unblind(&r, &blindPaymentToken); - let proof = prove(rng, &comParams, r, wallet1.clone(), wallet3, commitment2.clone(), rprime, &paymentToken, &mpk, &keypair); - assert_eq!(verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), false); + let commitment1 = pubParams.comParams.commit(&wallet1.as_fr_vec().clone(), &r); + let commitment2 = pubParams.comParams.commit(&wallet3.as_fr_vec(), &rprime); + let blindPaymentToken = pubParams.keypair.sign_blind(rng, &pubParams.mpk, commitment1.clone()); + let paymentToken = pubParams.keypair.unblind(&r, &blindPaymentToken); + let proof = pubParams.prove(rng, r, wallet1.clone(), wallet3, commitment2.clone(), rprime, &paymentToken); + assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, &commitment2, wpk), false); let mut bm2Prime = bm.clone(); let wallet4 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2Prime }; - let commitment2 = comParams.commit(&wallet4.as_fr_vec(), &rprime); - let proof = prove(rng, &comParams, r, wallet1.clone(), wallet4, commitment2.clone(), rprime, &paymentToken, &mpk, &keypair); - assert_eq!(verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), false); + let commitment2 = pubParams.comParams.commit(&wallet4.as_fr_vec(), &rprime); + let proof = pubParams.prove(rng, r, wallet1.clone(), wallet4, commitment2.clone(), rprime, &paymentToken); + assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, &commitment2, wpk), false); let wallet5 = Wallet { pkc: Fr::rand(rng), wpk: wpkprime, bc: bc2, bm: bm2 }; - let commitment2 = comParams.commit(&wallet5.as_fr_vec(), &rprime); - let proof = prove(rng, &comParams, r, wallet1.clone(), wallet5, commitment2.clone(), rprime, &paymentToken, &mpk, &keypair); - assert_eq!(verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), false); + let commitment2 = pubParams.comParams.commit(&wallet5.as_fr_vec(), &rprime); + let proof = pubParams.prove(rng, r, wallet1.clone(), wallet5, commitment2.clone(), rprime, &paymentToken); + assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, &commitment2, wpk), false); } } \ No newline at end of file From 20650bc7b0aface41384ec4514a136932676c00a Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Sun, 21 Jul 2019 11:02:36 -0400 Subject: [PATCH 11/11] nizk: pass optional random values for signature commitment --- src/ccs08.rs | 12 +++---- src/channels.rs | 4 +-- src/cl.rs | 87 ++++++++++++++++++++++++------------------------- src/nizk.rs | 6 ++-- src/util.rs | 6 ++-- 5 files changed, 57 insertions(+), 58 deletions(-) diff --git a/src/ccs08.rs b/src/ccs08.rs index fd7caef..a60d83f 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -142,7 +142,7 @@ impl ParamsUL { hm.mul_assign(m); for i in 0..self.l as usize { let signature = self.signatures.get(&decx[i].to_string()).unwrap(); - let proofState = self.kp.prove_commitment(rng, &self.mpk, &signature); + let proofState = self.kp.prove_commitment(rng, &self.mpk, &signature, None, None); V.push(proofState.blindSig.clone()); proofStates.push(proofState); @@ -642,11 +642,11 @@ mod tests { let m1 = Fr::rand(rng); let m2 = Fr::rand(rng); let sig = kp.sign(rng, &vec! {m1, m2}); - let state = kp.prove_commitment(rng, ¶ms, &sig); - let state1 = kp.prove_commitment(rng, ¶ms, &sig); - let state2 = kp.prove_commitment(rng, ¶ms, &sig); - let state3 = kp.prove_commitment(rng, ¶ms, &sig); - let state4 = kp.prove_commitment(rng, ¶ms, &sig); + let state = kp.prove_commitment(rng, ¶ms, &sig, None, None); + let state1 = kp.prove_commitment(rng, ¶ms, &sig, None, None); + let state2 = kp.prove_commitment(rng, ¶ms, &sig, None, None); + let state3 = kp.prove_commitment(rng, ¶ms, &sig, None, None); + let state4 = kp.prove_commitment(rng, ¶ms, &sig, None, None); let a = vec! {state.a, state1.a, state2.a}; let a2 = vec! {state3.a, state4.a}; assert_eq!(hash::(a.clone(), vec!(D.clone())).is_zero(), false); diff --git a/src/channels.rs b/src/channels.rs index bcdc2ec..5674f6f 100644 --- a/src/channels.rs +++ b/src/channels.rs @@ -192,7 +192,7 @@ impl CustomerWallet { // generate nizk proof of knowledge of commitment opening pub fn generate_proof(&mut self, csprng: &mut R, channel_token: &ChannelToken) -> CommitmentProof { - return CommitmentProof::::new(csprng, &channel_token.comParams, &self.w_com.c1, &self.w_vec, &self.r); + return CommitmentProof::::new(csprng, &channel_token.comParams, &self.w_com.c, &self.w_vec, &self.r); } } @@ -237,7 +237,7 @@ impl MerchantWallet { } pub fn verify_proof(&self, csprng: &mut R, channel: &ChannelState, com: &Commitment, com_proof: &CommitmentProof) -> Signature { - let is_valid = util::verify(&self.comParams, &com.c1, &com_proof); + let is_valid = util::verify(&self.comParams, &com.c, &com_proof); let cp = channel.cp.as_ref().unwrap(); if is_valid { println!("Commitment PoK is valid!"); diff --git a/src/cl.rs b/src/cl.rs index bca1162..45915b8 100644 --- a/src/cl.rs +++ b/src/cl.rs @@ -13,13 +13,13 @@ use std::fmt::LowerHex; #[derive(Clone)] pub struct PublicParams { pub g1: E::G1, - pub g2: E::G2 + pub g2: E::G2, } #[derive(Clone)] pub struct SecretKey { pub x: E::Fr, - pub y: Vec + pub y: Vec, } #[derive(Clone, Serialize, Deserialize)] @@ -61,19 +61,19 @@ pub struct BlindPublicKey { #[derive(Clone)] pub struct Signature { pub h: E::G1, - pub H: E::G1 + pub H: E::G1, } #[derive(Clone)] pub struct KeyPair { pub secret: SecretKey, - pub public: PublicKey + pub public: PublicKey, } #[derive(Clone)] pub struct BlindKeyPair { pub secret: SecretKey, - pub public: BlindPublicKey + pub public: BlindPublicKey, } #[derive(Clone)] @@ -83,7 +83,7 @@ pub struct ProofState { pub t: Vec, pub tt: E::Fr, pub a: E::Fqk, - pub blindSig: Signature + pub blindSig: Signature, } #[derive(Clone)] @@ -91,14 +91,14 @@ pub struct SignatureProof { pub zx: E::Fr, pub zsig: Vec, pub zv: E::Fr, - pub a: E::Fqk + pub a: E::Fqk, } impl SecretKey { pub fn generate(csprng: &mut R, l: usize) -> Self { let mut y: Vec = Vec::new(); - for i in 0 .. l { + for i in 0..l { let _y = E::Fr::rand(csprng); y.push(_y); } @@ -111,7 +111,7 @@ impl SecretKey { let mut s = E::Fr::zero(); // check vector length first assert_eq!(self.y.len(), message.len()); - for i in 0 .. message.len() { + for i in 0..message.len() { // s = s + (self.y[i] * message[i]); let mut res_yi = self.y[i]; res_yi.mul_assign(&message[i]); @@ -143,7 +143,6 @@ impl SecretKey { H1.mul_assign(r); Signature { h: h1, H: H1 } } - } @@ -186,7 +185,7 @@ impl SecretKey { impl PublicKey { pub fn from_secret(mpk: &PublicParams, secret: &SecretKey) -> Self { let mut Y: Vec = Vec::new(); - for i in 0 .. secret.y.len() { + for i in 0..secret.y.len() { // Y[i] = g2 ^ y[i] let mut g2 = mpk.g2; g2.mul_assign(secret.y[i]); @@ -197,13 +196,13 @@ impl PublicKey { X.mul_assign(secret.x); PublicKey { X: X, - Y: Y + Y: Y, } } pub fn verify(&self, mpk: &PublicParams, message: &Vec, signature: &Signature) -> bool { let mut L = E::G2::zero(); - for i in 0 .. self.Y.len() { + for i in 0..self.Y.len() { // L = L + self.Y[i].mul(message[i]); let mut Y = self.Y[i]; Y.mul_assign(message[i]); // Y_i ^ m_i @@ -218,7 +217,7 @@ impl PublicKey { } } -impl BlindPublicKey { +impl BlindPublicKey { pub fn from_secret(mpk: &PublicParams, secret: &SecretKey) -> Self { let mut Y1: Vec = Vec::new(); let mut Y2: Vec = Vec::new(); @@ -241,7 +240,7 @@ impl BlindPublicKey { X1: X1, X2: X2, Y1: Y1, - Y2: Y2 + Y2: Y2, } } @@ -250,7 +249,7 @@ impl BlindPublicKey { let l = self.Y2.len(); assert_eq!(message.len(), l + 1); - for i in 0 .. l { + for i in 0..l { // L = L + self.Y[i].mul(message[i]); let mut Y = self.Y2[i]; Y.mul_assign(message[i]); // Y_i ^ m_i @@ -288,11 +287,9 @@ impl BlindPublicKey { g.mul_assign(&p.a); gx == g } - } - pub fn setup(csprng: &mut R) -> PublicParams { let g1 = E::G1::rand(csprng); let g2 = E::G2::rand(csprng); @@ -335,7 +332,7 @@ impl BlindKeyPair { let mut com_bases = vec! {mpk.g1}; com_bases.append(&mut self.public.Y1.clone()); - CSMultiParams { pub_bases: com_bases} + CSMultiParams { pub_bases: com_bases } } /// extract unblinded public key @@ -391,16 +388,19 @@ impl BlindKeyPair { /// prove knowledge of a signature: commitment phase /// returns the proof state, including commitment a and a blind signature blindSig - pub fn prove_commitment(&self, rng: &mut R, mpk: &PublicParams, signature: &Signature) -> ProofState { + pub fn prove_commitment(&self, rng: &mut R, mpk: &PublicParams, signature: &Signature, + tOptional: Option>, ttOptional: Option) -> ProofState { let v = E::Fr::rand(rng); let blindSig = self.blind(rng, &v, signature); let s = E::Fr::rand(rng); - let mut t = Vec::::with_capacity(self.public.Y2.len()); - let tt = E::Fr::rand(rng); + let mut t = tOptional.unwrap_or(Vec::::with_capacity(self.public.Y2.len())); + let tt = ttOptional.unwrap_or(E::Fr::rand(rng)); let mut gx = E::pairing(blindSig.h, self.public.X2); gx = gx.pow(s.into_repr()); for j in 0..self.public.Y2.len() { - t.push(E::Fr::rand(rng)); + if t.len() == j { + t.push(E::Fr::rand(rng)); + } let mut gy = E::pairing(blindSig.h, self.public.Y2[j]); gy = gy.pow(t[j].into_repr()); gx.mul_assign(&gy); @@ -426,7 +426,7 @@ impl BlindKeyPair { let mut vic = ps.v.clone(); vic.mul_assign(&challenge); zv.add_assign(&vic); - SignatureProof {zsig, zx, zv, a: ps.a } + SignatureProof { zsig, zx, zv, a: ps.a } } } @@ -458,7 +458,7 @@ mod tests { use ff::Rand; use pairing::bls12_381::{Bls12, Fr}; - use rand::{SeedableRng}; + use rand::SeedableRng; use rand_xorshift::XorShiftRng; use ped92::CSMultiParams; @@ -475,8 +475,8 @@ mod tests { println!("PUBLIC KEY => {}", keypair.public); - let mut message1 : Vec = Vec::new(); - let mut message2 : Vec = Vec::new(); + let mut message1: Vec = Vec::new(); + let mut message2: Vec = Vec::new(); for i in 0..l { message1.push(Fr::rand(&mut rng)); @@ -499,8 +499,8 @@ mod tests { let public_key = keypair.get_public_key(&mpk); - let mut message1 : Vec = Vec::new(); - let mut message2 : Vec = Vec::new(); + let mut message1: Vec = Vec::new(); + let mut message2: Vec = Vec::new(); for i in 0..l { message1.push(Fr::rand(&mut rng)); @@ -512,15 +512,15 @@ mod tests { assert_eq!(public_key.verify(&mpk, &message2, &sig), false); let t = Fr::rand(&mut rng); - let blind_sig = keypair.blind(&mut rng, &t,&sig); + let blind_sig = keypair.blind(&mut rng, &t, &sig); // pick another blinding factor let t1 = Fr::rand(&mut rng); // verify blind signatures and provide blinding factor as input - assert_eq!(keypair.verify(&mpk,&message1, &t,&blind_sig), true); - assert_eq!(keypair.verify(&mpk,&message2, &t,&blind_sig), false); - assert_eq!(keypair.verify(&mpk,&message1, &t1,&blind_sig), false); + assert_eq!(keypair.verify(&mpk, &message1, &t, &blind_sig), true); + assert_eq!(keypair.verify(&mpk, &message2, &t, &blind_sig), false); + assert_eq!(keypair.verify(&mpk, &message1, &t1, &blind_sig), false); } #[test] @@ -532,7 +532,7 @@ mod tests { let mpk = setup(&mut rng); let keypair = BlindKeyPair::::generate(&mut rng, &mpk, l); - let mut message1 : Vec = Vec::new(); + let mut message1: Vec = Vec::new(); for i in 0..l { message1.push(Fr::rand(&mut rng)); @@ -559,8 +559,8 @@ mod tests { let public_key = keypair.get_public_key(&mpk); - let mut message1 : Vec = Vec::new(); - let mut message2 : Vec = Vec::new(); + let mut message1: Vec = Vec::new(); + let mut message2: Vec = Vec::new(); for i in 0..l { message1.push(Fr::rand(&mut rng)); @@ -577,11 +577,11 @@ mod tests { let t1 = Fr::rand(&mut rng); - assert_eq!(keypair.get_public_key(&mpk).verify(&mpk,&message1, &unblinded_sig), true); - assert_eq!(keypair.verify(&mpk,&message1, &t, &signature), true); - assert_eq!(keypair.get_public_key(&mpk).verify(&mpk,&message2, &unblinded_sig), false); - assert_eq!(keypair.verify(&mpk,&message2, &t, &signature), false); - assert_eq!(keypair.verify(&mpk,&message1, &t1, &signature), false); + assert_eq!(keypair.get_public_key(&mpk).verify(&mpk, &message1, &unblinded_sig), true); + assert_eq!(keypair.verify(&mpk, &message1, &t, &signature), true); + assert_eq!(keypair.get_public_key(&mpk).verify(&mpk, &message2, &unblinded_sig), false); + assert_eq!(keypair.verify(&mpk, &message2, &t, &signature), false); + assert_eq!(keypair.verify(&mpk, &message1, &t1, &signature), false); } #[test] @@ -594,19 +594,18 @@ mod tests { let public_key = keypair.get_public_key(&mpk); - let mut message1 : Vec = Vec::new(); + let mut message1: Vec = Vec::new(); for i in 0..l { message1.push(Fr::rand(&mut rng)); } let sig = keypair.sign(&mut rng, &message1); - let proof_state = keypair.prove_commitment(rng, &mpk, &sig); + let proof_state = keypair.prove_commitment(rng, &mpk, &sig, None, None); let challenge = Fr::rand(&mut rng); let proof = keypair.prove_response(&proof_state.clone(), challenge, &mut message1); assert_eq!(keypair.public.verify_proof(&mpk, proof_state.blindSig, proof, challenge), true); } - } diff --git a/src/nizk.rs b/src/nizk.rs index becb970..7d4d11a 100644 --- a/src/nizk.rs +++ b/src/nizk.rs @@ -55,9 +55,6 @@ impl NIZKPublicParams { h.mul_assign(t2); T.add_assign(&h); - //commit signature - let proofState = self.keypair.prove_commitment(rng, &self.mpk, &paymentToken); - //commit commitment let mut D = E::G1::zero(); let mut t = Vec::::with_capacity(self.comParams.pub_bases.len() - 1); @@ -69,6 +66,9 @@ impl NIZKPublicParams { D.add_assign(>); } + //commit signature + let proofState = self.keypair.prove_commitment(rng, &self.mpk, &paymentToken, Some(t[1..].to_vec()), Some(t[0].clone())); + //commit range proof let rpStateBC = self.rpParamsBC.prove_commitment(rng, newWallet.bc.clone(), newWalletCom.clone(), 3); let rpStateBM = self.rpParamsBM.prove_commitment(rng, newWallet.bm.clone(), newWalletCom.clone(), 4); diff --git a/src/util.rs b/src/util.rs index 017b039..73a5cac 100644 --- a/src/util.rs +++ b/src/util.rs @@ -70,8 +70,8 @@ pub struct CommitmentProof { impl CommitmentProof { pub fn new(csprng: &mut R, com_params: &CSMultiParams, com: &E::G1, wallet: &Vec, r: &E::Fr) -> Self { let mut Tvals = E::G1::zero(); - let mut t = Vec::::with_capacity(com_params.pub_bases1.len() - 1); - for g in com_params.pub_bases1.clone() { + let mut t = Vec::::with_capacity(com_params.pub_bases.len() - 1); + for g in com_params.pub_bases.clone() { let ti = E::Fr::rand(csprng); t.push(ti); let mut gt = g.clone(); @@ -118,7 +118,7 @@ pub fn verify(com_params: &CSMultiParams, com: &E::G1, proof: &Com let mut x = E::G1::zero(); for i in 0..proof.z.len() { - let mut base = com_params.pub_bases1[i].clone(); + let mut base = com_params.pub_bases[i].clone(); base.mul_assign(proof.z[i].into_repr()); x.add_assign(&base); }