commit
628c167748
|
@ -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]
|
||||
|
|
18
src/cl.rs
18
src/cl.rs
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
77
src/nizk.rs
77
src/nizk.rs
|
@ -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]
|
||||
|
|
16
src/util.rs
16
src/util.rs
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue