From 37ab55bc72e57abd4ac6d3d31f87bfe4259f7520 Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Fri, 14 Jun 2019 18:14:06 -0400 Subject: [PATCH 01/11] ccs08: basics for ccs08 implementation --- src/ccs08.rs | 249 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 2 files changed, 250 insertions(+) create mode 100644 src/ccs08.rs diff --git a/src/ccs08.rs b/src/ccs08.rs new file mode 100644 index 0000000..7f9743c --- /dev/null +++ b/src/ccs08.rs @@ -0,0 +1,249 @@ +/* +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 +*/ +extern crate pairing; +extern crate rand; + +use super::*; +use cl::{KeyPair, Signature, PublicParams, setup}; +use pairing::Engine; +use std::collections::HashMap; +use rand::Rng; +use ff::PrimeField; +use commit_scheme::{ped92_setup, ped92_commit, ped92_decommit, Commitment}; + +/* +paramsUL contains elements generated by the verifier, which are necessary for the prover. +This must be computed in a trusted setup. +*/ +#[derive(Clone)] +struct ParamsUL { + pub mpk: PublicParams, + pub signatures: Vec<(i64, Signature)>, + pub h: E::G2, + kp: KeyPair, + // 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, +} + +/* +proofUL contains the necessary elements for the ZK range proof. +*/ +#[derive(Clone)] +struct ProofUL { + v: Vec, + d: E::G2, + comm: Commitment, + a: Vec, + s: Vec, + t: Vec, + zsig: Vec, + zv: Vec, + ch: E::Fr, + m: E::Fr, + zr: E::Fr, +} + +#[derive(Clone)] +pub struct RangeProof { + p1: ProofUL, + 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)] +pub struct RPPublicParams { + p: ParamsUL, + a: i64, + b: i64, +} + +/* +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. +*/ +fn setup_ul(u: i64, l: i64) -> ParamsUL { + let mut rng = &mut rand::thread_rng(); + + let mpk = setup(&mut rng); + let kp = KeyPair::::generate(&mut rng, &mpk, 1); + + let mut signatures: Vec<(i64, Signature)> = Vec::new(); + for i in 0..u { + let sig_i = kp.sign(&mut rng, &vec! {E::Fr::from_str(i.to_string().as_str()).unwrap()}); + signatures.push((i, sig_i)); + } + + let h = E::G2::rand(rng); + return ParamsUL { mpk, signatures, h, kp, u, l }; +} + +/* +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) -> Vec { + let l = (x as f64).log(u as f64).ceil() as usize; + 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; +} + +///* +//prove_ul method is used to produce the ZKRP proof that secret x belongs to the interval [0,U^L]. +//*/ +//fn prove_ul(x: E::Fr, r: E::Fr, p: ParamsUL) -> ProofUL { +// let decx = decompose(x, p.u); +// +//// Initialize variables +// let mut v = Vec::::with_capacity(p.l as usize); +// let mut V = Vec::::with_capacity(p.l as usize); +// let mut a = Vec::::with_capacity(p.l as usize); +// let mut s = Vec::::with_capacity(p.l as usize); +// let mut t = Vec::::with_capacity(p.l as usize); +// let mut zsig = Vec::::with_capacity(p.l as usize); +// let mut zv = Vec::::with_capacity(p.l as usize); +// let mut one: E::G2::one(); +// let mut D = E::G2::zero().add_assign(one.negate()); +// let mut m = rand.Int(rand.Reader, bn256.Order); +// +//// D = H^m +// D = new(bn256.G2).ScalarMult(p.H, proof_out.m); +// for i in 0..p.l { +// v.push(rand.Int(rand.Reader, bn256.Order)); +// let A = p.signatures[strconv.FormatInt(decx[i], 10)]; +// V.push(new(bn256.G2).ScalarMult(A, v[i])); +// s.push(rand.Int(rand.Reader, bn256.Order)); +// t.push(rand.Int(rand.Reader, bn256.Order)); +// a.push(bn256.Pair(G1, proof_out.V[i])); +// a[i].ScalarMult(proof_out.a[i], proof_out.s[i]); +// a[i].Invert(proof_out.a[i]); +// a[i].Add(proof_out.a[i], new(bn256.GT).ScalarMult(E, proof_out.t[i])); +// +// let ui = new(big.Int).Exp(new(big.Int).SetInt64(p.u), new(big.Int).SetInt64(i), nil); +// let mut muisi = new(big.Int).Mul(proof_out.s[i], ui); +// muisi = Mod(muisi, bn256.Order); +// let aux = new(bn256.G2).ScalarBaseMult(muisi); +// D.Add(D, aux); +// } +// proof_out.D.Add(proof_out.D, D); +// +//// Consider passing C as input, +//// so that it is possible to delegate the commitment computation to an external party. +// let C = ped92_commit(p.H, x, r); //TODO: commit +//// Fiat-Shamir heuristic +// let mut c = Hash(proof_out.a, proof_out.D); +// c = Mod(proof_out.c, bn256.Order); +// +// let mut zr = Sub(proof_out.m, Multiply(r, proof_out.c)); +// zr = Mod(proof_out.zr, bn256.Order); +// for i in 0..p.l { +// proof_out.zsig[i] = Sub(proof_out.s[i], Multiply(new(big.Int).SetInt64(decx[i]), proof_out.c)); +// proof_out.zsig[i] = Mod(proof_out.zsig[i], bn256.Order); +// proof_out.zv[i] = Sub(proof_out.t[i], Multiply(v[i], proof_out.c)); +// proof_out.zv[i] = Mod(proof_out.zv[i], bn256.Order); +// } +// return ProofUL {v, d: D, comm: C, a, s, t, zsig, zv, ch: c, m, zr}; +//} + + +/* +Setup receives integers a and b, and configures the parameters for the rangeproof scheme. +*/ +pub fn ccs08_setup(a: i64, b: i64) -> RPPublicParams { + // Compute optimal values for u and l + if a > b { + panic!("a must be less than or equal to b"); + } + let p: PublicParams; + let logb = (b as f64).log10(); + if logb != 0.0 { + let u = b / logb as i64; + if u != 0 { + let l = (b as f64).log(u as f64).ceil() as i64; + let params_out: ParamsUL = setup_ul(u, l); + return RPPublicParams { p: params_out, a, b }; + } else { + panic!("u is zero"); + } + } else { + panic!("log(b) is zero"); + } +} + + +#[cfg(test)] +mod tests { + use super::*; + use pairing::bls12_381::{Bls12, Fr}; + + #[test] + fn setup_ul_works() { + let mut rng = &mut rand::thread_rng(); + let params_set = setup_ul::(2, 3); + assert_eq!(2, params_set.signatures.len()); + for (m, s) in params_set.signatures { + assert_eq!(true, params_set.kp.verify(¶ms_set.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &s)); + } + } + + #[test] + fn decompose_works() { + assert_eq!(vec! {1, 2, 2}, decompose(25, 3)); + assert_eq!(vec! {0, 6, 6}, decompose(336, 7)); + assert_eq!(vec! {5, 3, 4}, decompose(285, 8)); + assert_eq!(vec! {8, 9}, decompose(125, 13)); + assert_eq!(vec! {5, 2, 0, 3, 2, 0, 3}, decompose(143225, 6)); + } + + #[test] + fn setup_works() { + let mut rng = &mut rand::thread_rng(); + let public_params = ccs08_setup::(2, 10); + assert_eq!(2, public_params.a); + assert_eq!(10, public_params.b); + assert_eq!(10, public_params.p.signatures.len()); + assert_eq!(10 / ((10 as f64).log10() as i64), public_params.p.u); + assert_eq!(((10 / (10 / ((10 as f64).log10() as i64))) as f64).ceil() as i64, public_params.p.l); + for (m, s) in public_params.p.signatures { + assert_eq!(true, public_params.p.kp.verify(&public_params.p.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &s)); + } + } + + #[test] + #[should_panic(expected = "a must be less than or equal to b")] + fn setup_wrong_a_and_b() { + let mut rng = &mut rand::thread_rng(); + let public_params = ccs08_setup::(10, 2); + } + + #[test] + #[should_panic(expected = "u is zero")] + fn setup_wrong_b() { + let mut rng = &mut rand::thread_rng(); + let public_params = ccs08_setup::(-1, 0); + } + + #[test] + #[should_panic(expected = "log(b) is zero")] + fn setup_wrong_logb() { + let mut rng = &mut rand::thread_rng(); + let public_params = ccs08_setup::(-1, 1); + } +} diff --git a/src/lib.rs b/src/lib.rs index 935a22a..226f018 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,6 +64,7 @@ pub mod sym; pub mod ote; pub mod cl; pub mod clsigs; +pub mod ccs08; pub mod commit_scheme; pub mod clproto; pub mod serialization_wrappers; From 497adf2455a50b63b4bfdcab5e39179a06f2e6e6 Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Sun, 16 Jun 2019 12:27:35 -0400 Subject: [PATCH 02/11] ccs08: prove_ul first draft --- src/ccs08.rs | 167 ++++++++++++++++++++++++++++++--------------------- src/ped92.rs | 6 +- 2 files changed, 102 insertions(+), 71 deletions(-) diff --git a/src/ccs08.rs b/src/ccs08.rs index 7f9743c..07017cc 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -9,11 +9,11 @@ extern crate rand; use super::*; use cl::{KeyPair, Signature, PublicParams, setup}; -use pairing::Engine; -use std::collections::HashMap; -use rand::Rng; +use ped92::{CSPublicKey, Commitment}; +use pairing::{Engine, CurveProjective}; use ff::PrimeField; -use commit_scheme::{ped92_setup, ped92_commit, ped92_decommit, Commitment}; +use std::collections::HashMap; +use std::fmt::Display; /* paramsUL contains elements generated by the verifier, which are necessary for the prover. @@ -22,8 +22,8 @@ This must be computed in a trusted setup. #[derive(Clone)] struct ParamsUL { pub mpk: PublicParams, - pub signatures: Vec<(i64, Signature)>, - pub h: E::G2, + pub signatures: HashMap>, + pub com: CSPublicKey, kp: KeyPair, // 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. @@ -40,9 +40,9 @@ proofUL contains the necessary elements for the ZK range proof. */ #[derive(Clone)] struct ProofUL { - v: Vec, + v: Vec, d: E::G2, - comm: Commitment, + comm: Commitment, a: Vec, s: Vec, t: Vec, @@ -80,14 +80,14 @@ fn setup_ul(u: i64, l: i64) -> ParamsUL { let mpk = setup(&mut rng); let kp = KeyPair::::generate(&mut rng, &mpk, 1); - let mut signatures: Vec<(i64, Signature)> = Vec::new(); + let mut signatures: HashMap> = HashMap::new(); for i in 0..u { let sig_i = kp.sign(&mut rng, &vec! {E::Fr::from_str(i.to_string().as_str()).unwrap()}); - signatures.push((i, sig_i)); + signatures.insert(i.to_string(), sig_i); } - let h = E::G2::rand(rng); - return ParamsUL { mpk, signatures, h, kp, u, l }; + let com = CSPublicKey::setup(rng); + return ParamsUL { mpk, signatures, com, kp, u, l }; } /* @@ -105,62 +105,93 @@ fn decompose(x: i64, u: i64) -> Vec { return result; } -///* -//prove_ul method is used to produce the ZKRP proof that secret x belongs to the interval [0,U^L]. -//*/ -//fn prove_ul(x: E::Fr, r: E::Fr, p: ParamsUL) -> ProofUL { -// let decx = decompose(x, p.u); -// -//// Initialize variables -// let mut v = Vec::::with_capacity(p.l as usize); -// let mut V = Vec::::with_capacity(p.l as usize); -// let mut a = Vec::::with_capacity(p.l as usize); -// let mut s = Vec::::with_capacity(p.l as usize); -// let mut t = Vec::::with_capacity(p.l as usize); -// let mut zsig = Vec::::with_capacity(p.l as usize); -// let mut zv = Vec::::with_capacity(p.l as usize); -// let mut one: E::G2::one(); -// let mut D = E::G2::zero().add_assign(one.negate()); -// let mut m = rand.Int(rand.Reader, bn256.Order); -// -//// D = H^m -// D = new(bn256.G2).ScalarMult(p.H, proof_out.m); -// for i in 0..p.l { -// v.push(rand.Int(rand.Reader, bn256.Order)); -// let A = p.signatures[strconv.FormatInt(decx[i], 10)]; -// V.push(new(bn256.G2).ScalarMult(A, v[i])); -// s.push(rand.Int(rand.Reader, bn256.Order)); -// t.push(rand.Int(rand.Reader, bn256.Order)); -// a.push(bn256.Pair(G1, proof_out.V[i])); -// a[i].ScalarMult(proof_out.a[i], proof_out.s[i]); -// a[i].Invert(proof_out.a[i]); -// a[i].Add(proof_out.a[i], new(bn256.GT).ScalarMult(E, proof_out.t[i])); -// -// let ui = new(big.Int).Exp(new(big.Int).SetInt64(p.u), new(big.Int).SetInt64(i), nil); -// let mut muisi = new(big.Int).Mul(proof_out.s[i], ui); -// muisi = Mod(muisi, bn256.Order); -// let aux = new(bn256.G2).ScalarBaseMult(muisi); -// D.Add(D, aux); -// } -// proof_out.D.Add(proof_out.D, D); -// -//// Consider passing C as input, -//// so that it is possible to delegate the commitment computation to an external party. -// let C = ped92_commit(p.H, x, r); //TODO: commit -//// Fiat-Shamir heuristic -// let mut c = Hash(proof_out.a, proof_out.D); -// c = Mod(proof_out.c, bn256.Order); -// -// let mut zr = Sub(proof_out.m, Multiply(r, proof_out.c)); -// zr = Mod(proof_out.zr, bn256.Order); -// for i in 0..p.l { -// proof_out.zsig[i] = Sub(proof_out.s[i], Multiply(new(big.Int).SetInt64(decx[i]), proof_out.c)); -// proof_out.zsig[i] = Mod(proof_out.zsig[i], bn256.Order); -// proof_out.zv[i] = Sub(proof_out.t[i], Multiply(v[i], proof_out.c)); -// proof_out.zv[i] = Mod(proof_out.zv[i], bn256.Order); -// } -// return ProofUL {v, d: D, comm: C, a, s, t, zsig, zv, ch: c, m, zr}; -//} +/* +prove_ul method is used to produce the ZKRP proof that secret x belongs to the interval [0,U^L]. +*/ +fn prove_ul(x: i64, r: E::Fr, p: ParamsUL) -> ProofUL { + let mut rng = &mut rand::thread_rng(); + let mut mutr = r.clone(); + + let decx = decompose(x, p.u); + let modx = E::Fr::from_str(&(x.to_string())).unwrap(); + +// Initialize variables + let mut v = Vec::::with_capacity(p.l as usize); + let mut V = Vec::::with_capacity(p.l as usize); + let mut a = Vec::::with_capacity(p.l as usize); + let mut s = Vec::::with_capacity(p.l as usize); + let mut t = Vec::::with_capacity(p.l as usize); + let mut zsig = Vec::::with_capacity(p.l as usize); + let mut zv = Vec::::with_capacity(p.l as usize); + let mut one = E::G2::one(); + let mut D = E::G2::zero(); + one.negate(); + D.add_assign(&one); + let mut m = E::Fr::rand(rng); + +// D = H^m + let mut Dnew = p.com.h; + Dnew.mul_assign(m); + for i in 0..p.l as usize { + v.push(E::Fr::rand(rng)); + let mut A = p.signatures.get(&decx[i].to_string()).unwrap().H; + A.mul_assign(v[i]); + V.push(A); + s.push(E::Fr::rand(rng)); + t.push(E::Fr::rand(rng)); + a.push(E::pairing( V[i], p.mpk.g2)); + a[i].pow(s[i].into_repr()); + a[i] = a[i].inverse().unwrap(); + let mut E = E::pairing(p.mpk.g1, p.mpk.g2); + E.pow(t[i].into_repr()); + a[i].add_assign(&E); + + let ui = p.u.pow(i as u32); + let mut muisi = s[i].clone(); + muisi.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap()); + let mut aux = p.mpk.g2.clone(); + aux.mul_assign(muisi); + D.add_assign(&aux); + } + D.add_assign(&Dnew); + + let C = p.com.commit(rng, modx, Some(mutr)); +// Fiat-Shamir heuristic + let c = Hash::(a.clone(), D.clone()); + + let mut zr = m.clone(); + mutr.mul_assign(&c); + zr.sub_assign(&mutr); + for i in 0..p.l as usize { + zsig[i] = s[i].clone(); + let mut dx = E::Fr::from_str(&decx[i].to_string()).unwrap(); + dx.mul_assign(&c); + zsig[i].sub_assign(&dx); + let mut vi = v[i].clone(); + vi.mul_assign(&c); + let mut ti = t[i].clone(); + ti.sub_assign(&vi); + zv[i] = ti.clone(); + } + return ProofUL {v: V, d: D, comm: C, a, s, t, zsig, zv, ch: c, m, zr}; +} + +fn Hash(a: Vec, D: E::G2) -> 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(); + x_vec.extend(format!("{}", D).bytes()); + a_vec.extend(x_vec); + let sha2_digest = sha512::hash(a_vec.as_slice()); + + let mut hash_buf: [u8; 64] = [0; 64]; + hash_buf.copy_from_slice(&sha2_digest[0..64]); + return E::Fr::from_str(&str::from_utf8(&hash_buf).unwrap()).unwrap(); +} /* diff --git a/src/ped92.rs b/src/ped92.rs index 762377f..d37aa7a 100644 --- a/src/ped92.rs +++ b/src/ped92.rs @@ -1,12 +1,12 @@ // ped92.rs use rand::{thread_rng, Rng}; -use pairing::{Engine, CurveProjective, CurveAffine}; +use pairing::{Engine, CurveProjective}; use ff::Rand; #[derive(Clone)] pub struct CSPublicKey { - g: E::G2, - h: E::G2, + pub g: E::G2, + pub h: E::G2, } #[derive(Clone)] From 65336bf8cc150f14daa95f6c1469a9903584f9ff Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Sun, 16 Jun 2019 15:38:07 -0400 Subject: [PATCH 03/11] ccs08: test and fix hash --- src/ccs08.rs | 93 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 61 insertions(+), 32 deletions(-) diff --git a/src/ccs08.rs b/src/ccs08.rs index 07017cc..8da0528 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -14,6 +14,7 @@ use pairing::{Engine, CurveProjective}; use ff::PrimeField; use std::collections::HashMap; use std::fmt::Display; +use std::mem::transmute; /* paramsUL contains elements generated by the verifier, which are necessary for the prover. @@ -139,7 +140,7 @@ fn prove_ul(x: i64, r: E::Fr, p: ParamsUL) -> ProofUL { V.push(A); s.push(E::Fr::rand(rng)); t.push(E::Fr::rand(rng)); - a.push(E::pairing( V[i], p.mpk.g2)); + a.push(E::pairing(V[i], p.mpk.g2)); a[i].pow(s[i].into_repr()); a[i] = a[i].inverse().unwrap(); let mut E = E::pairing(p.mpk.g1, p.mpk.g2); @@ -173,7 +174,7 @@ fn prove_ul(x: i64, r: E::Fr, p: ParamsUL) -> ProofUL { ti.sub_assign(&vi); zv[i] = ti.clone(); } - return ProofUL {v: V, d: D, comm: C, a, s, t, zsig, zv, ch: c, m, zr}; + return ProofUL { v: V, d: D, comm: C, a, s, t, zsig, zv, ch: c, m, zr }; } fn Hash(a: Vec, D: E::G2) -> E::Fr { @@ -190,31 +191,45 @@ fn Hash(a: Vec, D: E::G2) -> E::Fr { let mut hash_buf: [u8; 64] = [0; 64]; hash_buf.copy_from_slice(&sha2_digest[0..64]); - return E::Fr::from_str(&str::from_utf8(&hash_buf).unwrap()).unwrap(); + let mut hexresult = fmt_bytes_to_int(hash_buf); + let result = E::Fr::from_str(&hexresult); + return result.unwrap(); } - -/* -Setup receives integers a and b, and configures the parameters for the rangeproof scheme. -*/ -pub fn ccs08_setup(a: i64, b: i64) -> RPPublicParams { - // Compute optimal values for u and l - if a > b { - panic!("a must be less than or equal to b"); +fn fmt_bytes_to_int(bytearray: [u8; 64]) -> String { + let mut result: String = "".to_string(); + for byte in bytearray.iter() { + // Decide if you want upper- or lowercase results, + // padding the values to two characters, spaces + // between bytes, etc. + result = result + &format!("{}", *byte as u8); } - let p: PublicParams; - let logb = (b as f64).log10(); - if logb != 0.0 { - let u = b / logb as i64; - if u != 0 { - let l = (b as f64).log(u as f64).ceil() as i64; - let params_out: ParamsUL = setup_ul(u, l); - return RPPublicParams { p: params_out, a, b }; - } else { - panic!("u is zero"); + result.to_string() +} + +impl RPPublicParams { + /* + Setup receives integers a and b, and configures the parameters for the rangeproof scheme. + */ + pub fn setup(a: i64, b: i64) -> RPPublicParams { + // Compute optimal values for u and l + if a > b { + panic!("a must be less than or equal to b"); + } + let p: PublicParams; + let logb = (b as f64).log10(); + if logb != 0.0 { + let u = b / logb as i64; + if u != 0 { + let l = (b as f64).log(u as f64).ceil() as i64; + let params_out: ParamsUL = setup_ul(u, l); + return RPPublicParams { p: params_out, a, b }; + } else { + panic!("u is zero"); + } + } else { + panic!("log(b) is zero"); } - } else { - panic!("log(b) is zero"); } } @@ -222,11 +237,10 @@ pub fn ccs08_setup(a: i64, b: i64) -> RPPublicParams { #[cfg(test)] mod tests { use super::*; - use pairing::bls12_381::{Bls12, Fr}; + use pairing::bls12_381::{Bls12, G2, Fq12, Fr}; #[test] fn setup_ul_works() { - let mut rng = &mut rand::thread_rng(); let params_set = setup_ul::(2, 3); assert_eq!(2, params_set.signatures.len()); for (m, s) in params_set.signatures { @@ -245,8 +259,7 @@ mod tests { #[test] fn setup_works() { - let mut rng = &mut rand::thread_rng(); - let public_params = ccs08_setup::(2, 10); + let public_params = RPPublicParams::::setup(2, 10); assert_eq!(2, public_params.a); assert_eq!(10, public_params.b); assert_eq!(10, public_params.p.signatures.len()); @@ -260,21 +273,37 @@ mod tests { #[test] #[should_panic(expected = "a must be less than or equal to b")] fn setup_wrong_a_and_b() { - let mut rng = &mut rand::thread_rng(); - let public_params = ccs08_setup::(10, 2); + let public_params = RPPublicParams::::setup(10, 2); } #[test] #[should_panic(expected = "u is zero")] fn setup_wrong_b() { - let mut rng = &mut rand::thread_rng(); - let public_params = ccs08_setup::(-1, 0); + let public_params = RPPublicParams::::setup(-1, 0); } #[test] #[should_panic(expected = "log(b) is zero")] fn setup_wrong_logb() { + let public_params = RPPublicParams::::setup(-1, 1); + } + + #[test] + fn fmt_byte_to_int_works() { + assert_eq!("122352312313431223523123134312235231231343122352312313431223523123134312235231231343122352312313431223523123134312235231231343122352312313431223523123", + fmt_bytes_to_int([12,235,23,123,13,43,12,235,23,123,13,43,12,235,23,123,13,43,12,235,23,123,13,43,12,235,23,123,13,43,12,235,23,123,13,43,12,235,23,123,13,43,12,235,23,123,13,43,12,235,23,123,13,43,12,235,23,123,13,43,12,235,23,123])); + } + + #[test] + fn hash_works() { let mut rng = &mut rand::thread_rng(); - let public_params = ccs08_setup::(-1, 1); + let D = G2::rand(rng); + let D2 = G2::rand(rng); + let a = vec! {Fq12::rand(rng), Fq12::rand(rng), Fq12::rand(rng)}; + let a2 = vec! {Fq12::rand(rng), Fq12::rand(rng), Fq12::rand(rng)}; + assert_eq!(false, Hash::(a.clone(), D.clone()).is_zero()); + assert_ne!(Hash::(a2.clone(), D.clone()), Hash::(a.clone(), D.clone())); + assert_ne!(Hash::(a.clone(), D2.clone()), Hash::(a.clone(), D.clone())); + assert_ne!(Hash::(a2.clone(), D2.clone()), Hash::(a.clone(), D.clone())); } } From 5310eeb564503b4f5a82a641ae81a1bce98287f3 Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Sun, 16 Jun 2019 16:29:48 -0400 Subject: [PATCH 04/11] ccs08: prove_ul runs --- src/ccs08.rs | 208 +++++++++++++++++++++++++++------------------------ 1 file changed, 111 insertions(+), 97 deletions(-) diff --git a/src/ccs08.rs b/src/ccs08.rs index 8da0528..6b4a545 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -7,6 +7,7 @@ Asiacrypt 2008 extern crate pairing; extern crate rand; +use rand::{thread_rng, Rng}; use super::*; use cl::{KeyPair, Signature, PublicParams, setup}; use ped92::{CSPublicKey, Commitment}; @@ -70,111 +71,95 @@ pub struct RPPublicParams { b: i64, } -/* +impl ParamsUL { + /* 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. */ -fn setup_ul(u: i64, l: i64) -> ParamsUL { - let mut rng = &mut rand::thread_rng(); + pub fn setup_ul(rng: &mut R, u: i64, l: i64) -> ParamsUL { + let mpk = setup(rng); + let kp = KeyPair::::generate(rng, &mpk, 1); - let mpk = setup(&mut rng); - let kp = KeyPair::::generate(&mut 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 mut signatures: HashMap> = HashMap::new(); - for i in 0..u { - let sig_i = kp.sign(&mut rng, &vec! {E::Fr::from_str(i.to_string().as_str()).unwrap()}); - signatures.insert(i.to_string(), sig_i); + let com = CSPublicKey::setup(rng); + return ParamsUL { mpk, signatures, com, kp, u, l }; } - let com = CSPublicKey::setup(rng); - return ParamsUL { mpk, signatures, com, kp, u, l }; -} - -/* -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) -> Vec { - let l = (x as f64).log(u as f64).ceil() as usize; - 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; -} - -/* + /* prove_ul method is used to produce the ZKRP proof that secret x belongs to the interval [0,U^L]. */ -fn prove_ul(x: i64, r: E::Fr, p: ParamsUL) -> ProofUL { - let mut rng = &mut rand::thread_rng(); - let mut mutr = r.clone(); + pub fn prove_ul(&self, rng: &mut R, x: i64, r: E::Fr) -> ProofUL { + let mut mutr = r.clone(); - let decx = decompose(x, p.u); - let modx = E::Fr::from_str(&(x.to_string())).unwrap(); + let decx = decompose(x, self.u); + let modx = E::Fr::from_str(&(x.to_string())).unwrap(); // Initialize variables - let mut v = Vec::::with_capacity(p.l as usize); - let mut V = Vec::::with_capacity(p.l as usize); - let mut a = Vec::::with_capacity(p.l as usize); - let mut s = Vec::::with_capacity(p.l as usize); - let mut t = Vec::::with_capacity(p.l as usize); - let mut zsig = Vec::::with_capacity(p.l as usize); - let mut zv = Vec::::with_capacity(p.l as usize); - let mut one = E::G2::one(); - let mut D = E::G2::zero(); - one.negate(); - D.add_assign(&one); - let mut m = E::Fr::rand(rng); + let mut v = Vec::::with_capacity(self.l as usize); + let mut V = Vec::::with_capacity(self.l as usize); + let mut a = Vec::::with_capacity(self.l as usize); + let mut s = Vec::::with_capacity(self.l as usize); + let mut t = Vec::::with_capacity(self.l as usize); + let mut zsig = Vec::::with_capacity(self.l as usize); + let mut zv = Vec::::with_capacity(self.l as usize); + let mut one = E::G2::one(); + let mut D = E::G2::zero(); + one.negate(); + D.add_assign(&one); + let mut m = E::Fr::rand(rng); // D = H^m - let mut Dnew = p.com.h; - Dnew.mul_assign(m); - for i in 0..p.l as usize { - v.push(E::Fr::rand(rng)); - let mut A = p.signatures.get(&decx[i].to_string()).unwrap().H; - A.mul_assign(v[i]); - V.push(A); - s.push(E::Fr::rand(rng)); - t.push(E::Fr::rand(rng)); - a.push(E::pairing(V[i], p.mpk.g2)); - a[i].pow(s[i].into_repr()); - a[i] = a[i].inverse().unwrap(); - let mut E = E::pairing(p.mpk.g1, p.mpk.g2); - E.pow(t[i].into_repr()); - a[i].add_assign(&E); + let mut Dnew = self.com.h; + Dnew.mul_assign(m); + for i in 0..self.l as usize { + v.push(E::Fr::rand(rng)); + let mut A = self.signatures.get(&decx[i].to_string()).unwrap().H; + A.mul_assign(v[i]); + V.push(A); + s.push(E::Fr::rand(rng)); + t.push(E::Fr::rand(rng)); + a.push(E::pairing(V[i], self.mpk.g2)); + a[i].pow(s[i].into_repr()); + a[i] = a[i].inverse().unwrap(); + let mut E = E::pairing(self.mpk.g1, self.mpk.g2); + E.pow(t[i].into_repr()); + a[i].add_assign(&E); - let ui = p.u.pow(i as u32); - let mut muisi = s[i].clone(); - muisi.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap()); - let mut aux = p.mpk.g2.clone(); - aux.mul_assign(muisi); - D.add_assign(&aux); - } - D.add_assign(&Dnew); + let ui = self.u.pow(i as u32); + let mut muisi = s[i].clone(); + muisi.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap()); + let mut aux = self.mpk.g2.clone(); + aux.mul_assign(muisi); + D.add_assign(&aux); + } + D.add_assign(&Dnew); - let C = p.com.commit(rng, modx, Some(mutr)); + let C = self.com.commit(rng, modx, Some(mutr)); // Fiat-Shamir heuristic - let c = Hash::(a.clone(), D.clone()); + let c = Hash::(a.clone(), D.clone()); - let mut zr = m.clone(); - mutr.mul_assign(&c); - zr.sub_assign(&mutr); - for i in 0..p.l as usize { - zsig[i] = s[i].clone(); - let mut dx = E::Fr::from_str(&decx[i].to_string()).unwrap(); - dx.mul_assign(&c); - zsig[i].sub_assign(&dx); - let mut vi = v[i].clone(); - vi.mul_assign(&c); - let mut ti = t[i].clone(); - ti.sub_assign(&vi); - zv[i] = ti.clone(); + let mut zr = m.clone(); + mutr.mul_assign(&c); + zr.sub_assign(&mutr); + for i in 0..self.l as usize { + zsig.push(s[i].clone()); + let mut dx = E::Fr::from_str(&decx[i].to_string()).unwrap(); + dx.mul_assign(&c); + zsig[i].sub_assign(&dx); + let mut vi = v[i].clone(); + vi.mul_assign(&c); + let mut ti = t[i].clone(); + ti.sub_assign(&vi); + zv.push(ti.clone()); + } + return ProofUL { v: V, d: D, comm: C, a, s, t, zsig, zv, ch: c, m, zr }; } - return ProofUL { v: V, d: D, comm: C, a, s, t, zsig, zv, ch: c, m, zr }; } fn Hash(a: Vec, D: E::G2) -> E::Fr { @@ -196,6 +181,21 @@ fn Hash(a: Vec, D: E::G2) -> E::Fr { return result.unwrap(); } +/* +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) -> Vec { + let l = (x as f64).log(u as f64).ceil() as usize; + 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; +} + fn fmt_bytes_to_int(bytearray: [u8; 64]) -> String { let mut result: String = "".to_string(); for byte in bytearray.iter() { @@ -211,7 +211,7 @@ impl RPPublicParams { /* Setup receives integers a and b, and configures the parameters for the rangeproof scheme. */ - pub fn setup(a: i64, b: i64) -> RPPublicParams { + pub fn setup(rng: &mut R, a: i64, b: i64) -> RPPublicParams { // Compute optimal values for u and l if a > b { panic!("a must be less than or equal to b"); @@ -222,7 +222,7 @@ impl RPPublicParams { let u = b / logb as i64; if u != 0 { let l = (b as f64).log(u as f64).ceil() as i64; - let params_out: ParamsUL = setup_ul(u, l); + let params_out: ParamsUL = ParamsUL::::setup_ul(rng, u, l); return RPPublicParams { p: params_out, a, b }; } else { panic!("u is zero"); @@ -241,13 +241,23 @@ mod tests { #[test] fn setup_ul_works() { - let params_set = setup_ul::(2, 3); - assert_eq!(2, params_set.signatures.len()); - for (m, s) in params_set.signatures { - assert_eq!(true, params_set.kp.verify(¶ms_set.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &s)); + let rng = &mut rand::thread_rng(); + let params = ParamsUL::::setup_ul(rng, 2, 3); + assert_eq!(2, params.signatures.len()); + for (m, s) in params.signatures { + assert_eq!(true, params.kp.verify(¶ms.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &s)); } } + #[test] + fn prove_ul_works() { + let rng = &mut rand::thread_rng(); + let params = ParamsUL::::setup_ul(rng, 2, 3); + let fr = Fr::rand(rng); + let proof = params.prove_ul(rng, 10, fr); + + } + #[test] fn decompose_works() { assert_eq!(vec! {1, 2, 2}, decompose(25, 3)); @@ -259,7 +269,8 @@ mod tests { #[test] fn setup_works() { - let public_params = RPPublicParams::::setup(2, 10); + let rng = &mut rand::thread_rng(); + let public_params = RPPublicParams::::setup(rng, 2, 10); assert_eq!(2, public_params.a); assert_eq!(10, public_params.b); assert_eq!(10, public_params.p.signatures.len()); @@ -273,30 +284,33 @@ mod tests { #[test] #[should_panic(expected = "a must be less than or equal to b")] fn setup_wrong_a_and_b() { - let public_params = RPPublicParams::::setup(10, 2); + let rng = &mut rand::thread_rng(); + let public_params = RPPublicParams::::setup(rng, 10, 2); } #[test] #[should_panic(expected = "u is zero")] fn setup_wrong_b() { - let public_params = RPPublicParams::::setup(-1, 0); + let rng = &mut rand::thread_rng(); + let public_params = RPPublicParams::::setup(rng, -1, 0); } #[test] #[should_panic(expected = "log(b) is zero")] fn setup_wrong_logb() { - let public_params = RPPublicParams::::setup(-1, 1); + let rng = &mut rand::thread_rng(); + let public_params = RPPublicParams::::setup(rng, -1, 1); } #[test] fn fmt_byte_to_int_works() { assert_eq!("122352312313431223523123134312235231231343122352312313431223523123134312235231231343122352312313431223523123134312235231231343122352312313431223523123", - fmt_bytes_to_int([12,235,23,123,13,43,12,235,23,123,13,43,12,235,23,123,13,43,12,235,23,123,13,43,12,235,23,123,13,43,12,235,23,123,13,43,12,235,23,123,13,43,12,235,23,123,13,43,12,235,23,123,13,43,12,235,23,123,13,43,12,235,23,123])); + fmt_bytes_to_int([12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123])); } #[test] fn hash_works() { - let mut rng = &mut rand::thread_rng(); + let rng = &mut rand::thread_rng(); let D = G2::rand(rng); let D2 = G2::rand(rng); let a = vec! {Fq12::rand(rng), Fq12::rand(rng), Fq12::rand(rng)}; From b4f895f477ca7d58d68611a2e8463631b3e0dd5d Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Mon, 17 Jun 2019 15:01:31 -0400 Subject: [PATCH 05/11] ccs08: verification algorithm, non-working part 2 --- src/ccs08.rs | 184 +++++++++++++++++++++++++++++++++++++++------------ src/ped92.rs | 6 +- 2 files changed, 146 insertions(+), 44 deletions(-) diff --git a/src/ccs08.rs b/src/ccs08.rs index 6b4a545..e73c476 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -42,8 +42,8 @@ proofUL contains the necessary elements for the ZK range proof. */ #[derive(Clone)] struct ProofUL { - v: Vec, - d: E::G2, + V: Vec, + D: E::G2, comm: Commitment, a: Vec, s: Vec, @@ -77,7 +77,7 @@ 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) -> ParamsUL { + pub fn setup_ul(rng: &mut R, u: i64, l: i64) -> Self { let mpk = setup(rng); let kp = KeyPair::::generate(rng, &mpk, 1); @@ -95,9 +95,7 @@ order to get smaller parameters, at the cost of having worse performance. prove_ul method is used to produce the ZKRP proof that secret x belongs to the interval [0,U^L]. */ pub fn prove_ul(&self, rng: &mut R, x: i64, r: E::Fr) -> ProofUL { - let mut mutr = r.clone(); - - let decx = decompose(x, self.u); + let decx = decompose(x, self.u, self.l); let modx = E::Fr::from_str(&(x.to_string())).unwrap(); // Initialize variables @@ -108,20 +106,18 @@ prove_ul method is used to produce the ZKRP proof that secret x belongs to the i let mut t = Vec::::with_capacity(self.l as usize); let mut zsig = Vec::::with_capacity(self.l as usize); let mut zv = Vec::::with_capacity(self.l as usize); - let mut one = E::G2::one(); let mut D = E::G2::zero(); - one.negate(); - D.add_assign(&one); let mut m = E::Fr::rand(rng); // D = H^m - let mut Dnew = self.com.h; - Dnew.mul_assign(m); + let mut hm = self.com.h.clone(); + hm.mul_assign(m); for i in 0..self.l as usize { v.push(E::Fr::rand(rng)); let mut A = self.signatures.get(&decx[i].to_string()).unwrap().H; A.mul_assign(v[i]); V.push(A); + assert_eq!(A, V[i]); //TODO: remove s.push(E::Fr::rand(rng)); t.push(E::Fr::rand(rng)); a.push(E::pairing(V[i], self.mpk.g2)); @@ -129,36 +125,87 @@ prove_ul method is used to produce the ZKRP proof that secret x belongs to the i a[i] = a[i].inverse().unwrap(); let mut E = E::pairing(self.mpk.g1, self.mpk.g2); E.pow(t[i].into_repr()); - a[i].add_assign(&E); + a[i].mul_assign(&E); //TODO: add or mul let ui = self.u.pow(i as u32); let mut muisi = s[i].clone(); muisi.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap()); - let mut aux = self.mpk.g2.clone(); + let mut aux = self.com.g.clone(); aux.mul_assign(muisi); D.add_assign(&aux); } - D.add_assign(&Dnew); + D.add_assign(&hm); - let C = self.com.commit(rng, modx, Some(mutr)); + let C = self.com.commit(rng, modx, Some(r)); // Fiat-Shamir heuristic let c = Hash::(a.clone(), D.clone()); let mut zr = m.clone(); - mutr.mul_assign(&c); - zr.sub_assign(&mutr); + let mut rc = r.clone(); + rc.mul_assign(&c); + zr.sub_assign(&rc); for i in 0..self.l as usize { zsig.push(s[i].clone()); + assert_eq!(s[i], zsig[i]); //TODO: remove let mut dx = E::Fr::from_str(&decx[i].to_string()).unwrap(); dx.mul_assign(&c); zsig[i].sub_assign(&dx); - let mut vi = v[i].clone(); - vi.mul_assign(&c); + let mut vic = v[i].clone(); + vic.mul_assign(&c); let mut ti = t[i].clone(); - ti.sub_assign(&vi); - zv.push(ti.clone()); + ti.sub_assign(&vic); + zv.push(ti); } - return ProofUL { v: V, d: D, comm: C, a, s, t, zsig, zv, ch: c, m, zr }; + + return ProofUL { V, D, comm: C, a, s, t, zsig, zv, ch: c, m, zr }; + } + + /* +verify_ul is used to validate the ZKRP proof. It returns true iff the proof is valid. +*/ + pub fn verify_ul(&self, proof: &ProofUL) -> bool { + // D == C^c.h^ zr.g^zsig ? + let r1 = self.verify_part1(&proof); + let r2 = self.verify_part2(&proof); + return r1 && r2; + } + + fn verify_part2(&self, proof: &ProofUL) -> bool { + let mut r2 = true; + for i in 0..self.l as usize { + // a == [e(V,y)^c].[e(V,g)^-zsig].[e(g,g)^zv] + let mut p1 = E::pairing(proof.V[i], self.kp.public.X); + p1.pow(proof.ch.into_repr()); + let mut p2 = E::pairing(proof.V[i], self.mpk.g2); + p2.pow(proof.zsig[i].into_repr()); + p2 = p2.inverse().unwrap(); + p1.mul_assign(&p2); // TODO: add or mul + let mut E = E::pairing(self.mpk.g1, self.mpk.g2); + E.pow(proof.zv[i].into_repr()); + p1.mul_assign(&E); //TODO: add or mul + + print!("{}\n", p1); + print!("{}\n", proof.a[i]); + r2 = r2 && p1 == proof.a[i]; + } + return r2; + } + + fn verify_part1(&self, proof: &ProofUL) -> bool { + let mut D = proof.comm.c.clone(); + D.mul_assign(proof.ch); + let mut hzr = self.com.h.clone(); + hzr.mul_assign(proof.zr); + D.add_assign(&hzr); + for i in 0..self.l { + let ui = self.u.pow(i as u32); + let mut muizsigi = proof.zsig[i as usize]; + muizsigi.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap()); + let mut aux = self.com.g.clone(); + aux.mul_assign(muizsigi); + D.add_assign(&aux); + } + return D == proof.D; } } @@ -185,8 +232,7 @@ fn Hash(a: Vec, D: E::G2) -> E::Fr { Decompose receives as input an integer x and outputs an array of integers such that x = sum(xi.u^i), i.e. it returns the decomposition of x into base u. */ -fn decompose(x: i64, u: i64) -> Vec { - let l = (x as f64).log(u as f64).ceil() as usize; +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 { @@ -211,7 +257,7 @@ impl RPPublicParams { /* Setup receives integers a and b, and configures the parameters for the rangeproof scheme. */ - pub fn setup(rng: &mut R, a: i64, b: i64) -> RPPublicParams { + pub fn setup(rng: &mut R, a: i64, b: i64) -> Self { // Compute optimal values for u and l if a > b { panic!("a must be less than or equal to b"); @@ -243,9 +289,9 @@ mod tests { fn setup_ul_works() { let rng = &mut rand::thread_rng(); let params = ParamsUL::::setup_ul(rng, 2, 3); - assert_eq!(2, params.signatures.len()); + assert_eq!(params.signatures.len(), 2); for (m, s) in params.signatures { - assert_eq!(true, params.kp.verify(¶ms.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &s)); + assert_eq!(params.kp.verify(¶ms.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &s), true); } } @@ -255,29 +301,85 @@ mod tests { let params = ParamsUL::::setup_ul(rng, 2, 3); let fr = Fr::rand(rng); let proof = params.prove_ul(rng, 10, fr); + assert_eq!(proof.a.len(), 3); + assert_eq!(proof.s.len(), 3); + assert_eq!(proof.t.len(), 3); + assert_eq!(proof.V.len(), 3); + assert_eq!(proof.zsig.len(), 3); + let mut s = proof.s[0].clone(); + let mut ch = proof.ch.clone(); + ch.mul_assign(&Fr::from_str(&decompose(10, 2, 4).get(0).unwrap().to_string()).unwrap()); + s.sub_assign(&ch); + assert_eq!(proof.zsig[0], s); + assert_eq!(proof.zv.len(), 3); + } + #[test] + fn prove_and_verify_part1_ul_works() { + let rng = &mut rand::thread_rng(); + let params = ParamsUL::::setup_ul(rng, 2, 4); + let fr = Fr::rand(rng); + let proof = params.prove_ul(rng, 10, fr); + assert_eq!(params.verify_part1(&proof), true); + } + + #[test] + #[ignore] + fn prove_and_verify_part2_ul_works() { + let rng = &mut rand::thread_rng(); + let params = ParamsUL::::setup_ul(rng, 2, 4); + let fr = Fr::rand(rng); + let proof = params.prove_ul(rng, 10, fr); + assert_eq!(params.verify_part2(&proof), true); + } + + #[test] + #[ignore] + fn prove_and_verify_ul_works() { + let rng = &mut rand::thread_rng(); + let params = ParamsUL::::setup_ul(rng, 2, 4); + let fr = Fr::rand(rng); + let proof = params.prove_ul(rng, 10, fr); + assert_eq!(params.verify_ul(&proof), true); } #[test] fn decompose_works() { - assert_eq!(vec! {1, 2, 2}, decompose(25, 3)); - assert_eq!(vec! {0, 6, 6}, decompose(336, 7)); - assert_eq!(vec! {5, 3, 4}, decompose(285, 8)); - assert_eq!(vec! {8, 9}, decompose(125, 13)); - assert_eq!(vec! {5, 2, 0, 3, 2, 0, 3}, decompose(143225, 6)); + 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 public_params = RPPublicParams::::setup(rng, 2, 10); - assert_eq!(2, public_params.a); - assert_eq!(10, public_params.b); - assert_eq!(10, public_params.p.signatures.len()); - assert_eq!(10 / ((10 as f64).log10() as i64), public_params.p.u); - assert_eq!(((10 / (10 / ((10 as f64).log10() as i64))) as f64).ceil() as i64, public_params.p.l); + assert_eq!(public_params.a, 2); + assert_eq!(public_params.b, 10); + assert_eq!(public_params.p.signatures.len(), 10); + assert_eq!(public_params.p.u, 10 / ((10 as f64).log10() as i64)); + assert_eq!(public_params.p.l, ((10 / (10 / ((10 as f64).log10() as i64))) as f64).ceil() as i64); for (m, s) in public_params.p.signatures { - assert_eq!(true, public_params.p.kp.verify(&public_params.p.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &s)); + assert_eq!(public_params.p.kp.verify(&public_params.p.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &s), true); } } @@ -304,8 +406,8 @@ mod tests { #[test] fn fmt_byte_to_int_works() { - assert_eq!("122352312313431223523123134312235231231343122352312313431223523123134312235231231343122352312313431223523123134312235231231343122352312313431223523123", - fmt_bytes_to_int([12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123])); + assert_eq!(fmt_bytes_to_int([12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123]), + "122352312313431223523123134312235231231343122352312313431223523123134312235231231343122352312313431223523123134312235231231343122352312313431223523123"); } #[test] @@ -315,7 +417,7 @@ mod tests { let D2 = G2::rand(rng); let a = vec! {Fq12::rand(rng), Fq12::rand(rng), Fq12::rand(rng)}; let a2 = vec! {Fq12::rand(rng), Fq12::rand(rng), Fq12::rand(rng)}; - assert_eq!(false, Hash::(a.clone(), D.clone()).is_zero()); + assert_eq!(Hash::(a.clone(), D.clone()).is_zero(), false); assert_ne!(Hash::(a2.clone(), D.clone()), Hash::(a.clone(), D.clone())); assert_ne!(Hash::(a.clone(), D2.clone()), Hash::(a.clone(), D.clone())); assert_ne!(Hash::(a2.clone(), D2.clone()), Hash::(a.clone(), D.clone())); diff --git a/src/ped92.rs b/src/ped92.rs index d37aa7a..f06361b 100644 --- a/src/ped92.rs +++ b/src/ped92.rs @@ -170,8 +170,8 @@ mod tests { let r = Fr::rand(rng); let c = pk.commit(rng, m1, Some(r)); - assert_eq!(true, pk.decommit(&c, m1)); - assert_eq!(false, pk.decommit(&c, m2)); + assert_eq!(pk.decommit(&c, m1), true); + assert_eq!(pk.decommit(&c, m2), false); } #[test] @@ -187,6 +187,6 @@ mod tests { let r = m[0].clone(); let c = csp.commit(rng, &m, r); - assert_eq!(true, csp.decommit(&c, &m)); + assert_eq!(csp.decommit(&c, &m), true); } } From fe613a260c05695d8e4a5479bf3a6fcea220bd8d Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Tue, 18 Jun 2019 16:20:16 -0400 Subject: [PATCH 06/11] ccs08: verify ul part 2, but weird stuff happening --- src/ccs08.rs | 135 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 87 insertions(+), 48 deletions(-) diff --git a/src/ccs08.rs b/src/ccs08.rs index e73c476..cfbce40 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -42,16 +42,14 @@ proofUL contains the necessary elements for the ZK range proof. */ #[derive(Clone)] struct ProofUL { - V: Vec, + V: Vec<(E::G1, E::G1)>, D: E::G2, comm: Commitment, a: Vec, - s: Vec, - t: Vec, + zx: Vec, zsig: Vec, zv: Vec, ch: E::Fr, - m: E::Fr, zr: E::Fr, } @@ -95,69 +93,81 @@ order to get smaller parameters, at the cost of having worse performance. prove_ul method is used to produce the ZKRP proof that secret x belongs to the interval [0,U^L]. */ pub fn prove_ul(&self, rng: &mut R, x: i64, r: E::Fr) -> ProofUL { + //TODO: check if x in range let decx = decompose(x, self.u, self.l); let modx = E::Fr::from_str(&(x.to_string())).unwrap(); // Initialize variables let mut v = Vec::::with_capacity(self.l as usize); - let mut V = Vec::::with_capacity(self.l as usize); + let mut V = Vec::<(E::G1, E::G1)>::with_capacity(self.l as usize); let mut a = Vec::::with_capacity(self.l as usize); let mut s = Vec::::with_capacity(self.l as usize); let mut t = Vec::::with_capacity(self.l as usize); + let mut tt = Vec::::with_capacity(self.l as usize); + let mut zx = Vec::::with_capacity(self.l as usize); let mut zsig = Vec::::with_capacity(self.l as usize); let mut zv = Vec::::with_capacity(self.l as usize); let mut D = E::G2::zero(); let mut m = E::Fr::rand(rng); -// D = H^m + // D = H^m let mut hm = self.com.h.clone(); hm.mul_assign(m); for i in 0..self.l as usize { v.push(E::Fr::rand(rng)); - let mut A = self.signatures.get(&decx[i].to_string()).unwrap().H; - A.mul_assign(v[i]); - V.push(A); - assert_eq!(A, V[i]); //TODO: remove + let r = E::Fr::rand(rng); + let mut A = self.signatures.get(&decx[i].to_string()).unwrap().h; + let mut B = self.signatures.get(&decx[i].to_string()).unwrap().H; + let mut Aprime = A.clone(); + A.mul_assign(r); + Aprime.mul_assign(v[i]); + B.add_assign(&Aprime); + B.mul_assign(r); + V.push((A, B)); s.push(E::Fr::rand(rng)); + let mut gx = E::pairing(V[i].0, self.kp.public.X); + gx.pow(s[i].into_repr()); + a.push(gx); t.push(E::Fr::rand(rng)); - a.push(E::pairing(V[i], self.mpk.g2)); - a[i].pow(s[i].into_repr()); - a[i] = a[i].inverse().unwrap(); - let mut E = E::pairing(self.mpk.g1, self.mpk.g2); - E.pow(t[i].into_repr()); - a[i].mul_assign(&E); //TODO: add or mul + let mut gy = E::pairing(V[i].0, self.kp.public.Y[0]); + gy.pow(t[i].into_repr()); + a[i].mul_assign(&gy); + tt.push(E::Fr::rand(rng)); + let mut h = E::pairing(V[i].0, self.mpk.g2); + h.pow(tt[i].into_repr()); + a[i].mul_assign(&h); let ui = self.u.pow(i as u32); - let mut muisi = s[i].clone(); - muisi.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap()); + let mut muiti = t[i].clone(); + muiti.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap()); let mut aux = self.com.g.clone(); - aux.mul_assign(muisi); + aux.mul_assign(muiti); D.add_assign(&aux); } D.add_assign(&hm); let C = self.com.commit(rng, modx, Some(r)); -// Fiat-Shamir heuristic + // Fiat-Shamir heuristic let c = Hash::(a.clone(), D.clone()); let mut zr = m.clone(); let mut rc = r.clone(); rc.mul_assign(&c); - zr.sub_assign(&rc); + zr.add_assign(&rc); for i in 0..self.l as usize { - zsig.push(s[i].clone()); - assert_eq!(s[i], zsig[i]); //TODO: remove + zsig.push(t[i].clone()); let mut dx = E::Fr::from_str(&decx[i].to_string()).unwrap(); dx.mul_assign(&c); - zsig[i].sub_assign(&dx); + zsig[i].add_assign(&dx); + zx.push(c.clone()); + zx[i].add_assign(&s[i]); + zv.push(tt[i].clone()); let mut vic = v[i].clone(); vic.mul_assign(&c); - let mut ti = t[i].clone(); - ti.sub_assign(&vic); - zv.push(ti); + tt[i].add_assign(&vic); } - return ProofUL { V, D, comm: C, a, s, t, zsig, zv, ch: c, m, zr }; + return ProofUL { V, D, comm: C, a, zx, zsig, zv, ch: c, zr }; } /* @@ -173,20 +183,25 @@ verify_ul is used to validate the ZKRP proof. It returns true iff the proof is v fn verify_part2(&self, proof: &ProofUL) -> bool { let mut r2 = true; for i in 0..self.l as usize { - // a == [e(V,y)^c].[e(V,g)^-zsig].[e(g,g)^zv] - let mut p1 = E::pairing(proof.V[i], self.kp.public.X); - p1.pow(proof.ch.into_repr()); - let mut p2 = E::pairing(proof.V[i], self.mpk.g2); - p2.pow(proof.zsig[i].into_repr()); - p2 = p2.inverse().unwrap(); - p1.mul_assign(&p2); // TODO: add or mul - let mut E = E::pairing(self.mpk.g1, self.mpk.g2); - E.pow(proof.zv[i].into_repr()); - p1.mul_assign(&E); //TODO: add or mul + let mut g = E::pairing(proof.V[i].1, self.mpk.g2); + g.pow(proof.ch.into_repr()); + g = g.inverse().unwrap(); - print!("{}\n", p1); + let mut gx = E::pairing(proof.V[i].0, self.kp.public.X); + gx.pow(proof.zx[i].into_repr()); + g.mul_assign(&gx); + + let mut gy = E::pairing(proof.V[i].0, self.kp.public.Y[0]); + gy.pow(proof.zsig[i].into_repr()); + g.mul_assign(&gy); + + let mut h = E::pairing(proof.V[i].0, self.mpk.g2); + h.pow(proof.zv[i].into_repr()); + g.mul_assign(&h); + + print!("{}\n", g); print!("{}\n", proof.a[i]); - r2 = r2 && p1 == proof.a[i]; + r2 = r2 && g == proof.a[i]; } return r2; } @@ -194,6 +209,7 @@ verify_ul is used to validate the ZKRP proof. It returns true iff the proof is v fn verify_part1(&self, proof: &ProofUL) -> bool { let mut D = proof.comm.c.clone(); D.mul_assign(proof.ch); + D.negate(); let mut hzr = self.com.h.clone(); hzr.mul_assign(proof.zr); D.add_assign(&hzr); @@ -283,7 +299,7 @@ impl RPPublicParams { #[cfg(test)] mod tests { use super::*; - use pairing::bls12_381::{Bls12, G2, Fq12, Fr}; + use pairing::bls12_381::{Bls12, G1, G2, Fq12, Fr}; #[test] fn setup_ul_works() { @@ -302,15 +318,8 @@ mod tests { let fr = Fr::rand(rng); let proof = params.prove_ul(rng, 10, fr); assert_eq!(proof.a.len(), 3); - assert_eq!(proof.s.len(), 3); - assert_eq!(proof.t.len(), 3); assert_eq!(proof.V.len(), 3); assert_eq!(proof.zsig.len(), 3); - let mut s = proof.s[0].clone(); - let mut ch = proof.ch.clone(); - ch.mul_assign(&Fr::from_str(&decompose(10, 2, 4).get(0).unwrap().to_string()).unwrap()); - s.sub_assign(&ch); - assert_eq!(proof.zsig[0], s); assert_eq!(proof.zv.len(), 3); } @@ -422,4 +431,34 @@ mod tests { assert_ne!(Hash::(a.clone(), D2.clone()), Hash::(a.clone(), D.clone())); assert_ne!(Hash::(a2.clone(), D2.clone()), Hash::(a.clone(), D.clone())); } + + #[test] + fn weird_stuff_happening() { + let rng = &mut rand::thread_rng(); + let g1 = G1::rand(rng); + let g2 = G2::rand(rng); + let mut g = Bls12::pairing(g1, g2); + let mut c = Fr::rand(rng); + print!("{}\n", c); + let mut gprime = Bls12::pairing(g1, g2); +// let mut cneg = c.clone(); +// cneg.negate(); + let mut cneg = Fr::zero(); + cneg.sub_assign(&c); + let mut zero = cneg.clone(); + zero.add_assign(&c); + assert_eq!(zero, Fr::zero()); + gprime.pow(cneg.into_repr()); + g.pow(c.into_repr()); + let mut gtest = g.clone(); + let ginv = g.inverse().unwrap(); + //TODO: this should actually work: assert_eq!(ginv, gprime); + + //TODO: instead this works: + gprime.mul_assign(&g); + g.square(); +// cneg.add_assign(&c); +// assert_eq!(cneg, Fr::zero()); + assert_eq!(gprime, g); + } } From 04b495c3072256fae9e6201f1b7304c32c10cd38 Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Tue, 18 Jun 2019 17:43:05 -0400 Subject: [PATCH 07/11] ccs08: extra testing of weirdness in used library --- src/ccs08.rs | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 2 deletions(-) diff --git a/src/ccs08.rs b/src/ccs08.rs index cfbce40..78d8564 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -457,8 +457,89 @@ mod tests { //TODO: instead this works: gprime.mul_assign(&g); g.square(); -// cneg.add_assign(&c); -// assert_eq!(cneg, Fr::zero()); + cneg.add_assign(&c); + assert_eq!(cneg, Fr::zero()); assert_eq!(gprime, g); } + + #[test] + fn more_weird_stuff_happening() { + let rng = &mut rand::thread_rng(); + let g1 = G1::rand(rng); + let g2 = G2::rand(rng); +// let mut g = Bls12::pairing(g1, g2); + let mut g = Fq12::rand(rng); + let mut c = Fr::rand(rng); + print!("{}\n", c); + let mut gprime = g.clone(); + let mut gc = g.clone(); + gc.pow(c.into_repr()); + g.mul_assign(&gc); + + c.add_assign(&Fr::one()); + gprime.pow(c.into_repr()); + + //Todo: should: assert_eq!(gprime, g); + } + + #[test] + fn test_more_weird_stuff_with_bn() { + use bn::{Fr, G1, G2, Gt, pairing, SerializableGt}; + use std::ops::Add; + use std::ops::Mul; + + let rng = &mut rand::thread_rng(); + let g1 = G1::random(rng); + let g2 = G2::random(rng); + let mut g = pairing(g1, g2); + let mut c = Fr::random(rng); + let mut gprime = g.clone(); + let mut gc = g.clone(); + gc = gc.pow(c); + g = g.mul(gc); + + c = c.add(Fr::one()); + gprime = gprime.pow(c); + + debug_gt_in_hex("", &gprime); + debug_gt_in_hex("", &g); + assert!(gprime == g); + } + + #[test] + fn test_weird_stuff_with_bn() { + use bn::{Fr, G1, G2, Gt, pairing, SerializableGt}; + use std::ops::Add; + use std::ops::Sub; + use std::ops::Mul; + + let rng = &mut rand::thread_rng(); + let g1 = G1::random(rng); + let g2 = G2::random(rng); + let mut g = pairing(g1, g2); + let mut c = Fr::random(rng); + let mut gprime = pairing(g1, g2); +// let mut cneg = c.clone(); +// cneg.negate(); + let mut cneg = Fr::zero(); + cneg = cneg.sub(c); + + gprime = gprime.pow(cneg); + g = g.pow(c); + let mut gtest = g.clone(); + let ginv = g.inverse(); + + debug_gt_in_hex("", &ginv); + debug_gt_in_hex("", &gprime); + assert!(gprime == ginv); + } + + pub fn debug_gt_in_hex(prefix: &str, g: &Gt) { + let encoded: Vec = encode(&g, Infinite).unwrap(); + print!("{} (hex) = 0x", prefix); + for e in encoded.iter() { + print!("{:x}", e); + } + print!("\n"); + } } From 86449da92ec39b83faa885af9af75d9ed74d9b57 Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Tue, 18 Jun 2019 17:49:58 -0400 Subject: [PATCH 08/11] ccs08: fix after merge --- src/ccs08.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ccs08.rs b/src/ccs08.rs index 78d8564..0d5f3c9 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -10,7 +10,7 @@ extern crate rand; use rand::{thread_rng, Rng}; use super::*; use cl::{KeyPair, Signature, PublicParams, setup}; -use ped92::{CSPublicKey, Commitment}; +use ped92::{CSParams, Commitment}; use pairing::{Engine, CurveProjective}; use ff::PrimeField; use std::collections::HashMap; @@ -25,7 +25,7 @@ This must be computed in a trusted setup. struct ParamsUL { pub mpk: PublicParams, pub signatures: HashMap>, - pub com: CSPublicKey, + pub com: CSParams, kp: KeyPair, // 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. @@ -85,7 +85,7 @@ order to get smaller parameters, at the cost of having worse performance. signatures.insert(i.to_string(), sig_i); } - let com = CSPublicKey::setup(rng); + let com = CSParams::setup(rng); return ParamsUL { mpk, signatures, com, kp, u, l }; } From 9d6c4095b257d0a282fe98274a74b9c0f66f76c7 Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Tue, 18 Jun 2019 18:17:51 -0400 Subject: [PATCH 09/11] ccs08: add general proving and verifying method --- src/ccs08.rs | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/ccs08.rs b/src/ccs08.rs index 0d5f3c9..f26608f 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -293,6 +293,33 @@ impl RPPublicParams { panic!("log(b) is zero"); } } + + /* + Prove method is responsible for generating the zero knowledge proof. + */ + pub fn prove(&self, rng: &mut R, x: i64) -> RangeProof { + let ul = self.p.u.pow(self.p.l as u32); + let r = E::Fr::rand(rng); + + // x - b + ul + let xb = x + self.b + ul; + let first = self.p.prove_ul(rng, xb, r); + + // x - a + let xa = x - self.a; + let second = self.p.prove_ul(rng, xa, r); + + return RangeProof { p1: first, p2: second }; + } + + /* + Verify is responsible for validating the proof. + */ + pub fn verify(&self, proof: RangeProof) -> bool { + let first = self.p.verify_ul(&proof.p1); + let second = self.p.verify_ul(&proof.p2); + return first && second; + } } @@ -352,6 +379,16 @@ mod tests { assert_eq!(params.verify_ul(&proof), true); } + #[test] + #[ignore] + fn prove_and_verify_works() { + let rng = &mut rand::thread_rng(); + let params = RPPublicParams::::setup(rng, 2, 25); + let fr = Fr::rand(rng); + let proof = params.prove(rng, 10); + assert_eq!(params.verify(proof), true); + } + #[test] fn decompose_works() { assert_eq!(decompose(25, 3, 3), vec! {1, 2, 2}); From 6044b1b320c9ea4edcb582b3a12752baa7076d58 Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Wed, 26 Jun 2019 12:37:27 -0400 Subject: [PATCH 10/11] ccs08: finish range proof --- src/ccs08.rs | 167 ++++++++------------------------------------------- 1 file changed, 25 insertions(+), 142 deletions(-) diff --git a/src/ccs08.rs b/src/ccs08.rs index f26608f..efad2e7 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -113,28 +113,30 @@ prove_ul method is used to produce the ZKRP proof that secret x belongs to the i // D = H^m let mut hm = self.com.h.clone(); hm.mul_assign(m); - for i in 0..self.l as usize { + let x1 = for i in 0..self.l as usize { v.push(E::Fr::rand(rng)); - let r = E::Fr::rand(rng); - let mut A = self.signatures.get(&decx[i].to_string()).unwrap().h; - let mut B = self.signatures.get(&decx[i].to_string()).unwrap().H; + let r2 = E::Fr::rand(rng); + let signature = self.signatures.get(&decx[i].to_string()).unwrap(); + let mut A = signature.h; + let mut B = signature.H; let mut Aprime = A.clone(); - A.mul_assign(r); + A.mul_assign(r2); Aprime.mul_assign(v[i]); B.add_assign(&Aprime); - B.mul_assign(r); + B.mul_assign(r2); V.push((A, B)); s.push(E::Fr::rand(rng)); let mut gx = E::pairing(V[i].0, self.kp.public.X); - gx.pow(s[i].into_repr()); + gx = gx.pow(s[i].into_repr()); a.push(gx); t.push(E::Fr::rand(rng)); + assert_eq!(self.kp.public.Y.len(), 1); let mut gy = E::pairing(V[i].0, self.kp.public.Y[0]); - gy.pow(t[i].into_repr()); + gy = gy.pow(t[i].into_repr()); a[i].mul_assign(&gy); tt.push(E::Fr::rand(rng)); let mut h = E::pairing(V[i].0, self.mpk.g2); - h.pow(tt[i].into_repr()); + h = h.pow(tt[i].into_repr()); a[i].mul_assign(&h); let ui = self.u.pow(i as u32); @@ -143,7 +145,7 @@ prove_ul method is used to produce the ZKRP proof that secret x belongs to the i let mut aux = self.com.g.clone(); aux.mul_assign(muiti); D.add_assign(&aux); - } + }; D.add_assign(&hm); let C = self.com.commit(rng, modx, Some(r)); @@ -159,12 +161,12 @@ prove_ul method is used to produce the ZKRP proof that secret x belongs to the i let mut dx = E::Fr::from_str(&decx[i].to_string()).unwrap(); dx.mul_assign(&c); zsig[i].add_assign(&dx); - zx.push(c.clone()); - zx[i].add_assign(&s[i]); + zx.push(s[i].clone()); + zx[i].add_assign(&c); zv.push(tt[i].clone()); let mut vic = v[i].clone(); vic.mul_assign(&c); - tt[i].add_assign(&vic); + zv[i].add_assign(&vic); } return ProofUL { V, D, comm: C, a, zx, zsig, zv, ch: c, zr }; @@ -183,25 +185,21 @@ verify_ul is used to validate the ZKRP proof. It returns true iff the proof is v fn verify_part2(&self, proof: &ProofUL) -> bool { let mut r2 = true; for i in 0..self.l as usize { - let mut g = E::pairing(proof.V[i].1, self.mpk.g2); - g.pow(proof.ch.into_repr()); - g = g.inverse().unwrap(); - let mut gx = E::pairing(proof.V[i].0, self.kp.public.X); - gx.pow(proof.zx[i].into_repr()); - g.mul_assign(&gx); + gx = gx.pow(proof.zx[i].into_repr()); let mut gy = E::pairing(proof.V[i].0, self.kp.public.Y[0]); - gy.pow(proof.zsig[i].into_repr()); - g.mul_assign(&gy); + gy = gy.pow(proof.zsig[i].into_repr()); + gx.mul_assign(&gy); let mut h = E::pairing(proof.V[i].0, self.mpk.g2); - h.pow(proof.zv[i].into_repr()); - g.mul_assign(&h); + h = h.pow(proof.zv[i].into_repr()); + gx.mul_assign(&h); - print!("{}\n", g); - print!("{}\n", proof.a[i]); - r2 = r2 && g == proof.a[i]; + let mut g = E::pairing(proof.V[i].1, self.mpk.g2); + g = g.pow(proof.ch.into_repr()); + g.mul_assign(&proof.a[i]); + r2 = r2 && gx == g; } return r2; } @@ -302,7 +300,7 @@ impl RPPublicParams { let r = E::Fr::rand(rng); // x - b + ul - let xb = x + self.b + ul; + let xb = x - self.b + ul; let first = self.p.prove_ul(rng, xb, r); // x - a @@ -360,7 +358,6 @@ mod tests { } #[test] - #[ignore] fn prove_and_verify_part2_ul_works() { let rng = &mut rand::thread_rng(); let params = ParamsUL::::setup_ul(rng, 2, 4); @@ -370,7 +367,6 @@ mod tests { } #[test] - #[ignore] fn prove_and_verify_ul_works() { let rng = &mut rand::thread_rng(); let params = ParamsUL::::setup_ul(rng, 2, 4); @@ -380,11 +376,9 @@ mod tests { } #[test] - #[ignore] fn prove_and_verify_works() { let rng = &mut rand::thread_rng(); let params = RPPublicParams::::setup(rng, 2, 25); - let fr = Fr::rand(rng); let proof = params.prove(rng, 10); assert_eq!(params.verify(proof), true); } @@ -468,115 +462,4 @@ mod tests { assert_ne!(Hash::(a.clone(), D2.clone()), Hash::(a.clone(), D.clone())); assert_ne!(Hash::(a2.clone(), D2.clone()), Hash::(a.clone(), D.clone())); } - - #[test] - fn weird_stuff_happening() { - let rng = &mut rand::thread_rng(); - let g1 = G1::rand(rng); - let g2 = G2::rand(rng); - let mut g = Bls12::pairing(g1, g2); - let mut c = Fr::rand(rng); - print!("{}\n", c); - let mut gprime = Bls12::pairing(g1, g2); -// let mut cneg = c.clone(); -// cneg.negate(); - let mut cneg = Fr::zero(); - cneg.sub_assign(&c); - let mut zero = cneg.clone(); - zero.add_assign(&c); - assert_eq!(zero, Fr::zero()); - gprime.pow(cneg.into_repr()); - g.pow(c.into_repr()); - let mut gtest = g.clone(); - let ginv = g.inverse().unwrap(); - //TODO: this should actually work: assert_eq!(ginv, gprime); - - //TODO: instead this works: - gprime.mul_assign(&g); - g.square(); - cneg.add_assign(&c); - assert_eq!(cneg, Fr::zero()); - assert_eq!(gprime, g); - } - - #[test] - fn more_weird_stuff_happening() { - let rng = &mut rand::thread_rng(); - let g1 = G1::rand(rng); - let g2 = G2::rand(rng); -// let mut g = Bls12::pairing(g1, g2); - let mut g = Fq12::rand(rng); - let mut c = Fr::rand(rng); - print!("{}\n", c); - let mut gprime = g.clone(); - let mut gc = g.clone(); - gc.pow(c.into_repr()); - g.mul_assign(&gc); - - c.add_assign(&Fr::one()); - gprime.pow(c.into_repr()); - - //Todo: should: assert_eq!(gprime, g); - } - - #[test] - fn test_more_weird_stuff_with_bn() { - use bn::{Fr, G1, G2, Gt, pairing, SerializableGt}; - use std::ops::Add; - use std::ops::Mul; - - let rng = &mut rand::thread_rng(); - let g1 = G1::random(rng); - let g2 = G2::random(rng); - let mut g = pairing(g1, g2); - let mut c = Fr::random(rng); - let mut gprime = g.clone(); - let mut gc = g.clone(); - gc = gc.pow(c); - g = g.mul(gc); - - c = c.add(Fr::one()); - gprime = gprime.pow(c); - - debug_gt_in_hex("", &gprime); - debug_gt_in_hex("", &g); - assert!(gprime == g); - } - - #[test] - fn test_weird_stuff_with_bn() { - use bn::{Fr, G1, G2, Gt, pairing, SerializableGt}; - use std::ops::Add; - use std::ops::Sub; - use std::ops::Mul; - - let rng = &mut rand::thread_rng(); - let g1 = G1::random(rng); - let g2 = G2::random(rng); - let mut g = pairing(g1, g2); - let mut c = Fr::random(rng); - let mut gprime = pairing(g1, g2); -// let mut cneg = c.clone(); -// cneg.negate(); - let mut cneg = Fr::zero(); - cneg = cneg.sub(c); - - gprime = gprime.pow(cneg); - g = g.pow(c); - let mut gtest = g.clone(); - let ginv = g.inverse(); - - debug_gt_in_hex("", &ginv); - debug_gt_in_hex("", &gprime); - assert!(gprime == ginv); - } - - pub fn debug_gt_in_hex(prefix: &str, g: &Gt) { - let encoded: Vec = encode(&g, Infinite).unwrap(); - print!("{} (hex) = 0x", prefix); - for e in encoded.iter() { - print!("{:x}", e); - } - print!("\n"); - } } From cacdefd0f78dd5f28c93daf0a7ed105548d59ab6 Mon Sep 17 00:00:00 2001 From: Gijs Van Laer Date: Wed, 26 Jun 2019 13:33:08 -0400 Subject: [PATCH 11/11] ccs08: cleanup warnings --- src/ccs08.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/ccs08.rs b/src/ccs08.rs index efad2e7..02c938f 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -108,12 +108,12 @@ prove_ul method is used to produce the ZKRP proof that secret x belongs to the i let mut zsig = Vec::::with_capacity(self.l as usize); let mut zv = Vec::::with_capacity(self.l as usize); let mut D = E::G2::zero(); - let mut m = E::Fr::rand(rng); + let m = E::Fr::rand(rng); // D = H^m let mut hm = self.com.h.clone(); hm.mul_assign(m); - let x1 = for i in 0..self.l as usize { + for i in 0..self.l as usize { v.push(E::Fr::rand(rng)); let r2 = E::Fr::rand(rng); let signature = self.signatures.get(&decx[i].to_string()).unwrap(); @@ -145,7 +145,7 @@ prove_ul method is used to produce the ZKRP proof that secret x belongs to the i let mut aux = self.com.g.clone(); aux.mul_assign(muiti); D.add_assign(&aux); - }; + } D.add_assign(&hm); let C = self.com.commit(rng, modx, Some(r)); @@ -237,7 +237,7 @@ fn Hash(a: Vec, D: E::G2) -> E::Fr { let mut hash_buf: [u8; 64] = [0; 64]; hash_buf.copy_from_slice(&sha2_digest[0..64]); - let mut hexresult = fmt_bytes_to_int(hash_buf); + let hexresult = fmt_bytes_to_int(hash_buf); let result = E::Fr::from_str(&hexresult); return result.unwrap(); } @@ -249,7 +249,7 @@ 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 { + for _i in 0..l { result.push(decomposer % u); decomposer = decomposer / u; } @@ -276,7 +276,6 @@ impl RPPublicParams { if a > b { panic!("a must be less than or equal to b"); } - let p: PublicParams; let logb = (b as f64).log10(); if logb != 0.0 { let u = b / logb as i64; @@ -427,21 +426,21 @@ mod tests { #[should_panic(expected = "a must be less than or equal to b")] fn setup_wrong_a_and_b() { let rng = &mut rand::thread_rng(); - let public_params = RPPublicParams::::setup(rng, 10, 2); + RPPublicParams::::setup(rng, 10, 2); } #[test] #[should_panic(expected = "u is zero")] fn setup_wrong_b() { let rng = &mut rand::thread_rng(); - let public_params = RPPublicParams::::setup(rng, -1, 0); + RPPublicParams::::setup(rng, -1, 0); } #[test] #[should_panic(expected = "log(b) is zero")] fn setup_wrong_logb() { let rng = &mut rand::thread_rng(); - let public_params = RPPublicParams::::setup(rng, -1, 1); + RPPublicParams::::setup(rng, -1, 1); } #[test]