2019-07-05 12:41:22 -07:00
|
|
|
extern crate pairing;
|
2019-07-03 16:05:27 -07:00
|
|
|
extern crate rand;
|
|
|
|
|
2019-07-05 12:41:22 -07:00
|
|
|
use super::*;
|
2019-08-22 21:50:41 -07:00
|
|
|
use rand::Rng;
|
2019-09-10 19:21:09 -07:00
|
|
|
use cl::{Signature, PublicParams, setup, BlindKeyPair, SignatureProof, PublicKey, BlindPublicKey};
|
2019-08-30 11:57:21 -07:00
|
|
|
use ped92::{Commitment, CSMultiParams, CommitmentProof};
|
2019-07-05 12:41:22 -07:00
|
|
|
use pairing::{Engine, CurveProjective};
|
2019-07-12 14:20:08 -07:00
|
|
|
use wallet::Wallet;
|
2019-09-13 08:38:23 -07:00
|
|
|
use ccs08::{SecretParamsUL, ParamsUL, ProofUL};
|
2019-07-29 14:13:40 -07:00
|
|
|
use serde::{Serialize, Deserialize};
|
2019-08-19 15:29:26 -07:00
|
|
|
use util;
|
2019-08-27 13:58:30 -07:00
|
|
|
use std::borrow::BorrowMut;
|
2019-07-03 16:05:27 -07:00
|
|
|
|
2019-08-27 13:58:30 -07:00
|
|
|
/// NIZKProof is the object that represents the NIZK Proof of Knowledge during the payment and closing protocol
|
2019-07-31 19:06:57 -07:00
|
|
|
#[derive(Clone, Serialize, Deserialize)]
|
|
|
|
#[serde(bound(serialize = "<E as ff::ScalarEngine>::Fr: serde::Serialize, \
|
|
|
|
<E as pairing::Engine>::G1: serde::Serialize, \
|
|
|
|
<E as pairing::Engine>::G2: serde::Serialize, \
|
|
|
|
<E as pairing::Engine>::Fqk: serde::Serialize"
|
|
|
|
))]
|
|
|
|
#[serde(bound(deserialize = "<E as ff::ScalarEngine>::Fr: serde::Deserialize<'de>, \
|
|
|
|
<E as pairing::Engine>::G1: serde::Deserialize<'de>, \
|
|
|
|
<E as pairing::Engine>::G2: serde::Deserialize<'de>, \
|
|
|
|
<E as pairing::Engine>::Fqk: serde::Deserialize<'de>"
|
|
|
|
))]
|
2019-08-27 13:58:30 -07:00
|
|
|
pub struct NIZKProof<E: Engine> {
|
2019-07-19 12:19:28 -07:00
|
|
|
pub sig: Signature<E>,
|
|
|
|
pub sigProof: SignatureProof<E>,
|
2019-08-27 13:58:30 -07:00
|
|
|
pub comProof: CommitmentProof<E>,
|
2019-09-13 08:38:23 -07:00
|
|
|
pub rpBC: ProofUL<E>,
|
|
|
|
pub rpBM: ProofUL<E>,
|
2019-07-03 16:05:27 -07:00
|
|
|
}
|
|
|
|
|
2019-08-27 13:58:30 -07:00
|
|
|
/// NIZKPublicParams are public parameters to perform a NIZK Proof of Knowledge during the payment and closing protocol
|
2019-07-29 21:53:58 -07:00
|
|
|
#[derive(Clone, Serialize, Deserialize)]
|
|
|
|
#[serde(bound(serialize = "<E as ff::ScalarEngine>::Fr: serde::Serialize, \
|
|
|
|
<E as pairing::Engine>::G1: serde::Serialize, \
|
|
|
|
<E as pairing::Engine>::G2: serde::Serialize"
|
|
|
|
))]
|
|
|
|
#[serde(bound(deserialize = "<E as ff::ScalarEngine>::Fr: serde::Deserialize<'de>, \
|
|
|
|
<E as pairing::Engine>::G1: serde::Deserialize<'de>, \
|
|
|
|
<E as pairing::Engine>::G2: serde::Deserialize<'de>"
|
|
|
|
))]
|
2019-07-21 07:05:27 -07:00
|
|
|
pub struct NIZKPublicParams<E: Engine> {
|
|
|
|
pub mpk: PublicParams<E>,
|
2019-09-10 19:21:09 -07:00
|
|
|
pub pk: BlindPublicKey<E>,
|
2019-07-21 07:05:27 -07:00
|
|
|
pub comParams: CSMultiParams<E>,
|
2019-09-13 08:38:23 -07:00
|
|
|
pub rpParams: ParamsUL<E>,
|
2019-07-21 07:05:27 -07:00
|
|
|
}
|
2019-07-05 13:57:30 -07:00
|
|
|
|
2019-09-10 19:21:09 -07:00
|
|
|
/// NIZKSecretParams are secret parameters to perform the verification of a NIZK Proof of Knowledge during the payment and closing protocol
|
|
|
|
#[derive(Clone, Serialize, Deserialize)]
|
|
|
|
#[serde(bound(serialize = "<E as ff::ScalarEngine>::Fr: serde::Serialize, \
|
|
|
|
<E as pairing::Engine>::G1: serde::Serialize, \
|
|
|
|
<E as pairing::Engine>::G2: serde::Serialize"
|
|
|
|
))]
|
|
|
|
#[serde(bound(deserialize = "<E as ff::ScalarEngine>::Fr: serde::Deserialize<'de>, \
|
|
|
|
<E as pairing::Engine>::G1: serde::Deserialize<'de>, \
|
|
|
|
<E as pairing::Engine>::G2: serde::Deserialize<'de>"
|
|
|
|
))]
|
|
|
|
pub struct NIZKSecretParams<E: Engine> {
|
|
|
|
pub pubParams: NIZKPublicParams<E>,
|
|
|
|
pub keypair: BlindKeyPair<E>,
|
2019-09-13 08:38:23 -07:00
|
|
|
pub rpParams: SecretParamsUL<E>,
|
2019-09-10 19:21:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<E: Engine> NIZKSecretParams<E> {
|
2019-08-27 13:58:30 -07:00
|
|
|
/// Basic setup for the NIZKPublicParams
|
|
|
|
/// Takes as input a random generator and the length of the message which should be 4 during payment protocol and 5 for the closing protocol
|
2019-07-24 14:13:56 -07:00
|
|
|
pub fn setup<R: Rng>(rng: &mut R, messageLength: usize) -> Self {
|
2019-07-21 07:05:27 -07:00
|
|
|
let mpk = setup(rng);
|
2019-07-24 14:13:56 -07:00
|
|
|
let keypair = BlindKeyPair::<E>::generate(rng, &mpk, messageLength);
|
2019-07-21 07:05:27 -07:00
|
|
|
let comParams = keypair.generate_cs_multi_params(&mpk);
|
2019-09-27 10:02:31 -07:00
|
|
|
let u = 128; //TODO: make u and l configurable
|
|
|
|
let l = 9;
|
2019-09-13 08:38:23 -07:00
|
|
|
let rpParams = SecretParamsUL::setup_ul(rng, u, l, comParams.clone());
|
2019-09-11 11:14:59 -07:00
|
|
|
let pubParams = NIZKPublicParams { mpk, pk: keypair.public.clone(), comParams, rpParams: rpParams.pubParams.clone() };
|
2019-09-10 19:21:09 -07:00
|
|
|
|
2019-09-11 11:14:59 -07:00
|
|
|
NIZKSecretParams { pubParams, keypair, rpParams }
|
2019-09-10 19:21:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Verify a NIZK Proof of Knowledge during payment or closing protocol
|
|
|
|
Input:
|
|
|
|
proof: A NIZK proof created by the Customer
|
|
|
|
epsilon: The transaction amount of the payment
|
|
|
|
com: Commitment of the new wallet that needs to be signed
|
|
|
|
wpk: reveal of wallet public key of the old wallet.
|
|
|
|
*/
|
|
|
|
pub fn verify(&self, proof: NIZKProof<E>, epsilon: E::Fr, com: &Commitment<E>, wpk: E::Fr) -> bool {
|
|
|
|
//verify signature is not the identity
|
|
|
|
let r0 = proof.sig.h != E::G1::one();
|
|
|
|
|
|
|
|
//compute challenge
|
2019-09-13 08:38:23 -07:00
|
|
|
let challenge = NIZKPublicParams::<E>::hash(proof.sigProof.a, vec! {proof.comProof.T, proof.rpBC.D, proof.rpBM.D});
|
2019-09-10 19:21:09 -07:00
|
|
|
|
|
|
|
//verify knowledge of signature
|
|
|
|
let mut r1 = self.keypair.public.verify_proof(&self.pubParams.mpk, proof.sig, proof.sigProof.clone(), challenge);
|
|
|
|
let mut wpkc = wpk.clone();
|
|
|
|
wpkc.mul_assign(&challenge.clone());
|
|
|
|
r1 = r1 && proof.sigProof.zsig[1] == wpkc;
|
|
|
|
|
|
|
|
//verify knowledge of commitment
|
2019-09-13 13:16:35 -07:00
|
|
|
let r2 = proof.comProof.verify_proof(&self.pubParams.comParams, &com.c.clone(), &challenge, None);
|
2019-09-10 19:21:09 -07:00
|
|
|
|
|
|
|
//verify range proofs
|
2019-09-13 08:38:23 -07:00
|
|
|
let r3 = self.rpParams.verify_ul(&proof.rpBC.clone(), challenge.clone(), 3);
|
|
|
|
let r4 = self.rpParams.verify_ul(&proof.rpBM.clone(), challenge.clone(), 4);
|
2019-09-10 19:21:09 -07:00
|
|
|
|
|
|
|
//verify linear relationship
|
|
|
|
let mut r5 = proof.comProof.z[1] == proof.sigProof.zsig[0];
|
|
|
|
let mut zsig2 = proof.sigProof.zsig[2].clone();
|
|
|
|
let mut epsC = epsilon.clone();
|
|
|
|
epsC.mul_assign(&challenge.clone());
|
|
|
|
zsig2.sub_assign(&epsC.clone());
|
|
|
|
r5 = r5 && proof.comProof.z[3] == zsig2;
|
|
|
|
let mut zsig3 = proof.sigProof.zsig[3].clone();
|
|
|
|
zsig3.add_assign(&epsC.clone());
|
|
|
|
r5 = r5 && proof.comProof.z[4] == zsig3;
|
2019-07-12 16:52:16 -07:00
|
|
|
|
2019-09-10 19:21:09 -07:00
|
|
|
r0 && r1 && r2 && r3 && r4 && r5
|
2019-07-21 07:05:27 -07:00
|
|
|
}
|
2019-09-10 19:21:09 -07:00
|
|
|
}
|
2019-07-03 16:05:27 -07:00
|
|
|
|
2019-09-10 19:21:09 -07:00
|
|
|
impl<E: Engine> NIZKPublicParams<E> {
|
2019-08-27 13:58:30 -07:00
|
|
|
/** This method can be called to create the proof during the payment and closing protocol
|
|
|
|
Input:
|
|
|
|
rng: random generator
|
|
|
|
oldWallet: This is the wallet before payment occurs
|
|
|
|
newWallet: This is the new state of the wallet after payment
|
|
|
|
newWalletCom: A commitment of the new wallet
|
2019-08-30 11:57:21 -07:00
|
|
|
rPrime: blinding value of commitment of new wallet
|
2019-08-27 13:58:30 -07:00
|
|
|
paymentToken: A blind signature on the old wallet
|
|
|
|
Output:
|
|
|
|
NIZKProof: a proof that can be verified by the merchant during payment or closing protocol
|
|
|
|
*/
|
2019-08-30 11:57:21 -07:00
|
|
|
pub fn prove<R: Rng>(&self, rng: &mut R, oldWallet: Wallet<E>, newWallet: Wallet<E>,
|
2019-08-27 13:58:30 -07:00
|
|
|
newWalletCom: Commitment<E>, rPrime: E::Fr, paymentToken: &Signature<E>) -> NIZKProof<E> {
|
2019-07-21 07:05:27 -07:00
|
|
|
//Commitment phase
|
|
|
|
//commit commitment
|
2019-07-27 12:09:03 -07:00
|
|
|
let w_len = newWallet.as_fr_vec().len();
|
|
|
|
let diff = self.comParams.pub_bases.len() - w_len;
|
2019-08-08 07:21:01 -07:00
|
|
|
let max = match diff > 1 {
|
2019-07-27 12:09:03 -07:00
|
|
|
true => w_len,
|
|
|
|
false => self.comParams.pub_bases.len()
|
|
|
|
};
|
|
|
|
|
2019-09-13 13:16:35 -07:00
|
|
|
let (D, t) = CommitmentProof::<E>::prove_commitment(rng, &self.comParams, &newWallet.as_fr_vec(), None);
|
2019-07-21 07:05:27 -07:00
|
|
|
|
2019-07-21 08:02:36 -07:00
|
|
|
//commit signature
|
2019-08-08 07:21:01 -07:00
|
|
|
let zero = E::Fr::zero();
|
|
|
|
let tOptional = match max > 4 {
|
|
|
|
true => Some(vec!(t[1], zero, t[3].clone(), t[4].clone())),
|
|
|
|
false => Some(vec!(t[1], zero, t[3].clone()))
|
2019-07-27 12:09:03 -07:00
|
|
|
};
|
2019-09-10 19:21:09 -07:00
|
|
|
let proofState = self.pk.prove_commitment(rng, &self.mpk, &paymentToken, tOptional, None);
|
2019-07-21 08:02:36 -07:00
|
|
|
|
2019-07-21 07:05:27 -07:00
|
|
|
//commit range proof
|
2019-09-13 08:38:23 -07:00
|
|
|
let rpStateBC = self.rpParams.prove_ul_commitment(rng, newWallet.bc.clone(), 3, None, None);
|
|
|
|
let rpStateBM = self.rpParams.prove_ul_commitment(rng, newWallet.bm.clone(), 4, None, None);
|
2019-07-21 07:05:27 -07:00
|
|
|
|
|
|
|
//Compute challenge
|
2019-09-13 08:38:23 -07:00
|
|
|
let challenge = NIZKPublicParams::<E>::hash(proofState.a, vec! {D, rpStateBC.D, rpStateBM.D});
|
2019-07-21 07:05:27 -07:00
|
|
|
|
|
|
|
//Response phase
|
|
|
|
//response for signature
|
|
|
|
let oldWalletVec = oldWallet.as_fr_vec();
|
2019-09-10 19:21:09 -07:00
|
|
|
let sigProof = self.pk.prove_response(&proofState, challenge, &mut oldWalletVec.clone());
|
2019-07-21 07:05:27 -07:00
|
|
|
|
|
|
|
//response commitment
|
|
|
|
let newWalletVec = newWallet.as_fr_vec();
|
2019-09-13 13:16:35 -07:00
|
|
|
let comProof = CommitmentProof::<E>::prove_response(&newWalletVec, &rPrime, D, &t, &challenge);
|
2019-07-21 07:05:27 -07:00
|
|
|
|
|
|
|
//response range proof
|
2019-07-24 14:13:56 -07:00
|
|
|
let mut vec01 = newWalletVec[0..2].to_vec();
|
|
|
|
let mut vecWithout2 = vec01.clone();
|
|
|
|
let mut vec3 = newWalletVec[3..].to_vec();
|
|
|
|
vecWithout2.append(&mut vec3);
|
2019-08-22 21:50:41 -07:00
|
|
|
let vec2 = newWalletVec[2].clone();
|
2019-08-27 13:58:30 -07:00
|
|
|
vec01.push(vec2);
|
2019-07-24 14:13:56 -07:00
|
|
|
if newWalletVec.len() > 4 {
|
|
|
|
let mut vec4 = newWalletVec[4..].to_vec();
|
|
|
|
vec01.append(&mut vec4);
|
|
|
|
}
|
2019-09-13 08:38:23 -07:00
|
|
|
let rpBC = self.rpParams.prove_ul_response(rPrime.clone(), newWalletCom.clone(), &rpStateBC, challenge.clone(), 3, vecWithout2.to_vec());
|
|
|
|
let rpBM = self.rpParams.prove_ul_response(rPrime.clone(), newWalletCom.clone(), &rpStateBM, challenge.clone(), 4, vec01.to_vec());
|
2019-07-21 07:05:27 -07:00
|
|
|
|
2019-08-27 13:58:30 -07:00
|
|
|
NIZKProof { sig: proofState.blindSig, sigProof, comProof, rpBC, rpBM }
|
2019-07-05 13:57:30 -07:00
|
|
|
}
|
2019-07-12 16:52:16 -07:00
|
|
|
|
2019-07-21 07:05:27 -07:00
|
|
|
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());
|
|
|
|
}
|
2019-07-03 16:05:27 -07:00
|
|
|
|
2019-07-21 07:05:27 -07:00
|
|
|
util::hash_to_fr::<E>(x_vec)
|
2019-07-19 12:19:28 -07:00
|
|
|
}
|
2019-07-05 13:14:14 -07:00
|
|
|
}
|
|
|
|
|
2019-08-19 15:29:26 -07:00
|
|
|
///
|
2019-08-27 13:58:30 -07:00
|
|
|
/// Verify PoK for the opening of a commitment during the establishment protocol
|
2019-08-19 15:29:26 -07:00
|
|
|
///
|
2019-09-27 10:02:31 -07:00
|
|
|
pub fn verify_opening<E: Engine>(com_params: &CSMultiParams<E>, com: &E::G1, proof: &CommitmentProof<E>, pkc: &E::Fr, init_cust: i64, init_merch: i64) -> bool {
|
2019-08-27 13:58:30 -07:00
|
|
|
let xvec: Vec<E::G1> = vec![proof.T.clone(), com.clone()];
|
2019-08-19 15:29:26 -07:00
|
|
|
let challenge = util::hash_g1_to_fr::<E>(&xvec);
|
|
|
|
|
|
|
|
// compute the
|
2019-09-27 10:02:31 -07:00
|
|
|
let com_equal = proof.verify_proof(com_params, com, &challenge, Some(vec!{None, Some(pkc.clone()), None, Some(util::convert_int_to_fr::<E>(init_cust as i64)), Some(util::convert_int_to_fr::<E>(init_merch as i64))}));
|
2019-08-19 15:29:26 -07:00
|
|
|
|
2019-09-13 13:16:35 -07:00
|
|
|
return com_equal;
|
2019-08-19 15:29:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-07-03 16:05:27 -07:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
2019-07-07 14:15:36 -07:00
|
|
|
use pairing::bls12_381::{Bls12, Fr};
|
2019-08-08 05:41:59 -07:00
|
|
|
use util::convert_int_to_fr;
|
2019-08-30 11:57:21 -07:00
|
|
|
use rand::thread_rng;
|
|
|
|
use ff::PrimeField;
|
2019-07-03 16:05:27 -07:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn nizk_proof_works() {
|
|
|
|
let rng = &mut rand::thread_rng();
|
|
|
|
let pkc = Fr::rand(rng);
|
|
|
|
let wpk = Fr::rand(rng);
|
|
|
|
let wpkprime = Fr::rand(rng);
|
2019-09-27 13:40:00 -07:00
|
|
|
let bc = rng.gen_range(100, 1000);
|
2019-07-03 16:05:27 -07:00
|
|
|
let mut bc2 = bc.clone();
|
2019-09-27 13:40:00 -07:00
|
|
|
let bm = rng.gen_range(100, 1000);
|
2019-07-03 16:05:27 -07:00
|
|
|
let mut bm2 = bm.clone();
|
2019-09-27 13:40:00 -07:00
|
|
|
let epsilon = rng.gen_range(1, 100);
|
|
|
|
bc2 -= epsilon;
|
|
|
|
bm2 += epsilon;
|
2019-07-03 16:05:27 -07:00
|
|
|
let r = Fr::rand(rng);
|
|
|
|
let rprime = Fr::rand(rng);
|
|
|
|
|
2019-09-10 19:21:09 -07:00
|
|
|
let secParams = NIZKSecretParams::<Bls12>::setup(rng, 4);
|
2019-07-24 14:13:56 -07:00
|
|
|
let wallet1 = Wallet { pkc, wpk, bc, bm, close: None };
|
2019-09-10 19:21:09 -07:00
|
|
|
let commitment1 = secParams.pubParams.comParams.commit(&wallet1.as_fr_vec(), &r);
|
2019-07-24 14:13:56 -07:00
|
|
|
let wallet2 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2, close: None };
|
2019-09-10 19:21:09 -07:00
|
|
|
let commitment2 = secParams.pubParams.comParams.commit(&wallet2.as_fr_vec(), &rprime);
|
|
|
|
let blindPaymentToken = secParams.keypair.sign_blind(rng, &secParams.pubParams.mpk, commitment1.clone());
|
|
|
|
let paymentToken = secParams.keypair.unblind(&r, &blindPaymentToken);
|
2019-07-03 16:05:27 -07:00
|
|
|
|
2019-09-10 19:21:09 -07:00
|
|
|
let proof = secParams.pubParams.prove(rng, wallet1, wallet2,
|
2019-09-11 11:14:59 -07:00
|
|
|
commitment2.clone(), rprime, &paymentToken);
|
2019-09-27 10:02:31 -07:00
|
|
|
let fr = convert_int_to_fr::<Bls12>(epsilon);
|
2019-09-10 19:21:09 -07:00
|
|
|
assert_eq!(secParams.verify(proof, fr, &commitment2, wpk), true);
|
2019-08-08 05:41:59 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn nizk_proof_negative_value_works() {
|
|
|
|
let rng = &mut rand::thread_rng();
|
|
|
|
let pkc = Fr::rand(rng);
|
|
|
|
let wpk = Fr::rand(rng);
|
|
|
|
let wpkprime = Fr::rand(rng);
|
2019-09-27 13:40:00 -07:00
|
|
|
let bc = rng.gen_range(100, 1000);
|
2019-08-08 05:41:59 -07:00
|
|
|
let mut bc2 = bc.clone();
|
2019-09-27 13:40:00 -07:00
|
|
|
let bm = rng.gen_range(100, 1000);
|
2019-08-08 05:41:59 -07:00
|
|
|
let mut bm2 = bm.clone();
|
2019-09-27 13:40:00 -07:00
|
|
|
let epsilon = rng.gen_range(-100, -1);
|
|
|
|
bc2 -= epsilon;
|
|
|
|
bm2 += epsilon;
|
2019-08-08 05:41:59 -07:00
|
|
|
let r = Fr::rand(rng);
|
|
|
|
let rprime = Fr::rand(rng);
|
|
|
|
|
2019-09-10 19:21:09 -07:00
|
|
|
let secParams = NIZKSecretParams::<Bls12>::setup(rng, 4);
|
2019-08-08 05:41:59 -07:00
|
|
|
let wallet1 = Wallet { pkc, wpk, bc, bm, close: None };
|
2019-09-10 19:21:09 -07:00
|
|
|
let commitment1 = secParams.pubParams.comParams.commit(&wallet1.as_fr_vec(), &r);
|
2019-08-08 05:41:59 -07:00
|
|
|
let wallet2 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2, close: None };
|
2019-09-10 19:21:09 -07:00
|
|
|
let commitment2 = secParams.pubParams.comParams.commit(&wallet2.as_fr_vec(), &rprime);
|
|
|
|
let blindPaymentToken = secParams.keypair.sign_blind(rng, &secParams.pubParams.mpk, commitment1.clone());
|
|
|
|
let paymentToken = secParams.keypair.unblind(&r, &blindPaymentToken);
|
2019-07-05 14:21:48 -07:00
|
|
|
|
2019-09-10 19:21:09 -07:00
|
|
|
let proof = secParams.pubParams.prove(rng, wallet1, wallet2,
|
2019-09-11 11:14:59 -07:00
|
|
|
commitment2.clone(), rprime, &paymentToken);
|
2019-09-27 10:02:31 -07:00
|
|
|
let fr = convert_int_to_fr::<Bls12>(epsilon);
|
2019-09-10 19:21:09 -07:00
|
|
|
assert_eq!(secParams.verify(proof, fr, &commitment2, wpk), true);
|
2019-07-05 14:21:48 -07:00
|
|
|
}
|
|
|
|
|
2019-07-24 14:13:56 -07:00
|
|
|
#[test]
|
|
|
|
fn nizk_proof_close_works() {
|
|
|
|
let rng = &mut rand::thread_rng();
|
|
|
|
let pkc = Fr::rand(rng);
|
|
|
|
let wpk = Fr::rand(rng);
|
|
|
|
let wpkprime = Fr::rand(rng);
|
2019-09-27 13:40:00 -07:00
|
|
|
let bc = rng.gen_range(100, 1000);
|
2019-07-24 14:13:56 -07:00
|
|
|
let mut bc2 = bc.clone();
|
2019-09-27 13:40:00 -07:00
|
|
|
let bm = rng.gen_range(100, 1000);
|
2019-07-24 14:13:56 -07:00
|
|
|
let mut bm2 = bm.clone();
|
2019-09-27 13:40:00 -07:00
|
|
|
let epsilon = rng.gen_range(1, 100);
|
|
|
|
bc2 -= epsilon;
|
|
|
|
bm2 += epsilon;
|
2019-07-24 14:13:56 -07:00
|
|
|
let r = Fr::rand(rng);
|
|
|
|
let rprime = Fr::rand(rng);
|
|
|
|
|
2019-07-27 12:09:03 -07:00
|
|
|
let _closeToken = Fr::rand(rng);
|
2019-09-10 19:21:09 -07:00
|
|
|
let secParams = NIZKSecretParams::<Bls12>::setup(rng, 5);
|
2019-07-24 14:13:56 -07:00
|
|
|
let wallet1 = Wallet { pkc, wpk, bc, bm, close: None };
|
2019-09-10 19:21:09 -07:00
|
|
|
let commitment1 = secParams.pubParams.comParams.commit(&wallet1.as_fr_vec(), &r);
|
2019-07-27 12:09:03 -07:00
|
|
|
let wallet2 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2, close: Some(_closeToken) };
|
2019-09-10 19:21:09 -07:00
|
|
|
let commitment2 = secParams.pubParams.comParams.commit(&wallet2.as_fr_vec(), &rprime);
|
|
|
|
let blindPaymentToken = secParams.keypair.sign_blind(rng, &secParams.pubParams.mpk, commitment1.clone());
|
|
|
|
let paymentToken = secParams.keypair.unblind(&r, &blindPaymentToken);
|
2019-07-24 14:13:56 -07:00
|
|
|
|
2019-09-10 19:21:09 -07:00
|
|
|
let blindCloseToken = secParams.keypair.sign_blind(rng, &secParams.pubParams.mpk, commitment2.clone());
|
|
|
|
let closeToken = secParams.pubParams.pk.unblind(&rprime, &blindCloseToken);
|
2019-07-27 12:09:03 -07:00
|
|
|
|
|
|
|
// verify the blind signatures
|
2019-09-10 19:21:09 -07:00
|
|
|
let pk = secParams.keypair.get_public_key(&secParams.pubParams.mpk);
|
|
|
|
assert!(pk.verify(&secParams.pubParams.mpk, &wallet1.as_fr_vec(), &paymentToken));
|
2019-07-27 12:09:03 -07:00
|
|
|
|
|
|
|
println!("close => {}", &wallet2);
|
2019-09-10 19:21:09 -07:00
|
|
|
assert!(pk.verify(&secParams.pubParams.mpk, &wallet2.as_fr_vec(), &closeToken));
|
2019-07-27 12:09:03 -07:00
|
|
|
|
2019-09-10 19:21:09 -07:00
|
|
|
let proof = secParams.pubParams.prove(rng, wallet1, wallet2,
|
2019-09-11 11:14:59 -07:00
|
|
|
commitment2.clone(), rprime, &paymentToken);
|
2019-07-24 14:13:56 -07:00
|
|
|
|
2019-09-10 19:21:09 -07:00
|
|
|
assert_eq!(secParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), true);
|
2019-07-24 14:13:56 -07:00
|
|
|
}
|
|
|
|
|
2019-07-05 14:21:48 -07:00
|
|
|
#[test]
|
|
|
|
fn nizk_proof_false_statements() {
|
|
|
|
let rng = &mut rand::thread_rng();
|
|
|
|
let pkc = Fr::rand(rng);
|
|
|
|
let wpk = Fr::rand(rng);
|
|
|
|
let wpkprime = Fr::rand(rng);
|
2019-09-27 13:40:00 -07:00
|
|
|
let bc = rng.gen_range(100, 1000);
|
2019-07-05 14:21:48 -07:00
|
|
|
let mut bc2 = bc.clone();
|
2019-09-27 13:40:00 -07:00
|
|
|
let bm = rng.gen_range(100, 1000);
|
2019-07-05 14:21:48 -07:00
|
|
|
let mut bm2 = bm.clone();
|
2019-09-27 13:40:00 -07:00
|
|
|
let epsilon = rng.gen_range(1, 100);
|
|
|
|
bc2 -= epsilon;
|
|
|
|
bm2 += epsilon;
|
2019-07-05 14:21:48 -07:00
|
|
|
let r = Fr::rand(rng);
|
|
|
|
let rprime = Fr::rand(rng);
|
|
|
|
|
2019-09-10 19:21:09 -07:00
|
|
|
let secParams = NIZKSecretParams::<Bls12>::setup(rng, 4);
|
2019-07-24 14:13:56 -07:00
|
|
|
let wallet1 = Wallet { pkc, wpk, bc, bm, close: None };
|
2019-07-05 14:21:48 -07:00
|
|
|
|
2019-07-21 11:55:38 -07:00
|
|
|
let bc2Prime = bc.clone();
|
2019-07-24 14:13:56 -07:00
|
|
|
let wallet3 = Wallet { pkc, wpk: wpkprime, bc: bc2Prime, bm: bm2, close: None };
|
2019-09-10 19:21:09 -07:00
|
|
|
let commitment1 = secParams.pubParams.comParams.commit(&wallet1.as_fr_vec().clone(), &r);
|
|
|
|
let commitment2 = secParams.pubParams.comParams.commit(&wallet3.as_fr_vec(), &rprime);
|
|
|
|
let blindPaymentToken = secParams.keypair.sign_blind(rng, &secParams.pubParams.mpk, commitment1.clone());
|
|
|
|
let paymentToken = secParams.keypair.unblind(&r, &blindPaymentToken);
|
|
|
|
let proof = secParams.pubParams.prove(rng, wallet1.clone(), wallet3, commitment2.clone(), rprime, &paymentToken);
|
|
|
|
assert_eq!(secParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), false);
|
2019-07-05 14:21:48 -07:00
|
|
|
|
2019-07-21 11:55:38 -07:00
|
|
|
let bm2Prime = bm.clone();
|
2019-07-24 14:13:56 -07:00
|
|
|
let wallet4 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2Prime, close: None };
|
2019-09-10 19:21:09 -07:00
|
|
|
let commitment2 = secParams.pubParams.comParams.commit(&wallet4.as_fr_vec(), &rprime);
|
|
|
|
let proof = secParams.pubParams.prove(rng, wallet1.clone(), wallet4, commitment2.clone(), rprime, &paymentToken);
|
|
|
|
assert_eq!(secParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), false);
|
2019-07-05 14:21:48 -07:00
|
|
|
|
2019-07-24 14:13:56 -07:00
|
|
|
let wallet5 = Wallet { pkc: Fr::rand(rng), wpk: wpkprime, bc: bc2, bm: bm2, close: None };
|
2019-09-10 19:21:09 -07:00
|
|
|
let commitment2 = secParams.pubParams.comParams.commit(&wallet5.as_fr_vec(), &rprime);
|
|
|
|
let proof = secParams.pubParams.prove(rng, wallet1.clone(), wallet5, commitment2.clone(), rprime, &paymentToken);
|
|
|
|
assert_eq!(secParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), false);
|
2019-07-03 16:05:27 -07:00
|
|
|
}
|
2019-07-29 21:53:58 -07:00
|
|
|
|
2019-08-19 15:29:26 -07:00
|
|
|
#[test]
|
|
|
|
fn nizk_proof_commitment_opening_works() {
|
|
|
|
let rng = &mut rand::thread_rng();
|
|
|
|
let pkc = Fr::rand(rng);
|
|
|
|
let wpk = Fr::rand(rng);
|
|
|
|
let t = Fr::rand(rng);
|
|
|
|
|
2019-09-27 13:40:00 -07:00
|
|
|
let bc = rng.gen_range(100, 1000);
|
|
|
|
let bm = rng.gen_range(100, 1000);
|
2019-08-19 15:29:26 -07:00
|
|
|
let wallet = Wallet::<Bls12> { pkc: pkc, wpk: wpk, bc: bc, bm: bm, close: None };
|
|
|
|
|
2019-09-10 19:21:09 -07:00
|
|
|
let secParams = NIZKSecretParams::<Bls12>::setup(rng, 4);
|
|
|
|
let com = secParams.pubParams.comParams.commit(&wallet.as_fr_vec().clone(), &t);
|
2019-08-19 15:29:26 -07:00
|
|
|
|
2019-09-10 19:21:09 -07:00
|
|
|
let com_proof = CommitmentProof::<Bls12>::new(rng, &secParams.pubParams.comParams,
|
2019-08-19 15:29:26 -07:00
|
|
|
&com.c, &wallet.as_fr_vec(), &t, &vec![1, 3, 4]);
|
|
|
|
|
2019-09-13 13:16:35 -07:00
|
|
|
assert!(verify_opening(&secParams.pubParams.comParams, &com.c, &com_proof, &pkc.clone(), bc, bm));
|
2019-08-19 15:29:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn nizk_proof_false_commitment() {
|
|
|
|
let rng = &mut rand::thread_rng();
|
|
|
|
let pkc = Fr::rand(rng);
|
|
|
|
let wpk = Fr::rand(rng);
|
|
|
|
let t = Fr::rand(rng);
|
|
|
|
|
2019-09-27 13:40:00 -07:00
|
|
|
let bc = rng.gen_range(100, 1000);
|
|
|
|
let bc2 = rng.gen_range(100, 1000);
|
|
|
|
let bm = rng.gen_range(100, 1000);
|
2019-08-19 15:29:26 -07:00
|
|
|
let wallet1 = Wallet::<Bls12> { pkc: pkc, wpk: wpk, bc: bc, bm: bm, close: None };
|
|
|
|
let wallet2 = Wallet::<Bls12> { pkc: pkc, wpk: wpk, bc: bc2, bm: bm, close: None };
|
|
|
|
|
2019-09-10 19:21:09 -07:00
|
|
|
let secParams = NIZKSecretParams::<Bls12>::setup(rng, 4);
|
|
|
|
let com1 = secParams.pubParams.comParams.commit(&wallet1.as_fr_vec().clone(), &t);
|
|
|
|
let com2 = secParams.pubParams.comParams.commit(&wallet2.as_fr_vec().clone(), &t);
|
2019-08-19 15:29:26 -07:00
|
|
|
|
2019-09-10 19:21:09 -07:00
|
|
|
let com1_proof = CommitmentProof::<Bls12>::new(rng, &secParams.pubParams.comParams,
|
2019-08-27 13:58:30 -07:00
|
|
|
&com1.c, &wallet1.as_fr_vec(), &t, &vec![1, 3, 4]);
|
2019-08-19 15:29:26 -07:00
|
|
|
|
2019-09-13 13:16:35 -07:00
|
|
|
assert!(verify_opening(&secParams.pubParams.comParams, &com1.c, &com1_proof, &pkc.clone(), bc, bm));
|
|
|
|
assert!(!verify_opening(&secParams.pubParams.comParams, &com2.c, &com1_proof, &pkc.clone(), bc2, bm));
|
2019-08-19 15:29:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-07-29 21:53:58 -07:00
|
|
|
#[test]
|
|
|
|
fn test_nizk_serialization() {
|
|
|
|
let mut rng = &mut rand::thread_rng();
|
|
|
|
|
|
|
|
let l = 5;
|
|
|
|
let mpk = setup(&mut rng);
|
|
|
|
let blindkeypair = BlindKeyPair::<Bls12>::generate(&mut rng, &mpk, l);
|
|
|
|
let comParams = blindkeypair.generate_cs_multi_params(&mpk);
|
2019-09-27 10:02:31 -07:00
|
|
|
let u = 256; //TODO: optimize u?
|
|
|
|
let l = 8;
|
2019-09-13 08:38:23 -07:00
|
|
|
let rpParams = ccs08::SecretParamsUL::setup_ul(rng, u, l, comParams.clone());
|
2019-07-29 21:53:58 -07:00
|
|
|
|
2019-09-13 08:38:23 -07:00
|
|
|
let nizk_params = NIZKPublicParams { mpk: mpk, pk: blindkeypair.public, comParams: comParams, rpParams: rpParams.pubParams.clone() };
|
2019-07-29 21:53:58 -07:00
|
|
|
|
|
|
|
let is_serialized = serde_json::to_vec(&nizk_params).unwrap();
|
|
|
|
println!("NIZK Struct len: {}", is_serialized.len());
|
|
|
|
|
|
|
|
// deserialize
|
|
|
|
}
|
2019-07-25 17:39:36 -07:00
|
|
|
}
|