diff --git a/src/ccs08.rs b/src/ccs08.rs index bead5fd..52d3112 100644 --- a/src/ccs08.rs +++ b/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 { V: Vec>, D: E::G2, comm: Commitment, - sigProofs: Vec>, + sigProofs: Vec>, ch: E::Fr, zr: E::Fr, } @@ -102,7 +103,7 @@ impl ParamsUL { // Initialize variables let mut proofStates = Vec::>::with_capacity(self.l as usize); - let mut sigProofs = Vec::>::with_capacity(self.l as usize); + let mut sigProofs = Vec::>::with_capacity(self.l as usize); let mut V = Vec::>::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 { 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 RPPublicParams { /** Setup receives integers a and b, and configures the parameters for the rangeproof scheme. @@ -459,12 +449,6 @@ mod tests { RPPublicParams::::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(); diff --git a/src/cl.rs b/src/cl.rs index 66bb983..4db0b44 100644 --- a/src/cl.rs +++ b/src/cl.rs @@ -64,7 +64,7 @@ pub struct ProofState { } #[derive(Clone)] -pub struct Proof { +pub struct SignatureProof { pub zx: E::Fr, pub zsig: Vec, pub zv: E::Fr, @@ -245,7 +245,7 @@ impl BlindPublicKey { /// 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, blindSig: Signature, p: Proof, challenge: E::Fr) -> bool { + pub fn verify_proof(&self, mpk: &PublicParams, blindSig: Signature, p: SignatureProof, 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 BlindKeyPair { /// 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, challenge: E::Fr, message: &mut Vec) -> Proof { + pub fn prove_response(&self, ps: ProofState, challenge: E::Fr, message: &mut Vec) -> SignatureProof { let mut zsig = ps.t.clone(); for i in 0..zsig.len() { let mut message1 = message[i]; @@ -377,7 +377,7 @@ impl BlindKeyPair { 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 } } } diff --git a/src/lib.rs b/src/lib.rs index ae2716a..0e3b281 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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 diff --git a/src/nizk.rs b/src/nizk.rs new file mode 100644 index 0000000..6963d66 --- /dev/null +++ b/src/nizk.rs @@ -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 { + sigProof: SignatureProof, + T: E::G1, + z: Vec +} + +fn prove(rng: &mut R, com1: &Commitment, com2: &Commitment, oldWallet: Vec, r: E::Fr, + newWallet: Vec, rprime: E::Fr, paymentToken: &Signature, + mpk: &PublicParams, kp: &BlindKeyPair) -> Proof { + 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::(&com1.c)}); + + Proof {sigProof, T: E::G1::rand(rng), z: vec!{}} +} + +fn verify(proof: Proof, epsilon: E::Fr, com1: &Commitment, com2: &Commitment, + paymentToken: &Signature, wpk: E::Fr, mpk: &PublicParams, pk: &BlindPublicKey) -> 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::::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::::generate( rng, &mpk, 1); + let payment_token = keypair.sign(rng, &vec! {hash_g2_to_fr::(&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); + } +} \ No newline at end of file diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 0000000..2b64973 --- /dev/null +++ b/src/util.rs @@ -0,0 +1,48 @@ +use sodiumoxide::crypto::hash::sha512; +use pairing::Engine; +use ff::PrimeField; + +pub fn hash_g2_to_fr(x: &E::G2) -> E::Fr { + let mut x_vec: Vec = 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::(&two)); + assert_eq!(format!("{}", hash_g2_to_fr::(&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"); + } +} \ No newline at end of file