nizk: start implementation of nizk
This commit is contained in:
parent
b3e1b76a05
commit
e4c1129a20
24
src/ccs08.rs
24
src/ccs08.rs
|
@ -9,13 +9,14 @@ extern crate rand;
|
|||
|
||||
use rand::{thread_rng, Rng};
|
||||
use super::*;
|
||||
use cl::{KeyPair, Signature, PublicParams, setup, BlindKeyPair, ProofState, Proof};
|
||||
use cl::{KeyPair, Signature, PublicParams, setup, BlindKeyPair, ProofState, SignatureProof};
|
||||
use ped92::{CSParams, Commitment};
|
||||
use pairing::{Engine, CurveProjective};
|
||||
use ff::PrimeField;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Display;
|
||||
use std::mem::transmute;
|
||||
use util::fmt_bytes_to_int;
|
||||
|
||||
/**
|
||||
paramsUL contains elements generated by the verifier, which are necessary for the prover.
|
||||
|
@ -45,7 +46,7 @@ struct ProofUL<E: Engine> {
|
|||
V: Vec<Signature<E>>,
|
||||
D: E::G2,
|
||||
comm: Commitment<E>,
|
||||
sigProofs: Vec<Proof<E>>,
|
||||
sigProofs: Vec<SignatureProof<E>>,
|
||||
ch: E::Fr,
|
||||
zr: E::Fr,
|
||||
}
|
||||
|
@ -102,7 +103,7 @@ impl<E: Engine> ParamsUL<E> {
|
|||
|
||||
// Initialize variables
|
||||
let mut proofStates = Vec::<ProofState<E>>::with_capacity(self.l as usize);
|
||||
let mut sigProofs = Vec::<Proof<E>>::with_capacity(self.l as usize);
|
||||
let mut sigProofs = Vec::<SignatureProof<E>>::with_capacity(self.l as usize);
|
||||
let mut V = Vec::<Signature<E>>::with_capacity(self.l as usize);
|
||||
let mut D = E::G2::zero();
|
||||
let m = E::Fr::rand(rng);
|
||||
|
@ -221,17 +222,6 @@ fn decompose(x: i64, u: i64, l: i64) -> Vec<i64> {
|
|||
return result;
|
||||
}
|
||||
|
||||
fn fmt_bytes_to_int(bytearray: [u8; 64]) -> String {
|
||||
let mut result: String = "".to_string();
|
||||
for byte in bytearray.iter() {
|
||||
// Decide if you want upper- or lowercase results,
|
||||
// padding the values to two characters, spaces
|
||||
// between bytes, etc.
|
||||
result = result + &format!("{}", *byte as u8);
|
||||
}
|
||||
result.to_string()
|
||||
}
|
||||
|
||||
impl<E: Engine> RPPublicParams<E> {
|
||||
/**
|
||||
Setup receives integers a and b, and configures the parameters for the rangeproof scheme.
|
||||
|
@ -459,12 +449,6 @@ mod tests {
|
|||
RPPublicParams::<Bls12>::setup(rng, -2, -1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fmt_byte_to_int_works() {
|
||||
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 hash_works() {
|
||||
let rng = &mut rand::thread_rng();
|
||||
|
|
|
@ -64,7 +64,7 @@ pub struct ProofState<E: Engine> {
|
|||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Proof<E: Engine> {
|
||||
pub struct SignatureProof<E: Engine> {
|
||||
pub zx: E::Fr,
|
||||
pub zsig: Vec<E::Fr>,
|
||||
pub zv: E::Fr,
|
||||
|
@ -245,7 +245,7 @@ impl<E: Engine> BlindPublicKey<E> {
|
|||
/// Verify a proof of knowledge of a signature
|
||||
/// Takes in a proof generated by prove_response(), a blind signature, and a challenge
|
||||
/// outputs: boolean
|
||||
pub fn verify_proof(&self, mpk: &PublicParams<E>, blindSig: Signature<E>, p: Proof<E>, challenge: E::Fr) -> bool {
|
||||
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.X);
|
||||
gx = gx.pow(p.zx.into_repr());
|
||||
for j in 0..self.Y2.len() {
|
||||
|
@ -364,7 +364,7 @@ impl<E: Engine> BlindKeyPair<E> {
|
|||
|
||||
/// prove knowledge of a signature: response phase
|
||||
/// returns a proof that can be send to the verifier together with the challenge and the blind signature
|
||||
pub fn prove_response(&self, ps: ProofState<E>, challenge: E::Fr, message: &mut Vec<E::Fr>) -> Proof<E> {
|
||||
pub fn prove_response(&self, ps: ProofState<E>, challenge: E::Fr, message: &mut Vec<E::Fr>) -> SignatureProof<E> {
|
||||
let mut zsig = ps.t.clone();
|
||||
for i in 0..zsig.len() {
|
||||
let mut message1 = message[i];
|
||||
|
@ -377,7 +377,7 @@ impl<E: Engine> BlindKeyPair<E> {
|
|||
let mut vic = ps.v.clone();
|
||||
vic.mul_assign(&challenge);
|
||||
zv.add_assign(&vic);
|
||||
Proof {zsig, zx, zv, a: ps.a }
|
||||
SignatureProof {zsig, zx, zv, a: ps.a }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -70,6 +70,8 @@ pub mod commit_scheme;
|
|||
pub mod ped92;
|
||||
pub mod clproto;
|
||||
pub mod serialization_wrappers;
|
||||
pub mod nizk;
|
||||
pub mod util;
|
||||
|
||||
const E_MIN: i32 = 1;
|
||||
const E_MAX: i32 = 255; // TODO: should be 2^32 - 1
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
extern crate rand;
|
||||
|
||||
use rand::{thread_rng, Rng};
|
||||
use pairing::{Engine, CurveProjective};
|
||||
use cl::{KeyPair, Signature, PublicParams, setup, BlindKeyPair, ProofState, SignatureProof, BlindPublicKey};
|
||||
use ped92::{CSMultiParams, Commitment};
|
||||
use ff::{Rand, Field, PrimeField};
|
||||
use util::hash_g2_to_fr;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Proof<E: Engine> {
|
||||
sigProof: SignatureProof<E>,
|
||||
T: E::G1,
|
||||
z: Vec<E::Fr>
|
||||
}
|
||||
|
||||
fn prove<R: Rng, E: Engine>(rng: &mut R, com1: &Commitment<E>, com2: &Commitment<E>, oldWallet: Vec<E::Fr>, r: E::Fr,
|
||||
newWallet: Vec<E::Fr>, rprime: E::Fr, paymentToken: &Signature<E>,
|
||||
mpk: &PublicParams<E>, kp: &BlindKeyPair<E>) -> Proof<E> {
|
||||
let proofState = kp.prove_commitment(rng, &mpk, &paymentToken);
|
||||
let mut challenge = E::Fr::one();
|
||||
challenge.double();
|
||||
let sigProof = kp.prove_response(proofState, challenge, &mut vec! {hash_g2_to_fr::<E>(&com1.c)});
|
||||
|
||||
Proof {sigProof, T: E::G1::rand(rng), z: vec!{}}
|
||||
}
|
||||
|
||||
fn verify<E: Engine>(proof: Proof<E>, epsilon: E::Fr, com1: &Commitment<E>, com2: &Commitment<E>,
|
||||
paymentToken: &Signature<E>, wpk: E::Fr, mpk: &PublicParams<E>, pk: &BlindPublicKey<E>) -> bool {
|
||||
let mut challenge = E::Fr::one();
|
||||
challenge.double();
|
||||
pk.verify_proof(&mpk, paymentToken.clone(), proof.sigProof, challenge)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use pairing::bls12_381::{Bls12, G1, G2, Fq12, Fr};
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
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);
|
||||
let bc = Fr::rand(rng);
|
||||
let mut bc2 = bc.clone();
|
||||
let bm = Fr::rand(rng);
|
||||
let mut bm2 = bm.clone();
|
||||
let epsilon = &Fr::rand(rng);
|
||||
bc2.sub_assign(epsilon);
|
||||
bm2.add_assign(epsilon);
|
||||
let r = Fr::rand(rng);
|
||||
let rprime = Fr::rand(rng);
|
||||
|
||||
let com_params = CSMultiParams::<Bls12>::setup_gen_params(rng, 4);
|
||||
let wallet1 = vec! {pkc, wpk, bc, bm};
|
||||
let commitment1 = com_params.commit(rng, &wallet1, &r);
|
||||
let wallet2 = vec! {pkc, wpkprime, bc2, bm2};
|
||||
let commitment2 = com_params.commit(rng, &wallet2, &rprime);
|
||||
let mpk = setup(rng);
|
||||
let keypair = BlindKeyPair::<Bls12>::generate( rng, &mpk, 1);
|
||||
let payment_token = keypair.sign(rng, &vec! {hash_g2_to_fr::<Bls12>(&commitment1.c)});
|
||||
|
||||
let proof = prove(rng, &commitment1, &commitment2, wallet1, r, wallet2, rprime, &payment_token, &mpk, &keypair);
|
||||
|
||||
assert_eq!(verify(proof, *epsilon, &commitment1, &commitment2, &payment_token, wpk, &mpk, &keypair.public), true);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
use sodiumoxide::crypto::hash::sha512;
|
||||
use pairing::Engine;
|
||||
use ff::PrimeField;
|
||||
|
||||
pub fn hash_g2_to_fr<E: Engine>(x: &E::G2) -> E::Fr {
|
||||
let mut x_vec: Vec<u8> = Vec::new();
|
||||
x_vec.extend(format!("{}", x).bytes());
|
||||
let sha2_digest = sha512::hash(x_vec.as_slice());
|
||||
|
||||
let mut hash_buf: [u8; 64] = [0; 64];
|
||||
hash_buf.copy_from_slice(&sha2_digest[0..64]);
|
||||
return E::Fr::from_str(&fmt_bytes_to_int(hash_buf)).unwrap();
|
||||
}
|
||||
|
||||
pub fn fmt_bytes_to_int(bytearray: [u8; 64]) -> String {
|
||||
let mut result: String = "".to_string();
|
||||
for byte in bytearray.iter() {
|
||||
// Decide if you want upper- or lowercase results,
|
||||
// padding the values to two characters, spaces
|
||||
// between bytes, etc.
|
||||
result = result + &format!("{}", *byte as u8);
|
||||
}
|
||||
result.to_string()
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use pairing::bls12_381::{Bls12, G2, Fr};
|
||||
use pairing::CurveProjective;
|
||||
use ff::Field;
|
||||
|
||||
#[test]
|
||||
fn hash_g2_to_fr_works() {
|
||||
let mut two = G2::one();
|
||||
two.double();
|
||||
print!("{}\n", hash_g2_to_fr::<Bls12>(&two));
|
||||
assert_eq!(format!("{}", hash_g2_to_fr::<Bls12>(&two).into_repr()),
|
||||
"0x27cd26f702a777dbf782534ae6bf2ec4aa6cb4617c8366f10f59bef13beb8c56");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fmt_byte_to_int_works() {
|
||||
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");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue