libbolt/src/ccs08.rs

613 lines
22 KiB
Rust
Raw Normal View History

2019-06-14 15:14:06 -07:00
/*
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;
2019-06-16 13:29:48 -07:00
use rand::{thread_rng, Rng};
2019-06-14 15:14:06 -07:00
use super::*;
2019-07-03 16:05:27 -07:00
use cl::{KeyPair, Signature, PublicParams, setup, BlindKeyPair, ProofState, SignatureProof};
2019-07-12 16:52:16 -07:00
use ped92::{Commitment, CSMultiParams};
2019-06-16 09:27:35 -07:00
use pairing::{Engine, CurveProjective};
2019-06-14 15:14:06 -07:00
use ff::PrimeField;
2019-06-16 09:27:35 -07:00
use std::collections::HashMap;
use std::fmt::Display;
2019-06-16 12:38:07 -07:00
use std::mem::transmute;
2019-07-03 16:05:27 -07:00
use util::fmt_bytes_to_int;
2019-06-14 15:14:06 -07:00
2019-07-02 15:39:23 -07:00
/**
2019-06-14 15:14:06 -07:00
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<E: Engine> {
pub mpk: PublicParams<E>,
2019-06-16 09:27:35 -07:00
pub signatures: HashMap<String, Signature<E>>,
2019-07-12 16:52:16 -07:00
pub csParams: CSMultiParams<E>,
2019-07-01 18:51:24 -07:00
kp: BlindKeyPair<E>,
2019-06-14 15:14:06 -07:00
// 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,
}
#[derive(Clone)]
struct ProofULState<E: Engine> {
decx: Vec<i64>,
proofStates: Vec<ProofState<E>>,
V: Vec<Signature<E>>,
D: E::G1,
m: E::Fr,
}
2019-07-02 15:39:23 -07:00
/**
proofUL contains the necessary elements for the ZK range proof with range [0,u^l).
2019-06-14 15:14:06 -07:00
*/
#[derive(Clone)]
struct ProofUL<E: Engine> {
2019-07-02 15:39:23 -07:00
V: Vec<Signature<E>>,
2019-07-12 07:46:25 -07:00
D: E::G1,
2019-06-16 09:27:35 -07:00
comm: Commitment<E>,
2019-07-03 16:05:27 -07:00
sigProofs: Vec<SignatureProof<E>>,
2019-06-14 15:14:06 -07:00
zr: E::Fr,
}
#[derive(Clone)]
pub struct RangeProofState<E: Engine> {
com1: Commitment<E>,
ps1: ProofULState<E>,
com2: Commitment<E>,
ps2: ProofULState<E>,
}
2019-07-02 15:39:23 -07:00
/**
RangeProof contains the necessary elements for the ZK range proof.
*/
2019-06-14 15:14:06 -07:00
#[derive(Clone)]
pub struct RangeProof<E: Engine> {
p1: ProofUL<E>,
p2: ProofUL<E>,
}
2019-07-02 15:39:23 -07:00
/**
2019-06-14 15:14:06 -07:00
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<E: Engine> {
p: ParamsUL<E>,
a: i64,
b: i64,
}
2019-06-16 13:29:48 -07:00
impl<E: Engine> ParamsUL<E> {
2019-07-02 15:39:23 -07:00
/**
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.
*/
2019-07-12 16:52:16 -07:00
pub fn setup_ul<R: Rng>(rng: &mut R, u: i64, l: i64, csParams: CSMultiParams<E>) -> Self {
2019-06-16 13:29:48 -07:00
let mpk = setup(rng);
2019-07-01 18:51:24 -07:00
let kp = BlindKeyPair::<E>::generate(rng, &mpk, 1);
2019-06-14 15:14:06 -07:00
2019-06-16 13:29:48 -07:00
let mut signatures: HashMap<String, Signature<E>> = 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);
}
2019-06-14 15:14:06 -07:00
return ParamsUL { mpk, signatures, csParams, kp, u, l };
2019-06-14 15:14:06 -07:00
}
2019-07-02 15:39:23 -07:00
/**
prove_ul method is used to produce the ZKRP proof that secret x belongs to the interval [0,U^L).
*/
2019-07-12 16:52:16 -07:00
pub fn prove_ul<R: Rng>(&self, rng: &mut R, x: i64, r: E::Fr, C: Commitment<E>, k: usize) -> 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)
}
2019-07-12 16:52:16 -07:00
fn prove_ul_commitment<R: Rng>(&self, rng: &mut R, x: i64, k: usize) -> ProofULState<E> {
2019-06-28 14:44:14 -07:00
if x > self.u.pow(self.l as u32) || x < 0 {
panic!("x is not within the range.");
}
let decx = decompose(x, self.u, self.l);
2019-06-16 09:27:35 -07:00
2019-07-02 15:39:23 -07:00
// Initialize variables
let mut proofStates = Vec::<ProofState<E>>::with_capacity(self.l as usize);
2019-07-02 15:39:23 -07:00
let mut V = Vec::<Signature<E>>::with_capacity(self.l as usize);
2019-07-12 07:46:25 -07:00
let mut D = E::G1::zero();
2019-06-26 10:33:08 -07:00
let m = E::Fr::rand(rng);
2019-06-16 09:27:35 -07:00
// D = H^m
2019-07-12 16:52:16 -07:00
let mut hm = self.csParams.pub_bases[0].clone();
hm.mul_assign(m);
2019-06-26 10:33:08 -07:00
for i in 0..self.l as usize {
2019-07-01 18:51:24 -07:00
let signature = self.signatures.get(&decx[i].to_string()).unwrap();
let proofState = self.kp.prove_commitment(rng, &self.mpk, &signature);
2019-07-01 18:51:24 -07:00
V.push(proofState.blindSig.clone());
proofStates.push(proofState);
2019-06-16 09:27:35 -07:00
2019-06-16 13:29:48 -07:00
let ui = self.u.pow(i as u32);
2019-07-12 16:52:16 -07:00
let mut aux = self.csParams.pub_bases[k].clone();
2019-07-12 07:46:25 -07:00
for j in 0..self.kp.public.Y1.len() {
let mut muiti = proofStates[i].t[j].clone();
2019-07-02 14:28:49 -07:00
muiti.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap());
aux.mul_assign(muiti);
}
2019-06-16 13:29:48 -07:00
D.add_assign(&aux);
2019-06-26 10:33:08 -07:00
}
D.add_assign(&hm);
ProofULState { decx, proofStates, V, D, m }
}
2019-06-16 13:29:48 -07:00
fn prove_ul_response(&self, r: E::Fr, C: Commitment<E>, proofUlState: &ProofULState<E>, c: 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();
rc.mul_assign(&c);
zr.add_assign(&rc);
2019-06-16 13:29:48 -07:00
for i in 0..self.l as usize {
let mut dx = E::Fr::from_str(&proofUlState.decx[i].to_string()).unwrap();
2019-07-01 18:51:24 -07:00
let proof = self.kp.prove_response(&proofUlState.proofStates[i].clone(), c, &mut vec! {dx});
2019-07-01 18:51:24 -07:00
sigProofs.push(proof);
}
ProofUL { V: proofUlState.V.clone(), D: proofUlState.D.clone(), comm: C, sigProofs, zr }
}
2019-07-02 15:39:23 -07:00
/**
verify_ul is used to validate the ZKRP proof. It returns true iff the proof is valid.
*/
2019-07-12 16:52:16 -07:00
pub fn verify_ul(&self, proof: &ProofUL<E>, ch: E::Fr, k: usize) -> bool {
// D == C^c.h^ zr.g^zsig ?
2019-07-12 16:52:16 -07:00
let r1 = self.verify_part1(&proof, ch.clone(), k);
let r2 = self.verify_part2(&proof, ch.clone());
2019-07-12 16:52:16 -07:00
// r1 && r2 //TODO: fix
r2
2019-07-04 08:35:55 -07:00
}
fn compute_challenge(&self, proof: &ProofUL<E>) -> E::Fr {
2019-07-04 08:35:55 -07:00
let mut a = Vec::<E::Fqk>::with_capacity(self.l as usize);
for sigProof in proof.sigProofs.clone() {
a.push(sigProof.a);
}
hash::<E>(a, vec!(proof.D.clone()))
}
fn verify_part2(&self, proof: &ProofUL<E>, challenge: E::Fr) -> bool {
let mut r2 = true;
for i in 0..self.l as usize {
let subResult = self.kp.public.verify_proof(&self.mpk, proof.V[i].clone(), proof.sigProofs[i].clone(), challenge);
2019-07-01 18:51:24 -07:00
r2 = r2 && subResult;
}
r2
}
2019-07-12 16:52:16 -07:00
fn verify_part1(&self, proof: &ProofUL<E>, challenge: E::Fr, k: usize) -> bool {
2019-07-12 07:46:25 -07:00
let mut D = proof.comm.c.clone();
D.mul_assign(challenge);
D.negate();
2019-07-12 16:52:16 -07:00
let mut hzr = self.csParams.pub_bases[0].clone();
hzr.mul_assign(proof.zr);
D.add_assign(&hzr);
2019-07-02 14:28:49 -07:00
for i in 0..self.l as usize {
let ui = self.u.pow(i as u32);
2019-07-12 16:52:16 -07:00
let mut aux = self.csParams.pub_bases[k].clone();
2019-07-12 07:46:25 -07:00
for j in 0..self.kp.public.Y1.len() {
let mut muizsigi = proof.sigProofs[i].zsig[j];
2019-07-02 14:28:49 -07:00
muizsigi.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap());
aux.mul_assign(muizsigi);
}
D.add_assign(&aux);
2019-06-16 13:29:48 -07:00
}
2019-07-04 08:35:55 -07:00
D == proof.D
2019-06-16 09:27:35 -07:00
}
}
fn hash<E: Engine>(a: Vec<E::Fqk>, D: Vec<E::G1>) -> E::Fr {
2019-06-16 09:27:35 -07:00
// create a Sha256 object
let mut a_vec: Vec<u8> = Vec::new();
for a_el in a {
2019-07-04 08:35:55 -07:00
a_vec.extend(format!("{}", a_el).bytes());
2019-06-16 09:27:35 -07:00
}
let mut x_vec: Vec<u8> = Vec::new();
for d_el in D {
x_vec.extend(format!("{}", d_el).bytes());
}
2019-06-16 09:27:35 -07:00
a_vec.extend(x_vec);
2019-07-04 08:35:55 -07:00
util::hash_to_fr::<E>(a_vec)
2019-06-16 09:27:35 -07:00
}
2019-06-14 15:14:06 -07:00
2019-06-16 13:29:48 -07:00
/*
Decompose receives as input an integer x and outputs an array of integers such that
x = sum(xi.u^i), i.e. it returns the decomposition of x into base u.
*/
fn decompose(x: i64, u: i64, l: i64) -> Vec<i64> {
2019-06-16 13:29:48 -07:00
let mut result = Vec::with_capacity(l as usize);
let mut decomposer = x.clone();
2019-06-26 10:33:08 -07:00
for _i in 0..l {
2019-06-16 13:29:48 -07:00
result.push(decomposer % u);
decomposer = decomposer / u;
}
return result;
}
2019-06-16 12:38:07 -07:00
impl<E: Engine> RPPublicParams<E> {
2019-07-02 15:39:23 -07:00
/**
Setup receives integers a and b, and configures the parameters for the rangeproof scheme.
2019-06-16 12:38:07 -07:00
*/
2019-07-12 16:52:16 -07:00
pub fn setup<R: Rng>(rng: &mut R, a: i64, b: i64, csParams: CSMultiParams<E>) -> Self {
2019-06-16 12:38:07 -07:00
// Compute optimal values for u and l
if a > b {
panic!("a must be less than or equal to b");
}
2019-06-28 14:44:14 -07:00
//TODO: optimize u?
let logb = (b as f64).log2();
2019-07-01 18:51:24 -07:00
let loglogb = logb.log2();
if loglogb > 0.0 {
let mut u = (logb / loglogb) as i64;
if u < 2 {
u = 2;
2019-06-16 12:38:07 -07:00
}
2019-07-01 18:51:24 -07:00
let l = (b as f64).log(u as f64).ceil() as i64;
let params_out: ParamsUL<E> = ParamsUL::<E>::setup_ul(rng, u, l, csParams.clone());
2019-07-01 18:51:24 -07:00
return RPPublicParams { p: params_out, a, b };
2019-06-14 15:14:06 -07:00
} else {
2019-07-01 18:51:24 -07:00
panic!("log(log(b)) is zero");
2019-06-14 15:14:06 -07:00
}
}
2019-07-02 15:39:23 -07:00
/**
Prove method is responsible for generating the zero knowledge range proof.
*/
2019-07-12 16:52:16 -07:00
pub fn prove<R: Rng>(&self, rng: &mut R, x: i64, C: Commitment<E>, r: E::Fr, k: usize) -> 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()));
2019-07-12 16:52:16 -07:00
self.prove_response(r, &rpState, ch)
}
2019-07-12 16:52:16 -07:00
pub fn prove_commitment<R: Rng>(&self, rng: &mut R, x: i64, C: Commitment<E>, k: usize) -> RangeProofState<E> {
2019-06-28 14:44:14 -07:00
if x > self.b || x < self.a {
panic!("x is not within the range.");
}
let ul = self.p.u.pow(self.p.l as u32);
// x - b + ul
2019-06-26 09:37:27 -07:00
let xb = x - self.b + ul;
2019-07-12 16:52:16 -07:00
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());
2019-07-12 16:52:16 -07:00
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);
2019-07-12 16:52:16 -07:00
let firstState = self.p.prove_ul_commitment(rng, xb, k);
// x - a
let xa = x - self.a;
2019-07-12 16:52:16 -07:00
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);
2019-07-12 16:52:16 -07:00
let secondState = self.p.prove_ul_commitment(rng, xa, k);
RangeProofState{com1: comXB, ps1: firstState, com2: comXA, ps2: secondState}
}
2019-07-12 16:52:16 -07:00
pub fn prove_response(&self, r: E::Fr, rpState: &RangeProofState<E>, ch: E::Fr) -> RangeProof<E> {
let first = self.p.prove_ul_response(r.clone(), rpState.com1.clone(), &rpState.ps1, ch.clone());
let second = self.p.prove_ul_response(r.clone(), rpState.com2.clone(), &rpState.ps2, ch.clone());
RangeProof { p1: first, p2: second }
}
2019-07-02 15:39:23 -07:00
/**
Verify is responsible for validating the range proof.
*/
2019-07-12 16:52:16 -07:00
pub fn verify(&self, proof: RangeProof<E>, ch: E::Fr, k: usize) -> bool {
let first = self.p.verify_ul(&proof.p1, ch.clone(), k);
let second = self.p.verify_ul(&proof.p2, ch.clone(), k);
first && second
}
fn compute_challenge(&self, proof: &RangeProof<E>) -> 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);
}
2019-07-12 16:52:16 -07:00
hash::<E>(a, vec!(proof.p1.D.clone(), proof.p2.D.clone()))
}
2019-06-14 15:14:06 -07:00
}
#[cfg(test)]
mod tests {
use super::*;
2019-07-12 07:46:25 -07:00
use pairing::bls12_381::{Bls12, G1, Fq12, Fr};
2019-06-28 14:44:14 -07:00
use time::PreciseTime;
use std::ops::Add;
use core::mem;
2019-07-04 08:35:55 -07:00
use rand::rngs::ThreadRng;
2019-06-14 15:14:06 -07:00
#[test]
fn setup_ul_works() {
2019-06-16 13:29:48 -07:00
let rng = &mut rand::thread_rng();
2019-07-12 16:52:16 -07:00
let csParams = CSMultiParams::setup_gen_params(rng, 1);
2019-07-12 16:52:16 -07:00
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 3, csParams.clone());
assert_eq!(params.signatures.len(), 2);
2019-06-16 13:29:48 -07:00
for (m, s) in params.signatures {
2019-07-02 14:28:49 -07:00
assert_eq!(params.kp.verify(&params.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &Fr::zero(), &s), true);
2019-06-14 15:14:06 -07:00
}
}
2019-06-16 13:29:48 -07:00
#[test]
fn prove_ul_works() {
let rng = &mut rand::thread_rng();
2019-07-12 16:52:16 -07:00
let csParams = CSMultiParams::setup_gen_params(rng, 1);
2019-07-12 16:52:16 -07:00
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 4, csParams.clone());
2019-06-16 13:29:48 -07:00
let fr = Fr::rand(rng);
let modx = Fr::from_str(&(10.to_string())).unwrap();
2019-07-12 16:52:16 -07:00
let C = csParams.commit(&vec!(modx), &fr.clone());
let proof = params.prove_ul(rng, 10, fr, C, 1);
2019-06-28 14:44:14 -07:00
assert_eq!(proof.V.len(), 4);
assert_eq!(proof.sigProofs.len(), 4);
2019-06-28 14:44:14 -07:00
}
#[test]
#[should_panic(expected = "x is not within the range")]
fn prove_ul_not_in_range() {
let rng = &mut rand::thread_rng();
2019-07-12 16:52:16 -07:00
let csParams = CSMultiParams::setup_gen_params(rng, 1);
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 3, csParams.clone());
2019-06-28 14:44:14 -07:00
let fr = Fr::rand(rng);
let modx = Fr::from_str(&(100.to_string())).unwrap();
2019-07-12 16:52:16 -07:00
let C = csParams.commit(&vec!(modx), &fr.clone());
params.prove_ul(rng, 100, fr, C, 1);
}
#[test]
fn prove_and_verify_part1_ul_works() {
let rng = &mut rand::thread_rng();
2019-07-12 16:52:16 -07:00
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 modx = Fr::from_str(&(10.to_string())).unwrap();
2019-07-12 16:52:16 -07:00
let C = csParams.commit(&vec!(modx), &fr.clone());
let proof = params.prove_ul(rng, 10, fr, C, 1);
let ch = params.compute_challenge(&proof);
2019-07-12 16:52:16 -07:00
assert_eq!(params.verify_part1(&proof, ch, 1), true);
}
#[test]
fn prove_and_verify_part2_ul_works() {
let rng = &mut rand::thread_rng();
2019-07-12 16:52:16 -07:00
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 modx = Fr::from_str(&(10.to_string())).unwrap();
2019-07-12 16:52:16 -07:00
let C = csParams.commit(&vec!(modx), &fr.clone());
let proof = params.prove_ul(rng, 10, fr, C, 1);
let ch = params.compute_challenge(&proof);
assert_eq!(params.verify_part2(&proof, ch), true);
}
2019-06-16 13:29:48 -07:00
#[test]
fn prove_and_verify_ul_works() {
let rng = &mut rand::thread_rng();
2019-07-12 16:52:16 -07:00
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 modx = Fr::from_str(&(10.to_string())).unwrap();
2019-07-12 16:52:16 -07:00
let C = csParams.commit(&vec!(modx), &fr.clone());
let proof = params.prove_ul(rng, 10, fr, C, 1);
let ch = params.compute_challenge(&proof);
2019-07-12 16:52:16 -07:00
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 C = csParams.commit(&vec!(Fr::rand(rng), modx, Fr::rand(rng)), &fr.clone());
let proof = params.prove_ul(rng, 10, fr, C, 2);
let ch = params.compute_challenge(&proof);
assert_eq!(params.verify_ul(&proof, ch, 2), true);
2019-06-16 13:29:48 -07:00
}
#[test]
fn prove_and_verify_works() {
let rng = &mut rand::thread_rng();
2019-07-12 16:52:16 -07:00
let csParams = CSMultiParams::setup_gen_params(rng, 1);
let params = RPPublicParams::<Bls12>::setup(rng, 2, 25, csParams.clone());
let fr = Fr::rand(rng);
let modx = Fr::from_str(&(10.to_string())).unwrap();
2019-07-12 16:52:16 -07:00
let C = csParams.commit(&vec!(modx), &fr.clone());
let proof = params.prove(rng, 10, C, fr, 1);
let ch = params.compute_challenge(&proof);
assert_eq!(params.verify(proof, ch, 1), true);
}
#[test]
fn prove_and_verify_bigger_commit_works() {
let rng = &mut rand::thread_rng();
let csParams = CSMultiParams::setup_gen_params(rng, 3);
let params = RPPublicParams::<Bls12>::setup(rng, 2, 25, csParams.clone());
let fr = Fr::rand(rng);
let modx = Fr::from_str(&(10.to_string())).unwrap();
let C = csParams.commit(&vec!(Fr::rand(rng), modx, Fr::rand(rng)), &fr.clone());
let proof = params.prove(rng, 10, C, fr, 2);
let ch = params.compute_challenge(&proof);
assert_eq!(params.verify(proof, ch, 2), true);
}
2019-06-28 14:44:14 -07:00
#[test]
#[should_panic(expected = "x is not within the range")]
fn prove_not_in_range() {
let rng = &mut rand::thread_rng();
2019-07-12 16:52:16 -07:00
let csParams = CSMultiParams::setup_gen_params(rng, 1);
let params = RPPublicParams::<Bls12>::setup(rng, 2, 25, csParams.clone());
let fr = Fr::rand(rng);
let modx = Fr::from_str(&(26.to_string())).unwrap();
2019-07-12 16:52:16 -07:00
let C = csParams.commit(&vec!(modx), &fr.clone());
params.prove(rng, 26, C, fr, 1);
2019-06-28 14:44:14 -07:00
}
#[test]
#[ignore]
fn prove_and_verify_performance() {
let rng = &mut rand::thread_rng();
let mut averageSetup = time::Duration::nanoseconds(0);
let mut averageSetupSize = 0;
let mut averageProve = time::Duration::nanoseconds(0);
let mut averageProofSize = 0;
let mut averageVerify = time::Duration::nanoseconds(0);
let iter = 5;
for i in 0..iter {
let a = rng.gen_range(0, 1000000);
let b = rng.gen_range(a, 1000000);
let x = rng.gen_range(a, b);
let sSetup = PreciseTime::now();
2019-07-12 16:52:16 -07:00
let csParams = CSMultiParams::setup_gen_params(rng, 1);
let params = RPPublicParams::<Bls12>::setup(rng, a, b, csParams.clone());
2019-06-28 14:44:14 -07:00
averageSetup = averageSetup.add(sSetup.to(PreciseTime::now()));
averageSetupSize += mem::size_of_val(&params);
let sProve = PreciseTime::now();
let fr = Fr::rand(rng);
let modx = Fr::from_str(&(x.to_string())).unwrap();
2019-07-12 16:52:16 -07:00
let C = csParams.commit(&vec!(modx), &fr.clone());
let proof = params.prove(rng, x, C, fr, 1);
2019-06-28 14:44:14 -07:00
averageProve = averageProve.add(sProve.to(PreciseTime::now()));
averageProofSize += mem::size_of_val(&proof);
let sVerify = PreciseTime::now();
2019-07-12 16:52:16 -07:00
let ch = params.compute_challenge(&proof);
params.verify(proof, ch, 1);
2019-06-28 14:44:14 -07:00
averageVerify = averageVerify.add(sVerify.to(PreciseTime::now()));
}
print!("Setup: {}\n", averageSetup.num_milliseconds() / iter);
print!("Setup size: {}\n", averageSetupSize / iter as usize);
print!("Prove: {}\n", averageProve.num_milliseconds() / iter);
print!("Proof size: {}\n", averageProofSize / iter as usize);
print!("Verify: {}\n", averageVerify.num_milliseconds() / iter);
}
2019-06-14 15:14:06 -07:00
#[test]
fn decompose_works() {
assert_eq!(decompose(25, 3, 3), vec! {1, 2, 2});
assert_eq!(decompose(336, 7, 3), vec! {0, 6, 6});
assert_eq!(decompose(285, 8, 3), vec! {5, 3, 4});
assert_eq!(decompose(125, 13, 2), vec! {8, 9});
assert_eq!(decompose(143225, 6, 7), vec! {5, 2, 0, 3, 2, 0, 3});
}
#[test]
fn decompose_recompose_works() {
let vec1 = decompose(25, 3, 5);
let mut result = 0;
for i in 0..5 {
result += vec1[i] * 3i64.pow(i as u32);
}
assert_eq!(result, 25);
let vec1 = decompose(143225, 6, 7);
let mut result = 0;
for i in 0..7 {
result += vec1[i] * 6i64.pow(i as u32);
}
assert_eq!(result, 143225);
2019-06-14 15:14:06 -07:00
}
#[test]
fn setup_works() {
2019-06-16 13:29:48 -07:00
let rng = &mut rand::thread_rng();
2019-07-12 16:52:16 -07:00
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.b, 10);
2019-07-01 18:51:24 -07:00
assert_eq!(public_params.p.signatures.len(), 2);
assert_eq!(public_params.p.u, 2);
assert_eq!(public_params.p.l, 4);
2019-06-14 15:14:06 -07:00
for (m, s) in public_params.p.signatures {
2019-07-02 14:28:49 -07:00
assert_eq!(public_params.p.kp.verify(&public_params.p.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &Fr::zero(), &s), true);
2019-06-14 15:14:06 -07:00
}
}
#[test]
#[should_panic(expected = "a must be less than or equal to b")]
fn setup_wrong_a_and_b() {
2019-06-16 13:29:48 -07:00
let rng = &mut rand::thread_rng();
2019-07-12 16:52:16 -07:00
let csParams = CSMultiParams::setup_gen_params(rng, 1);
RPPublicParams::<Bls12>::setup(rng, 10, 2, csParams);
2019-06-14 15:14:06 -07:00
}
#[test]
2019-07-01 18:51:24 -07:00
#[should_panic(expected = "log(log(b)) is zero")]
2019-06-14 15:14:06 -07:00
fn setup_wrong_logb() {
2019-06-16 13:29:48 -07:00
let rng = &mut rand::thread_rng();
2019-07-12 16:52:16 -07:00
let csParams = CSMultiParams::setup_gen_params(rng, 1);
RPPublicParams::<Bls12>::setup(rng, -2, -1, csParams);
2019-06-16 12:38:07 -07:00
}
#[test]
fn hash_works() {
2019-06-16 13:29:48 -07:00
let rng = &mut rand::thread_rng();
2019-07-12 07:46:25 -07:00
let D = G1::rand(rng);
let D2 = G1::rand(rng);
2019-07-04 08:35:55 -07:00
let params = setup::<ThreadRng, Bls12>(rng);
let kp = BlindKeyPair::generate(rng, &params, 2);
let m1 = Fr::rand(rng);
let m2 = Fr::rand(rng);
let sig = kp.sign(rng, &vec! {m1, m2});
let state = kp.prove_commitment(rng, &params, &sig);
let state1 = kp.prove_commitment(rng, &params, &sig);
let state2 = kp.prove_commitment(rng, &params, &sig);
let state3 = kp.prove_commitment(rng, &params, &sig);
let state4 = kp.prove_commitment(rng, &params, &sig);
2019-07-04 08:35:55 -07:00
let a = vec! {state.a, state1.a, state2.a};
let a2 = vec! {state3.a, state4.a};
assert_eq!(hash::<Bls12>(a.clone(), vec!(D.clone())).is_zero(), false);
assert_ne!(hash::<Bls12>(a2.clone(), vec!(D.clone())), hash::<Bls12>(a.clone(), vec!(D.clone())));
assert_ne!(hash::<Bls12>(a.clone(), vec!(D2.clone())), hash::<Bls12>(a.clone(), vec!(D.clone())));
assert_ne!(hash::<Bls12>(a2.clone(), vec!(D2.clone())), hash::<Bls12>(a.clone(), vec!(D.clone())))
2019-06-14 15:14:06 -07:00
}
}