nizk: update proof of linear relationship

This commit is contained in:
Gijs Van Laer 2019-07-23 14:08:19 -04:00
parent b0fa32f533
commit db71866b2c
1 changed files with 42 additions and 81 deletions

View File

@ -16,7 +16,6 @@ use ccs08::{RPPublicParams, RangeProof};
pub struct Proof<E: Engine> { pub struct Proof<E: Engine> {
pub sig: Signature<E>, pub sig: Signature<E>,
pub sigProof: SignatureProof<E>, pub sigProof: SignatureProof<E>,
pub T: E::G1,
pub D: E::G1, pub D: E::G1,
pub z: Vec<E::Fr>, pub z: Vec<E::Fr>,
pub rpBC: RangeProof<E>, pub rpBC: RangeProof<E>,
@ -44,20 +43,11 @@ impl<E: Engine> NIZKPublicParams<E> {
} }
pub fn prove<R: Rng>(&self, rng: &mut R, r: E::Fr, oldWallet: Wallet<E>, newWallet: Wallet<E>, 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> { newWalletCom: Commitment<E>, rPrime: E::Fr, paymentToken: &Signature<E>) -> Proof<E> {
//Commitment phase //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);
//commit commitment //commit commitment
let mut D = E::G1::zero(); let mut D = E::G1::zero();
let mut t = Vec::<E::Fr>::with_capacity(self.comParams.pub_bases.len() - 1); let mut t = Vec::<E::Fr>::with_capacity(self.comParams.pub_bases.len());
for g in self.comParams.pub_bases.clone() { for g in self.comParams.pub_bases.clone() {
let ti = E::Fr::rand(rng); let ti = E::Fr::rand(rng);
t.push(ti); t.push(ti);
@ -67,34 +57,23 @@ impl<E: Engine> NIZKPublicParams<E> {
} }
//commit signature //commit signature
let proofState = self.keypair.prove_commitment(rng, &self.mpk, &paymentToken, Some(vec!(t[1])), None); let fr1 = E::Fr::rand(rng);
let proofState = self.keypair.prove_commitment(rng, &self.mpk, &paymentToken, Some(vec!(t[1], fr1, t[3].clone(), t[4].clone())), None);
//commit range proof //commit range proof
let rpStateBC = self.rpParamsBC.prove_commitment(rng, newWallet.bc.clone(), newWalletCom.clone(), 3, Some(t[1..].to_vec()), Some(t[0].clone())); let rpStateBC = self.rpParamsBC.prove_commitment(rng, newWallet.bc.clone(), newWalletCom.clone(), 3, Some(t[1..].to_vec()), Some(t[0].clone()));
let rpStateBM = self.rpParamsBM.prove_commitment(rng, newWallet.bm.clone(), newWalletCom.clone(), 4, Some(t[1..].to_vec()), Some(t[0].clone())); let rpStateBM = self.rpParamsBM.prove_commitment(rng, newWallet.bm.clone(), newWalletCom.clone(), 4, Some(t[1..].to_vec()), Some(t[0].clone()));
//Compute challenge //Compute challenge
let challenge = NIZKPublicParams::<E>::hash(proofState.a, vec! {T, D, rpStateBC.ps1.D, rpStateBC.ps2.D, rpStateBM.ps1.D, rpStateBM.ps2.D}); let challenge = NIZKPublicParams::<E>::hash(proofState.a, vec! {D, rpStateBC.ps1.D, rpStateBC.ps2.D, rpStateBM.ps1.D, rpStateBM.ps2.D});
//Response phase //Response phase
//response for signature //response for signature
let oldWalletVec = oldWallet.as_fr_vec(); let oldWalletVec = oldWallet.as_fr_vec();
let sigProof = self.keypair.prove_response(&proofState, challenge, &mut oldWalletVec.clone()); 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 //response commitment
let mut z = Vec::<E::Fr>::with_capacity(t.len());
let mut z0 = rPrime.clone(); let mut z0 = rPrime.clone();
z0.mul_assign(&challenge); z0.mul_assign(&challenge);
z0.add_assign(&t[0]); z0.add_assign(&t[0]);
@ -111,39 +90,12 @@ impl<E: Engine> NIZKPublicParams<E> {
let rpBC = self.rpParamsBC.prove_response(rPrime.clone(), &rpStateBC, challenge.clone(), 3, vec! {newWalletVec[0], newWalletVec[1], newWalletVec[3]}); 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]}); 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 } Proof { sig: proofState.blindSig, sigProof, D, z, rpBC, rpBM }
} }
pub fn verify(&self, proof: Proof<E>, epsilon: E::Fr, com1: &Commitment<E>, com2: &Commitment<E>, wpk: E::Fr) -> bool { pub fn verify(&self, proof: Proof<E>, epsilon: E::Fr, com2: &Commitment<E>, wpk: E::Fr) -> bool {
//compute challenge //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}); let challenge = NIZKPublicParams::<E>::hash(proof.sigProof.a, vec! {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 //verify knowledge of signature
let r1 = self.keypair.public.verify_proof(&self.mpk, proof.sig, proof.sigProof.clone(), challenge); let r1 = self.keypair.public.verify_proof(&self.mpk, proof.sig, proof.sigProof.clone(), challenge);
@ -153,8 +105,8 @@ impl<E: Engine> NIZKPublicParams<E> {
comc.mul_assign(challenge.into_repr()); comc.mul_assign(challenge.into_repr());
comc.add_assign(&proof.D.clone()); comc.add_assign(&proof.D.clone());
let mut x = E::G1::zero(); let mut x = E::G1::zero();
for i in 2..proof.z.len() { for i in 0..proof.z.len() {
let mut base = self.comParams.pub_bases[i - 2].clone(); let mut base = self.comParams.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);
} }
@ -164,27 +116,37 @@ impl<E: Engine> NIZKPublicParams<E> {
let r3 = self.rpParamsBC.verify(proof.rpBC.clone(), challenge.clone(), 3); let r3 = self.rpParamsBC.verify(proof.rpBC.clone(), challenge.clone(), 3);
let r4 = self.rpParamsBM.verify(proof.rpBM.clone(), challenge.clone(), 4); let r4 = self.rpParamsBM.verify(proof.rpBM.clone(), challenge.clone(), 4);
let mut r5 = proof.z[3] == proof.sigProof.zsig[0]; //verify linear relationship
r5 = r5 && proof.z[2] == proof.rpBC.p1.zr; let mut r5 = proof.z[1] == proof.sigProof.zsig[0];
r5 = r5 && proof.z[2] == proof.rpBC.p2.zr; let mut zsig2 = proof.sigProof.zsig[2].clone();
r5 = r5 && proof.z[2] == proof.rpBM.p1.zr; let mut epsC = epsilon.clone();
r5 = r5 && proof.z[2] == proof.rpBM.p2.zr; epsC.mul_assign(&challenge.clone());
for i in 3..proof.z.len() { zsig2.sub_assign(&epsC.clone());
if i == 5 { r5 = r5 && proof.z[3] == zsig2;
r5 = r5 && proof.z[i] == proof.rpBM.p1.zs[i-3]; let mut zsig3 = proof.sigProof.zsig[3].clone();
r5 = r5 && proof.z[i] == proof.rpBM.p2.zs[i-3].clone(); zsig3.add_assign(&epsC.clone());
} else if i == 6 { r5 = r5 && proof.z[4] == zsig3;
r5 = r5 && proof.z[i] == proof.rpBC.p1.zs[i-4].clone();
r5 = r5 && proof.z[i] == proof.rpBC.p2.zs[i-4].clone(); r5 = r5 && proof.z[0] == proof.rpBC.p1.zr;
r5 = r5 && proof.z[0] == proof.rpBC.p2.zr;
r5 = r5 && proof.z[0] == proof.rpBM.p1.zr;
r5 = r5 && proof.z[0] == proof.rpBM.p2.zr;
for i in 1..proof.z.len() {
if i == 3 {
r5 = r5 && proof.z[i] == proof.rpBM.p1.zs[i-1];
r5 = r5 && proof.z[i] == proof.rpBM.p2.zs[i-1].clone();
} else if i == 4 {
r5 = r5 && proof.z[i] == proof.rpBC.p1.zs[i-2].clone();
r5 = r5 && proof.z[i] == proof.rpBC.p2.zs[i-2].clone();
} else { } else {
r5 = r5 && proof.z[i] == proof.rpBC.p1.zs[i-3].clone(); r5 = r5 && proof.z[i] == proof.rpBC.p1.zs[i-1].clone();
r5 = r5 && proof.z[i] == proof.rpBC.p2.zs[i-3].clone(); r5 = r5 && proof.z[i] == proof.rpBC.p2.zs[i-1].clone();
r5 = r5 && proof.z[i] == proof.rpBM.p1.zs[i-3].clone(); r5 = r5 && proof.z[i] == proof.rpBM.p1.zs[i-1].clone();
r5 = r5 && proof.z[i] == proof.rpBM.p2.zs[i-3].clone(); r5 = r5 && proof.z[i] == proof.rpBM.p2.zs[i-1].clone();
} }
} }
r && r1 && r2 && r3 && r4 && r5 r1 && r2 && r3 && r4 && r5
} }
fn hash(a: E::Fqk, T: Vec<E::G1>) -> E::Fr { fn hash(a: E::Fqk, T: Vec<E::G1>) -> E::Fr {
@ -230,8 +192,7 @@ mod tests {
let proof = pubParams.prove(rng, r, wallet1, wallet2, let proof = pubParams.prove(rng, r, wallet1, wallet2,
commitment2.clone(), rprime, &paymentToken); commitment2.clone(), rprime, &paymentToken);
assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), true);
&commitment2, wpk), true);
} }
#[test] #[test]
@ -261,17 +222,17 @@ mod tests {
let blindPaymentToken = pubParams.keypair.sign_blind(rng, &pubParams.mpk, commitment1.clone()); let blindPaymentToken = pubParams.keypair.sign_blind(rng, &pubParams.mpk, commitment1.clone());
let paymentToken = pubParams.keypair.unblind(&r, &blindPaymentToken); let paymentToken = pubParams.keypair.unblind(&r, &blindPaymentToken);
let proof = pubParams.prove(rng, r, wallet1.clone(), wallet3, commitment2.clone(), rprime, &paymentToken); let proof = pubParams.prove(rng, r, wallet1.clone(), wallet3, commitment2.clone(), rprime, &paymentToken);
assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, &commitment2, wpk), false); assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), false);
let bm2Prime = bm.clone(); let bm2Prime = bm.clone();
let wallet4 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2Prime }; let wallet4 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2Prime };
let commitment2 = pubParams.comParams.commit(&wallet4.as_fr_vec(), &rprime); let commitment2 = pubParams.comParams.commit(&wallet4.as_fr_vec(), &rprime);
let proof = pubParams.prove(rng, r, wallet1.clone(), wallet4, commitment2.clone(), rprime, &paymentToken); let proof = pubParams.prove(rng, r, wallet1.clone(), wallet4, commitment2.clone(), rprime, &paymentToken);
assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment1, &commitment2, wpk), false); assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), false);
let wallet5 = Wallet { pkc: Fr::rand(rng), wpk: wpkprime, bc: bc2, bm: bm2 }; let wallet5 = Wallet { pkc: Fr::rand(rng), wpk: wpkprime, bc: bc2, bm: bm2 };
let commitment2 = pubParams.comParams.commit(&wallet5.as_fr_vec(), &rprime); let commitment2 = pubParams.comParams.commit(&wallet5.as_fr_vec(), &rprime);
let proof = pubParams.prove(rng, r, wallet1.clone(), wallet5, commitment2.clone(), rprime, &paymentToken); 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); assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), false);
} }
} }