From 8a52a76ce4699c709b792cd6e1c8fc04b4732859 Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Tue, 10 Sep 2019 22:21:09 -0400 Subject: [PATCH] nizk: split secret and public params --- examples/bolt_test.rs | 6 +- src/ccs08.rs | 304 +++++++++++++++++++++++------------------- src/channels.rs | 170 +++++++++++------------ src/cl.rs | 188 +++++++++++++------------- src/ffishim.rs | 5 +- src/lib.rs | 47 +++---- src/nizk.rs | 226 +++++++++++++++++-------------- 7 files changed, 488 insertions(+), 458 deletions(-) diff --git a/examples/bolt_test.rs b/examples/bolt_test.rs index 13e85ee..123f0c3 100644 --- a/examples/bolt_test.rs +++ b/examples/bolt_test.rs @@ -50,16 +50,12 @@ fn main() { let mut channel_state = bidirectional::ChannelState::::new(String::from("Channel A -> B"), false); let mut rng = &mut rand::thread_rng(); - channel_state.setup(&mut rng); // or load_setup params - let b0_customer = 150; let b0_merchant = 10; let pay_inc = 20; let pay_inc2 = 10; - let (mut channel_token, mut merch_state) = bidirectional::init_merchant(rng, &mut channel_state, "Merchant Bob"); - // initialize the balance for merch_state - merch_state.init_balance(b0_merchant); + let (mut channel_token, mut merch_state, mut channel_state) = bidirectional::init_merchant(rng, &mut channel_state, "Merchant Bob"); let mut cust_state = bidirectional::init_customer(rng, &mut channel_state, &mut channel_token, b0_customer, b0_merchant, "Alice"); diff --git a/src/ccs08.rs b/src/ccs08.rs index 625f3d9..0f107d7 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -9,7 +9,7 @@ extern crate rand; use rand::Rng; use super::*; -use cl::{Signature, PublicParams, setup, BlindKeyPair, ProofState, SignatureProof}; +use cl::{Signature, PublicParams, setup, BlindKeyPair, ProofState, SignatureProof, BlindPublicKey}; use ped92::{Commitment, CSMultiParams}; use pairing::{Engine, CurveProjective}; use ff::PrimeField; @@ -26,7 +26,7 @@ struct ParamsUL { pub mpk: PublicParams, pub signatures: HashMap>, pub csParams: CSMultiParams, - kp: BlindKeyPair, + pk: BlindPublicKey, // 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. @@ -37,6 +37,18 @@ struct ParamsUL { l: i32, } +/** +paramsUL contains elements generated by the verifier, which are necessary for the prover. +This must be computed in a trusted setup. +*/ +#[derive(Clone, Serialize, Deserialize)] +#[serde(bound(serialize = "::Fr: serde::Serialize, ::G1: serde::Serialize, ::G2: serde::Serialize"))] +#[serde(bound(deserialize = "::Fr: serde::Deserialize<'de>, ::G1: serde::Deserialize<'de>, ::G2: serde::Deserialize<'de>"))] +struct SecretParamsUL { + pub pubParams: ParamsUL, + kp: BlindKeyPair, +} + #[derive(Clone)] pub struct ProofULState { pub decx: Vec, @@ -110,7 +122,19 @@ pub struct RPPublicParams { b: i32, } -impl ParamsUL { +/** +params contains elements generated by the verifier, which are necessary for the prover. +This must be computed in a trusted setup. +*/ +#[derive(Clone, Serialize, Deserialize)] +#[serde(bound(serialize = "::Fr: serde::Serialize, ::G1: serde::Serialize, ::G2: serde::Serialize"))] +#[serde(bound(deserialize = "::Fr: serde::Deserialize<'de>, ::G1: serde::Deserialize<'de>, ::G2: serde::Deserialize<'de>"))] +pub struct RPSecretParams { + pub pubParams: RPPublicParams, + p: SecretParamsUL, +} + +impl SecretParamsUL { /** setup_ul generates the signature for the interval [0,u^l). The value of u should be roughly b/log(b), but we can choose smaller values in @@ -125,10 +149,74 @@ impl ParamsUL { let sig_i = kp.sign(rng, &vec! {E::Fr::from_str(i.to_string().as_str()).unwrap()}); signatures.insert(i.to_string(), sig_i); } + let pubParams = ParamsUL { mpk, signatures, csParams, pk: kp.public.clone(), u, l }; - return ParamsUL { mpk, signatures, csParams, kp, u, l }; + SecretParamsUL{pubParams, kp} } + /** + 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 { + let r1 = self.verify_part1(&proof, ch.clone(), k); + let r2 = self.verify_part2(&proof, ch.clone()); + r1 && r2 + } + + fn compute_challenge(&self, proof: &ProofUL) -> E::Fr { + let mut a = Vec::::with_capacity(self.pubParams.l as usize); + for sigProof in proof.sigProofs.clone() { + a.push(sigProof.a); + } + hash::(a, vec!(proof.D.clone())) + } + + fn verify_part2(&self, proof: &ProofUL, challenge: E::Fr) -> bool { + let mut r2 = true; + for i in 0..self.pubParams.l as usize { + let subResult = self.kp.public.verify_proof(&self.pubParams.mpk, proof.V[i].clone(), proof.sigProofs[i].clone(), challenge); + + r2 = r2 && subResult; + } + r2 + } + + 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.pubParams.csParams.pub_bases[0].clone(); + hzr.mul_assign(proof.zr); + D.add_assign(&hzr); + for i in 0..self.pubParams.l as usize { + let ui = self.pubParams.u.pow(i as u32); + let mut aux = self.pubParams.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()); + aux.mul_assign(muizsigi); + } + D.add_assign(&aux); + } + for i in 1..self.pubParams.csParams.pub_bases.len() { + let j: usize; + if i < k { + j = i - 1; + } else if i > k { + j = i - 2; + } else { + continue; + } + let mut g = self.pubParams.csParams.pub_bases[i].clone(); + g.mul_assign(proof.zs[j].into_repr()); + D.add_assign(&g); + } + D == proof.D + } +} + +impl ParamsUL { + /** prove_ul method is used to produce the ZKRP proof that secret x belongs to the interval [0,U^L). */ @@ -163,14 +251,14 @@ 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, None, None); + let proofState = self.pk.prove_commitment(rng, &self.mpk, &signature, None, None); V.push(proofState.blindSig.clone()); proofStates.push(proofState); let ui = self.u.pow(i as u32); let mut aux = self.csParams.pub_bases[k].clone(); - for j in 0..self.kp.public.Y1.len() { + for j in 0..self.pk.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); @@ -207,7 +295,7 @@ impl ParamsUL { for i in 0..self.l as usize { let dx = E::Fr::from_str(&proofUlState.decx[i].to_string()).unwrap(); - let proof = self.kp.prove_response(&proofUlState.proofStates[i].clone(), c, &mut vec! {dx}); + let proof = self.pk.prove_response(&proofUlState.proofStates[i].clone(), c, &mut vec! {dx}); sigProofs.push(proof); } @@ -230,66 +318,6 @@ impl ParamsUL { } 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 { - let r1 = self.verify_part1(&proof, ch.clone(), k); - let r2 = self.verify_part2(&proof, ch.clone()); - r1 && r2 - } - - 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); - } - hash::(a, vec!(proof.D.clone())) - } - - 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(), challenge); - - r2 = r2 && subResult; - } - r2 - } - - 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.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.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()); - aux.mul_assign(muizsigi); - } - D.add_assign(&aux); - } - for i in 1..self.csParams.pub_bases.len() { - let 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 { @@ -322,7 +350,7 @@ fn decompose(x: i32, u: i32, l: i32) -> Vec { return result; } -impl RPPublicParams { +impl RPSecretParams { /** Setup receives integers a and b, and configures the parameters for the rangeproof scheme. */ @@ -339,13 +367,34 @@ impl RPPublicParams { u = 57; //TODO: optimize u? 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 }; + let secParamsOut = SecretParamsUL::::setup_ul(rng, u, l, csParams.clone()); + let pubParams = RPPublicParams { p: secParamsOut.pubParams.clone(), a, b }; + RPSecretParams{pubParams, p: secParamsOut} } else { panic!("log(log(b)) is zero"); } } + /** + Verify is responsible for validating the range proof. + */ + 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 + } + + pub fn compute_challenge(&self, proof: &RangeProof) -> E::Fr { + let mut a = Vec::::with_capacity(self.p.pubParams.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); + } + hash::(a, vec!(proof.p1.D.clone(), proof.p2.D.clone())) + } +} + +impl RPPublicParams { /** Prove method is responsible for generating the zero knowledge range proof. */ @@ -396,24 +445,6 @@ impl RPPublicParams { let second = self.p.prove_ul_response(r.clone(), rpState.com2.clone(), &rpState.ps2, ch.clone(), k, otherM.clone()); RangeProof { p1: first, p2: second } } - - /** - Verify is responsible for validating the range proof. - */ - 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 - } - - pub 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); - } - hash::(a, vec!(proof.p1.D.clone(), proof.p2.D.clone())) - } } @@ -431,10 +462,10 @@ mod tests { let rng = &mut rand::thread_rng(); let csParams = CSMultiParams::setup_gen_params(rng, 1); - 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); + let secParams = SecretParamsUL::::setup_ul(rng, 2, 3, csParams.clone()); + assert_eq!(secParams.pubParams.signatures.len(), 2); + for (m, s) in secParams.pubParams.signatures { + assert_eq!(secParams.kp.public.verify_blind(&secParams.pubParams.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &Fr::zero(), &s), true); } } @@ -443,11 +474,11 @@ mod tests { let rng = &mut rand::thread_rng(); let csParams = CSMultiParams::setup_gen_params(rng, 1); - let params = ParamsUL::::setup_ul(rng, 2, 4, csParams.clone()); + let secParams = SecretParamsUL::::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!(modx), &fr.clone()); - let proof = params.prove_ul(rng, 10, fr, C, 1, vec!{}); + let proof = secParams.pubParams.prove_ul(rng, 10, fr, C, 1, vec!{}); assert_eq!(proof.V.len(), 4); assert_eq!(proof.sigProofs.len(), 4); } @@ -457,95 +488,95 @@ mod tests { fn prove_ul_not_in_range() { let rng = &mut rand::thread_rng(); let csParams = CSMultiParams::setup_gen_params(rng, 1); - let params = ParamsUL::::setup_ul(rng, 2, 3, csParams.clone()); + let secParams = SecretParamsUL::::setup_ul(rng, 2, 3, csParams.clone()); 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, vec!{}); + secParams.pubParams.prove_ul(rng, 100, fr, C, 1, vec!{}); } #[test] fn prove_and_verify_part1_ul_works() { let rng = &mut rand::thread_rng(); let csParams = CSMultiParams::setup_gen_params(rng, 1); - let params = ParamsUL::::setup_ul(rng, 2, 4, csParams.clone()); + let secParams = SecretParamsUL::::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!(modx), &fr.clone()); - 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); + let proof = secParams.pubParams.prove_ul(rng, 10, fr, C, 1, vec!{}); + let ch = secParams.compute_challenge(&proof); + assert_eq!(secParams.verify_part1(&proof, ch, 1), true); } #[test] fn prove_and_verify_part2_ul_works() { let rng = &mut rand::thread_rng(); let csParams = CSMultiParams::setup_gen_params(rng, 1); - let params = ParamsUL::::setup_ul(rng, 2, 4, csParams.clone()); + let secParams = SecretParamsUL::::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!(modx), &fr.clone()); - 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); + let proof = secParams.pubParams.prove_ul(rng, 10, fr, C, 1, vec!{}); + let ch = secParams.compute_challenge(&proof); + assert_eq!(secParams.verify_part2(&proof, ch), true); } #[test] fn prove_and_verify_ul_works() { let rng = &mut rand::thread_rng(); let csParams = CSMultiParams::setup_gen_params(rng, 1); - let params = ParamsUL::::setup_ul(rng, 2, 4, csParams.clone()); + let secParams = SecretParamsUL::::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!(modx), &fr.clone()); - 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); + let proof = secParams.pubParams.prove_ul(rng, 10, fr, C, 1, vec!{}); + let ch = secParams.compute_challenge(&proof); + assert_eq!(secParams.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 secParams = SecretParamsUL::::setup_ul(rng, 2, 4, csParams.clone()); let fr = Fr::rand(rng); let modx = Fr::from_str(&(10.to_string())).unwrap(); 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); + let proof = secParams.pubParams.prove_ul(rng, 10, fr, C, 2, vec!{fr1, fr2}); + let ch = secParams.compute_challenge(&proof); + assert_eq!(secParams.verify_ul(&proof, ch, 2), true); } #[test] fn prove_and_verify_works() { let rng = &mut rand::thread_rng(); let csParams = CSMultiParams::setup_gen_params(rng, 1); - let params = RPPublicParams::::setup(rng, 2, 25, csParams.clone()); + let secParams = RPSecretParams::::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!(modx), &fr.clone()); - let proof = params.prove(rng, 10, C, fr, 1, vec!{}); - let ch = params.compute_challenge(&proof); + let proof = secParams.pubParams.prove(rng, 10, C, fr, 1, vec!{}); + let ch = secParams.compute_challenge(&proof); - assert_eq!(params.verify(proof, ch, 1), true); + assert_eq!(secParams.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 secParams = RPSecretParams::::setup(rng, 2, 25, csParams.clone()); let fr = Fr::rand(rng); let modx = Fr::from_str(&(10.to_string())).unwrap(); 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); + let proof = secParams.pubParams.prove(rng, 10, C, fr, 2, vec!{fr1, fr2}); + let ch = secParams.compute_challenge(&proof); - assert_eq!(params.verify(proof, ch, 2), true); + assert_eq!(secParams.verify(proof, ch, 2), true); } #[test] @@ -553,11 +584,11 @@ mod tests { fn prove_not_in_range() { let rng = &mut rand::thread_rng(); let csParams = CSMultiParams::setup_gen_params(rng, 1); - let params = RPPublicParams::::setup(rng, 2, 25, csParams.clone()); + let secParams = RPSecretParams::::setup(rng, 2, 25, csParams.clone()); 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, vec!{}); + secParams.pubParams.prove(rng, 26, C, fr, 1, vec!{}); } #[test] @@ -577,21 +608,21 @@ mod tests { let sSetup = PreciseTime::now(); let csParams = CSMultiParams::setup_gen_params(rng, 1); - let params = RPPublicParams::::setup(rng, a, b, csParams.clone()); + let secParams = RPSecretParams::::setup(rng, a, b, csParams.clone()); averageSetup = averageSetup.add(sSetup.to(PreciseTime::now())); - averageSetupSize += mem::size_of_val(¶ms); + averageSetupSize += mem::size_of_val(&secParams.pubParams); let sProve = PreciseTime::now(); 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, vec!{}); + let proof = secParams.pubParams.prove(rng, x, C, fr, 1, vec!{}); averageProve = averageProve.add(sProve.to(PreciseTime::now())); averageProofSize += mem::size_of_val(&proof); let sVerify = PreciseTime::now(); - let ch = params.compute_challenge(&proof); - params.verify(proof, ch, 1); + let ch = secParams.compute_challenge(&proof); + secParams.verify(proof, ch, 1); averageVerify = averageVerify.add(sVerify.to(PreciseTime::now())); } print!("Setup: {}\n", averageSetup.num_milliseconds() / iter); @@ -631,14 +662,15 @@ mod tests { fn setup_works() { let rng = &mut rand::thread_rng(); let csParams = CSMultiParams::setup_gen_params(rng, 1); - let public_params = RPPublicParams::::setup(rng, 2, 10, csParams); + let secParams = RPSecretParams::::setup(rng, 2, 10, csParams); + let public_params = secParams.pubParams.clone(); assert_eq!(public_params.a, 2); assert_eq!(public_params.b, 10); assert_eq!(public_params.p.signatures.len(), 57); assert_eq!(public_params.p.u, 57); assert_eq!(public_params.p.l, 1); for (m, s) in public_params.p.signatures { - assert_eq!(public_params.p.kp.verify(&public_params.p.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &Fr::zero(), &s), true); + assert_eq!(secParams.p.kp.public.verify_blind(&public_params.p.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &Fr::zero(), &s), true); } } @@ -647,7 +679,7 @@ mod tests { fn setup_wrong_a_and_b() { let rng = &mut rand::thread_rng(); let csParams = CSMultiParams::setup_gen_params(rng, 1); - RPPublicParams::::setup(rng, 10, 2, csParams); + RPSecretParams::::setup(rng, 10, 2, csParams); } #[test] @@ -655,7 +687,7 @@ mod tests { fn setup_wrong_logb() { let rng = &mut rand::thread_rng(); let csParams = CSMultiParams::setup_gen_params(rng, 1); - RPPublicParams::::setup(rng, -2, -1, csParams); + RPSecretParams::::setup(rng, -2, -1, csParams); } #[test] @@ -668,11 +700,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, 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 state = kp.public.prove_commitment(rng, ¶ms, &sig, None, None); + let state1 = kp.public.prove_commitment(rng, ¶ms, &sig, None, None); + let state2 = kp.public.prove_commitment(rng, ¶ms, &sig, None, None); + let state3 = kp.public.prove_commitment(rng, ¶ms, &sig, None, None); + let state4 = kp.public.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 4244b96..4597827 100644 --- a/src/channels.rs +++ b/src/channels.rs @@ -11,7 +11,7 @@ extern crate rand; use super::*; use pairing::{Engine, CurveProjective}; -use pairing::bls12_381::{Bls12}; +use pairing::bls12_381::Bls12; use ff::PrimeField; use cl::{BlindKeyPair, KeyPair, Signature, PublicParams, setup}; use ped92::{CSParams, Commitment, CSMultiParams, CommitmentProof}; @@ -21,7 +21,7 @@ use std::collections::HashMap; use std::fmt::Display; use serde::{Serialize, Deserialize}; use std::ptr::hash; -use nizk::{NIZKPublicParams, NIZKProof}; +use nizk::{NIZKPublicParams, NIZKSecretParams, NIZKProof}; use wallet::Wallet; use std::error::Error; use std::fmt; @@ -34,13 +34,13 @@ pub type ResultBoltType = Result; impl BoltError { fn new(msg: &str) -> BoltError { - BoltError{details: msg.to_string()} + BoltError { details: msg.to_string() } } } impl fmt::Display for BoltError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f,"{}",self.details) + write!(f, "{}", self.details) } } @@ -54,7 +54,7 @@ impl Error for BoltError { #[derive(Clone, Serialize, Deserialize)] pub struct PubKeyMap { pub wpk: secp256k1::PublicKey, - pub revoke_token: Option + pub revoke_token: Option, } #[derive(Clone, Serialize, Deserialize)] @@ -68,8 +68,9 @@ pub struct PubKeyMap { ))] pub struct ChannelParams { pub pub_params: NIZKPublicParams, - l: usize, // messages for commitment - extra_verify: bool // extra verification for certain points in the establish/pay protocol + l: usize, + // messages for commitment + extra_verify: bool, // extra verification for certain points in the establish/pay protocol } @@ -89,7 +90,7 @@ pub struct ChannelState { pub name: String, pub pay_init: bool, pub channel_established: bool, - pub third_party: bool + pub third_party: bool, } #[derive(Clone, Serialize, Deserialize)] @@ -102,10 +103,14 @@ pub struct ChannelState { ::G2: serde::Deserialize<'de>" ))] pub struct ChannelToken { - pub pk_c: Option, // pk_c - pub pk_m: secp256k1::PublicKey, // pk_m - pub cl_pk_m: cl::PublicKey, // PK_m (used for verifying blind signatures) - pub mpk: cl::PublicParams, // mpk for PK_m + pub pk_c: Option, + // pk_c + pub pk_m: secp256k1::PublicKey, + // pk_m + pub cl_pk_m: cl::PublicKey, + // PK_m (used for verifying blind signatures) + pub mpk: cl::PublicParams, + // mpk for PK_m pub comParams: CSMultiParams, } @@ -119,9 +124,9 @@ impl ChannelToken { } pub fn compute_id(&self) -> [u8; 32] - where ::G1: serde::Serialize, - ::G2: serde::Serialize, - ::Fr: serde::Serialize + where ::G1: serde::Serialize, + ::G2: serde::Serialize, + ::Fr: serde::Serialize { let mut input = Vec::new(); @@ -140,7 +145,6 @@ impl ChannelToken { return hash_to_slice(&input); } - } // add methods to check if channel token is initialized // (only if @@ -149,7 +153,6 @@ impl ChannelToken { /// Channel state for generating/loading channel parameters and generating keypairs /// impl ChannelState { - pub fn new(name: String, third_party_support: bool) -> ChannelState { ChannelState { R: 0, @@ -158,7 +161,7 @@ impl ChannelState { name: name.to_string(), pay_init: false, channel_established: false, - third_party: third_party_support + third_party: third_party_support, } } @@ -166,17 +169,6 @@ impl ChannelState { sodiumoxide::init(); } - /// - /// setup - generate public parameters for bidirectional payment channels - /// - pub fn setup(&mut self, csprng: &mut R) { - let l = 5; - let pubParams = NIZKPublicParams::::setup(csprng, l); - - let cp = ChannelParams { pub_params: pubParams, l: l, extra_verify: true }; - self.cp = Some(cp); - } - /// /// keygen - takes as input public parameters and generates a digital signature keypair /// @@ -203,7 +195,7 @@ impl ChannelState { #[derive(Copy, Clone, Serialize, Deserialize)] struct WalletKeyPair { pub wpk: secp256k1::PublicKey, - pub wsk: secp256k1::SecretKey + pub wsk: secp256k1::SecretKey, } /// @@ -222,17 +214,23 @@ pub struct CustomerState { pub name: String, pub pk_c: secp256k1::PublicKey, sk_c: secp256k1::SecretKey, - pub cust_balance: i32, // + pub cust_balance: i32, + // pub merch_balance: i32, - pub wpk: secp256k1::PublicKey, // keypair bound to the wallet + pub wpk: secp256k1::PublicKey, + // keypair bound to the wallet wsk: secp256k1::SecretKey, - old_kp: Option, // old wallet key pair - t: E::Fr, // randomness used to form the commitment - wallet: Wallet, // vector of field elements that represent wallet - pub w_com: Commitment, // commitment to the current state of the wallet + old_kp: Option, + // old wallet key pair + t: E::Fr, + // randomness used to form the commitment + wallet: Wallet, + // vector of field elements that represent wallet + pub w_com: Commitment, + // commitment to the current state of the wallet index: i32, close_tokens: HashMap>, - pay_tokens: HashMap> + pay_tokens: HashMap>, } impl CustomerState { @@ -251,7 +249,7 @@ impl CustomerState { // randomness for commitment let t = E::Fr::rand(csprng); // initialize wallet vector - let wallet = Wallet { pkc: pk_h, wpk: wpk_h, bc: cust_bal, bm: merch_bal, close: None }; + let wallet = Wallet { pkc: pk_h, wpk: wpk_h, bc: cust_bal, bm: merch_bal, close: None }; let w_com = channel_token.comParams.commit(&wallet.as_fr_vec(), &t); @@ -259,8 +257,8 @@ impl CustomerState { assert!(channel_token.is_init()); - let ct_db= HashMap::new(); - let pt_db= HashMap::new(); + let ct_db = HashMap::new(); + let pt_db = HashMap::new(); return CustomerState { name: name, @@ -276,8 +274,8 @@ impl CustomerState { wallet: wallet, index: 0, close_tokens: ct_db, - pay_tokens: pt_db - } + pay_tokens: pt_db, + }; } pub fn get_wallet(&self) -> Wallet { @@ -304,21 +302,21 @@ impl CustomerState { let mpk = cp.pub_params.mpk.clone(); //println!("verify_close_token - Wallet: {}", &self.wallet); - let is_close_valid = cp.pub_params.keypair.verify(&mpk, &close_wallet, &self.t, &close_token); + let is_close_valid = cp.pub_params.pk.verify_blind(&mpk, &close_wallet, &self.t, &close_token); if is_close_valid { //println!("verify_close_token - Blinded close token is valid!!"); - let pk = cp.pub_params.keypair.get_public_key(&mpk); - let unblind_close_token = cp.pub_params.keypair.unblind(&self.t, &close_token); + let unblind_close_token = cp.pub_params.pk.unblind(&self.t, &close_token); + let pk = cp.pub_params.pk.get_pub_key(); let is_valid = pk.verify(&mpk, &close_wallet, &unblind_close_token); if is_valid { // record the unblinded close token - self.close_tokens.insert( self.index, unblind_close_token); + self.close_tokens.insert(self.index, unblind_close_token); } return is_valid; } //println!("Customer - Verification failed for close token!"); - return false; + return is_close_valid; } pub fn verify_pay_token(&mut self, channel: &ChannelState, pay_token: &Signature) -> bool { @@ -329,11 +327,11 @@ impl CustomerState { let wallet = self.wallet.without_close(); //println!("verify_pay_token - Wallet: {}", &self.wallet); - let is_pay_valid = cp.pub_params.keypair.verify(&mpk, &wallet, &self.t, &pay_token); + let is_pay_valid = cp.pub_params.pk.verify_blind(&mpk, &wallet, &self.t, &pay_token); if is_pay_valid { //println!("verify_pay_token - Blinded pay token is valid!!"); - let unblind_pay_token = cp.pub_params.keypair.unblind(&self.t, &pay_token); - let pk = cp.pub_params.keypair.get_public_key(&mpk); + let unblind_pay_token = cp.pub_params.pk.unblind(&self.t, &pay_token); + let pk = cp.pub_params.pk.get_pub_key(); let is_valid = pk.verify(&mpk, &wallet, &unblind_pay_token); if is_valid { self.pay_tokens.insert(self.index, unblind_pay_token); @@ -342,7 +340,7 @@ impl CustomerState { } //println!("Customer - Verification failed for pay token!"); - return false; + return is_pay_valid; } pub fn has_tokens(&self) -> bool { @@ -361,13 +359,13 @@ impl CustomerState { let wpk_h = hash_pubkey_to_fr::(&new_wpk); // 2 - form new wallet and commitment - let new_cust_bal= self.cust_balance - amount; + let new_cust_bal = self.cust_balance - amount; let new_merch_bal = self.merch_balance + amount; let new_t = E::Fr::rand(csprng); let cp = channel.cp.as_ref().unwrap(); let old_wallet = Wallet { pkc: self.wallet.pkc.clone(), wpk: self.wallet.wpk.clone(), bc: self.cust_balance, bm: self.merch_balance, close: None }; - let new_wallet = Wallet { pkc: self.wallet.pkc.clone(), wpk: wpk_h, bc: new_cust_bal, bm: new_merch_bal, close: Some(self.wallet.close.unwrap()) }; + let new_wallet = Wallet { pkc: self.wallet.pkc.clone(), wpk: wpk_h, bc: new_cust_bal, bm: new_merch_bal, close: Some(self.wallet.close.unwrap()) }; let new_wcom = cp.pub_params.comParams.commit(&new_wallet.as_fr_vec(), &new_t); // 3 - generate new blinded and randomized pay token @@ -376,7 +374,7 @@ impl CustomerState { //println!("Found prev pay token: {}", prev_pay_token); let pay_proof = cp.pub_params.prove(csprng, old_wallet, new_wallet.clone(), - new_wcom.clone(), new_t, &prev_pay_token); + new_wcom.clone(), new_t, &prev_pay_token); // update internal state after proof has been verified by remote let new_cw = CustomerState { @@ -393,7 +391,7 @@ impl CustomerState { wallet: new_wallet.clone(), index: self.index, // increment index here close_tokens: self.close_tokens.clone(), - pay_tokens: self.pay_tokens.clone() + pay_tokens: self.pay_tokens.clone(), }; return (pay_proof, new_wcom, self.wpk, new_cw); @@ -433,7 +431,6 @@ impl CustomerState { Err(BoltError::new("generate_revoke_token - could not verify the close token.")) } - } impl fmt::Display for CustomerState { @@ -468,7 +465,7 @@ impl fmt::Display for CustomerState { pub struct ChannelcloseM { pub address: String, pub revoke: Option, - pub signature: secp256k1::Signature + pub signature: secp256k1::Signature, } /// @@ -485,55 +482,55 @@ pub struct ChannelcloseM { ))] pub struct MerchantState { keypair: cl::BlindKeyPair, - pub init_balance: i32, - pk: secp256k1::PublicKey, // pk_m - sk: secp256k1::SecretKey, // sk_m + nizkParams: NIZKSecretParams, + pk: secp256k1::PublicKey, + // pk_m + sk: secp256k1::SecretKey, + // sk_m comParams: CSMultiParams, pub keys: HashMap, - pub pay_tokens: HashMap> + pub pay_tokens: HashMap>, } impl MerchantState { - pub fn new(csprng: &mut R, channel: &mut ChannelState, id: String) -> Self { + pub fn new(csprng: &mut R, channel: &mut ChannelState, id: String) -> (Self, ChannelState) { + let l = 5; // generate keys here let mut tx_kp = secp256k1::Secp256k1::new(); tx_kp.randomize(csprng); let (wsk, wpk) = tx_kp.generate_keypair(csprng); - let cp = channel.cp.as_ref().unwrap(); // if not set, then panic! + let mut ch = channel.clone(); + let nizkParams = NIZKSecretParams::::setup(csprng, l); + ch.cp = Some(ChannelParams:: { pub_params: nizkParams.pubParams.clone(), l, extra_verify: true }); - MerchantState { - keypair: cp.pub_params.keypair.clone(), - init_balance: 0, + (MerchantState { + keypair: nizkParams.keypair.clone(), + nizkParams: nizkParams.clone(), pk: wpk, sk: wsk, - comParams: cp.pub_params.comParams.clone(), + comParams: nizkParams.pubParams.comParams.clone(), keys: HashMap::new(), // store wpks/revoke_tokens - pay_tokens: HashMap::new() - } + pay_tokens: HashMap::new(), + }, ch) } pub fn init(&mut self, csprng: &mut R, channel: &mut ChannelState) -> ChannelToken { let cp = channel.cp.as_ref().unwrap(); // if not set, then panic! let mpk = cp.pub_params.mpk.clone(); - let cl_pk = cp.pub_params.keypair.get_public_key(&mpk); + let cl_pk = self.keypair.get_public_key(&mpk); return ChannelToken { pk_c: None, cl_pk_m: cl_pk.clone(), // extract the regular public key pk_m: self.pk.clone(), mpk: mpk, - comParams: self.comParams.clone() - } - } - - pub fn init_balance(&mut self, balance: i32) { - // set by the escrow/funding transactionf for the channel - self.init_balance = balance; + comParams: self.comParams.clone(), + }; } pub fn issue_close_token(&self, csprng: &mut R, cp: &ChannelParams, com: &Commitment, extend_close: bool) -> Signature { //println!("issue_close_token => generating token"); - let x = hash_to_fr::(String::from("close").into_bytes() ); + let x = hash_to_fr::(String::from("close").into_bytes()); let close_com = match extend_close { true => self.comParams.extend_commit(com, &x), false => com.clone() @@ -544,7 +541,7 @@ impl MerchantState { pub fn issue_pay_token(&self, csprng: &mut R, cp: &ChannelParams, com: &Commitment, remove_close: bool) -> Signature { //println!("issue_pay_token => generating token"); - let x = hash_to_fr::(String::from("close").into_bytes() ); + let x = hash_to_fr::(String::from("close").into_bytes()); let pay_com = match remove_close { true => self.comParams.remove_commit(com, &x), false => com.clone() @@ -584,7 +581,7 @@ impl MerchantState { let prev_wpk = hash_pubkey_to_fr::(&wpk); let epsilon = util::convert_int_to_fr::(amount); - if cp.pub_params.verify(pay_proof, epsilon, com, prev_wpk) { + if self.nizkParams.verify(pay_proof, epsilon, com, prev_wpk) { // 1 - proceed with generating close and pay token let close_token = self.issue_close_token(csprng, cp, com, false); let pay_token = self.issue_pay_token(csprng, cp, com, true); @@ -613,11 +610,10 @@ impl MerchantState { let r = revoke_token.unwrap().serialize_der().to_vec(); msg.extend(r); } - let msg2 = secp256k1::Message::from_slice(&hash_to_slice(&msg) ).unwrap(); + let msg2 = secp256k1::Message::from_slice(&hash_to_slice(&msg)).unwrap(); let merch_sig = secp.sign(&msg2, &self.sk); return ChannelcloseM { address: address.clone(), revoke: revoke_token.clone(), signature: merch_sig }; } - } #[cfg(test)] @@ -625,8 +621,8 @@ mod tests { use super::*; use ff::Rand; - use pairing::bls12_381::{Bls12}; - use rand::{SeedableRng}; + use pairing::bls12_381::Bls12; + use rand::SeedableRng; use rand_xorshift::XorShiftRng; #[test] @@ -634,16 +630,12 @@ mod tests { let mut channel = ChannelState::::new(String::from("Channel A <-> B"), false); let mut rng = &mut rand::thread_rng(); - // run setup to generate the public parameters - channel.setup(&mut rng); // or load_setup params - let b0_cust = 100; let b0_merch = 20; // each party executes the init algorithm on the agreed initial challenge balance // in order to derive the channel tokens // initialize on the merchant side with balance: b0_merch - let mut merch_state = MerchantState::::new(rng, &mut channel, String::from("Merchant B")); - merch_state.init_balance(b0_merch); + let (mut merch_state, mut channel) = MerchantState::::new(rng, &mut channel, String::from("Merchant B")); // initialize the merchant wallet with the balance let mut channel_token = merch_state.init(rng, &mut channel); diff --git a/src/cl.rs b/src/cl.rs index 4a0dee0..6ce5e94 100644 --- a/src/cl.rs +++ b/src/cl.rs @@ -36,7 +36,6 @@ pub struct SecretKey { impl fmt::Display for SecretKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut y_str = String::new(); let mut i = 0; for y in self.y.iter() { @@ -63,7 +62,6 @@ pub struct PublicKey { impl fmt::Display for PublicKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut y_s = String::new(); let mut i = 0; for y in self.Y.iter() { @@ -92,7 +90,6 @@ pub struct BlindPublicKey { impl fmt::Display for BlindPublicKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut y1_str = String::new(); for y in self.Y1.iter() { y1_str = format!("{}\n{}", y1_str, y); @@ -206,22 +203,6 @@ impl SecretKey { Signature { h: h, H: H } } - - pub fn blind(&self, csprng: &mut R, bf: &E::Fr, signature: &Signature) -> Signature { - let r = E::Fr::rand(csprng); - let t = bf.clone(); - let mut h1 = signature.h; - h1.mul_assign(r); // sigma1 ^ r - - let mut h = signature.h; - let mut H1 = signature.H; - h.mul_assign(t); // sigma1 ^ t (blinding factor) - H1.add_assign(&h); // (sigma2 * sigma1 ^ t) - - // (sigma2 * sigma1 ^ t) ^ r - H1.mul_assign(r); - Signature { h: h1, H: H1 } - } } /// @@ -302,6 +283,10 @@ impl BlindPublicKey { } } + pub fn get_pub_key(&self) -> PublicKey { + PublicKey { X: self.X2.clone(), Y: self.Y2.clone() } + } + pub fn verify(&self, mpk: &PublicParams, message: &Vec, signature: &Signature) -> bool { let mut L = E::G2::zero(); let l = self.Y2.len(); @@ -339,6 +324,14 @@ impl BlindPublicKey { signature.h != E::G1::one() && lhs == rhs } + /// verify a blinded signature without unblinding it first + pub fn verify_blind(&self, mpk: &PublicParams, message: &Vec, bf: &E::Fr, signature: &Signature) -> bool { + let mut m = message.clone(); + let t = bf.clone(); + m.push(t); + self.verify(mpk, &m, signature) + } + /// Verify a proof of knowledge of a signature /// Takes in a proof generated by prove_response(), a blind signature, and a challenge /// outputs: boolean @@ -358,6 +351,80 @@ impl BlindPublicKey { g.mul_assign(&p.a); gx == g } + + pub fn blind(&self, csprng: &mut R, bf: &E::Fr, signature: &Signature) -> Signature { + let r = E::Fr::rand(csprng); + let t = bf.clone(); + let mut h1 = signature.h; + h1.mul_assign(r); // sigma1 ^ r + + let mut h = signature.h; + let mut H1 = signature.H; + h.mul_assign(t); // sigma1 ^ t (blinding factor) + H1.add_assign(&h); // (sigma2 * sigma1 ^ t) + + // (sigma2 * sigma1 ^ t) ^ r + H1.mul_assign(r); + Signature { h: h1, H: H1 } + } + + pub fn unblind(&self, bf: &E::Fr, signature: &Signature) -> Signature { + let mut H = signature.h; + let mut inv_bf = bf.clone(); + inv_bf.negate(); + + // sigma2 / sigma1 ^ t + H.mul_assign(inv_bf); + H.add_assign(&signature.H); + + Signature { h: signature.h, H: H } + } + + + /// 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, + tOptional: Option>, ttOptional: Option) -> ProofState { + let v = E::Fr::rand(rng); + let blindSig = self.blind(rng, &v, signature); + let mut t = tOptional.unwrap_or(Vec::::with_capacity(self.Y2.len())); + let tt = ttOptional.unwrap_or(E::Fr::rand(rng)); + let mut a = E::Fqk::one(); + // TODO: consider optimizations to pairing in loop + for j in 0..self.Y2.len() { + if t.len() == j { + t.push(E::Fr::rand(rng)); + } + let mut gy = E::pairing(blindSig.h, self.Y2[j]); + gy = gy.pow(t[j].into_repr()); + a.mul_assign(&gy); + } + let mut h = E::pairing(blindSig.h, mpk.g2); + h = h.pow(tt.into_repr()); + a.mul_assign(&h); + ProofState { v, t, tt, a, blindSig } + } + + /// prove knowledge of a signature: response phase + /// returns a proof that can be send to the verifier together with the challenge and the blind signature + pub fn prove_response(&self, ps: &ProofState, challenge: E::Fr, message: &mut Vec) -> SignatureProof { + let mut zsig = ps.t.clone(); + let z_len = zsig.len(); + + for i in 0..message.len() { + if i < z_len { + let mut message1 = message[i]; + message1.mul_assign(&challenge); + zsig[i].add_assign(&message1); + } + } + + let mut zv = ps.tt.clone(); + let mut vic = ps.v.clone(); + vic.mul_assign(&challenge); + zv.add_assign(&vic); + SignatureProof { zsig, zv, a: ps.a } + } } @@ -442,74 +509,13 @@ impl BlindKeyPair { /// computes a blind signature from an existing one pub fn blind(&self, csprng: &mut R, bf: &E::Fr, signature: &Signature) -> Signature { - self.secret.blind(csprng, bf, signature) + self.public.blind(csprng, bf, signature) } /// unblinds a signature given knowledge of blinding factor, t. Output should be /// verifiable with standard signature scheme. pub fn unblind(&self, bf: &E::Fr, signature: &Signature) -> Signature { - let mut H = signature.h; - let mut inv_bf = bf.clone(); - inv_bf.negate(); - - // sigma2 / sigma1 ^ t - H.mul_assign(inv_bf); - H.add_assign(&signature.H); - - Signature { h: signature.h, H: H } - } - - /// verify a blinded signature without unblinding it first - pub fn verify(&self, mpk: &PublicParams, message: &Vec, bf: &E::Fr, signature: &Signature) -> bool { - let mut m = message.clone(); - let t = bf.clone(); - m.push(t); - self.public.verify(mpk, &m, signature) - } - - /// 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, - tOptional: Option>, ttOptional: Option) -> ProofState { - let v = E::Fr::rand(rng); - let blindSig = self.blind(rng, &v, signature); - let mut t = tOptional.unwrap_or(Vec::::with_capacity(self.public.Y2.len())); - let tt = ttOptional.unwrap_or(E::Fr::rand(rng)); - let mut a = E::Fqk::one(); - // TODO: consider optimizations to pairing in loop - for j in 0..self.public.Y2.len() { - 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()); - a.mul_assign(&gy); - } - let mut h = E::pairing(blindSig.h, mpk.g2); - h = h.pow(tt.into_repr()); - a.mul_assign(&h); - ProofState { v, t, tt, a, blindSig } - } - - /// prove knowledge of a signature: response phase - /// returns a proof that can be send to the verifier together with the challenge and the blind signature - pub fn prove_response(&self, ps: &ProofState, challenge: E::Fr, message: &mut Vec) -> SignatureProof { - let mut zsig = ps.t.clone(); - let z_len = zsig.len(); - - for i in 0..message.len() { - if i < z_len { - let mut message1 = message[i]; - message1.mul_assign(&challenge); - zsig[i].add_assign(&message1); - } - } - - let mut zv = ps.tt.clone(); - let mut vic = ps.v.clone(); - vic.mul_assign(&challenge); - zv.add_assign(&vic); - SignatureProof { zsig, zv, a: ps.a } + self.public.unblind(bf, signature) } } @@ -587,9 +593,9 @@ mod tests { 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.public.verify_blind(&mpk, &message1, &t, &blind_sig), true); + assert_eq!(keypair.public.verify_blind(&mpk, &message2, &t, &blind_sig), false); + assert_eq!(keypair.public.verify_blind(&mpk, &message1, &t1, &blind_sig), false); let rand_sig = keypair.rerandomize_signature(&mut rng, &sig); assert_eq!(public_key.verify(&mpk, &message1, &rand_sig), true); @@ -616,7 +622,7 @@ mod tests { assert_eq!(keypair.get_public_key(&mpk).verify(&mpk, &message1, &signature1), true); assert_eq!(keypair.get_public_key(&mpk).verify(&mpk, &message1, &blind_sig), false); - assert_eq!(keypair.verify(&mpk, &message1, &r, &blind_sig), true); + assert_eq!(keypair.public.verify_blind(&mpk, &message1, &r, &blind_sig), true); } #[test] @@ -648,10 +654,10 @@ 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.public.verify_blind(&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.public.verify_blind(&mpk, &message2, &t, &signature), false); + assert_eq!(keypair.public.verify_blind(&mpk, &message1, &t1, &signature), false); } #[test] @@ -671,9 +677,9 @@ mod tests { } let sig = keypair.sign(&mut rng, &message1); - let proof_state = keypair.prove_commitment(rng, &mpk, &sig, None, None); + let proof_state = keypair.public.prove_commitment(rng, &mpk, &sig, None, None); let challenge = Fr::rand(&mut rng); - let proof = keypair.prove_response(&proof_state.clone(), challenge, &mut message1); + let proof = keypair.public.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/ffishim.rs b/src/ffishim.rs index b18eb23..9adbcb7 100644 --- a/src/ffishim.rs +++ b/src/ffishim.rs @@ -95,7 +95,6 @@ pub mod ffishim { let mut channel_state = bidirectional::ChannelState::::new(name.to_string(), tps); let mut rng = &mut rand::thread_rng(); - channel_state.setup(&mut rng); let ser = ["{\'channel_state\':\'", serde_json::to_string(&channel_state).unwrap().as_str(), "\'}"].concat(); let cser = CString::new(ser).unwrap(); cser.into_raw() @@ -112,9 +111,7 @@ pub mod ffishim { let bytes = unsafe { CStr::from_ptr(name_ptr).to_bytes() }; let name: &str = str::from_utf8(bytes).unwrap(); // make sure the bytes are UTF-8 - let (channel_token, mut merch_state) = bidirectional::init_merchant(rng, &mut channel_state, name); - // initialize the balance for merch_state - merch_state.init_balance(balance); + let (channel_token, mut merch_state, mut channel_state) = bidirectional::init_merchant(rng, &mut channel_state, name); let ser = ["{\'channel_token\':\'", serde_json::to_string(&channel_token).unwrap().as_str(), "\', \'merch_state\':\'", serde_json::to_string(&merch_state).unwrap().as_str() ,"\'}"].concat(); diff --git a/src/lib.rs b/src/lib.rs index 7190712..e73af8b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -186,14 +186,14 @@ pub mod bidirectional { /// init_merchant - takes as input the public params, merchant balance and keypair. /// Generates merchant data which consists of channel token and merchant state. /// - pub fn init_merchant<'a, R: Rng, E: Engine>(csprng: &mut R, channel_state: &mut ChannelState, name: &'a str) -> (ChannelToken, MerchantState) { + pub fn init_merchant<'a, R: Rng, E: Engine>(csprng: &mut R, channel_state: &mut ChannelState, name: &'a str) -> (ChannelToken, MerchantState, ChannelState) { // create new merchant state let merch_name = String::from(name); - let mut merch_state = MerchantState::::new(csprng, channel_state, merch_name); + let (mut merch_state, mut channel_state) = MerchantState::::new(csprng, channel_state, merch_name); // initialize the merchant state - let channel_token = merch_state.init(csprng, channel_state); + let channel_token = merch_state.init(csprng, &mut channel_state); - return (channel_token, merch_state); + return (channel_token, merch_state, channel_state.clone()); } /// @@ -231,7 +231,7 @@ pub mod bidirectional { init_cust_balance: i32, init_merch_balance: i32, merch_state: &MerchantState) -> BoltResult> { // verifies proof of committed values and derives blind signature on the committed values to the customer's initial wallet - match merch_state.verify_proof(csprng, channel_state, com, com_proof, init_cust_balance, merch_state.init_balance) { + match merch_state.verify_proof(csprng, channel_state, com, com_proof, init_cust_balance, init_merch_balance) { Ok(n) => Ok(Some(n.0)), // just close token Err(err) => Err(String::from(err.to_string())) } @@ -402,7 +402,7 @@ pub mod bidirectional { let close_token = cust_state.get_close_token(); let cp = channel_state.cp.as_ref().unwrap(); - let pk = cp.pub_params.keypair.get_public_key(&cp.pub_params.mpk); + let pk = cp.pub_params.pk.get_pub_key(); let close_wallet = wallet.with_close(String::from("close")); assert!(pk.verify(&cp.pub_params.mpk, &close_wallet, &close_token)); @@ -435,7 +435,7 @@ pub mod bidirectional { } let cp = channel_state.cp.as_ref().unwrap(); - let pk = cp.pub_params.keypair.get_public_key(&channel_token.mpk); + let pk = cp.pub_params.pk.get_pub_key(); let mut wallet = cust_close.message.clone(); let close_wallet = wallet.with_close(String::from("close")).clone(); let close_token = cust_close.signature.clone(); @@ -532,10 +532,11 @@ mod tests { use ff::Rand; use pairing::bls12_381::{Bls12}; use rand::Rng; + use channels::ChannelState; fn setup_new_channel_helper(channel_state: &mut bidirectional::ChannelState, init_cust_bal: i32, init_merch_bal: i32) - -> (bidirectional::ChannelToken, bidirectional::MerchantState, bidirectional::CustomerState) { + -> (bidirectional::ChannelToken, bidirectional::MerchantState, bidirectional::CustomerState, bidirectional::ChannelState) { let mut rng = &mut rand::thread_rng(); let merch_name = "Bob"; @@ -547,13 +548,12 @@ mod tests { // each party executes the init algorithm on the agreed initial challenge balance // in order to derive the channel tokens // initialize on the merchant side with balance: b0_merch - let (mut channel_token, mut merch_state) = bidirectional::init_merchant(rng, channel_state, merch_name); - merch_state.init_balance(b0_merch); + let (mut channel_token, mut merch_state, mut channel_state) = bidirectional::init_merchant(rng, channel_state, merch_name); // initialize on the customer side with balance: b0_cust - let cust_state = bidirectional::init_customer(rng, channel_state, &mut channel_token, b0_cust, b0_merch, cust_name); + let cust_state = bidirectional::init_customer(rng, &channel_state, &mut channel_token, b0_cust, b0_merch, cust_name); - return (channel_token, merch_state, cust_state); + return (channel_token, merch_state, cust_state, channel_state); } fn execute_establish_protocol_helper(channel_state: &mut bidirectional::ChannelState, @@ -614,16 +614,12 @@ mod tests { let mut channel_state = bidirectional::ChannelState::::new(String::from("Channel A -> B"), false); let mut rng = &mut rand::thread_rng(); - channel_state.setup(&mut rng); // or load_setup params - let total_owed = 40; let b0_customer = 90; let b0_merchant = 20; let payment_increment = 20; - let (mut channel_token, mut merch_state) = bidirectional::init_merchant(rng, &mut channel_state, "Merchant Bob"); - // initialize the balance for merch_state - merch_state.init_balance(b0_merchant); + let (mut channel_token, mut merch_state, mut channel_state) = bidirectional::init_merchant(rng, &mut channel_state, "Merchant Bob"); let mut cust_state = bidirectional::init_customer(rng, &mut channel_state, &mut channel_token, b0_customer, b0_merchant, "Alice"); @@ -682,8 +678,6 @@ mod tests { let mut channel_state = bidirectional::ChannelState::::new(String::from("Channel A -> B"), false); let mut rng = &mut rand::thread_rng(); - channel_state.setup(&mut rng); // or load_setup params - // set fee for channel let fee = 5; channel_state.set_channel_fee(fee); @@ -729,9 +723,7 @@ mod tests { let mut channel_state = bidirectional::ChannelState::::new(String::from("Channel A -> B"), false); let mut rng = &mut rand::thread_rng(); - channel_state.setup(&mut rng); // or load_setup params - - let (mut channel_token, mut merch_state, mut cust_state) = setup_new_channel_helper( &mut channel_state, b0_customer, b0_merchant); + let (mut channel_token, mut merch_state, mut cust_state, mut channel_state) = setup_new_channel_helper( &mut channel_state, b0_customer, b0_merchant); // run establish protocol for customer and merchant channel execute_establish_protocol_helper(&mut channel_state, &mut channel_token, b0_customer, b0_merchant, &mut merch_state, &mut cust_state); @@ -759,9 +751,7 @@ mod tests { let mut channel_state = bidirectional::ChannelState::::new(String::from("Channel A -> B"), false); - channel_state.setup(&mut rng); // or load_setup params - - let (mut channel_token, mut merch_state, mut cust_state) = setup_new_channel_helper( &mut channel_state, b0_customer, b0_merchant); + let (mut channel_token, mut merch_state, mut cust_state, mut channel_state) = setup_new_channel_helper( &mut channel_state, b0_customer, b0_merchant); // run establish protocol for customer and merchant channel execute_establish_protocol_helper(&mut channel_state, &mut channel_token, b0_customer, b0_merchant, &mut merch_state, &mut cust_state); @@ -806,9 +796,7 @@ mod tests { let mut channel_state = bidirectional::ChannelState::::new(String::from("Channel A -> B"), false); - channel_state.setup(&mut rng); // or load_setup params - - let (mut channel_token, mut merch_state, mut cust_state) = setup_new_channel_helper( &mut channel_state, b0_customer, b0_merchant); + let (mut channel_token, mut merch_state, mut cust_state, mut channel_state) = setup_new_channel_helper( &mut channel_state, b0_customer, b0_merchant); // run establish protocol for customer and merchant channel execute_establish_protocol_helper(&mut channel_state, &mut channel_token, b0_customer, b0_merchant, &mut merch_state, &mut cust_state); @@ -935,14 +923,13 @@ mod tests { fn serialization_tests() { let mut channel_state = bidirectional::ChannelState::::new(String::from("Channel A -> B"), false); let mut rng = &mut rand::thread_rng(); - channel_state.setup(&mut rng); let serialized = serde_json::to_string(&channel_state).unwrap(); println!("new channel state len: {}", &serialized.len()); let chan_state: bidirectional::ChannelState = serde_json::from_str(&serialized).unwrap(); - let (mut channel_token, mut merch_state) = bidirectional::init_merchant(rng, &mut channel_state, "Merchant A"); + let (mut channel_token, mut merch_state, mut channel_state) = bidirectional::init_merchant(rng, &mut channel_state, "Merchant A"); let b0_cust = 100; let b0_merch = 10; diff --git a/src/nizk.rs b/src/nizk.rs index 1c63113..d53f618 100644 --- a/src/nizk.rs +++ b/src/nizk.rs @@ -3,11 +3,11 @@ extern crate rand; use super::*; use rand::Rng; -use cl::{Signature, PublicParams, setup, BlindKeyPair, SignatureProof}; +use cl::{Signature, PublicParams, setup, BlindKeyPair, SignatureProof, PublicKey, BlindPublicKey}; use ped92::{Commitment, CSMultiParams, CommitmentProof}; use pairing::{Engine, CurveProjective}; use wallet::Wallet; -use ccs08::{RPPublicParams, RangeProof}; +use ccs08::{RPPublicParams, RPSecretParams, RangeProof}; use serde::{Serialize, Deserialize}; use util; use std::borrow::BorrowMut; @@ -44,25 +44,87 @@ pub struct NIZKProof { ))] pub struct NIZKPublicParams { pub mpk: PublicParams, - pub keypair: BlindKeyPair, + pub pk: BlindPublicKey, pub comParams: CSMultiParams, pub rpParamsBC: RPPublicParams, pub rpParamsBM: RPPublicParams, } -impl NIZKPublicParams { +/// NIZKSecretParams are secret parameters to perform the verification of a NIZK Proof of Knowledge during the payment and closing protocol +#[derive(Clone, Serialize, Deserialize)] +#[serde(bound(serialize = "::Fr: serde::Serialize, \ +::G1: serde::Serialize, \ +::G2: serde::Serialize" +))] +#[serde(bound(deserialize = "::Fr: serde::Deserialize<'de>, \ +::G1: serde::Deserialize<'de>, \ +::G2: serde::Deserialize<'de>" +))] +pub struct NIZKSecretParams { + pub pubParams: NIZKPublicParams, + pub keypair: BlindKeyPair, + pub rpParamsBC: RPSecretParams, + pub rpParamsBM: RPSecretParams, +} + +impl NIZKSecretParams { /// Basic setup for the NIZKPublicParams /// Takes as input a random generator and the length of the message which should be 4 during payment protocol and 5 for the closing protocol pub fn setup(rng: &mut R, messageLength: usize) -> Self { let mpk = setup(rng); let keypair = BlindKeyPair::::generate(rng, &mpk, messageLength); 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()); + let rpParamsBC = RPSecretParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone()); + let rpParamsBM = RPSecretParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone()); + let pubParams = NIZKPublicParams { mpk, pk: keypair.public.clone(), comParams, rpParamsBC: rpParamsBC.pubParams.clone(), rpParamsBM: rpParamsBM.pubParams.clone() }; - NIZKPublicParams { mpk, keypair, comParams, rpParamsBC, rpParamsBM } + NIZKSecretParams{pubParams, keypair, rpParamsBC, rpParamsBM} } + /** + Verify a NIZK Proof of Knowledge during payment or closing protocol + Input: + proof: A NIZK proof created by the Customer + epsilon: The transaction amount of the payment + com: Commitment of the new wallet that needs to be signed + wpk: reveal of wallet public key of the old wallet. + */ + pub fn verify(&self, proof: NIZKProof, epsilon: E::Fr, com: &Commitment, wpk: E::Fr) -> bool { + //verify signature is not the identity + let r0 = proof.sig.h != E::G1::one(); + + //compute challenge + let challenge = NIZKPublicParams::::hash(proof.sigProof.a, vec! {proof.comProof.T, proof.rpBC.p1.D, proof.rpBC.p2.D, proof.rpBM.p1.D, proof.rpBM.p2.D}); + + //verify knowledge of signature + let mut r1 = self.keypair.public.verify_proof(&self.pubParams.mpk, proof.sig, proof.sigProof.clone(), challenge); + let mut wpkc = wpk.clone(); + wpkc.mul_assign(&challenge.clone()); + r1 = r1 && proof.sigProof.zsig[1] == wpkc; + + //verify knowledge of commitment + let r2 = proof.comProof.verify_proof(&self.pubParams.comParams, &com.c.clone(), &challenge); + + //verify range proofs + let r3 = self.rpParamsBC.verify(proof.rpBC.clone(), challenge.clone(), 3); + let r4 = self.rpParamsBM.verify(proof.rpBM.clone(), challenge.clone(), 4); + + //verify linear relationship + let mut r5 = proof.comProof.z[1] == proof.sigProof.zsig[0]; + let mut zsig2 = proof.sigProof.zsig[2].clone(); + let mut epsC = epsilon.clone(); + epsC.mul_assign(&challenge.clone()); + zsig2.sub_assign(&epsC.clone()); + r5 = r5 && proof.comProof.z[3] == zsig2; + let mut zsig3 = proof.sigProof.zsig[3].clone(); + zsig3.add_assign(&epsC.clone()); + r5 = r5 && proof.comProof.z[4] == zsig3; + + r0 && r1 && r2 && r3 && r4 && r5 + } +} + +impl NIZKPublicParams { /** This method can be called to create the proof during the payment and closing protocol Input: rng: random generator @@ -93,7 +155,7 @@ impl NIZKPublicParams { true => Some(vec!(t[1], zero, t[3].clone(), t[4].clone())), false => Some(vec!(t[1], zero, t[3].clone())) }; - let proofState = self.keypair.prove_commitment(rng, &self.mpk, &paymentToken, tOptional, None); + let proofState = self.pk.prove_commitment(rng, &self.mpk, &paymentToken, tOptional, None); //commit range proof let rpStateBC = self.rpParamsBC.prove_commitment(rng, newWallet.bc.clone(), newWalletCom.clone(), 3, None, None); @@ -105,7 +167,7 @@ impl NIZKPublicParams { //Response phase //response for signature let oldWalletVec = oldWallet.as_fr_vec(); - let sigProof = self.keypair.prove_response(&proofState, challenge, &mut oldWalletVec.clone()); + let sigProof = self.pk.prove_response(&proofState, challenge, &mut oldWalletVec.clone()); //response commitment let newWalletVec = newWallet.as_fr_vec(); @@ -128,48 +190,6 @@ impl NIZKPublicParams { NIZKProof { sig: proofState.blindSig, sigProof, comProof, rpBC, rpBM } } - /** - Verify a NIZK Proof of Knowledge during payment or closing protocl - Input: - proof: A NIZK proof created by the Customer - epsilon: The transaction amount of the payment - com: Commitment of the new wallet that needs to be signed - wpk: reveal of wallet public key of the old wallet. - */ - pub fn verify(&self, proof: NIZKProof, epsilon: E::Fr, com: &Commitment, wpk: E::Fr) -> bool { - //verify signature is not the identity - let r0 = proof.sig.h != E::G1::one(); - - //compute challenge - let challenge = NIZKPublicParams::::hash(proof.sigProof.a, vec! {proof.comProof.T, proof.rpBC.p1.D, proof.rpBC.p2.D, proof.rpBM.p1.D, proof.rpBM.p2.D}); - - //verify knowledge of signature - let mut r1 = self.keypair.public.verify_proof(&self.mpk, proof.sig, proof.sigProof.clone(), challenge); - let mut wpkc = wpk.clone(); - wpkc.mul_assign(&challenge.clone()); - r1 = r1 && proof.sigProof.zsig[1] == wpkc; - - //verify knowledge of commitment - let r2 = proof.comProof.verify_proof(&self.comParams, &com.c.clone(), &challenge); - - //verify range proofs - let r3 = self.rpParamsBC.verify(proof.rpBC.clone(), challenge.clone(), 3); - let r4 = self.rpParamsBM.verify(proof.rpBM.clone(), challenge.clone(), 4); - - //verify linear relationship - let mut r5 = proof.comProof.z[1] == proof.sigProof.zsig[0]; - let mut zsig2 = proof.sigProof.zsig[2].clone(); - let mut epsC = epsilon.clone(); - epsC.mul_assign(&challenge.clone()); - zsig2.sub_assign(&epsC.clone()); - r5 = r5 && proof.comProof.z[3] == zsig2; - let mut zsig3 = proof.sigProof.zsig[3].clone(); - zsig3.add_assign(&epsC.clone()); - r5 = r5 && proof.comProof.z[4] == zsig3; - - r0 && r1 && r2 && r3 && r4 && r5 - } - fn hash(a: E::Fqk, T: Vec) -> E::Fr { let mut x_vec: Vec = Vec::new(); x_vec.extend(format!("{}", a).bytes()); @@ -245,18 +265,18 @@ mod tests { let r = Fr::rand(rng); let rprime = Fr::rand(rng); - let pubParams = NIZKPublicParams::::setup(rng, 4); + let secParams = NIZKSecretParams::::setup(rng, 4); let wallet1 = Wallet { pkc, wpk, bc, bm, close: None }; - let commitment1 = pubParams.comParams.commit(&wallet1.as_fr_vec(), &r); + let commitment1 = secParams.pubParams.comParams.commit(&wallet1.as_fr_vec(), &r); let wallet2 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2, close: None }; - 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 commitment2 = secParams.pubParams.comParams.commit(&wallet2.as_fr_vec(), &rprime); + let blindPaymentToken = secParams.keypair.sign_blind(rng, &secParams.pubParams.mpk, commitment1.clone()); + let paymentToken = secParams.keypair.unblind(&r, &blindPaymentToken); - let proof = pubParams.prove(rng, wallet1, wallet2, + let proof = secParams.pubParams.prove(rng, wallet1, wallet2, commitment2.clone(), rprime, &paymentToken); let fr = convert_int_to_fr::(*epsilon); - assert_eq!(pubParams.verify(proof, fr, &commitment2, wpk), true); + assert_eq!(secParams.verify(proof, fr, &commitment2, wpk), true); } #[test] @@ -275,18 +295,18 @@ mod tests { let r = Fr::rand(rng); let rprime = Fr::rand(rng); - let pubParams = NIZKPublicParams::::setup(rng, 4); + let secParams = NIZKSecretParams::::setup(rng, 4); let wallet1 = Wallet { pkc, wpk, bc, bm, close: None }; - let commitment1 = pubParams.comParams.commit(&wallet1.as_fr_vec(), &r); + let commitment1 = secParams.pubParams.comParams.commit(&wallet1.as_fr_vec(), &r); let wallet2 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2, close: None }; - 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 commitment2 = secParams.pubParams.comParams.commit(&wallet2.as_fr_vec(), &rprime); + let blindPaymentToken = secParams.keypair.sign_blind(rng, &secParams.pubParams.mpk, commitment1.clone()); + let paymentToken = secParams.keypair.unblind(&r, &blindPaymentToken); - let proof = pubParams.prove(rng, wallet1, wallet2, + let proof = secParams.pubParams.prove(rng, wallet1, wallet2, commitment2.clone(), rprime, &paymentToken); let fr = convert_int_to_fr::(*epsilon); - assert_eq!(pubParams.verify(proof, fr, &commitment2, wpk), true); + assert_eq!(secParams.verify(proof, fr, &commitment2, wpk), true); } #[test] @@ -306,28 +326,28 @@ mod tests { let rprime = Fr::rand(rng); let _closeToken = Fr::rand(rng); - let pubParams = NIZKPublicParams::::setup(rng, 5); + let secParams = NIZKSecretParams::::setup(rng, 5); let wallet1 = Wallet { pkc, wpk, bc, bm, close: None }; - let commitment1 = pubParams.comParams.commit(&wallet1.as_fr_vec(), &r); + let commitment1 = secParams.pubParams.comParams.commit(&wallet1.as_fr_vec(), &r); let wallet2 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2, close: Some(_closeToken) }; - 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 commitment2 = secParams.pubParams.comParams.commit(&wallet2.as_fr_vec(), &rprime); + let blindPaymentToken = secParams.keypair.sign_blind(rng, &secParams.pubParams.mpk, commitment1.clone()); + let paymentToken = secParams.keypair.unblind(&r, &blindPaymentToken); - let blindCloseToken = pubParams.keypair.sign_blind(rng, &pubParams.mpk, commitment2.clone()); - let closeToken = pubParams.keypair.unblind(&rprime, &blindCloseToken); + let blindCloseToken = secParams.keypair.sign_blind(rng, &secParams.pubParams.mpk, commitment2.clone()); + let closeToken = secParams.pubParams.pk.unblind(&rprime, &blindCloseToken); // verify the blind signatures - let pk = pubParams.keypair.get_public_key(&pubParams.mpk); - assert!(pk.verify(&pubParams.mpk, &wallet1.as_fr_vec(), &paymentToken)); + let pk = secParams.keypair.get_public_key(&secParams.pubParams.mpk); + assert!(pk.verify(&secParams.pubParams.mpk, &wallet1.as_fr_vec(), &paymentToken)); println!("close => {}", &wallet2); - assert!(pk.verify(&pubParams.mpk, &wallet2.as_fr_vec(), &closeToken)); + assert!(pk.verify(&secParams.pubParams.mpk, &wallet2.as_fr_vec(), &closeToken)); - let proof = pubParams.prove(rng, wallet1, wallet2, + let proof = secParams.pubParams.prove(rng, wallet1, wallet2, commitment2.clone(), rprime, &paymentToken); - assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), true); + assert_eq!(secParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), true); } #[test] @@ -346,28 +366,28 @@ mod tests { let r = Fr::rand(rng); let rprime = Fr::rand(rng); - let pubParams = NIZKPublicParams::::setup(rng, 4); + let secParams = NIZKSecretParams::::setup(rng, 4); let wallet1 = Wallet { pkc, wpk, bc, bm, close: None }; let bc2Prime = bc.clone(); let wallet3 = Wallet { pkc, wpk: wpkprime, bc: bc2Prime, bm: bm2, close: None }; - 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, wallet1.clone(), wallet3, commitment2.clone(), rprime, &paymentToken); - assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), false); + let commitment1 = secParams.pubParams.comParams.commit(&wallet1.as_fr_vec().clone(), &r); + let commitment2 = secParams.pubParams.comParams.commit(&wallet3.as_fr_vec(), &rprime); + let blindPaymentToken = secParams.keypair.sign_blind(rng, &secParams.pubParams.mpk, commitment1.clone()); + let paymentToken = secParams.keypair.unblind(&r, &blindPaymentToken); + let proof = secParams.pubParams.prove(rng, wallet1.clone(), wallet3, commitment2.clone(), rprime, &paymentToken); + assert_eq!(secParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), false); let bm2Prime = bm.clone(); let wallet4 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2Prime, close: None }; - let commitment2 = pubParams.comParams.commit(&wallet4.as_fr_vec(), &rprime); - let proof = pubParams.prove(rng, wallet1.clone(), wallet4, commitment2.clone(), rprime, &paymentToken); - assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), false); + let commitment2 = secParams.pubParams.comParams.commit(&wallet4.as_fr_vec(), &rprime); + let proof = secParams.pubParams.prove(rng, wallet1.clone(), wallet4, commitment2.clone(), rprime, &paymentToken); + assert_eq!(secParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), false); let wallet5 = Wallet { pkc: Fr::rand(rng), wpk: wpkprime, bc: bc2, bm: bm2, close: None }; - let commitment2 = pubParams.comParams.commit(&wallet5.as_fr_vec(), &rprime); - let proof = pubParams.prove(rng, wallet1.clone(), wallet5, commitment2.clone(), rprime, &paymentToken); - assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), false); + let commitment2 = secParams.pubParams.comParams.commit(&wallet5.as_fr_vec(), &rprime); + let proof = secParams.pubParams.prove(rng, wallet1.clone(), wallet5, commitment2.clone(), rprime, &paymentToken); + assert_eq!(secParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), false); } #[test] @@ -381,13 +401,13 @@ mod tests { let bm = rng.gen_range(100, 1000); let wallet = Wallet:: { pkc: pkc, wpk: wpk, bc: bc, bm: bm, close: None }; - let pubParams = NIZKPublicParams::::setup(rng, 4); - let com = pubParams.comParams.commit(&wallet.as_fr_vec().clone(), &t); + let secParams = NIZKSecretParams::::setup(rng, 4); + let com = secParams.pubParams.comParams.commit(&wallet.as_fr_vec().clone(), &t); - let com_proof = CommitmentProof::::new(rng, &pubParams.comParams, + let com_proof = CommitmentProof::::new(rng, &secParams.pubParams.comParams, &com.c, &wallet.as_fr_vec(), &t, &vec![1, 3, 4]); - assert!(verify_opening(&pubParams.comParams, &com.c, &com_proof, bc, bm)); + assert!(verify_opening(&secParams.pubParams.comParams, &com.c, &com_proof, bc, bm)); } #[test] @@ -403,15 +423,15 @@ mod tests { let wallet1 = Wallet:: { pkc: pkc, wpk: wpk, bc: bc, bm: bm, close: None }; let wallet2 = Wallet:: { pkc: pkc, wpk: wpk, bc: bc2, bm: bm, close: None }; - let pubParams = NIZKPublicParams::::setup(rng, 4); - let com1 = pubParams.comParams.commit(&wallet1.as_fr_vec().clone(), &t); - let com2 = pubParams.comParams.commit(&wallet2.as_fr_vec().clone(), &t); + let secParams = NIZKSecretParams::::setup(rng, 4); + let com1 = secParams.pubParams.comParams.commit(&wallet1.as_fr_vec().clone(), &t); + let com2 = secParams.pubParams.comParams.commit(&wallet2.as_fr_vec().clone(), &t); - let com1_proof = CommitmentProof::::new(rng, &pubParams.comParams, + let com1_proof = CommitmentProof::::new(rng, &secParams.pubParams.comParams, &com1.c, &wallet1.as_fr_vec(), &t, &vec![1, 3, 4]); - assert!(verify_opening(&pubParams.comParams, &com1.c, &com1_proof, bc, bm)); - assert!(!verify_opening(&pubParams.comParams, &com2.c, &com1_proof, bc2, bm)); + assert!(verify_opening(&secParams.pubParams.comParams, &com1.c, &com1_proof, bc, bm)); + assert!(!verify_opening(&secParams.pubParams.comParams, &com2.c, &com1_proof, bc2, bm)); } @@ -423,10 +443,10 @@ mod tests { let mpk = setup(&mut rng); let blindkeypair = BlindKeyPair::::generate(&mut rng, &mpk, l); let comParams = blindkeypair.generate_cs_multi_params(&mpk); - let rpParamsBC = ccs08::RPPublicParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone()); - let rpParamsBM = ccs08::RPPublicParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone()); + let rpParamsBC = ccs08::RPSecretParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone()); + let rpParamsBM = ccs08::RPSecretParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone()); - let nizk_params = NIZKPublicParams { mpk: mpk, keypair: blindkeypair, comParams: comParams, rpParamsBC: rpParamsBC, rpParamsBM: rpParamsBM }; + let nizk_params = NIZKPublicParams { mpk: mpk, pk: blindkeypair.public, comParams: comParams, rpParamsBC: rpParamsBC.pubParams, rpParamsBM: rpParamsBM.pubParams }; let is_serialized = serde_json::to_vec(&nizk_params).unwrap(); println!("NIZK Struct len: {}", is_serialized.len());