Merge pull request #10 from boltlabs-inc/nizk

Nizk updates
This commit is contained in:
J. Ayo Akinyele 2019-08-09 07:31:07 -07:00 committed by GitHub
commit 628c167748
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 69 additions and 45 deletions

View File

@ -27,7 +27,8 @@ rustc-serialize = "0.3"
secp256k1 = { version = "0.15.0", features = ["rand", "serde"] }
curve25519-dalek = { version = "1", features = ["serde"] }
merlin = "1.0.0"
bulletproofs = { git = "https://github.com/dalek-cryptography/bulletproofs", branch = "main" }
#bulletproofs = { git = "https://github.com/dalek-cryptography/bulletproofs", branch = "main" }
bulletproofs = { git = "https://github.com/dalek-cryptography/bulletproofs", tag = "1.0.2" }
sha2 = { version = "0.8", default-features = false }
[dev-dependencies.bincode]

View File

@ -167,7 +167,6 @@ pub struct BlindKeyPair<E: Engine> {
#[derive(Clone)]
pub struct ProofState<E: Engine> {
pub v: E::Fr,
pub s: E::Fr,
pub t: Vec<E::Fr>,
pub tt: E::Fr,
pub a: E::Fqk,
@ -186,7 +185,6 @@ pub struct ProofState<E: Engine> {
<E as pairing::Engine>::Fqk: serde::Deserialize<'de>"
))]
pub struct SignatureProof<E: Engine> {
pub zx: E::Fr,
pub zsig: Vec<E::Fr>,
pub zv: E::Fr,
pub a: E::Fqk,
@ -363,7 +361,7 @@ impl<E: Engine> BlindPublicKey<E> {
/// outputs: boolean
pub fn verify_proof(&self, mpk: &PublicParams<E>, blindSig: Signature<E>, p: SignatureProof<E>, challenge: E::Fr) -> bool {
let mut gx = E::pairing(blindSig.h, self.X2);
gx = gx.pow(p.zx.into_repr());
gx = gx.pow(challenge.into_repr());
for j in 0..self.Y2.len() {
let mut gy = E::pairing(blindSig.h, self.Y2[j]);
gy = gy.pow(p.zsig[j].into_repr());
@ -492,23 +490,21 @@ impl<E: Engine> BlindKeyPair<E> {
tOptional: Option<Vec<E::Fr>>, ttOptional: Option<E::Fr>) -> ProofState<E> {
let v = E::Fr::rand(rng);
let blindSig = self.blind(rng, &v, signature);
let s = E::Fr::rand(rng);
let mut t = tOptional.unwrap_or(Vec::<E::Fr>::with_capacity(self.public.Y2.len()));
let tt = ttOptional.unwrap_or(E::Fr::rand(rng));
let mut gx = E::pairing(blindSig.h, self.public.X2);
gx = gx.pow(s.into_repr());
let mut a = E::Fqk::one();
for j in 0..self.public.Y2.len() {
if t.len() == j {
t.push(E::Fr::rand(rng));
}
let mut gy = E::pairing(blindSig.h, self.public.Y2[j]);
gy = gy.pow(t[j].into_repr());
gx.mul_assign(&gy);
a.mul_assign(&gy);
}
let mut h = E::pairing(blindSig.h, mpk.g2);
h = h.pow(tt.into_repr());
gx.mul_assign(&h);
ProofState { v, s, t, tt, a: gx, blindSig }
a.mul_assign(&h);
ProofState { v, t, tt, a, blindSig }
}
/// prove knowledge of a signature: response phase
@ -525,13 +521,11 @@ impl<E: Engine> BlindKeyPair<E> {
}
}
let mut zx = ps.s.clone();
zx.add_assign(&challenge);
let mut zv = ps.tt.clone();
let mut vic = ps.v.clone();
vic.mul_assign(&challenge);
zv.add_assign(&vic);
SignatureProof { zsig, zx, zv, a: ps.a }
SignatureProof { zsig, zv, a: ps.a }
}
}

View File

@ -7,7 +7,6 @@ use cl::{KeyPair, Signature, PublicParams, setup, BlindKeyPair, ProofState, Sign
use ped92::{CSParams, Commitment, CSMultiParams};
use pairing::{Engine, CurveProjective};
use ff::PrimeField;
use util::hash_g2_to_fr;
use commit_scheme::commit;
use wallet::Wallet;
use ccs08::{RPPublicParams, RangeProof};
@ -68,7 +67,7 @@ impl<E: Engine> NIZKPublicParams<E> {
let mut D = E::G1::zero();
let w_len = newWallet.as_fr_vec().len();
let diff = self.comParams.pub_bases.len() - w_len;
let max = match (diff > 1) {
let max = match diff > 1 {
true => w_len,
false => self.comParams.pub_bases.len()
};
@ -83,16 +82,16 @@ impl<E: Engine> NIZKPublicParams<E> {
}
//commit signature
let fr1 = E::Fr::rand(rng);
let tOptional = match (max > 4) {
true => Some(vec!(t[1], fr1, t[3].clone(), t[4].clone())),
false => Some(vec!(t[1], fr1, t[3].clone()))
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()))
};
let proofState = self.keypair.prove_commitment(rng, &self.mpk, &paymentToken, tOptional, None);
//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 rpStateBM = self.rpParamsBM.prove_commitment(rng, newWallet.bm.clone(), newWalletCom.clone(), 4, Some(t[1..].to_vec()), Some(t[0].clone()));
let rpStateBC = self.rpParamsBC.prove_commitment(rng, newWallet.bc.clone(), newWalletCom.clone(), 3, None, None);
let rpStateBM = self.rpParamsBM.prove_commitment(rng, newWallet.bm.clone(), newWalletCom.clone(), 4, None, None);
//Compute challenge
let challenge = NIZKPublicParams::<E>::hash(proofState.a, vec! {D, rpStateBC.ps1.D, rpStateBC.ps2.D, rpStateBM.ps1.D, rpStateBM.ps2.D});
@ -136,11 +135,17 @@ impl<E: Engine> NIZKPublicParams<E> {
}
pub fn verify(&self, proof: Proof<E>, epsilon: E::Fr, com2: &Commitment<E>, wpk: E::Fr) -> bool {
//verify signature is not the identity
let r0 = proof.sig.h != E::G1::one();
//compute challenge
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 knowledge of signature
let r1 = self.keypair.public.verify_proof(&self.mpk, proof.sig, proof.sigProof.clone(), challenge);
let mut r1 = self.keypair.public.verify_proof(&self.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
let mut comc = com2.c.clone();
@ -169,26 +174,7 @@ impl<E: Engine> NIZKPublicParams<E> {
zsig3.add_assign(&epsC.clone());
r5 = r5 && proof.z[4] == zsig3;
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 {
r5 = r5 && proof.z[i] == proof.rpBC.p1.zs[i-1].clone();
r5 = r5 && proof.z[i] == proof.rpBC.p2.zs[i-1].clone();
r5 = r5 && proof.z[i] == proof.rpBM.p1.zs[i-1].clone();
r5 = r5 && proof.z[i] == proof.rpBM.p2.zs[i-1].clone();
}
}
r1 && r2 && r3 && r4 && r5
r0 && r1 && r2 && r3 && r4 && r5
}
fn hash(a: E::Fqk, T: Vec<E::G1>) -> E::Fr {
@ -206,6 +192,7 @@ impl<E: Engine> NIZKPublicParams<E> {
mod tests {
use super::*;
use pairing::bls12_381::{Bls12, Fr};
use util::convert_int_to_fr;
#[test]
fn nizk_proof_works() {
@ -233,8 +220,38 @@ mod tests {
let proof = pubParams.prove(rng, r, wallet1, wallet2,
commitment2.clone(), rprime, &paymentToken);
let fr = convert_int_to_fr::<Bls12>(*epsilon);
assert_eq!(pubParams.verify(proof, fr, &commitment2, wpk), true);
}
assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), true);
#[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);
let bc = rng.gen_range(100, 1000);
let mut bc2 = bc.clone();
let bm = rng.gen_range(100, 1000);
let mut bm2 = bm.clone();
let epsilon = &rng.gen_range(-100, -1);
bc2 -= epsilon;
bm2 += epsilon;
let r = Fr::rand(rng);
let rprime = Fr::rand(rng);
let pubParams = NIZKPublicParams::<Bls12>::setup(rng, 4);
let wallet1 = Wallet { pkc, wpk, bc, bm, close: None };
let commitment1 = pubParams.comParams.commit(&wallet1.as_fr_vec(), &r);
let wallet2 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2, close: None };
let commitment2 = pubParams.comParams.commit(&wallet2.as_fr_vec(), &rprime);
let blindPaymentToken = pubParams.keypair.sign_blind(rng, &pubParams.mpk, commitment1.clone());
let paymentToken = pubParams.keypair.unblind(&r, &blindPaymentToken);
let proof = pubParams.prove(rng, r, wallet1, wallet2,
commitment2.clone(), rprime, &paymentToken);
let fr = convert_int_to_fr::<Bls12>(*epsilon);
assert_eq!(pubParams.verify(proof, fr, &commitment2, wpk), true);
}
#[test]

View File

@ -1,7 +1,7 @@
use super::*;
use sodiumoxide::crypto::hash::sha512;
use pairing::{Engine, CurveProjective};
use ff::PrimeField;
use ff::{PrimeField};
use rand::Rng;
use ped92::CSMultiParams;
use secp256k1::{Signature, PublicKey};
@ -81,7 +81,9 @@ pub fn convert_int_to_fr<E: Engine>(value: i32) -> E::Fr {
} else {
// negative value
let value2 = value * -1;
let res = E::Fr::from_str(value2.to_string().as_str()).unwrap();
let mut res = E::Fr::zero();
let val = E::Fr::from_str(value2.to_string().as_str()).unwrap();
res.sub_assign(&val);
// TODO: look at how to do negation
return res;
}
@ -258,4 +260,14 @@ mod tests {
assert_eq!(fmt_bytes_to_int([12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123]),
"122352312313431223523123134312235231231343122352312313431223523123134312235231231343122352312313431223523123134312235231231343122352312313431223523123");
}
#[test]
fn convert_int_to_fr_works() {
assert_eq!(format!("{}", convert_int_to_fr::<Bls12>(1).into_repr()),
"0x0000000000000000000000000000000000000000000000000000000000000001");
assert_eq!(format!("{}", convert_int_to_fr::<Bls12>(-1).into_repr()),
"0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000");
assert_eq!(format!("{}", convert_int_to_fr::<Bls12>(365).into_repr()),
"0x000000000000000000000000000000000000000000000000000000000000016d");
}
}