Merge pull request #7 from boltlabs-inc/nizk

Nizk updates
This commit is contained in:
J. Ayo Akinyele 2019-07-21 11:07:47 -04:00 committed by GitHub
commit ddbae8980e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 589 additions and 397 deletions

View File

@ -10,7 +10,7 @@ extern crate rand;
use rand::{thread_rng, Rng}; use rand::{thread_rng, Rng};
use super::*; use super::*;
use cl::{KeyPair, Signature, PublicParams, setup, BlindKeyPair, ProofState, SignatureProof}; use cl::{KeyPair, Signature, PublicParams, setup, BlindKeyPair, ProofState, SignatureProof};
use ped92::{CSParams, Commitment}; use ped92::{Commitment, CSMultiParams};
use pairing::{Engine, CurveProjective}; use pairing::{Engine, CurveProjective};
use ff::PrimeField; use ff::PrimeField;
use std::collections::HashMap; use std::collections::HashMap;
@ -26,29 +26,47 @@ This must be computed in a trusted setup.
struct ParamsUL<E: Engine> { struct ParamsUL<E: Engine> {
pub mpk: PublicParams<E>, pub mpk: PublicParams<E>,
pub signatures: HashMap<String, Signature<E>>, pub signatures: HashMap<String, Signature<E>>,
pub com: CSParams<E>, pub csParams: CSMultiParams<E>,
kp: BlindKeyPair<E>, kp: BlindKeyPair<E>,
// u determines the amount of signatures we need in the public params. // 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. // Each signature can be compressed to just 1 field element of 256 bits.
// Then the parameters have minimum size equal to 256*u bits. // Then the parameters have minimum size equal to 256*u bits.
u: i64, u: i32,
// l determines how many pairings we need to compute, then in order to improve // l determines how many pairings we need to compute, then in order to improve
// verifier`s performance we want to minize it. // verifier`s performance we want to minize it.
// Namely, we have 2*l pairings for the prover and 3*l for the verifier. // Namely, we have 2*l pairings for the prover and 3*l for the verifier.
l: i64, l: i32,
}
#[derive(Clone)]
pub struct ProofULState<E: Engine> {
pub decx: Vec<i32>,
pub proofStates: Vec<ProofState<E>>,
pub V: Vec<Signature<E>>,
pub D: E::G1,
pub m: E::Fr,
pub s: Vec<E::Fr>,
} }
/** /**
proofUL contains the necessary elements for the ZK range proof with range [0,u^l). proofUL contains the necessary elements for the ZK range proof with range [0,u^l).
*/ */
#[derive(Clone)] #[derive(Clone)]
struct ProofUL<E: Engine> { pub struct ProofUL<E: Engine> {
V: Vec<Signature<E>>, pub V: Vec<Signature<E>>,
D: E::G2, pub D: E::G1,
comm: Commitment<E>, pub comm: Commitment<E>,
sigProofs: Vec<SignatureProof<E>>, pub sigProofs: Vec<SignatureProof<E>>,
ch: E::Fr, pub zr: E::Fr,
zr: E::Fr, pub zs: Vec<E::Fr>,
}
#[derive(Clone)]
pub struct RangeProofState<E: Engine> {
pub com1: Commitment<E>,
pub ps1: ProofULState<E>,
pub com2: Commitment<E>,
pub ps2: ProofULState<E>,
} }
/** /**
@ -56,8 +74,8 @@ RangeProof contains the necessary elements for the ZK range proof.
*/ */
#[derive(Clone)] #[derive(Clone)]
pub struct RangeProof<E: Engine> { pub struct RangeProof<E: Engine> {
p1: ProofUL<E>, pub p1: ProofUL<E>,
p2: ProofUL<E>, pub p2: ProofUL<E>,
} }
/** /**
@ -67,8 +85,8 @@ This must be computed in a trusted setup.
#[derive(Clone)] #[derive(Clone)]
pub struct RPPublicParams<E: Engine> { pub struct RPPublicParams<E: Engine> {
p: ParamsUL<E>, p: ParamsUL<E>,
a: i64, a: i32,
b: i64, b: i32,
} }
impl<E: Engine> ParamsUL<E> { impl<E: Engine> ParamsUL<E> {
@ -77,7 +95,7 @@ impl<E: Engine> ParamsUL<E> {
The value of u should be roughly b/log(b), but we can choose smaller values in 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. order to get smaller parameters, at the cost of having worse performance.
*/ */
pub fn setup_ul<R: Rng>(rng: &mut R, u: i64, l: i64) -> Self { pub fn setup_ul<R: Rng>(rng: &mut R, u: i32, l: i32, csParams: CSMultiParams<E>) -> Self {
let mpk = setup(rng); let mpk = setup(rng);
let kp = BlindKeyPair::<E>::generate(rng, &mpk, 1); let kp = BlindKeyPair::<E>::generate(rng, &mpk, 1);
@ -87,131 +105,176 @@ impl<E: Engine> ParamsUL<E> {
signatures.insert(i.to_string(), sig_i); signatures.insert(i.to_string(), sig_i);
} }
let com = CSParams::setup(rng); return ParamsUL { mpk, signatures, csParams, kp, u, l };
return ParamsUL { mpk, signatures, com, kp, u, l };
} }
/** /**
prove_ul method is used to produce the ZKRP proof that secret x belongs to the interval [0,U^L). prove_ul method is used to produce the ZKRP proof that secret x belongs to the interval [0,U^L).
*/ */
pub fn prove_ul<R: Rng>(&self, rng: &mut R, x: i64, r: E::Fr) -> ProofUL<E> { pub fn prove_ul<R: Rng>(&self, rng: &mut R, x: i32, r: E::Fr, C: Commitment<E>, k: usize, otherM: Vec<E::Fr>) -> ProofUL<E> {
let proofUlState = self.prove_ul_commitment(rng, x, k);
// Fiat-Shamir heuristic
let mut a = Vec::<E::Fqk>::with_capacity(self.l as usize);
for state in proofUlState.proofStates.clone() {
a.push(state.a);
}
let c = hash::<E>(a, vec!(proofUlState.D.clone()));
self.prove_ul_response(r, C, &proofUlState, c, k, otherM)
}
fn prove_ul_commitment<R: Rng>(&self, rng: &mut R, x: i32, k: usize) -> ProofULState<E> {
if x > self.u.pow(self.l as u32) || x < 0 { if x > self.u.pow(self.l as u32) || x < 0 {
panic!("x is not within the range."); panic!("x is not within the range.");
} }
let decx = decompose(x, self.u, self.l); let decx = decompose(x, self.u, self.l);
let modx = E::Fr::from_str(&(x.to_string())).unwrap();
// Initialize variables // Initialize variables
let mut proofStates = Vec::<ProofState<E>>::with_capacity(self.l as usize); let mut proofStates = Vec::<ProofState<E>>::with_capacity(self.l as usize);
let mut sigProofs = Vec::<SignatureProof<E>>::with_capacity(self.l as usize);
let mut V = Vec::<Signature<E>>::with_capacity(self.l as usize); let mut V = Vec::<Signature<E>>::with_capacity(self.l as usize);
let mut D = E::G2::zero(); let mut s = Vec::<E::Fr>::with_capacity(self.csParams.pub_bases.len() - 2);
let mut D = E::G1::zero();
let m = E::Fr::rand(rng); let m = E::Fr::rand(rng);
// D = H^m // D = H^m
let mut hm = self.com.h2.clone(); let mut hm = self.csParams.pub_bases[0].clone();
hm.mul_assign(m); hm.mul_assign(m);
for i in 0..self.l as usize { for i in 0..self.l as usize {
let signature = self.signatures.get(&decx[i].to_string()).unwrap(); let signature = self.signatures.get(&decx[i].to_string()).unwrap();
let proofState = self.kp.prove_commitment(rng, &self.mpk, &signature); let proofState = self.kp.prove_commitment(rng, &self.mpk, &signature, None, None);
V.push(proofState.blindSig.clone()); V.push(proofState.blindSig.clone());
proofStates.push(proofState); proofStates.push(proofState);
let ui = self.u.pow(i as u32); let ui = self.u.pow(i as u32);
let mut aux = self.com.g2.clone(); let mut aux = self.csParams.pub_bases[k].clone();
for j in 0..self.kp.public.Y2.len() { for j in 0..self.kp.public.Y1.len() {
let mut muiti = proofStates[i].t[j].clone(); let mut muiti = proofStates[i].t[j].clone();
muiti.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap()); muiti.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap());
aux.mul_assign(muiti); aux.mul_assign(muiti);
} }
D.add_assign(&aux); D.add_assign(&aux);
} }
D.add_assign(&hm); for i in 1..self.csParams.pub_bases.len() {
if i != k {
let C = self.com.commit(rng, modx, Some(r)); let mut g = self.csParams.pub_bases[i].clone();
// Fiat-Shamir heuristic let s1 = E::Fr::rand(rng);
let mut a = Vec::<E::Fqk>::with_capacity(self.l as usize); s.push(s1);
for state in proofStates.clone() { g.mul_assign(s1);
a.push(state.a); D.add_assign(&g);
}
} }
let c = hash::<E>(a, D.clone());
let mut zr = m.clone(); D.add_assign(&hm);
ProofULState { decx, proofStates, V, D, m, s }
}
fn prove_ul_response(&self, r: E::Fr, C: Commitment<E>, proofUlState: &ProofULState<E>, c: E::Fr, k: usize, otherM: Vec<E::Fr>) -> ProofUL<E> {
let mut sigProofs = Vec::<SignatureProof<E>>::with_capacity(self.l as usize);
let mut zr = proofUlState.m.clone();
let mut rc = r.clone(); let mut rc = r.clone();
rc.mul_assign(&c); rc.mul_assign(&c);
zr.add_assign(&rc); zr.add_assign(&rc);
for i in 0..self.l as usize { for i in 0..self.l as usize {
let mut dx = E::Fr::from_str(&decx[i].to_string()).unwrap(); let mut dx = E::Fr::from_str(&proofUlState.decx[i].to_string()).unwrap();
let proof = self.kp.prove_response(&proofStates[i].clone(), c, &mut vec! {dx}); let proof = self.kp.prove_response(&proofUlState.proofStates[i].clone(), c, &mut vec! {dx});
sigProofs.push(proof); sigProofs.push(proof);
} }
return ProofUL { V, D, comm: C, sigProofs, ch: c, zr }; let mut zs = Vec::<E::Fr>::with_capacity(self.csParams.pub_bases.len() - 2);
for i in 1..self.csParams.pub_bases.len() {
let mut j: usize;
if i < k {
j = i - 1;
} else if i > k {
j = i - 2;
} else {
continue;
}
let mut mc = otherM[j].clone();
mc.mul_assign(&c);
let mut s = proofUlState.s[j].clone();
s.add_assign(&mc);
zs.push(s);
}
ProofUL { V: proofUlState.V.clone(), D: proofUlState.D.clone(), comm: C, sigProofs, zr, zs }
} }
/** /**
verify_ul is used to validate the ZKRP proof. It returns true iff the proof is valid. verify_ul is used to validate the ZKRP proof. It returns true iff the proof is valid.
*/ */
pub fn verify_ul(&self, proof: &ProofUL<E>) -> bool { pub fn verify_ul(&self, proof: &ProofUL<E>, ch: E::Fr, k: usize) -> bool {
// D == C^c.h^ zr.g^zsig ? let r1 = self.verify_part1(&proof, ch.clone(), k);
let r = self.verify_challenge(&proof); let r2 = self.verify_part2(&proof, ch.clone());
let r1 = self.verify_part1(&proof); r1 && r2
let r2 = self.verify_part2(&proof);
r && r1 && r2
} }
fn verify_challenge(&self, proof: &ProofUL<E>) -> bool { fn compute_challenge(&self, proof: &ProofUL<E>) -> E::Fr {
let mut a = Vec::<E::Fqk>::with_capacity(self.l as usize); let mut a = Vec::<E::Fqk>::with_capacity(self.l as usize);
for sigProof in proof.sigProofs.clone() { for sigProof in proof.sigProofs.clone() {
a.push(sigProof.a); a.push(sigProof.a);
} }
let c = hash::<E>(a, proof.D.clone()); hash::<E>(a, vec!(proof.D.clone()))
proof.ch == c
} }
fn verify_part2(&self, proof: &ProofUL<E>) -> bool { fn verify_part2(&self, proof: &ProofUL<E>, challenge: E::Fr) -> bool {
let mut r2 = true; let mut r2 = true;
for i in 0..self.l as usize { for i in 0..self.l as usize {
let subResult = self.kp.public.verify_proof(&self.mpk, proof.V[i].clone(), proof.sigProofs[i].clone(), proof.ch); let subResult = self.kp.public.verify_proof(&self.mpk, proof.V[i].clone(), proof.sigProofs[i].clone(), challenge);
r2 = r2 && subResult; r2 = r2 && subResult;
} }
r2 r2
} }
fn verify_part1(&self, proof: &ProofUL<E>) -> bool { fn verify_part1(&self, proof: &ProofUL<E>, challenge: E::Fr, k: usize) -> bool {
let mut D = proof.comm.c2.clone(); let mut D = proof.comm.c.clone();
D.mul_assign(proof.ch); D.mul_assign(challenge);
D.negate(); D.negate();
let mut hzr = self.com.h2.clone(); let mut hzr = self.csParams.pub_bases[0].clone();
hzr.mul_assign(proof.zr); hzr.mul_assign(proof.zr);
D.add_assign(&hzr); D.add_assign(&hzr);
for i in 0..self.l as usize { for i in 0..self.l as usize {
let ui = self.u.pow(i as u32); let ui = self.u.pow(i as u32);
let mut aux = self.com.g2.clone(); let mut aux = self.csParams.pub_bases[k].clone();
for j in 0..self.kp.public.Y2.len() { for j in 0..self.kp.public.Y1.len() {
let mut muizsigi = proof.sigProofs[i].zsig[j]; let mut muizsigi = proof.sigProofs[i].zsig[j];
muizsigi.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap()); muizsigi.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap());
aux.mul_assign(muizsigi); aux.mul_assign(muizsigi);
} }
D.add_assign(&aux); D.add_assign(&aux);
} }
for i in 1..self.csParams.pub_bases.len() {
let mut j: usize;
if i < k {
j = i - 1;
} else if i > k {
j = i - 2;
} else {
continue;
}
let mut g = self.csParams.pub_bases[i].clone();
g.mul_assign(proof.zs[j].into_repr());
D.add_assign(&g);
}
D == proof.D D == proof.D
} }
} }
fn hash<E: Engine>(a: Vec<E::Fqk>, D: E::G2) -> E::Fr { fn hash<E: Engine>(a: Vec<E::Fqk>, D: Vec<E::G1>) -> E::Fr {
// create a Sha256 object // create a Sha256 object
let mut a_vec: Vec<u8> = Vec::new(); let mut a_vec: Vec<u8> = Vec::new();
for a_el in a { for a_el in a {
a_vec.extend(format!("{}", a_el).bytes()); a_vec.extend(format!("{}", a_el).bytes());
} }
let mut x_vec: Vec<u8> = Vec::new(); let mut x_vec: Vec<u8> = Vec::new();
x_vec.extend(format!("{}", D).bytes()); for d_el in D {
x_vec.extend(format!("{}", d_el).bytes());
}
a_vec.extend(x_vec); a_vec.extend(x_vec);
util::hash_to_fr::<E>(a_vec) util::hash_to_fr::<E>(a_vec)
@ -221,7 +284,7 @@ fn hash<E: Engine>(a: Vec<E::Fqk>, D: E::G2) -> E::Fr {
Decompose receives as input an integer x and outputs an array of integers such that 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. 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<i64> { fn decompose(x: i32, u: i32, l: i32) -> Vec<i32> {
let mut result = Vec::with_capacity(l as usize); let mut result = Vec::with_capacity(l as usize);
let mut decomposer = x.clone(); let mut decomposer = x.clone();
for _i in 0..l { for _i in 0..l {
@ -235,21 +298,22 @@ impl<E: Engine> RPPublicParams<E> {
/** /**
Setup receives integers a and b, and configures the parameters for the rangeproof scheme. Setup receives integers a and b, and configures the parameters for the rangeproof scheme.
*/ */
pub fn setup<R: Rng>(rng: &mut R, a: i64, b: i64) -> Self { pub fn setup<R: Rng>(rng: &mut R, a: i32, b: i32, csParams: CSMultiParams<E>) -> Self {
// Compute optimal values for u and l // Compute optimal values for u and l
if a > b { if a > b {
panic!("a must be less than or equal to b"); panic!("a must be less than or equal to b");
} }
//TODO: optimize u? //TODO: optimize u?
let logb = (b as f64).log2(); let logb = (b as f32).log2();
let loglogb = logb.log2(); let loglogb = logb.log2();
if loglogb > 0.0 { if loglogb > 0.0 {
let mut u = (logb / loglogb) as i64; let mut u = (logb / loglogb) as i32;
if u < 2 { if u < 2 {
u = 2; u = 2;
} }
let l = (b as f64).log(u as f64).ceil() as i64; let l = (b as f32).log(u as f32).ceil() as i32;
let params_out: ParamsUL<E> = ParamsUL::<E>::setup_ul(rng, u, l);
let params_out: ParamsUL<E> = ParamsUL::<E>::setup_ul(rng, u, l, csParams.clone());
return RPPublicParams { p: params_out, a, b }; return RPPublicParams { p: params_out, a, b };
} else { } else {
panic!("log(log(b)) is zero"); panic!("log(log(b)) is zero");
@ -259,31 +323,70 @@ impl<E: Engine> RPPublicParams<E> {
/** /**
Prove method is responsible for generating the zero knowledge range proof. Prove method is responsible for generating the zero knowledge range proof.
*/ */
pub fn prove<R: Rng>(&self, rng: &mut R, x: i64) -> RangeProof<E> { pub fn prove<R: Rng>(&self, rng: &mut R, x: i32, C: Commitment<E>, r: E::Fr, k: usize, otherM: Vec<E::Fr>) -> RangeProof<E> {
let rpState = self.prove_commitment(rng, x, C, k);
let mut a = Vec::<E::Fqk>::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::<E>(a, vec!(rpState.ps1.D.clone(), rpState.ps2.D.clone()));
self.prove_response(r, &rpState, ch, k, otherM)
}
pub fn prove_commitment<R: Rng>(&self, rng: &mut R, x: i32, C: Commitment<E>, k: usize) -> RangeProofState<E> {
if x > self.b || x < self.a { if x > self.b || x < self.a {
panic!("x is not within the range."); panic!("x is not within the range.");
} }
let ul = self.p.u.pow(self.p.l as u32); let ul = self.p.u.pow(self.p.l as u32);
let r = E::Fr::rand(rng);
// x - b + ul // x - b + ul
let xb = x - self.b + ul; let xb = x - self.b + ul;
let first = self.p.prove_ul(rng, xb, r); 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);
// x - a // x - a
let xa = x - self.a; let xa = x - self.a;
let second = self.p.prove_ul(rng, xa, r); 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);
RangeProofState { com1: comXB, ps1: firstState, com2: comXA, ps2: secondState }
}
return RangeProof { p1: first, p2: second }; pub fn prove_response(&self, r: E::Fr, rpState: &RangeProofState<E>, ch: E::Fr, k: usize, otherM: Vec<E::Fr>) -> RangeProof<E> {
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 }
} }
/** /**
Verify is responsible for validating the range proof. Verify is responsible for validating the range proof.
*/ */
pub fn verify(&self, proof: RangeProof<E>) -> bool { pub fn verify(&self, proof: RangeProof<E>, ch: E::Fr, k: usize) -> bool {
let first = self.p.verify_ul(&proof.p1); let first = self.p.verify_ul(&proof.p1, ch.clone(), k);
let second = self.p.verify_ul(&proof.p2); let second = self.p.verify_ul(&proof.p2, ch.clone(), k);
return first && second; first & &second
}
fn compute_challenge(&self, proof: &RangeProof<E>) -> E::Fr {
let mut a = Vec::<E::Fqk>::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::<E>(a, vec!(proof.p1.D.clone(), proof.p2.D.clone()))
} }
} }
@ -291,7 +394,7 @@ impl<E: Engine> RPPublicParams<E> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use pairing::bls12_381::{Bls12, G1, G2, Fq12, Fr}; use pairing::bls12_381::{Bls12, G1, Fq12, Fr};
use time::PreciseTime; use time::PreciseTime;
use std::ops::Add; use std::ops::Add;
use core::mem; use core::mem;
@ -300,7 +403,9 @@ mod tests {
#[test] #[test]
fn setup_ul_works() { fn setup_ul_works() {
let rng = &mut rand::thread_rng(); let rng = &mut rand::thread_rng();
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 3); let csParams = CSMultiParams::setup_gen_params(rng, 1);
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 3, csParams.clone());
assert_eq!(params.signatures.len(), 2); assert_eq!(params.signatures.len(), 2);
for (m, s) in params.signatures { for (m, s) in params.signatures {
assert_eq!(params.kp.verify(&params.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &Fr::zero(), &s), true); assert_eq!(params.kp.verify(&params.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &Fr::zero(), &s), true);
@ -310,9 +415,13 @@ mod tests {
#[test] #[test]
fn prove_ul_works() { fn prove_ul_works() {
let rng = &mut rand::thread_rng(); let rng = &mut rand::thread_rng();
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 4); let csParams = CSMultiParams::setup_gen_params(rng, 1);
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 4, csParams.clone());
let fr = Fr::rand(rng); let fr = Fr::rand(rng);
let proof = params.prove_ul(rng, 10, fr); 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!{});
assert_eq!(proof.V.len(), 4); assert_eq!(proof.V.len(), 4);
assert_eq!(proof.sigProofs.len(), 4); assert_eq!(proof.sigProofs.len(), 4);
} }
@ -321,52 +430,108 @@ mod tests {
#[should_panic(expected = "x is not within the range")] #[should_panic(expected = "x is not within the range")]
fn prove_ul_not_in_range() { fn prove_ul_not_in_range() {
let rng = &mut rand::thread_rng(); let rng = &mut rand::thread_rng();
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 3); let csParams = CSMultiParams::setup_gen_params(rng, 1);
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 3, csParams.clone());
let fr = Fr::rand(rng); let fr = Fr::rand(rng);
params.prove_ul(rng, 100, fr); 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!{});
} }
#[test] #[test]
fn prove_and_verify_part1_ul_works() { fn prove_and_verify_part1_ul_works() {
let rng = &mut rand::thread_rng(); let rng = &mut rand::thread_rng();
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 4); let csParams = CSMultiParams::setup_gen_params(rng, 1);
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 4, csParams.clone());
let fr = Fr::rand(rng); let fr = Fr::rand(rng);
let proof = params.prove_ul(rng, 10, fr); let modx = Fr::from_str(&(10.to_string())).unwrap();
assert_eq!(params.verify_part1(&proof), true); 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);
} }
#[test] #[test]
fn prove_and_verify_part2_ul_works() { fn prove_and_verify_part2_ul_works() {
let rng = &mut rand::thread_rng(); let rng = &mut rand::thread_rng();
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 4); let csParams = CSMultiParams::setup_gen_params(rng, 1);
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 4, csParams.clone());
let fr = Fr::rand(rng); let fr = Fr::rand(rng);
let proof = params.prove_ul(rng, 10, fr); let modx = Fr::from_str(&(10.to_string())).unwrap();
assert_eq!(params.verify_part2(&proof), true); 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);
} }
#[test] #[test]
fn prove_and_verify_ul_works() { fn prove_and_verify_ul_works() {
let rng = &mut rand::thread_rng(); let rng = &mut rand::thread_rng();
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 4); let csParams = CSMultiParams::setup_gen_params(rng, 1);
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 4, csParams.clone());
let fr = Fr::rand(rng); let fr = Fr::rand(rng);
let proof = params.prove_ul(rng, 10, fr); let modx = Fr::from_str(&(10.to_string())).unwrap();
assert_eq!(params.verify_ul(&proof), true); 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);
}
#[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::<Bls12>::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);
} }
#[test] #[test]
fn prove_and_verify_works() { fn prove_and_verify_works() {
let rng = &mut rand::thread_rng(); let rng = &mut rand::thread_rng();
let params = RPPublicParams::<Bls12>::setup(rng, 2, 25); let csParams = CSMultiParams::setup_gen_params(rng, 1);
let proof = params.prove(rng, 10); let params = RPPublicParams::<Bls12>::setup(rng, 2, 25, csParams.clone());
assert_eq!(params.verify(proof), true); 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);
assert_eq!(params.verify(proof, ch, 1), true);
}
#[test]
fn prove_and_verify_bigger_commit_works() {
let rng = &mut rand::thread_rng();
let csParams = CSMultiParams::setup_gen_params(rng, 3);
let params = RPPublicParams::<Bls12>::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);
assert_eq!(params.verify(proof, ch, 2), true);
} }
#[test] #[test]
#[should_panic(expected = "x is not within the range")] #[should_panic(expected = "x is not within the range")]
fn prove_not_in_range() { fn prove_not_in_range() {
let rng = &mut rand::thread_rng(); let rng = &mut rand::thread_rng();
let params = RPPublicParams::<Bls12>::setup(rng, 2, 25); let csParams = CSMultiParams::setup_gen_params(rng, 1);
let proof = params.prove(rng, 26); let params = RPPublicParams::<Bls12>::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!{});
} }
#[test] #[test]
@ -385,17 +550,22 @@ mod tests {
let x = rng.gen_range(a, b); let x = rng.gen_range(a, b);
let sSetup = PreciseTime::now(); let sSetup = PreciseTime::now();
let params = RPPublicParams::<Bls12>::setup(rng, a, b); let csParams = CSMultiParams::setup_gen_params(rng, 1);
let params = RPPublicParams::<Bls12>::setup(rng, a, b, csParams.clone());
averageSetup = averageSetup.add(sSetup.to(PreciseTime::now())); averageSetup = averageSetup.add(sSetup.to(PreciseTime::now()));
averageSetupSize += mem::size_of_val(&params); averageSetupSize += mem::size_of_val(&params);
let sProve = PreciseTime::now(); let sProve = PreciseTime::now();
let proof = params.prove(rng, x); let fr = Fr::rand(rng);
let modx = Fr::from_str(&(x.to_string())).unwrap();
let C = csParams.commit(&vec!(modx), &fr.clone());
let proof = params.prove(rng, x, C, fr, 1, vec!{});
averageProve = averageProve.add(sProve.to(PreciseTime::now())); averageProve = averageProve.add(sProve.to(PreciseTime::now()));
averageProofSize += mem::size_of_val(&proof); averageProofSize += mem::size_of_val(&proof);
let sVerify = PreciseTime::now(); let sVerify = PreciseTime::now();
params.verify(proof); let ch = params.compute_challenge(&proof);
params.verify(proof, ch, 1);
averageVerify = averageVerify.add(sVerify.to(PreciseTime::now())); averageVerify = averageVerify.add(sVerify.to(PreciseTime::now()));
} }
print!("Setup: {}\n", averageSetup.num_milliseconds() / iter); print!("Setup: {}\n", averageSetup.num_milliseconds() / iter);
@ -419,14 +589,14 @@ mod tests {
let vec1 = decompose(25, 3, 5); let vec1 = decompose(25, 3, 5);
let mut result = 0; let mut result = 0;
for i in 0..5 { for i in 0..5 {
result += vec1[i] * 3i64.pow(i as u32); result += vec1[i] * 3i32.pow(i as u32);
} }
assert_eq!(result, 25); assert_eq!(result, 25);
let vec1 = decompose(143225, 6, 7); let vec1 = decompose(143225, 6, 7);
let mut result = 0; let mut result = 0;
for i in 0..7 { for i in 0..7 {
result += vec1[i] * 6i64.pow(i as u32); result += vec1[i] * 6i32.pow(i as u32);
} }
assert_eq!(result, 143225); assert_eq!(result, 143225);
} }
@ -434,7 +604,8 @@ mod tests {
#[test] #[test]
fn setup_works() { fn setup_works() {
let rng = &mut rand::thread_rng(); let rng = &mut rand::thread_rng();
let public_params = RPPublicParams::<Bls12>::setup(rng, 2, 10); let csParams = CSMultiParams::setup_gen_params(rng, 1);
let public_params = RPPublicParams::<Bls12>::setup(rng, 2, 10, csParams);
assert_eq!(public_params.a, 2); assert_eq!(public_params.a, 2);
assert_eq!(public_params.b, 10); assert_eq!(public_params.b, 10);
assert_eq!(public_params.p.signatures.len(), 2); assert_eq!(public_params.p.signatures.len(), 2);
@ -449,36 +620,38 @@ mod tests {
#[should_panic(expected = "a must be less than or equal to b")] #[should_panic(expected = "a must be less than or equal to b")]
fn setup_wrong_a_and_b() { fn setup_wrong_a_and_b() {
let rng = &mut rand::thread_rng(); let rng = &mut rand::thread_rng();
RPPublicParams::<Bls12>::setup(rng, 10, 2); let csParams = CSMultiParams::setup_gen_params(rng, 1);
RPPublicParams::<Bls12>::setup(rng, 10, 2, csParams);
} }
#[test] #[test]
#[should_panic(expected = "log(log(b)) is zero")] #[should_panic(expected = "log(log(b)) is zero")]
fn setup_wrong_logb() { fn setup_wrong_logb() {
let rng = &mut rand::thread_rng(); let rng = &mut rand::thread_rng();
RPPublicParams::<Bls12>::setup(rng, -2, -1); let csParams = CSMultiParams::setup_gen_params(rng, 1);
RPPublicParams::<Bls12>::setup(rng, -2, -1, csParams);
} }
#[test] #[test]
fn hash_works() { fn hash_works() {
let rng = &mut rand::thread_rng(); let rng = &mut rand::thread_rng();
let D = G2::rand(rng); let D = G1::rand(rng);
let D2 = G2::rand(rng); let D2 = G1::rand(rng);
let params = setup::<ThreadRng, Bls12>(rng); let params = setup::<ThreadRng, Bls12>(rng);
let kp = BlindKeyPair::generate(rng, &params, 2); let kp = BlindKeyPair::generate(rng, &params, 2);
let m1 = Fr::rand(rng); let m1 = Fr::rand(rng);
let m2 = Fr::rand(rng); let m2 = Fr::rand(rng);
let sig = kp.sign(rng, &vec! {m1, m2}); let sig = kp.sign(rng, &vec! {m1, m2});
let state = kp.prove_commitment(rng, &params, &sig); let state = kp.prove_commitment(rng, &params, &sig, None, None);
let state1 = kp.prove_commitment(rng, &params, &sig); let state1 = kp.prove_commitment(rng, &params, &sig, None, None);
let state2 = kp.prove_commitment(rng, &params, &sig); let state2 = kp.prove_commitment(rng, &params, &sig, None, None);
let state3 = kp.prove_commitment(rng, &params, &sig); let state3 = kp.prove_commitment(rng, &params, &sig, None, None);
let state4 = kp.prove_commitment(rng, &params, &sig); let state4 = kp.prove_commitment(rng, &params, &sig, None, None);
let a = vec! {state.a, state1.a, state2.a}; let a = vec! {state.a, state1.a, state2.a};
let a2 = vec! {state3.a, state4.a}; let a2 = vec! {state3.a, state4.a};
assert_eq!(hash::<Bls12>(a.clone(), D.clone()).is_zero(), false); assert_eq!(hash::<Bls12>(a.clone(), vec!(D.clone())).is_zero(), false);
assert_ne!(hash::<Bls12>(a2.clone(), D.clone()), hash::<Bls12>(a.clone(), D.clone())); assert_ne!(hash::<Bls12>(a2.clone(), vec!(D.clone())), hash::<Bls12>(a.clone(), vec!(D.clone())));
assert_ne!(hash::<Bls12>(a.clone(), D2.clone()), hash::<Bls12>(a.clone(), D.clone())); assert_ne!(hash::<Bls12>(a.clone(), vec!(D2.clone())), hash::<Bls12>(a.clone(), vec!(D.clone())));
assert_ne!(hash::<Bls12>(a2.clone(), D2.clone()), hash::<Bls12>(a.clone(), D.clone())); assert_ne!(hash::<Bls12>(a2.clone(), vec!(D2.clone())), hash::<Bls12>(a.clone(), vec!(D.clone())))
} }
} }

View File

@ -192,7 +192,7 @@ impl<E: Engine> CustomerWallet<E> {
// generate nizk proof of knowledge of commitment opening // generate nizk proof of knowledge of commitment opening
pub fn generate_proof<R: Rng>(&mut self, csprng: &mut R, channel_token: &ChannelToken<E>) -> CommitmentProof<E> { pub fn generate_proof<R: Rng>(&mut self, csprng: &mut R, channel_token: &ChannelToken<E>) -> CommitmentProof<E> {
return CommitmentProof::<E>::new(csprng, &channel_token.comParams, &self.w_com.c1, &self.w_vec, &self.r); return CommitmentProof::<E>::new(csprng, &channel_token.comParams, &self.w_com.c, &self.w_vec, &self.r);
} }
} }
@ -237,7 +237,7 @@ impl<E: Engine> MerchantWallet<E> {
} }
pub fn verify_proof<R: Rng>(&self, csprng: &mut R, channel: &ChannelState<E>, com: &Commitment<E>, com_proof: &CommitmentProof<E>) -> Signature<E> { pub fn verify_proof<R: Rng>(&self, csprng: &mut R, channel: &ChannelState<E>, com: &Commitment<E>, com_proof: &CommitmentProof<E>) -> Signature<E> {
let is_valid = util::verify(&self.comParams, &com.c1, &com_proof); let is_valid = util::verify(&self.comParams, &com.c, &com_proof);
let cp = channel.cp.as_ref().unwrap(); let cp = channel.cp.as_ref().unwrap();
if is_valid { if is_valid {
println!("Commitment PoK is valid!"); println!("Commitment PoK is valid!");

View File

@ -13,13 +13,13 @@ use std::fmt::LowerHex;
#[derive(Clone)] #[derive(Clone)]
pub struct PublicParams<E: Engine> { pub struct PublicParams<E: Engine> {
pub g1: E::G1, pub g1: E::G1,
pub g2: E::G2 pub g2: E::G2,
} }
#[derive(Clone)] #[derive(Clone)]
pub struct SecretKey<E: Engine> { pub struct SecretKey<E: Engine> {
pub x: E::Fr, pub x: E::Fr,
pub y: Vec<E::Fr> pub y: Vec<E::Fr>,
} }
#[derive(Clone, Serialize, Deserialize)] #[derive(Clone, Serialize, Deserialize)]
@ -61,19 +61,19 @@ pub struct BlindPublicKey<E: Engine> {
#[derive(Clone)] #[derive(Clone)]
pub struct Signature<E: Engine> { pub struct Signature<E: Engine> {
pub h: E::G1, pub h: E::G1,
pub H: E::G1 pub H: E::G1,
} }
#[derive(Clone)] #[derive(Clone)]
pub struct KeyPair<E: Engine> { pub struct KeyPair<E: Engine> {
pub secret: SecretKey<E>, pub secret: SecretKey<E>,
pub public: PublicKey<E> pub public: PublicKey<E>,
} }
#[derive(Clone)] #[derive(Clone)]
pub struct BlindKeyPair<E: Engine> { pub struct BlindKeyPair<E: Engine> {
pub secret: SecretKey<E>, pub secret: SecretKey<E>,
pub public: BlindPublicKey<E> pub public: BlindPublicKey<E>,
} }
#[derive(Clone)] #[derive(Clone)]
@ -83,7 +83,7 @@ pub struct ProofState<E: Engine> {
pub t: Vec<E::Fr>, pub t: Vec<E::Fr>,
pub tt: E::Fr, pub tt: E::Fr,
pub a: E::Fqk, pub a: E::Fqk,
pub blindSig: Signature<E> pub blindSig: Signature<E>,
} }
#[derive(Clone)] #[derive(Clone)]
@ -91,14 +91,14 @@ pub struct SignatureProof<E: Engine> {
pub zx: E::Fr, pub zx: E::Fr,
pub zsig: Vec<E::Fr>, pub zsig: Vec<E::Fr>,
pub zv: E::Fr, pub zv: E::Fr,
pub a: E::Fqk pub a: E::Fqk,
} }
impl<E: Engine> SecretKey<E> { impl<E: Engine> SecretKey<E> {
pub fn generate<R: Rng>(csprng: &mut R, l: usize) -> Self { pub fn generate<R: Rng>(csprng: &mut R, l: usize) -> Self {
let mut y: Vec<E::Fr> = Vec::new(); let mut y: Vec<E::Fr> = Vec::new();
for i in 0 .. l { for i in 0..l {
let _y = E::Fr::rand(csprng); let _y = E::Fr::rand(csprng);
y.push(_y); y.push(_y);
} }
@ -111,7 +111,7 @@ impl<E: Engine> SecretKey<E> {
let mut s = E::Fr::zero(); let mut s = E::Fr::zero();
// check vector length first // check vector length first
assert_eq!(self.y.len(), message.len()); assert_eq!(self.y.len(), message.len());
for i in 0 .. message.len() { for i in 0..message.len() {
// s = s + (self.y[i] * message[i]); // s = s + (self.y[i] * message[i]);
let mut res_yi = self.y[i]; let mut res_yi = self.y[i];
res_yi.mul_assign(&message[i]); res_yi.mul_assign(&message[i]);
@ -143,7 +143,6 @@ impl<E: Engine> SecretKey<E> {
H1.mul_assign(r); H1.mul_assign(r);
Signature { h: h1, H: H1 } Signature { h: h1, H: H1 }
} }
} }
@ -186,7 +185,7 @@ impl<E: Engine> SecretKey<E> {
impl<E: Engine> PublicKey<E> { impl<E: Engine> PublicKey<E> {
pub fn from_secret(mpk: &PublicParams<E>, secret: &SecretKey<E>) -> Self { pub fn from_secret(mpk: &PublicParams<E>, secret: &SecretKey<E>) -> Self {
let mut Y: Vec<E::G2> = Vec::new(); let mut Y: Vec<E::G2> = Vec::new();
for i in 0 .. secret.y.len() { for i in 0..secret.y.len() {
// Y[i] = g2 ^ y[i] // Y[i] = g2 ^ y[i]
let mut g2 = mpk.g2; let mut g2 = mpk.g2;
g2.mul_assign(secret.y[i]); g2.mul_assign(secret.y[i]);
@ -197,13 +196,13 @@ impl<E: Engine> PublicKey<E> {
X.mul_assign(secret.x); X.mul_assign(secret.x);
PublicKey { PublicKey {
X: X, X: X,
Y: Y Y: Y,
} }
} }
pub fn verify(&self, mpk: &PublicParams<E>, message: &Vec<E::Fr>, signature: &Signature<E>) -> bool { pub fn verify(&self, mpk: &PublicParams<E>, message: &Vec<E::Fr>, signature: &Signature<E>) -> bool {
let mut L = E::G2::zero(); let mut L = E::G2::zero();
for i in 0 .. self.Y.len() { for i in 0..self.Y.len() {
// L = L + self.Y[i].mul(message[i]); // L = L + self.Y[i].mul(message[i]);
let mut Y = self.Y[i]; let mut Y = self.Y[i];
Y.mul_assign(message[i]); // Y_i ^ m_i Y.mul_assign(message[i]); // Y_i ^ m_i
@ -218,7 +217,7 @@ impl<E: Engine> PublicKey<E> {
} }
} }
impl<E: Engine> BlindPublicKey<E> { impl<E: Engine> BlindPublicKey<E> {
pub fn from_secret(mpk: &PublicParams<E>, secret: &SecretKey<E>) -> Self { pub fn from_secret(mpk: &PublicParams<E>, secret: &SecretKey<E>) -> Self {
let mut Y1: Vec<E::G1> = Vec::new(); let mut Y1: Vec<E::G1> = Vec::new();
let mut Y2: Vec<E::G2> = Vec::new(); let mut Y2: Vec<E::G2> = Vec::new();
@ -241,7 +240,7 @@ impl<E: Engine> BlindPublicKey<E> {
X1: X1, X1: X1,
X2: X2, X2: X2,
Y1: Y1, Y1: Y1,
Y2: Y2 Y2: Y2,
} }
} }
@ -250,7 +249,7 @@ impl<E: Engine> BlindPublicKey<E> {
let l = self.Y2.len(); let l = self.Y2.len();
assert_eq!(message.len(), l + 1); assert_eq!(message.len(), l + 1);
for i in 0 .. l { for i in 0..l {
// L = L + self.Y[i].mul(message[i]); // L = L + self.Y[i].mul(message[i]);
let mut Y = self.Y2[i]; let mut Y = self.Y2[i];
Y.mul_assign(message[i]); // Y_i ^ m_i Y.mul_assign(message[i]); // Y_i ^ m_i
@ -288,11 +287,9 @@ impl<E: Engine> BlindPublicKey<E> {
g.mul_assign(&p.a); g.mul_assign(&p.a);
gx == g gx == g
} }
} }
pub fn setup<R: Rng, E: Engine>(csprng: &mut R) -> PublicParams<E> { pub fn setup<R: Rng, E: Engine>(csprng: &mut R) -> PublicParams<E> {
let g1 = E::G1::rand(csprng); let g1 = E::G1::rand(csprng);
let g2 = E::G2::rand(csprng); let g2 = E::G2::rand(csprng);
@ -332,13 +329,10 @@ impl<E: Engine> BlindKeyPair<E> {
} }
pub fn generate_cs_multi_params(&self, mpk: &PublicParams<E>) -> CSMultiParams<E> { pub fn generate_cs_multi_params(&self, mpk: &PublicParams<E>) -> CSMultiParams<E> {
let mut com_bases1 = vec! {mpk.g1}; let mut com_bases = vec! {mpk.g1};
com_bases1.append(&mut self.public.Y1.clone()); com_bases.append(&mut self.public.Y1.clone());
let mut com_bases2 = vec! {mpk.g2}; CSMultiParams { pub_bases: com_bases }
com_bases2.append(&mut self.public.Y2.clone());
CSMultiParams { pub_bases1: com_bases1, pub_bases2: com_bases2}
} }
/// extract unblinded public key /// extract unblinded public key
@ -357,7 +351,7 @@ impl<E: Engine> BlindKeyPair<E> {
let mut h1 = mpk.g1; let mut h1 = mpk.g1;
h1.mul_assign(u); // g1 ^ u h1.mul_assign(u); // g1 ^ u
let mut com1 = com.c1.clone(); let mut com1 = com.c.clone();
let mut H1 = self.public.X1.clone(); let mut H1 = self.public.X1.clone();
H1.add_assign(&com1); // (X * com) H1.add_assign(&com1); // (X * com)
H1.mul_assign(u); // (X * com) ^ u (blinding factor) H1.mul_assign(u); // (X * com) ^ u (blinding factor)
@ -394,16 +388,19 @@ impl<E: Engine> BlindKeyPair<E> {
/// prove knowledge of a signature: commitment phase /// prove knowledge of a signature: commitment phase
/// returns the proof state, including commitment a and a blind signature blindSig /// returns the proof state, including commitment a and a blind signature blindSig
pub fn prove_commitment<R: Rng>(&self, rng: &mut R, mpk: &PublicParams<E>, signature: &Signature<E>) -> ProofState<E> { pub fn prove_commitment<R: Rng>(&self, rng: &mut R, mpk: &PublicParams<E>, signature: &Signature<E>,
tOptional: Option<Vec<E::Fr>>, ttOptional: Option<E::Fr>) -> ProofState<E> {
let v = E::Fr::rand(rng); let v = E::Fr::rand(rng);
let blindSig = self.blind(rng, &v, signature); let blindSig = self.blind(rng, &v, signature);
let s = E::Fr::rand(rng); let s = E::Fr::rand(rng);
let mut t = Vec::<E::Fr>::with_capacity(self.public.Y2.len()); let mut t = tOptional.unwrap_or(Vec::<E::Fr>::with_capacity(self.public.Y2.len()));
let tt = E::Fr::rand(rng); let tt = ttOptional.unwrap_or(E::Fr::rand(rng));
let mut gx = E::pairing(blindSig.h, self.public.X2); let mut gx = E::pairing(blindSig.h, self.public.X2);
gx = gx.pow(s.into_repr()); gx = gx.pow(s.into_repr());
for j in 0..self.public.Y2.len() { for j in 0..self.public.Y2.len() {
t.push(E::Fr::rand(rng)); if t.len() == j {
t.push(E::Fr::rand(rng));
}
let mut gy = E::pairing(blindSig.h, self.public.Y2[j]); let mut gy = E::pairing(blindSig.h, self.public.Y2[j]);
gy = gy.pow(t[j].into_repr()); gy = gy.pow(t[j].into_repr());
gx.mul_assign(&gy); gx.mul_assign(&gy);
@ -429,7 +426,7 @@ impl<E: Engine> BlindKeyPair<E> {
let mut vic = ps.v.clone(); let mut vic = ps.v.clone();
vic.mul_assign(&challenge); vic.mul_assign(&challenge);
zv.add_assign(&vic); zv.add_assign(&vic);
SignatureProof {zsig, zx, zv, a: ps.a } SignatureProof { zsig, zx, zv, a: ps.a }
} }
} }
@ -461,7 +458,7 @@ mod tests {
use ff::Rand; use ff::Rand;
use pairing::bls12_381::{Bls12, Fr}; use pairing::bls12_381::{Bls12, Fr};
use rand::{SeedableRng}; use rand::SeedableRng;
use rand_xorshift::XorShiftRng; use rand_xorshift::XorShiftRng;
use ped92::CSMultiParams; use ped92::CSMultiParams;
@ -478,8 +475,8 @@ mod tests {
println!("PUBLIC KEY => {}", keypair.public); println!("PUBLIC KEY => {}", keypair.public);
let mut message1 : Vec<Fr> = Vec::new(); let mut message1: Vec<Fr> = Vec::new();
let mut message2 : Vec<Fr> = Vec::new(); let mut message2: Vec<Fr> = Vec::new();
for i in 0..l { for i in 0..l {
message1.push(Fr::rand(&mut rng)); message1.push(Fr::rand(&mut rng));
@ -502,8 +499,8 @@ mod tests {
let public_key = keypair.get_public_key(&mpk); let public_key = keypair.get_public_key(&mpk);
let mut message1 : Vec<Fr> = Vec::new(); let mut message1: Vec<Fr> = Vec::new();
let mut message2 : Vec<Fr> = Vec::new(); let mut message2: Vec<Fr> = Vec::new();
for i in 0..l { for i in 0..l {
message1.push(Fr::rand(&mut rng)); message1.push(Fr::rand(&mut rng));
@ -515,15 +512,15 @@ mod tests {
assert_eq!(public_key.verify(&mpk, &message2, &sig), false); assert_eq!(public_key.verify(&mpk, &message2, &sig), false);
let t = Fr::rand(&mut rng); let t = Fr::rand(&mut rng);
let blind_sig = keypair.blind(&mut rng, &t,&sig); let blind_sig = keypair.blind(&mut rng, &t, &sig);
// pick another blinding factor // pick another blinding factor
let t1 = Fr::rand(&mut rng); let t1 = Fr::rand(&mut rng);
// verify blind signatures and provide blinding factor as input // verify blind signatures and provide blinding factor as input
assert_eq!(keypair.verify(&mpk,&message1, &t,&blind_sig), true); 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, &message2, &t, &blind_sig), false);
assert_eq!(keypair.verify(&mpk,&message1, &t1,&blind_sig), false); assert_eq!(keypair.verify(&mpk, &message1, &t1, &blind_sig), false);
} }
#[test] #[test]
@ -535,7 +532,7 @@ mod tests {
let mpk = setup(&mut rng); let mpk = setup(&mut rng);
let keypair = BlindKeyPair::<Bls12>::generate(&mut rng, &mpk, l); let keypair = BlindKeyPair::<Bls12>::generate(&mut rng, &mpk, l);
let mut message1 : Vec<Fr> = Vec::new(); let mut message1: Vec<Fr> = Vec::new();
for i in 0..l { for i in 0..l {
message1.push(Fr::rand(&mut rng)); message1.push(Fr::rand(&mut rng));
@ -562,8 +559,8 @@ mod tests {
let public_key = keypair.get_public_key(&mpk); let public_key = keypair.get_public_key(&mpk);
let mut message1 : Vec<Fr> = Vec::new(); let mut message1: Vec<Fr> = Vec::new();
let mut message2 : Vec<Fr> = Vec::new(); let mut message2: Vec<Fr> = Vec::new();
for i in 0..l { for i in 0..l {
message1.push(Fr::rand(&mut rng)); message1.push(Fr::rand(&mut rng));
@ -580,11 +577,11 @@ mod tests {
let t1 = Fr::rand(&mut rng); let t1 = Fr::rand(&mut rng);
assert_eq!(keypair.get_public_key(&mpk).verify(&mpk,&message1, &unblinded_sig), true); 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.verify(&mpk, &message1, &t, &signature), true);
assert_eq!(keypair.get_public_key(&mpk).verify(&mpk,&message2, &unblinded_sig), false); 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, &message2, &t, &signature), false);
assert_eq!(keypair.verify(&mpk,&message1, &t1, &signature), false); assert_eq!(keypair.verify(&mpk, &message1, &t1, &signature), false);
} }
#[test] #[test]
@ -597,19 +594,18 @@ mod tests {
let public_key = keypair.get_public_key(&mpk); let public_key = keypair.get_public_key(&mpk);
let mut message1 : Vec<Fr> = Vec::new(); let mut message1: Vec<Fr> = Vec::new();
for i in 0..l { for i in 0..l {
message1.push(Fr::rand(&mut rng)); message1.push(Fr::rand(&mut rng));
} }
let sig = keypair.sign(&mut rng, &message1); let sig = keypair.sign(&mut rng, &message1);
let proof_state = keypair.prove_commitment(rng, &mpk, &sig); let proof_state = keypair.prove_commitment(rng, &mpk, &sig, None, None);
let challenge = Fr::rand(&mut rng); let challenge = Fr::rand(&mut rng);
let proof = keypair.prove_response(&proof_state.clone(), challenge, &mut message1); let proof = keypair.prove_response(&proof_state.clone(), challenge, &mut message1);
assert_eq!(keypair.public.verify_proof(&mpk, proof_state.blindSig, proof, challenge), true); assert_eq!(keypair.public.verify_proof(&mpk, proof_state.blindSig, proof, challenge), true);
} }
} }

View File

@ -73,6 +73,7 @@ pub mod clproto;
pub mod serialization_wrappers; pub mod serialization_wrappers;
pub mod nizk; pub mod nizk;
pub mod util; pub mod util;
pub mod wallet;
const E_MIN: i32 = 1; const E_MIN: i32 = 1;
const E_MAX: i32 = 255; // TODO: should be 2^32 - 1 const E_MAX: i32 = 255; // TODO: should be 2^32 - 1

View File

@ -9,135 +9,173 @@ use pairing::{Engine, CurveProjective};
use ff::PrimeField; use ff::PrimeField;
use util::hash_g2_to_fr; use util::hash_g2_to_fr;
use commit_scheme::commit; use commit_scheme::commit;
use wallet::Wallet;
use ccs08::{RPPublicParams, RangeProof};
#[derive(Clone)] #[derive(Clone)]
struct Proof<E: Engine> { pub struct Proof<E: Engine> {
sig: Signature<E>, pub sig: Signature<E>,
sigProof: SignatureProof<E>, pub sigProof: SignatureProof<E>,
T: E::G2, pub T: E::G1,
D: E::G2, pub D: E::G1,
z: Vec<E::Fr>, pub z: Vec<E::Fr>,
pub rpBC: RangeProof<E>,
pub rpBM: RangeProof<E>,
} }
fn prove<R: Rng, E: Engine>(rng: &mut R, comParams: &CSMultiParams<E>, com1: &Commitment<E>, r: E::Fr, #[derive(Clone)]
oldWallet: Vec<E::Fr>, newWallet: Vec<E::Fr>, rPrime: E::Fr, paymentToken: &Signature<E>, pub struct NIZKPublicParams<E: Engine> {
mpk: &PublicParams<E>, kp: &BlindKeyPair<E>) -> Proof<E> { pub mpk: PublicParams<E>,
//Commitment phase pub keypair: BlindKeyPair<E>,
//Commit linear relationship pub comParams: CSMultiParams<E>,
let mut T = comParams.pub_bases2[2].clone(); pub rpParamsBC: RPPublicParams<E>,
let t1 = E::Fr::rand(rng); pub rpParamsBM: RPPublicParams<E>,
T.mul_assign(t1);
let mut h = comParams.pub_bases2[0].clone();
let t2 = E::Fr::rand(rng);
h.mul_assign(t2);
T.add_assign(&h);
//commit signature
let proofState = kp.prove_commitment(rng, &mpk, &paymentToken);
//commit commitment
let mut D = E::G2::zero();
let mut t = Vec::<E::Fr>::with_capacity(comParams.pub_bases2.len() - 1);
for g in comParams.pub_bases2.clone() {
let ti = E::Fr::rand(rng);
t.push(ti);
let mut gt = g.clone();
gt.mul_assign(ti.into_repr());
D.add_assign(&gt);
}
//Compute challenge
let challenge = hash::<E>(proofState.a, T, D);
//Response phase
//response for signature
let sigProof = kp.prove_response(&proofState, challenge, &mut oldWallet.clone());
//response linear relationship
let mut z = Vec::<E::Fr>::with_capacity(t.len() + 2);
let mut z1 = newWallet[1].clone();
z1.negate();
z1.mul_assign(&challenge);
z1.add_assign(&t1);
z.push(z1);
let mut z2 = r.clone();
z2.sub_assign(&rPrime.clone());
z2.mul_assign(&challenge);
z2.add_assign(&t2);
z.push(z2);
//response commitment
let mut z0 = rPrime.clone();
z0.mul_assign(&challenge);
z0.add_assign(&t[0]);
z.push(z0);
for i in 1..t.len() {
let mut zi = newWallet[i-1].clone();
zi.mul_assign(&challenge);
zi.add_assign(&t[i]);
z.push(zi);
}
Proof { sig: proofState.blindSig, sigProof, T, D, z }
} }
fn verify<E: Engine>(proof: Proof<E>, epsilon: E::Fr, com1: &Commitment<E>, com2: &Commitment<E>, impl<E: Engine> NIZKPublicParams<E> {
wpk: E::Fr, comParams: &CSMultiParams<E>, mpk: &PublicParams<E>, pk: &BlindPublicKey<E>) -> bool { pub fn setup<R: Rng>(rng: &mut R) -> Self {
//compute challenge let mpk = setup(rng);
let challenge = hash::<E>(proof.sigProof.a, proof.T, proof.D); let keypair = BlindKeyPair::<E>::generate(rng, &mpk, 4);
let comParams = keypair.generate_cs_multi_params(&mpk);
let rpParamsBC = RPPublicParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone());
let rpParamsBM = RPPublicParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone());
//verify linear relationship NIZKPublicParams{mpk, keypair, comParams, rpParamsBC, rpParamsBM}
let mut gWpk = comParams.pub_bases2[2].clone();
let mut minWpk = wpk.clone();
minWpk.negate();
gWpk.mul_assign(minWpk.into_repr());
let mut gEps = comParams.pub_bases2[4].clone();
gEps.mul_assign(epsilon.into_repr());
let mut gMinEps = comParams.pub_bases2[3].clone();
let mut mineps = epsilon.clone();
mineps.negate();
gMinEps.mul_assign(mineps.into_repr());
let mut commitment = com1.c2.clone();
commitment.sub_assign(&com2.c2.clone());
commitment.add_assign(&gWpk);
commitment.add_assign(&gEps);
commitment.add_assign(&gMinEps);
commitment.mul_assign(challenge.into_repr());
commitment.add_assign(&proof.T);
let mut g2 = comParams.pub_bases2[2].clone();
g2.mul_assign(proof.z[0].into_repr());
let mut h = comParams.pub_bases2[0].clone();
h.mul_assign(proof.z[1].into_repr());
g2.add_assign(&h);
let r = commitment == g2;
//verify knowledge of signature
let r1 = pk.verify_proof(&mpk, proof.sig, proof.sigProof, challenge);
//verify knowledge of commitment
let mut comc = com2.c2.clone();
comc.mul_assign(challenge.into_repr());
comc.add_assign(&proof.D.clone());
let mut x = E::G2::zero();
for i in 2..proof.z.len() {
let mut base = comParams.pub_bases2[i - 2].clone();
base.mul_assign(proof.z[i].into_repr());
x.add_assign(&base);
} }
let r3 = x == comc;
r && r1 && r3 pub fn prove<R: Rng>(&self, rng: &mut R, r: E::Fr, oldWallet: Wallet<E>, newWallet: Wallet<E>,
} newWalletCom: Commitment<E>, rPrime: E::Fr, paymentToken: &Signature<E>, ) -> Proof<E> {
//Commitment phase
//Commit linear relationship
let mut T = self.comParams.pub_bases[2].clone();
let t1 = E::Fr::rand(rng);
T.mul_assign(t1);
let mut h = self.comParams.pub_bases[0].clone();
let t2 = E::Fr::rand(rng);
h.mul_assign(t2);
T.add_assign(&h);
fn hash<E: Engine>(a: E::Fqk, T: E::G2, D: E::G2) -> E::Fr { //commit commitment
let mut x_vec: Vec<u8> = Vec::new(); let mut D = E::G1::zero();
x_vec.extend(format!("{}", a).bytes()); let mut t = Vec::<E::Fr>::with_capacity(self.comParams.pub_bases.len() - 1);
x_vec.extend(format!("{}", T).bytes()); for g in self.comParams.pub_bases.clone() {
x_vec.extend(format!("{}", D).bytes()); let ti = E::Fr::rand(rng);
t.push(ti);
let mut gt = g.clone();
gt.mul_assign(ti.into_repr());
D.add_assign(&gt);
}
util::hash_to_fr::<E>(x_vec) //commit signature
let proofState = self.keypair.prove_commitment(rng, &self.mpk, &paymentToken, Some(t[1..].to_vec()), Some(t[0].clone()));
//commit range proof
let rpStateBC = self.rpParamsBC.prove_commitment(rng, newWallet.bc.clone(), newWalletCom.clone(), 3);
let rpStateBM = self.rpParamsBM.prove_commitment(rng, newWallet.bm.clone(), newWalletCom.clone(), 4);
//Compute challenge
let challenge = NIZKPublicParams::<E>::hash(proofState.a, vec! {T, D, rpStateBC.ps1.D, rpStateBC.ps2.D, rpStateBM.ps1.D, rpStateBM.ps2.D});
//Response phase
//response for signature
let oldWalletVec = oldWallet.as_fr_vec();
let sigProof = self.keypair.prove_response(&proofState, challenge, &mut oldWalletVec.clone());
//response linear relationship
let mut z = Vec::<E::Fr>::with_capacity(t.len() + 2);
let mut z1 = newWallet.wpk.clone();
z1.negate();
z1.mul_assign(&challenge);
z1.add_assign(&t1);
z.push(z1);
let mut z2 = r.clone();
z2.sub_assign(&rPrime.clone());
z2.mul_assign(&challenge);
z2.add_assign(&t2);
z.push(z2);
//response commitment
let mut z0 = rPrime.clone();
z0.mul_assign(&challenge);
z0.add_assign(&t[0]);
z.push(z0);
let newWalletVec = newWallet.as_fr_vec();
for i in 1..t.len() {
let mut zi = newWalletVec[i - 1].clone();
zi.mul_assign(&challenge);
zi.add_assign(&t[i]);
z.push(zi);
}
//response range proof
let rpBC = self.rpParamsBC.prove_response(rPrime.clone(), &rpStateBC, challenge.clone(), 3, vec! {newWalletVec[0], newWalletVec[1], newWalletVec[3]});
let rpBM = self.rpParamsBM.prove_response(rPrime.clone(), &rpStateBM, challenge.clone(), 4, vec! {newWalletVec[0], newWalletVec[1], newWalletVec[2]});
Proof { sig: proofState.blindSig, sigProof, T, D, z, rpBC, rpBM }
}
pub fn verify(&self, proof: Proof<E>, epsilon: E::Fr, com1: &Commitment<E>, com2: &Commitment<E>, wpk: E::Fr) -> bool {
//compute challenge
let challenge = NIZKPublicParams::<E>::hash(proof.sigProof.a, vec! {proof.T, proof.D, proof.rpBC.p1.D, proof.rpBC.p2.D, proof.rpBM.p1.D, proof.rpBM.p2.D});
//verify linear relationship
let mut gWpk = self.comParams.pub_bases[2].clone();
let mut minWpk = wpk.clone();
minWpk.negate();
gWpk.mul_assign(minWpk.into_repr());
let mut gEps = self.comParams.pub_bases[4].clone();
gEps.mul_assign(epsilon.into_repr());
let mut gMinEps = self.comParams.pub_bases[3].clone();
let mut mineps = epsilon.clone();
mineps.negate();
gMinEps.mul_assign(mineps.into_repr());
let mut commitment = com1.c.clone();
commitment.sub_assign(&com2.c.clone());
commitment.add_assign(&gWpk);
commitment.add_assign(&gEps);
commitment.add_assign(&gMinEps);
commitment.mul_assign(challenge.into_repr());
commitment.add_assign(&proof.T);
let mut g2 = self.comParams.pub_bases[2].clone();
g2.mul_assign(proof.z[0].into_repr());
let mut h = self.comParams.pub_bases[0].clone();
h.mul_assign(proof.z[1].into_repr());
g2.add_assign(&h);
let r = commitment == g2;
//verify knowledge of signature
let r1 = self.keypair.public.verify_proof(&self.mpk, proof.sig, proof.sigProof, challenge);
//verify knowledge of commitment
let mut comc = com2.c.clone();
comc.mul_assign(challenge.into_repr());
comc.add_assign(&proof.D.clone());
let mut x = E::G1::zero();
for i in 2..proof.z.len() {
let mut base = self.comParams.pub_bases[i - 2].clone();
base.mul_assign(proof.z[i].into_repr());
x.add_assign(&base);
}
let r2 = x == comc;
//verify range proofs
let r3 = self.rpParamsBC.verify(proof.rpBC, challenge.clone(), 3);
let r4 = self.rpParamsBM.verify(proof.rpBM, challenge.clone(), 4);
r && r1 && r2 && r3 && r4
}
fn hash(a: E::Fqk, T: Vec<E::G1>) -> E::Fr {
let mut x_vec: Vec<u8> = Vec::new();
x_vec.extend(format!("{}", a).bytes());
for t in T {
x_vec.extend(format!("{}", t).bytes());
}
util::hash_to_fr::<E>(x_vec)
}
} }
#[cfg(test)] #[cfg(test)]
@ -151,29 +189,29 @@ mod tests {
let pkc = Fr::rand(rng); let pkc = Fr::rand(rng);
let wpk = Fr::rand(rng); let wpk = Fr::rand(rng);
let wpkprime = Fr::rand(rng); let wpkprime = Fr::rand(rng);
let bc = Fr::rand(rng); let bc = rng.gen_range(100, 1000);
let mut bc2 = bc.clone(); let mut bc2 = bc.clone();
let bm = Fr::rand(rng); let bm = rng.gen_range(100, 1000);
let mut bm2 = bm.clone(); let mut bm2 = bm.clone();
let epsilon = &Fr::rand(rng); let epsilon = &rng.gen_range(1, 100);
bc2.sub_assign(epsilon); bc2 -= epsilon;
bm2.add_assign(epsilon); bm2 += epsilon;
let r = Fr::rand(rng); let r = Fr::rand(rng);
let rprime = Fr::rand(rng); let rprime = Fr::rand(rng);
let mpk = setup(rng); let pubParams = NIZKPublicParams::<Bls12>::setup(rng);
let keypair = BlindKeyPair::<Bls12>::generate(rng, &mpk, 4); let wallet1 = Wallet { pkc, wpk, bc, bm };
let comParams = keypair.generate_cs_multi_params(&mpk); let commitment1 = pubParams.comParams.commit(&wallet1.as_fr_vec(), &r);
let wallet1 = vec! {pkc, wpk, bc, bm}; let wallet2 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2 };
let commitment1 = comParams.commit(&wallet1, &r); let commitment2 = pubParams.comParams.commit(&wallet2.as_fr_vec(), &rprime);
let wallet2 = vec! {pkc, wpkprime, bc2, bm2}; let blindPaymentToken = pubParams.keypair.sign_blind(rng, &pubParams.mpk, commitment1.clone());
let commitment2 = comParams.commit(&wallet2, &rprime); let paymentToken = pubParams.keypair.unblind(&r, &blindPaymentToken);
let blindPaymentToken = keypair.sign_blind(rng, &mpk, commitment1.clone());
let paymentToken = keypair.unblind(&r, &blindPaymentToken);
let proof = prove(rng, &comParams, &commitment1, r, wallet1, wallet2, rprime, &paymentToken, &mpk, &keypair); let proof = pubParams.prove(rng, r, wallet1, wallet2,
commitment2.clone(), rprime, &paymentToken);
assert_eq!(verify(proof, *epsilon, &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), true); assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1,
&commitment2, wpk), true);
} }
#[test] #[test]
@ -182,41 +220,38 @@ mod tests {
let pkc = Fr::rand(rng); let pkc = Fr::rand(rng);
let wpk = Fr::rand(rng); let wpk = Fr::rand(rng);
let wpkprime = Fr::rand(rng); let wpkprime = Fr::rand(rng);
let bc = Fr::rand(rng); let bc = rng.gen_range(100, 1000);
let mut bc2 = bc.clone(); let mut bc2 = bc.clone();
let bm = Fr::rand(rng); let bm = rng.gen_range(100, 1000);
let mut bm2 = bm.clone(); let mut bm2 = bm.clone();
let epsilon = &Fr::rand(rng); let epsilon = &rng.gen_range(1, 100);
bc2.sub_assign(epsilon); bc2 -= epsilon;
bm2.add_assign(epsilon); bm2 += epsilon;
let r = Fr::rand(rng); let r = Fr::rand(rng);
let rprime = Fr::rand(rng); let rprime = Fr::rand(rng);
let mpk = setup(rng); let pubParams = NIZKPublicParams::<Bls12>::setup(rng);
let keypair = BlindKeyPair::<Bls12>::generate(rng, &mpk, 4); let wallet1 = Wallet { pkc, wpk, bc, bm };
let comParams = keypair.generate_cs_multi_params(&mpk); let wallet2 = Wallet::<Bls12> { pkc, wpk: wpkprime, bc: bc2, bm: bm2 };
let wallet1 = vec! {pkc, wpk, bc, bm};
let wallet2 = vec! {pkc, wpkprime, bc2, bm2};
let mut bc2Prime = bc.clone(); let mut bc2Prime = bc.clone();
let wallet3 = vec! {pkc, wpkprime, bc2Prime, bm2}; let wallet3 = Wallet { pkc, wpk: wpkprime, bc: bc2Prime, bm: bm2 };
let commitment1 = comParams.commit(&wallet1.clone(), &r); let commitment1 = pubParams.comParams.commit(&wallet1.as_fr_vec().clone(), &r);
let commitment2 = comParams.commit(&wallet3, &rprime); let commitment2 = pubParams.comParams.commit(&wallet3.as_fr_vec(), &rprime);
let blindPaymentToken = keypair.sign_blind(rng, &mpk, commitment1.clone()); let blindPaymentToken = pubParams.keypair.sign_blind(rng, &pubParams.mpk, commitment1.clone());
let paymentToken = keypair.unblind(&r, &blindPaymentToken); let paymentToken = pubParams.keypair.unblind(&r, &blindPaymentToken);
let proof = prove(rng, &comParams, &commitment1, r, wallet1.clone(), wallet3, rprime, &paymentToken, &mpk, &keypair); let proof = pubParams.prove(rng, r, wallet1.clone(), wallet3, commitment2.clone(), rprime, &paymentToken);
assert_eq!(verify(proof, *epsilon, &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), false); assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, &commitment2, wpk), false);
let mut bm2Prime = bm.clone(); let mut bm2Prime = bm.clone();
let wallet4 = vec! {pkc, wpkprime, bc2, bm2Prime}; let wallet4 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2Prime };
let commitment2 = comParams.commit(&wallet4, &rprime); let commitment2 = pubParams.comParams.commit(&wallet4.as_fr_vec(), &rprime);
let proof = prove(rng, &comParams, &commitment1, r, wallet1.clone(), wallet4, rprime, &paymentToken, &mpk, &keypair); let proof = pubParams.prove(rng, r, wallet1.clone(), wallet4, commitment2.clone(), rprime, &paymentToken);
assert_eq!(verify(proof, *epsilon, &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), false); assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, &commitment2, wpk), false);
let wallet5 = vec! {Fr::rand(rng), wpkprime, bc2, bm2};
let commitment2 = comParams.commit(&wallet5, &rprime);
let proof = prove(rng, &comParams, &commitment1, r, wallet1.clone(), wallet5, rprime, &paymentToken, &mpk, &keypair);
assert_eq!(verify(proof, *epsilon, &commitment1, &commitment2, wpk, &comParams, &mpk, &keypair.public), false);
let wallet5 = Wallet { pkc: Fr::rand(rng), wpk: wpkprime, bc: bc2, bm: bm2 };
let commitment2 = pubParams.comParams.commit(&wallet5.as_fr_vec(), &rprime);
let proof = pubParams.prove(rng, r, wallet1.clone(), wallet5, commitment2.clone(), rprime, &paymentToken);
assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, &commitment2, wpk), false);
} }
} }

View File

@ -5,22 +5,18 @@ use ff::Rand;
#[derive(Clone)] #[derive(Clone)]
pub struct CSParams<E: Engine> { pub struct CSParams<E: Engine> {
pub g1: E::G1, pub g: E::G1,
pub g2: E::G2, pub h: E::G1,
pub h1: E::G1,
pub h2: E::G2,
} }
#[derive(Clone)] #[derive(Clone)]
pub struct Commitment<E: Engine> { pub struct Commitment<E: Engine> {
pub c1: E::G1, pub c: E::G1,
pub c2: E::G2
} }
#[derive(Clone)] #[derive(Clone)]
pub struct CSMultiParams<E: Engine> { pub struct CSMultiParams<E: Engine> {
pub pub_bases1: Vec<E::G1>, pub pub_bases: Vec<E::G1>,
pub pub_bases2: Vec<E::G2>
} }
//impl<E: Engine> fmt::Display for CSParams<E> { //impl<E: Engine> fmt::Display for CSParams<E> {
@ -63,12 +59,9 @@ impl<E: Engine> CSParams<E> {
Implements the setup algorithm for the Pedersen92 commitment scheme Implements the setup algorithm for the Pedersen92 commitment scheme
*/ */
pub fn setup<R: Rng>(rng: &mut R) -> Self { pub fn setup<R: Rng>(rng: &mut R) -> Self {
let g1 = E::G1::rand(rng); let g = E::G1::rand(rng);
let g2 = E::G2::rand(rng); let h = E::G1::rand(rng);
let h1 = E::G1::rand(rng); CSParams { g, h }
let h2 = E::G2::rand(rng);
let csp = CSParams { g1, g2, h1, h2 };
return csp;
} }
/* /*
@ -81,20 +74,13 @@ commit(pk, msg) -> cm where
let r = R.unwrap_or(E::Fr::rand(rng)); let r = R.unwrap_or(E::Fr::rand(rng));
// c = g^m * h^r // c = g^m * h^r
let mut c1 = self.g1.clone(); let mut c = self.g.clone();
c1.mul_assign(m.clone()); c.mul_assign(m.clone());
let mut h1 = self.h1.clone(); let mut h = self.h.clone();
h1.mul_assign(r.clone()); h.mul_assign(r.clone());
c1.add_assign(&h1); c.add_assign(&h);
// c = g^m * h^r Commitment { c }
let mut c2 = self.g2.clone();
c2.mul_assign(m);
let mut h2 = self.h2.clone();
h2.mul_assign(r);
c2.add_assign(&h2);
Commitment { c1, c2 }
} }
/* /*
@ -104,18 +90,12 @@ decommit(csp, cm, msg) -> bool where
- outputs T/F for whether the cm is a valid commitment to the msg - outputs T/F for whether the cm is a valid commitment to the msg
*/ */
pub fn decommit(&self, cm: &Commitment<E>, m: &E::Fr, r: &E::Fr) -> bool { pub fn decommit(&self, cm: &Commitment<E>, m: &E::Fr, r: &E::Fr) -> bool {
let mut dm1 = self.g1.clone(); let mut dm = self.g.clone();
dm1.mul_assign(m.clone()); dm.mul_assign(m.clone());
let mut h1 = self.h1.clone(); let mut h = self.h.clone();
h1.mul_assign(r.clone()); h.mul_assign(r.clone());
dm1.add_assign(&h1); dm.add_assign(&h);
dm == cm.c
let mut dm2 = self.g2.clone();
dm2.mul_assign(m.clone());
let mut h2 = self.h2.clone();
h2.mul_assign(r.clone());
dm2.add_assign(&h2);
return dm2 == cm.c2 && dm1 == cm.c1;
} }
} }
@ -126,49 +106,37 @@ impl<E: Engine> CSMultiParams<E> {
a vector of messages of length len. a vector of messages of length len.
*/ */
pub fn setup_gen_params<R: Rng>(rng: &mut R, len: usize) -> Self { pub fn setup_gen_params<R: Rng>(rng: &mut R, len: usize) -> Self {
let mut p1: Vec<E::G1> = Vec::new(); let mut p: Vec<E::G1> = Vec::new();
let mut p2: Vec<E::G2> = Vec::new();
// 1 extra base element for the random parameter // 1 extra base element for the random parameter
for i in 0..len + 1 { for i in 0..len + 1 {
p1.push(E::G1::rand(rng)); p.push(E::G1::rand(rng));
p2.push(E::G2::rand(rng));
} }
return CSMultiParams { pub_bases1: p1, pub_bases2: p2 }; CSMultiParams { pub_bases: p }
} }
pub fn commit(&self, x: &Vec<E::Fr>, r: &E::Fr) -> Commitment<E> { pub fn commit(&self, x: &Vec<E::Fr>, r: &E::Fr) -> Commitment<E> {
// c = g1^m1 * ... * gn^mn * h^r // c = g1^m1 * ... * gn^mn * h^r
let mut c1 = self.pub_bases1[0].clone(); let mut c = self.pub_bases[0].clone();
let mut c2 = self.pub_bases2[0].clone(); c.mul_assign(r.clone());
c1.mul_assign(r.clone());
c2.mul_assign(r.clone());
for i in 0..x.len() { for i in 0..x.len() {
let mut basis1 = self.pub_bases1[i+1]; let mut basis = self.pub_bases[i+1];
basis1.mul_assign(x[i]); basis.mul_assign(x[i]);
c1.add_assign(&basis1); c.add_assign(&basis);
let mut basis2 = self.pub_bases2[i+1];
basis2.mul_assign(x[i]);
c2.add_assign(&basis2);
} }
Commitment { c1, c2 } Commitment { c }
} }
pub fn decommit(&self, cm: &Commitment<E>, x: &Vec<E::Fr>, r: &E::Fr) -> bool { pub fn decommit(&self, cm: &Commitment<E>, x: &Vec<E::Fr>, r: &E::Fr) -> bool {
let l = x.len(); let l = x.len();
// pub_base[0] => h, x[0] => r // pub_base[0] => h, x[0] => r
let mut dc1 = self.pub_bases1[0].clone(); let mut dc = self.pub_bases[0].clone();
let mut dc2 = self.pub_bases2[0].clone(); dc.mul_assign(r.clone());
dc1.mul_assign(r.clone());
dc2.mul_assign(r.clone());
for i in 0..l { for i in 0..l {
let mut basis1 = self.pub_bases1[i+1]; let mut basis = self.pub_bases[i+1];
basis1.mul_assign(x[i]); basis.mul_assign(x[i]);
dc1.add_assign(&basis1); dc.add_assign(&basis);
let mut basis2 = self.pub_bases2[i+1];
basis2.mul_assign(x[i]);
dc2.add_assign(&basis2);
} }
return dc2 == cm.c2 && dc1 == cm.c1; return dc == cm.c;
} }
} }

View File

@ -70,8 +70,8 @@ pub struct CommitmentProof<E: Engine> {
impl<E: Engine> CommitmentProof<E> { impl<E: Engine> CommitmentProof<E> {
pub fn new<R: Rng>(csprng: &mut R, com_params: &CSMultiParams<E>, com: &E::G1, wallet: &Vec<E::Fr>, r: &E::Fr) -> Self { pub fn new<R: Rng>(csprng: &mut R, com_params: &CSMultiParams<E>, com: &E::G1, wallet: &Vec<E::Fr>, r: &E::Fr) -> Self {
let mut Tvals = E::G1::zero(); let mut Tvals = E::G1::zero();
let mut t = Vec::<E::Fr>::with_capacity(com_params.pub_bases1.len() - 1); let mut t = Vec::<E::Fr>::with_capacity(com_params.pub_bases.len() - 1);
for g in com_params.pub_bases1.clone() { for g in com_params.pub_bases.clone() {
let ti = E::Fr::rand(csprng); let ti = E::Fr::rand(csprng);
t.push(ti); t.push(ti);
let mut gt = g.clone(); let mut gt = g.clone();
@ -118,7 +118,7 @@ pub fn verify<E: Engine>(com_params: &CSMultiParams<E>, com: &E::G1, proof: &Com
let mut x = E::G1::zero(); let mut x = E::G1::zero();
for i in 0..proof.z.len() { for i in 0..proof.z.len() {
let mut base = com_params.pub_bases1[i].clone(); let mut base = com_params.pub_bases[i].clone();
base.mul_assign(proof.z[i].into_repr()); base.mul_assign(proof.z[i].into_repr());
x.add_assign(&base); x.add_assign(&base);
} }

19
src/wallet.rs Normal file
View File

@ -0,0 +1,19 @@
extern crate pairing;
use super::*;
use pairing::{Engine, CurveProjective};
use ff::PrimeField;
#[derive(Clone)]
pub struct Wallet<E: Engine> {
pub pkc: E::Fr,
pub wpk: E::Fr,
pub bc: i32,
pub bm: i32,
}
impl<E: Engine> Wallet<E> {
pub fn as_fr_vec(&self) -> Vec<E::Fr> {
vec!(self.pkc, self.wpk, E::Fr::from_str(&self.bc.to_string()).unwrap(), E::Fr::from_str(&self.bm.to_string()).unwrap())
}
}