/* Implementation of the ZK Range Proof scheme, based on: Efficient Protocols for Set Membership and Range Proofs Jan Camenisch, Rafik Chaabouni, and abhi shelat Asiacrypt 2008 */ use super::*; use rand::Rng; use cl::{Signature, PublicParams, setup, BlindKeyPair, ProofState, SignatureProof, BlindPublicKey}; use ped92::{Commitment, CSMultiParams}; use pairing::{Engine, CurveProjective}; use ff::PrimeField; use std::collections::HashMap; /** 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>"))] pub struct ParamsUL { pub mpk: PublicParams, pub signatures: HashMap>, pub csParams: CSMultiParams, 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. u: i64, // 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, } /** 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>"))] pub struct SecretParamsUL { pub pubParams: ParamsUL, pub kp: BlindKeyPair, } #[derive(Clone)] 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, Serialize, Deserialize)] #[serde(bound(serialize = "::Fr: serde::Serialize, \ ::G1: serde::Serialize, \ ::G2: serde::Serialize, \ ::Fqk: serde::Serialize" ))] #[serde(bound(deserialize = "::Fr: serde::Deserialize<'de>, \ ::G1: serde::Deserialize<'de>, \ ::G2: serde::Deserialize<'de>, \ ::Fqk: serde::Deserialize<'de>" ))] 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 { pub com1: Commitment, pub ps1: ProofULState, pub com2: Commitment, pub ps2: ProofULState, } /** RangeProof contains the necessary elements for the ZK range proof. */ #[derive(Clone, Serialize, Deserialize)] #[serde(bound(serialize = "::Fr: serde::Serialize, \ ::G1: serde::Serialize, \ ::G2: serde::Serialize, \ ::Fqk: serde::Serialize" ))] #[serde(bound(deserialize = "::Fr: serde::Deserialize<'de>, \ ::G1: serde::Deserialize<'de>, \ ::G2: serde::Deserialize<'de>, \ ::Fqk: serde::Deserialize<'de>" ))] pub struct RangeProof { pub p1: ProofUL, pub p2: ProofUL, } /** 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 RPPublicParams { pub p: ParamsUL, pub a: i64, pub b: i64, } /** 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, pub 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 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 { let mpk = setup(rng); let kp = BlindKeyPair::::generate(rng, &mpk, 1); let mut signatures: HashMap> = HashMap::new(); for i in 0..u { 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 }; 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 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). */ 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, None, None); // 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, k, otherM) } pub fn prove_ul_commitment(&self, rng: &mut R, x: i64, k: usize, sOptional: Option>, mOptional: Option) -> ProofULState { if x > ((self.u as i128).pow(self.l as u32) - 1) as i64 || x < 0 { panic!("x is not within the range."); } let decx = decompose(x, self.u, self.l); // 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 = mOptional.unwrap_or(E::Fr::rand(rng)); // D = H^m 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(); 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.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); } D.add_assign(&aux); } let sVec = sOptional.unwrap_or(Vec::::with_capacity(0)); 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; if sVec.len() >= i { s1 = sVec[i-1]; } else { 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, s } } pub 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(); rc.mul_assign(&c); zr.add_assign(&rc); for i in 0..self.l as usize { let dx = E::Fr::from_str(&proofUlState.decx[i].to_string()).unwrap(); let proof = self.pk.prove_response(&proofUlState.proofStates[i].clone(), c, &mut vec! {dx}); sigProofs.push(proof); } let mut zs = Vec::::with_capacity(self.csParams.pub_bases.len() - 2); 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 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 } } } fn hash(a: Vec, D: Vec) -> E::Fr { // create a Sha256 object let mut a_vec: Vec = Vec::new(); for a_el in a { a_vec.extend(format!("{}", a_el).bytes()); } let mut x_vec: Vec = Vec::new(); for d_el in D { x_vec.extend(format!("{}", d_el).bytes()); } a_vec.extend(x_vec); util::hash_to_fr::(a_vec) } /* 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 { let mut result = Vec::with_capacity(l as usize); let mut decomposer = x.clone(); for _i in 0..l { result.push(decomposer % u); decomposer = decomposer / u; } return result; } impl RPSecretParams { /** 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 if a > b { panic!("a must be less than or equal to b"); } let logb = (b as f32).log2(); let loglogb = logb.log2(); if loglogb > 0.0 { // let mut u = (logb / loglogb) as i64; let u = 57; //TODO: optimize u? let l = (b as f64).log(u as f64).ceil() as i64; 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. */ 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, None, None); 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_response(r, &rpState, ch, k, otherM) } pub fn prove_commitment(&self, rng: &mut R, x: i64, C: Commitment, k: usize, sOptional: Option>, mOptional: Option) -> 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.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.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, k, sOptional.clone(), mOptional.clone()); // x - a let xa = x - self.a; 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, k, sOptional.clone(), mOptional.clone()); RangeProofState { com1: comXB, ps1: firstState, com2: comXA, ps2: secondState } } 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 } } } #[cfg(test)] mod tests { use super::*; use pairing::bls12_381::{Bls12, G1, Fr}; use time::PreciseTime; use std::ops::Add; use core::mem; use rand::rngs::ThreadRng; #[test] fn setup_ul_works() { let rng = &mut rand::thread_rng(); let csParams = CSMultiParams::setup_gen_params(rng, 1); 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); } } #[test] fn prove_ul_works() { let rng = &mut rand::thread_rng(); let csParams = CSMultiParams::setup_gen_params(rng, 1); 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 = secParams.pubParams.prove_ul(rng, 10, fr, C, 1, vec!{}); assert_eq!(proof.V.len(), 4); assert_eq!(proof.sigProofs.len(), 4); } #[test] #[should_panic(expected = "x is not within the range")] fn prove_ul_not_in_range() { let rng = &mut rand::thread_rng(); let csParams = CSMultiParams::setup_gen_params(rng, 1); 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()); 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 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 = secParams.pubParams.prove_ul(rng, 10, fr, C, 1, vec!{}); let ch = compute_challenge(secParams.pubParams.clone(), &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 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 = secParams.pubParams.prove_ul(rng, 10, fr, C, 1, vec!{}); let ch = compute_challenge(secParams.pubParams.clone(), &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 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 = secParams.pubParams.prove_ul(rng, 10, fr, C, 1, vec!{}); let ch = compute_challenge(secParams.pubParams.clone(), &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 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 = secParams.pubParams.prove_ul(rng, 10, fr, C, 2, vec!{fr1, fr2}); let ch = compute_challenge(secParams.pubParams.clone(), &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 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 = secParams.pubParams.prove(rng, 10, C, fr, 1, vec!{}); let ch = secParams.compute_challenge(&proof); 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 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 = secParams.pubParams.prove(rng, 10, C, fr, 2, vec!{fr1, fr2}); let ch = secParams.compute_challenge(&proof); assert_eq!(secParams.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 = CSMultiParams::setup_gen_params(rng, 1); 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()); secParams.pubParams.prove(rng, 26, C, fr, 1, vec!{}); } #[test] #[ignore] fn prove_and_verify_performance() { let rng = &mut rand::thread_rng(); let mut averageSetup = time::Duration::nanoseconds(0); let mut averageSetupSize = 0; let mut averageProve = time::Duration::nanoseconds(0); let mut averageProofSize = 0; let mut averageVerify = time::Duration::nanoseconds(0); let iter = 5; for _i in 0..iter { let a = rng.gen_range(0, 1000000); let b = rng.gen_range(a, 1000000); let x = rng.gen_range(a, b); let sSetup = PreciseTime::now(); let csParams = CSMultiParams::setup_gen_params(rng, 1); let secParams = RPSecretParams::::setup(rng, a, b, csParams.clone()); averageSetup = averageSetup.add(sSetup.to(PreciseTime::now())); 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 = 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 = secParams.compute_challenge(&proof); secParams.verify(proof, ch, 1); averageVerify = averageVerify.add(sVerify.to(PreciseTime::now())); } print!("Setup: {}\n", averageSetup.num_milliseconds() / iter); print!("Setup size: {}\n", averageSetupSize / iter as usize); print!("Prove: {}\n", averageProve.num_milliseconds() / iter); print!("Proof size: {}\n", averageProofSize / iter as usize); print!("Verify: {}\n", averageVerify.num_milliseconds() / iter); } #[test] fn decompose_works() { assert_eq!(decompose(25, 3, 3), vec! {1, 2, 2}); assert_eq!(decompose(336, 7, 3), vec! {0, 6, 6}); assert_eq!(decompose(285, 8, 3), vec! {5, 3, 4}); assert_eq!(decompose(125, 13, 2), vec! {8, 9}); assert_eq!(decompose(143225, 6, 7), vec! {5, 2, 0, 3, 2, 0, 3}); } #[test] fn decompose_recompose_works() { let vec1 = decompose(25, 3, 5); let mut result = 0; for i in 0..5 { result += vec1[i] * 3i64.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); } assert_eq!(result, 143225); } #[test] fn setup_works() { let rng = &mut rand::thread_rng(); let csParams = CSMultiParams::setup_gen_params(rng, 1); 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!(secParams.p.kp.public.verify_blind(&public_params.p.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &Fr::zero(), &s), true); } } #[test] #[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 = CSMultiParams::setup_gen_params(rng, 1); RPSecretParams::::setup(rng, 10, 2, csParams); } #[test] #[should_panic(expected = "log(log(b)) is zero")] fn setup_wrong_logb() { let rng = &mut rand::thread_rng(); let csParams = CSMultiParams::setup_gen_params(rng, 1); RPSecretParams::::setup(rng, -2, -1, csParams); } #[test] fn hash_works() { let rng = &mut rand::thread_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); let m2 = Fr::rand(rng); let sig = kp.sign(rng, &vec! {m1, m2}); 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); 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()))) } fn compute_challenge(pubParams: ParamsUL, proof: &ProofUL) -> E::Fr { let mut a = Vec::::with_capacity(pubParams.l as usize); for sigProof in proof.sigProofs.clone() { a.push(sigProof.a); } hash::(a, vec!(proof.D.clone())) } }