nizk: extract proof of knowledge of a commitment
This commit is contained in:
parent
c947a446ea
commit
cc921e5786
|
@ -14,14 +14,14 @@ use pairing::{Engine, CurveProjective};
|
||||||
use pairing::bls12_381::{Bls12};
|
use pairing::bls12_381::{Bls12};
|
||||||
use ff::PrimeField;
|
use ff::PrimeField;
|
||||||
use cl::{BlindKeyPair, KeyPair, Signature, PublicParams, setup};
|
use cl::{BlindKeyPair, KeyPair, Signature, PublicParams, setup};
|
||||||
use ped92::{CSParams, Commitment, CSMultiParams};
|
use ped92::{CSParams, Commitment, CSMultiParams, CommitmentProof};
|
||||||
use util::{hash_pubkey_to_fr, convert_int_to_fr, hash_to_fr, RevokedMessage, hash_to_slice};
|
use util::{hash_pubkey_to_fr, convert_int_to_fr, hash_to_fr, RevokedMessage, hash_to_slice};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use std::ptr::hash;
|
use std::ptr::hash;
|
||||||
use nizk::{NIZKPublicParams, CommitmentProof, Proof};
|
use nizk::{NIZKPublicParams, NIZKProof};
|
||||||
use wallet::Wallet;
|
use wallet::Wallet;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -330,7 +330,7 @@ impl<E: Engine> CustomerState<E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// for channel pay
|
// for channel pay
|
||||||
pub fn generate_payment<R: Rng>(&self, csprng: &mut R, channel: &ChannelState<E>, amount: i32) -> (Proof<E>, Commitment<E>, secp256k1::PublicKey, CustomerState<E>) {
|
pub fn generate_payment<R: Rng>(&self, csprng: &mut R, channel: &ChannelState<E>, amount: i32) -> (NIZKProof<E>, Commitment<E>, secp256k1::PublicKey, CustomerState<E>) {
|
||||||
// 1 - chooose new wpk/wsk pair
|
// 1 - chooose new wpk/wsk pair
|
||||||
let mut kp = secp256k1::Secp256k1::new();
|
let mut kp = secp256k1::Secp256k1::new();
|
||||||
kp.randomize(csprng);
|
kp.randomize(csprng);
|
||||||
|
@ -557,7 +557,7 @@ impl<E: Engine> MerchantState<E> {
|
||||||
return self.pay_tokens.get(&wpk_str).unwrap().clone();
|
return self.pay_tokens.get(&wpk_str).unwrap().clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_payment<R: Rng>(&mut self, csprng: &mut R, channel: &ChannelState<E>, proof: &Proof<E>, com: &Commitment<E>, wpk: &secp256k1::PublicKey, amount: i32) -> ResultBoltSig<Signature<E>> {
|
pub fn verify_payment<R: Rng>(&mut self, csprng: &mut R, channel: &ChannelState<E>, proof: &NIZKProof<E>, com: &Commitment<E>, wpk: &secp256k1::PublicKey, amount: i32) -> ResultBoltSig<Signature<E>> {
|
||||||
let cp = channel.cp.as_ref().unwrap();
|
let cp = channel.cp.as_ref().unwrap();
|
||||||
let pay_proof = proof.clone();
|
let pay_proof = proof.clone();
|
||||||
let prev_wpk = hash_pubkey_to_fr::<E>(&wpk);
|
let prev_wpk = hash_pubkey_to_fr::<E>(&wpk);
|
||||||
|
|
|
@ -130,9 +130,10 @@ pub mod bidirectional {
|
||||||
pub use BoltResult;
|
pub use BoltResult;
|
||||||
pub use channels::{ChannelState, ChannelToken, CustomerState, MerchantState, ChannelcloseM,
|
pub use channels::{ChannelState, ChannelToken, CustomerState, MerchantState, ChannelcloseM,
|
||||||
PubKeyMap, ChannelParams, BoltError, ResultBoltSig};
|
PubKeyMap, ChannelParams, BoltError, ResultBoltSig};
|
||||||
pub use nizk::{CommitmentProof, Proof};
|
pub use nizk::NIZKProof;
|
||||||
pub use wallet::Wallet;
|
pub use wallet::Wallet;
|
||||||
pub use cl::PublicParams;
|
pub use cl::PublicParams;
|
||||||
|
pub use ped92::CommitmentProof;
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
#[serde(bound(serialize = "<E as ff::ScalarEngine>::Fr: serde::Serialize, \
|
#[serde(bound(serialize = "<E as ff::ScalarEngine>::Fr: serde::Serialize, \
|
||||||
|
@ -157,7 +158,7 @@ pub mod bidirectional {
|
||||||
<E as pairing::Engine>::Fqk: serde::Deserialize<'de>"
|
<E as pairing::Engine>::Fqk: serde::Deserialize<'de>"
|
||||||
))]
|
))]
|
||||||
pub struct Payment<E: Engine> {
|
pub struct Payment<E: Engine> {
|
||||||
proof: Proof<E>,
|
proof: NIZKProof<E>,
|
||||||
com: Commitment<E>,
|
com: Commitment<E>,
|
||||||
wpk: secp256k1::PublicKey,
|
wpk: secp256k1::PublicKey,
|
||||||
amount: i32,
|
amount: i32,
|
||||||
|
|
185
src/nizk.rs
185
src/nizk.rs
|
@ -4,14 +4,16 @@ extern crate rand;
|
||||||
use super::*;
|
use super::*;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use cl::{KeyPair, Signature, PublicParams, setup, BlindKeyPair, ProofState, SignatureProof, BlindPublicKey};
|
use cl::{KeyPair, Signature, PublicParams, setup, BlindKeyPair, ProofState, SignatureProof, BlindPublicKey};
|
||||||
use ped92::{CSParams, Commitment, CSMultiParams};
|
use ped92::{CSParams, Commitment, CSMultiParams, CommitmentProof};
|
||||||
use pairing::{Engine, CurveProjective};
|
use pairing::{Engine, CurveProjective};
|
||||||
use ff::PrimeField;
|
use ff::PrimeField;
|
||||||
use wallet::Wallet;
|
use wallet::Wallet;
|
||||||
use ccs08::{RPPublicParams, RangeProof};
|
use ccs08::{RPPublicParams, RangeProof};
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use util;
|
use util;
|
||||||
|
use std::borrow::BorrowMut;
|
||||||
|
|
||||||
|
/// NIZKProof is the object that represents the NIZK Proof of Knowledge during the payment and closing protocol
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
#[serde(bound(serialize = "<E as ff::ScalarEngine>::Fr: serde::Serialize, \
|
#[serde(bound(serialize = "<E as ff::ScalarEngine>::Fr: serde::Serialize, \
|
||||||
<E as pairing::Engine>::G1: serde::Serialize, \
|
<E as pairing::Engine>::G1: serde::Serialize, \
|
||||||
|
@ -23,15 +25,15 @@ use util;
|
||||||
<E as pairing::Engine>::G2: serde::Deserialize<'de>, \
|
<E as pairing::Engine>::G2: serde::Deserialize<'de>, \
|
||||||
<E as pairing::Engine>::Fqk: serde::Deserialize<'de>"
|
<E as pairing::Engine>::Fqk: serde::Deserialize<'de>"
|
||||||
))]
|
))]
|
||||||
pub struct Proof<E: Engine> {
|
pub struct NIZKProof<E: Engine> {
|
||||||
pub sig: Signature<E>,
|
pub sig: Signature<E>,
|
||||||
pub sigProof: SignatureProof<E>,
|
pub sigProof: SignatureProof<E>,
|
||||||
pub D: E::G1,
|
pub comProof: CommitmentProof<E>,
|
||||||
pub z: Vec<E::Fr>,
|
|
||||||
pub rpBC: RangeProof<E>,
|
pub rpBC: RangeProof<E>,
|
||||||
pub rpBM: RangeProof<E>,
|
pub rpBM: RangeProof<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// NIZKPublicParams are public parameters to perform a NIZK Proof of Knowledge during the payment and closing protocol
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
#[serde(bound(serialize = "<E as ff::ScalarEngine>::Fr: serde::Serialize, \
|
#[serde(bound(serialize = "<E as ff::ScalarEngine>::Fr: serde::Serialize, \
|
||||||
<E as pairing::Engine>::G1: serde::Serialize, \
|
<E as pairing::Engine>::G1: serde::Serialize, \
|
||||||
|
@ -50,6 +52,8 @@ pub struct NIZKPublicParams<E: Engine> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Engine> NIZKPublicParams<E> {
|
impl<E: Engine> NIZKPublicParams<E> {
|
||||||
|
/// 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
|
||||||
pub fn setup<R: Rng>(rng: &mut R, messageLength: usize) -> Self {
|
pub fn setup<R: Rng>(rng: &mut R, messageLength: usize) -> Self {
|
||||||
let mpk = setup(rng);
|
let mpk = setup(rng);
|
||||||
let keypair = BlindKeyPair::<E>::generate(rng, &mpk, messageLength);
|
let keypair = BlindKeyPair::<E>::generate(rng, &mpk, messageLength);
|
||||||
|
@ -57,14 +61,25 @@ impl<E: Engine> NIZKPublicParams<E> {
|
||||||
let rpParamsBC = RPPublicParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone());
|
let rpParamsBC = RPPublicParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone());
|
||||||
let rpParamsBM = RPPublicParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone());
|
let rpParamsBM = RPPublicParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone());
|
||||||
|
|
||||||
NIZKPublicParams{mpk, keypair, comParams, rpParamsBC, rpParamsBM}
|
NIZKPublicParams { mpk, keypair, comParams, rpParamsBC, rpParamsBM }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** This method can be called to create the proof during the payment and closing protocol
|
||||||
|
Input:
|
||||||
|
rng: random generator
|
||||||
|
r: randomness of commitment of old wallet (TODO: still necessary?)
|
||||||
|
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
|
||||||
|
rPrime: randomness of commitment of new wallet
|
||||||
|
paymentToken: A blind signature on the old wallet
|
||||||
|
Output:
|
||||||
|
NIZKProof: a proof that can be verified by the merchant during payment or closing protocol
|
||||||
|
*/
|
||||||
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>) -> NIZKProof<E> {
|
||||||
//Commitment phase
|
//Commitment phase
|
||||||
//commit commitment
|
//commit commitment
|
||||||
let mut D = E::G1::zero();
|
|
||||||
let w_len = newWallet.as_fr_vec().len();
|
let w_len = newWallet.as_fr_vec().len();
|
||||||
let diff = self.comParams.pub_bases.len() - w_len;
|
let diff = self.comParams.pub_bases.len() - w_len;
|
||||||
let max = match diff > 1 {
|
let max = match diff > 1 {
|
||||||
|
@ -72,14 +87,7 @@ impl<E: Engine> NIZKPublicParams<E> {
|
||||||
false => self.comParams.pub_bases.len()
|
false => self.comParams.pub_bases.len()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut t = Vec::<E::Fr>::with_capacity(max );
|
let (D, t, rt, mut reveal_wallet) = CommitmentProof::<E>::prove_commitment(rng, &self.comParams, &newWallet.as_fr_vec(), &vec! {});
|
||||||
for i in 0 .. max {
|
|
||||||
let ti = E::Fr::rand(rng);
|
|
||||||
t.push(ti);
|
|
||||||
let mut gt = self.comParams.pub_bases[i].clone();
|
|
||||||
gt.mul_assign(ti.into_repr());
|
|
||||||
D.add_assign(>);
|
|
||||||
}
|
|
||||||
|
|
||||||
//commit signature
|
//commit signature
|
||||||
let zero = E::Fr::zero();
|
let zero = E::Fr::zero();
|
||||||
|
@ -102,18 +110,8 @@ impl<E: Engine> NIZKPublicParams<E> {
|
||||||
let sigProof = self.keypair.prove_response(&proofState, challenge, &mut oldWalletVec.clone());
|
let sigProof = self.keypair.prove_response(&proofState, challenge, &mut oldWalletVec.clone());
|
||||||
|
|
||||||
//response commitment
|
//response commitment
|
||||||
let mut z = Vec::<E::Fr>::with_capacity(t.len());
|
|
||||||
let mut z0 = rPrime.clone();
|
|
||||||
z0.mul_assign(&challenge);
|
|
||||||
z0.add_assign(&t[0]);
|
|
||||||
z.push(z0);
|
|
||||||
let newWalletVec = newWallet.as_fr_vec();
|
let newWalletVec = newWallet.as_fr_vec();
|
||||||
for i in 1..t.len() {
|
let comProof = CommitmentProof::<E>::prove_response(&newWalletVec, &rPrime, &vec! {}, D, &t, rt, reveal_wallet.borrow_mut(), &challenge);
|
||||||
let mut zi = newWalletVec[i - 1].clone();
|
|
||||||
zi.mul_assign(&challenge);
|
|
||||||
zi.add_assign(&t[i]);
|
|
||||||
z.push(zi);
|
|
||||||
}
|
|
||||||
|
|
||||||
//response range proof
|
//response range proof
|
||||||
let mut vec01 = newWalletVec[0..2].to_vec();
|
let mut vec01 = newWalletVec[0..2].to_vec();
|
||||||
|
@ -121,7 +119,7 @@ impl<E: Engine> NIZKPublicParams<E> {
|
||||||
let mut vec3 = newWalletVec[3..].to_vec();
|
let mut vec3 = newWalletVec[3..].to_vec();
|
||||||
vecWithout2.append(&mut vec3);
|
vecWithout2.append(&mut vec3);
|
||||||
let vec2 = newWalletVec[2].clone();
|
let vec2 = newWalletVec[2].clone();
|
||||||
vec01.push( vec2);
|
vec01.push(vec2);
|
||||||
if newWalletVec.len() > 4 {
|
if newWalletVec.len() > 4 {
|
||||||
let mut vec4 = newWalletVec[4..].to_vec();
|
let mut vec4 = newWalletVec[4..].to_vec();
|
||||||
vec01.append(&mut vec4);
|
vec01.append(&mut vec4);
|
||||||
|
@ -129,15 +127,23 @@ impl<E: Engine> NIZKPublicParams<E> {
|
||||||
let rpBC = self.rpParamsBC.prove_response(rPrime.clone(), &rpStateBC, challenge.clone(), 3, vecWithout2.to_vec());
|
let rpBC = self.rpParamsBC.prove_response(rPrime.clone(), &rpStateBC, challenge.clone(), 3, vecWithout2.to_vec());
|
||||||
let rpBM = self.rpParamsBM.prove_response(rPrime.clone(), &rpStateBM, challenge.clone(), 4, vec01.to_vec());
|
let rpBM = self.rpParamsBM.prove_response(rPrime.clone(), &rpStateBM, challenge.clone(), 4, vec01.to_vec());
|
||||||
|
|
||||||
Proof { sig: proofState.blindSig, sigProof, D, z, rpBC, rpBM }
|
NIZKProof { sig: proofState.blindSig, sigProof, comProof, rpBC, rpBM }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify(&self, proof: Proof<E>, epsilon: E::Fr, com2: &Commitment<E>, wpk: E::Fr) -> bool {
|
/**
|
||||||
|
Verify a NIZK Proof of Knowledge during payment or closing protocl
|
||||||
|
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
|
//verify signature is not the identity
|
||||||
let r0 = proof.sig.h != E::G1::one();
|
let r0 = proof.sig.h != E::G1::one();
|
||||||
|
|
||||||
//compute challenge
|
//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});
|
let challenge = NIZKPublicParams::<E>::hash(proof.sigProof.a, vec! {proof.comProof.T, proof.rpBC.p1.D, proof.rpBC.p2.D, proof.rpBM.p1.D, proof.rpBM.p2.D});
|
||||||
|
|
||||||
//verify knowledge of signature
|
//verify knowledge of signature
|
||||||
let mut 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);
|
||||||
|
@ -146,31 +152,22 @@ impl<E: Engine> NIZKPublicParams<E> {
|
||||||
r1 = r1 && proof.sigProof.zsig[1] == wpkc;
|
r1 = r1 && proof.sigProof.zsig[1] == wpkc;
|
||||||
|
|
||||||
//verify knowledge of commitment
|
//verify knowledge of commitment
|
||||||
let mut comc = com2.c.clone();
|
let r2 = proof.comProof.verify_proof(&self.comParams, &com.c.clone(), &challenge);
|
||||||
comc.mul_assign(challenge.into_repr());
|
|
||||||
comc.add_assign(&proof.D.clone());
|
|
||||||
let mut x = E::G1::zero();
|
|
||||||
for i in 0..proof.z.len() {
|
|
||||||
let mut base = self.comParams.pub_bases[i].clone();
|
|
||||||
base.mul_assign(proof.z[i].into_repr());
|
|
||||||
x.add_assign(&base);
|
|
||||||
}
|
|
||||||
let r2 = x == comc;
|
|
||||||
|
|
||||||
//verify range proofs
|
//verify range proofs
|
||||||
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);
|
||||||
|
|
||||||
//verify linear relationship
|
//verify linear relationship
|
||||||
let mut r5 = proof.z[1] == proof.sigProof.zsig[0];
|
let mut r5 = proof.comProof.z[1] == proof.sigProof.zsig[0];
|
||||||
let mut zsig2 = proof.sigProof.zsig[2].clone();
|
let mut zsig2 = proof.sigProof.zsig[2].clone();
|
||||||
let mut epsC = epsilon.clone();
|
let mut epsC = epsilon.clone();
|
||||||
epsC.mul_assign(&challenge.clone());
|
epsC.mul_assign(&challenge.clone());
|
||||||
zsig2.sub_assign(&epsC.clone());
|
zsig2.sub_assign(&epsC.clone());
|
||||||
r5 = r5 && proof.z[3] == zsig2;
|
r5 = r5 && proof.comProof.z[3] == zsig2;
|
||||||
let mut zsig3 = proof.sigProof.zsig[3].clone();
|
let mut zsig3 = proof.sigProof.zsig[3].clone();
|
||||||
zsig3.add_assign(&epsC.clone());
|
zsig3.add_assign(&epsC.clone());
|
||||||
r5 = r5 && proof.z[4] == zsig3;
|
r5 = r5 && proof.comProof.z[4] == zsig3;
|
||||||
|
|
||||||
r0 && r1 && r2 && r3 && r4 && r5
|
r0 && r1 && r2 && r3 && r4 && r5
|
||||||
}
|
}
|
||||||
|
@ -186,104 +183,17 @@ impl<E: Engine> NIZKPublicParams<E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
|
||||||
#[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 CommitmentProof<E: Engine> {
|
|
||||||
pub T: E::G1,
|
|
||||||
pub z: Vec<E::Fr>,
|
|
||||||
pub t: Vec<E::Fr>,
|
|
||||||
pub index: Vec<usize>,
|
|
||||||
pub reveal: Vec<E::Fr>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E: Engine> CommitmentProof<E> {
|
|
||||||
pub fn new<R: Rng>(csprng: &mut R, com_params: &CSMultiParams<E>, com: &E::G1, wallet: &Vec<E::Fr>, r: &E::Fr, reveal_index: &Vec<usize>) -> Self {
|
|
||||||
let mut Tvals = E::G1::zero();
|
|
||||||
assert!(wallet.len() <= com_params.pub_bases.len());
|
|
||||||
|
|
||||||
let mut t = Vec::<E::Fr>::with_capacity( wallet.len()+1 );
|
|
||||||
let mut rt: Vec<E::Fr> = Vec::new(); // t values that will be revealed
|
|
||||||
let mut reveal_wallet: Vec<E::Fr> = Vec::new(); // aspects of wallet being revealed
|
|
||||||
|
|
||||||
for i in 0..wallet.len()+1 {
|
|
||||||
let ti = E::Fr::rand(csprng);
|
|
||||||
t.push(ti);
|
|
||||||
// check if we are revealing this index
|
|
||||||
if (reveal_index.contains(&i)) {
|
|
||||||
rt.push(ti);
|
|
||||||
} else {
|
|
||||||
rt.push( E::Fr::zero());
|
|
||||||
}
|
|
||||||
let mut gt = com_params.pub_bases[i].clone();
|
|
||||||
gt.mul_assign(ti.into_repr());
|
|
||||||
Tvals.add_assign(>);
|
|
||||||
}
|
|
||||||
|
|
||||||
// compute the challenge
|
|
||||||
let x: Vec<E::G1> = vec![Tvals, com.clone()];
|
|
||||||
let challenge = util::hash_g1_to_fr::<E>(&x);
|
|
||||||
|
|
||||||
// compute the response
|
|
||||||
let mut z: Vec<E::Fr> = Vec::new();
|
|
||||||
let mut z0 = r.clone();
|
|
||||||
z0.mul_assign(&challenge);
|
|
||||||
z0.add_assign(&t[0]);
|
|
||||||
z.push(z0);
|
|
||||||
reveal_wallet.push( E::Fr::zero());
|
|
||||||
|
|
||||||
for i in 1..t.len() {
|
|
||||||
let mut zi = wallet[i-1].clone();
|
|
||||||
zi.mul_assign(&challenge);
|
|
||||||
zi.add_assign(&t[i]);
|
|
||||||
z.push(zi);
|
|
||||||
// check if we are revealing this index
|
|
||||||
if (reveal_index.contains(&i)) {
|
|
||||||
reveal_wallet.push(wallet[i-1].clone() );
|
|
||||||
} else {
|
|
||||||
reveal_wallet.push( E::Fr::zero());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CommitmentProof {
|
|
||||||
T: Tvals, // commitment challenge
|
|
||||||
z: z, // response values
|
|
||||||
t: rt, // randomness for verifying partial reveals
|
|
||||||
index: reveal_index.clone(),
|
|
||||||
reveal: reveal_wallet
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Verify PoK for the opening of a commitment
|
/// Verify PoK for the opening of a commitment during the establishment protocol
|
||||||
///
|
///
|
||||||
pub fn verify_opening<E: Engine>(com_params: &CSMultiParams<E>, com: &E::G1, proof: &CommitmentProof<E>, init_cust: i32, init_merch: i32) -> bool {
|
pub fn verify_opening<E: Engine>(com_params: &CSMultiParams<E>, com: &E::G1, proof: &CommitmentProof<E>, init_cust: i32, init_merch: i32) -> bool {
|
||||||
|
let xvec: Vec<E::G1> = vec![proof.T.clone(), com.clone()];
|
||||||
let mut comc = com.clone();
|
|
||||||
let T = proof.T.clone();
|
|
||||||
|
|
||||||
let xvec: Vec<E::G1> = vec![T, comc];
|
|
||||||
let challenge = util::hash_g1_to_fr::<E>(&xvec);
|
let challenge = util::hash_g1_to_fr::<E>(&xvec);
|
||||||
|
|
||||||
// compute the
|
// compute the
|
||||||
comc.mul_assign(challenge.into_repr());
|
let com_equal = proof.verify_proof(com_params, com, &challenge);
|
||||||
comc.add_assign(&T);
|
|
||||||
|
|
||||||
let mut x = E::G1::zero();
|
if proof.index.len() == 0 {
|
||||||
for i in 0..proof.z.len() {
|
|
||||||
let mut base = com_params.pub_bases[i].clone();
|
|
||||||
base.mul_assign(proof.z[i].into_repr());
|
|
||||||
x.add_assign(&base);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (proof.index.len() == 0) {
|
|
||||||
println!("verify_opening - doing any partial reveals?");
|
println!("verify_opening - doing any partial reveals?");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -309,7 +219,7 @@ pub fn verify_opening<E: Engine>(com_params: &CSMultiParams<E>, com: &E::G1, pro
|
||||||
let init_m = util::convert_int_to_fr::<E>(init_merch);
|
let init_m = util::convert_int_to_fr::<E>(init_merch);
|
||||||
let bm_equal = (s4 == proof.z[4]) && (proof.reveal[4] == init_m);
|
let bm_equal = (s4 == proof.z[4]) && (proof.reveal[4] == init_m);
|
||||||
|
|
||||||
return comc == x && pkc_equal && bc_equal && bm_equal;
|
return com_equal && pkc_equal && bc_equal && bm_equal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -344,7 +254,7 @@ mod tests {
|
||||||
let paymentToken = pubParams.keypair.unblind(&r, &blindPaymentToken);
|
let paymentToken = pubParams.keypair.unblind(&r, &blindPaymentToken);
|
||||||
|
|
||||||
let proof = pubParams.prove(rng, r, wallet1, wallet2,
|
let proof = pubParams.prove(rng, r, wallet1, wallet2,
|
||||||
commitment2.clone(), rprime, &paymentToken);
|
commitment2.clone(), rprime, &paymentToken);
|
||||||
let fr = convert_int_to_fr::<Bls12>(*epsilon);
|
let fr = convert_int_to_fr::<Bls12>(*epsilon);
|
||||||
assert_eq!(pubParams.verify(proof, fr, &commitment2, wpk), true);
|
assert_eq!(pubParams.verify(proof, fr, &commitment2, wpk), true);
|
||||||
}
|
}
|
||||||
|
@ -499,7 +409,7 @@ mod tests {
|
||||||
let com2 = pubParams.comParams.commit(&wallet2.as_fr_vec().clone(), &t);
|
let com2 = pubParams.comParams.commit(&wallet2.as_fr_vec().clone(), &t);
|
||||||
|
|
||||||
let com1_proof = CommitmentProof::<Bls12>::new(rng, &pubParams.comParams,
|
let com1_proof = CommitmentProof::<Bls12>::new(rng, &pubParams.comParams,
|
||||||
&com1.c, &wallet1.as_fr_vec(), &t, &vec![1, 3, 4]);
|
&com1.c, &wallet1.as_fr_vec(), &t, &vec![1, 3, 4]);
|
||||||
|
|
||||||
assert!(verify_opening(&pubParams.comParams, &com1.c, &com1_proof, bc, bm));
|
assert!(verify_opening(&pubParams.comParams, &com1.c, &com1_proof, bc, bm));
|
||||||
assert!(!verify_opening(&pubParams.comParams, &com2.c, &com1_proof, bc2, bm));
|
assert!(!verify_opening(&pubParams.comParams, &com2.c, &com1_proof, bc2, bm));
|
||||||
|
@ -524,5 +434,4 @@ mod tests {
|
||||||
|
|
||||||
// deserialize
|
// deserialize
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
101
src/ped92.rs
101
src/ped92.rs
|
@ -1,10 +1,12 @@
|
||||||
// ped92.rs
|
// ped92.rs
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use pairing::{Engine, CurveProjective};
|
use pairing::{Engine, CurveProjective};
|
||||||
use ff::Rand;
|
use ff::{Rand, Field, PrimeField};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use util::is_vec_g1_equal;
|
use util::is_vec_g1_equal;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
|
use util;
|
||||||
|
use std::borrow::BorrowMut;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CSParams<E: Engine> {
|
pub struct CSParams<E: Engine> {
|
||||||
|
@ -173,6 +175,103 @@ impl<E: Engine> CSMultiParams<E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||||
|
#[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 CommitmentProof<E: Engine> {
|
||||||
|
pub T: E::G1,
|
||||||
|
pub z: Vec<E::Fr>,
|
||||||
|
pub t: Vec<E::Fr>,
|
||||||
|
pub index: Vec<usize>,
|
||||||
|
pub reveal: Vec<E::Fr>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine> CommitmentProof<E> {
|
||||||
|
pub fn new<R: Rng>(csprng: &mut R, com_params: &CSMultiParams<E>, com: &E::G1, wallet: &Vec<E::Fr>, r: &E::Fr, reveal_index: &Vec<usize>) -> Self {
|
||||||
|
let (Tvals, t, rt, mut reveal_wallet) = CommitmentProof::<E>::prove_commitment::<R>(csprng, com_params, wallet, reveal_index);
|
||||||
|
|
||||||
|
// compute the challenge
|
||||||
|
let x: Vec<E::G1> = vec![Tvals, com.clone()];
|
||||||
|
let challenge = util::hash_g1_to_fr::<E>(&x);
|
||||||
|
|
||||||
|
// compute the response
|
||||||
|
CommitmentProof::<E>::prove_response(wallet, r, reveal_index, Tvals, &t, rt, reveal_wallet.borrow_mut(), &challenge)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prove_commitment<R: Rng>(csprng: &mut R, com_params: &CSMultiParams<E>, wallet: &Vec<E::Fr>, reveal_index: &Vec<usize>) -> (E::G1, Vec<E::Fr>, Vec<E::Fr>, Vec<E::Fr>) {
|
||||||
|
let mut Tvals = E::G1::zero();
|
||||||
|
assert!(wallet.len() <= com_params.pub_bases.len());
|
||||||
|
let mut t = Vec::<E::Fr>::with_capacity(wallet.len() + 1);
|
||||||
|
let mut rt: Vec<E::Fr> = Vec::new();
|
||||||
|
// t values that will be revealed
|
||||||
|
let mut reveal_wallet: Vec<E::Fr> = Vec::new();
|
||||||
|
// aspects of wallet being revealed
|
||||||
|
for i in 0..wallet.len() + 1 {
|
||||||
|
let ti = E::Fr::rand(csprng);
|
||||||
|
t.push(ti);
|
||||||
|
// check if we are revealing this index
|
||||||
|
if reveal_index.contains(&i) {
|
||||||
|
rt.push(ti);
|
||||||
|
} else {
|
||||||
|
rt.push(E::Fr::zero());
|
||||||
|
}
|
||||||
|
let mut gt = com_params.pub_bases[i].clone();
|
||||||
|
gt.mul_assign(ti.into_repr());
|
||||||
|
Tvals.add_assign(>);
|
||||||
|
}
|
||||||
|
(Tvals, t, rt, reveal_wallet)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prove_response(wallet: &Vec<E::Fr>, r: &E::Fr, reveal_index: &Vec<usize>, Tvals: E::G1, t: &Vec<E::Fr>, rt: Vec<E::Fr>, reveal_wallet: &mut Vec<E::Fr>, challenge: &E::Fr) -> CommitmentProof<E> {
|
||||||
|
let mut z: Vec<E::Fr> = Vec::new();
|
||||||
|
let mut z0 = r.clone();
|
||||||
|
z0.mul_assign(&challenge);
|
||||||
|
z0.add_assign(&t[0]);
|
||||||
|
z.push(z0);
|
||||||
|
reveal_wallet.push(E::Fr::zero());
|
||||||
|
for i in 1..t.len() {
|
||||||
|
let mut zi = wallet[i - 1].clone();
|
||||||
|
zi.mul_assign(&challenge);
|
||||||
|
zi.add_assign(&t[i]);
|
||||||
|
z.push(zi);
|
||||||
|
// check if we are revealing this index
|
||||||
|
if reveal_index.contains(&i) {
|
||||||
|
reveal_wallet.push(wallet[i - 1].clone());
|
||||||
|
} else {
|
||||||
|
reveal_wallet.push(E::Fr::zero());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CommitmentProof {
|
||||||
|
T: Tvals, // commitment challenge
|
||||||
|
z: z, // response values
|
||||||
|
t: rt, // randomness for verifying partial reveals
|
||||||
|
index: reveal_index.clone(),
|
||||||
|
reveal: reveal_wallet.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify_proof(&self, com_params: &CSMultiParams<E>, com: &<E as Engine>::G1, challenge: &E::Fr) -> bool {
|
||||||
|
let mut comc = com.clone();
|
||||||
|
let T = self.T.clone();
|
||||||
|
comc.mul_assign(challenge.into_repr());
|
||||||
|
comc.add_assign(&T);
|
||||||
|
let mut x = E::G1::zero();
|
||||||
|
for i in 0..self.z.len() {
|
||||||
|
let mut base = com_params.pub_bases[i].clone();
|
||||||
|
base.mul_assign(self.z[i].into_repr());
|
||||||
|
x.add_assign(&base);
|
||||||
|
}
|
||||||
|
comc == x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
Loading…
Reference in New Issue