Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zero Knowledge Proof #2

Merged
merged 14 commits into from
Jun 3, 2018
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
target
Cargo.lock
.idea
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ defaultgmp = []
[dependencies]
rand = "0.3"
num-traits = "0.1"
rust-crypto = "^0.2"
ramp = { version="0.3", optional=true }
framp = { version="0.3", optional=true }
num = { version="0.1", optional=true }
Expand Down
17 changes: 17 additions & 0 deletions src/arithimpl/gmpimpl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ impl ModPow for Mpz {
}
}

impl ModMul for Mpz {
fn modmul(base: &Self, exponent: &Self, modulus: &Self) -> Self {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not entirely sure I understand why this is needed as opposed to just doing a modulus reduction? in any case, the base and exponent arguments should probably be renamed

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mortendahl :
This is supposed to be : (A * B) mod C = (A mod C * B mod C) mod C .
It is used for example here: M′=MQ+Q((Q−1modP)(MP−MQ)modP).
@gbenattar : base and exponent should be renamed.

let base_mod_modulus = base.mod_floor(modulus);
let exponent_mod_modulus = exponent.mod_floor(modulus);
let mul_res = base_mod_modulus * exponent_mod_modulus;

mul_res.mod_floor(modulus)
}
}
impl ModInv for Mpz {
fn modinv(a: &Self, modulus: &Self) -> Self {
a.invert(modulus).unwrap()
Expand All @@ -57,6 +66,14 @@ impl EGCD for Mpz {
}
}

impl ToString for Mpz {
fn to_hex_str(a: &Self) -> String { a.to_str_radix(16) }
}

impl FromString<Mpz> for Mpz {
fn from_hex_str(a: String) -> Mpz { Mpz::from_str_radix(&a, 16).unwrap() }
}

impl ConvertFrom<Mpz> for u64 {
fn _from(x: &Mpz) -> u64 {
let foo: Option<u64> = x.into();
Expand Down
13 changes: 13 additions & 0 deletions src/arithimpl/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ pub trait ModPow
fn modpow(base: &Self, exponent: &Self, modulus: &Self) -> Self;
}

pub trait ModMul
{
fn modmul(base: &Self, exponent: &Self, modulus: &Self) -> Self;
}

pub trait EGCD
where
Self: Sized
Expand All @@ -38,6 +43,14 @@ pub trait ConvertFrom<T> {
fn _from(&T) -> Self;
}

pub trait ToString {
fn to_hex_str(a: &Self) -> String;
}

pub trait FromString<I> {
fn from_hex_str(a: String) -> I;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

&str instead of String?

}

use std::ops::{Add, Sub, Mul, Div, Rem, Shr, Neg};
use num_traits::{Zero, One};

Expand Down
101 changes: 99 additions & 2 deletions src/core/crt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
//! Faster decryption using the Chinese Remainder Theorem.

use super::*;

use crypto::sha2::Sha256;
use crypto::digest::Digest;
use std::error::Error;

/// Decryption key that should be kept private.
#[derive(Debug,Clone)]
Expand All @@ -22,7 +24,6 @@ pub struct DecryptionKey<I> {

impl<I> ::traits::DecryptionKey for DecryptionKey<I> {}


impl<'kp, I> From<&'kp Keypair<I>> for DecryptionKey<I>
where
I: Clone,
Expand Down Expand Up @@ -80,6 +81,7 @@ where
let cp = I::modpow(&c.0, &dk.pminusone, &dk.pp);
let lp = l(&cp, &dk.p);
let mp = (&lp * &dk.hp) % &dk.p;

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no changes here?

// process using q
let cq = I::modpow(&c.0, &dk.qminusone, &dk.qq);
let lq = l(&cq, &dk.q);
Expand All @@ -89,6 +91,101 @@ where
}
}

impl fmt::Display for ZKProverError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ZKProverError")
}
}

impl Error for ZKProverError {
fn description(&self) -> &str {
"Error while proving"
}
}

impl<I> ZKProver<I> for DecryptionKey<I>
where
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(all these bounds will go away in the upcoming simplification 🎉)

I : Samplable,
I : Eq,
I : One,
I : ModPow,
I : ModInv,
I : ModMul,
I : EGCD,
I : ToString,
I : FromString<I>,
for<'a> &'a I: Add<I, Output=I>,
for<'b> I: Add<&'b I, Output=I>,
for<'a,'b> &'a I: Sub<&'b I, Output=I>,
for<'a> I: Rem<&'a I, Output=I>,
for<'a,'b> &'a I: Rem<&'b I, Output=I>,
for<'a> &'a I: Mul<I, Output=I>
{

fn generate_proof(&self, challenge: &Vec<I>, e: &I, z: &Vec<I>) -> Result<I, ZKProverError> {
let phi = (&self.p - &I::one()) * (&self.q - &I::one());

let mut a : Vec<I> = Vec::new();
let mut i : usize = 0;
while i < ZK_SECURITY_FACTOR {
if I::egcd(&self.n, &z[i]).0 != I::one() ||
I::egcd(&self.n, &challenge[i]).0 != I::one() {
return Err(ZKProverError);
}

let zn = I::modpow(&z[i], &self.n, &self.n);
let cphi = I::modpow(&challenge[i], &phi, &self.n);
let cminphi = I::modinv(
&I::modpow(&challenge[i], &e, &self.n), &self.n);

a.push((zn * cphi * cminphi) % &self.n);

if I::egcd(&self.n, &z[i]).0 != I::one(){
return Err(ZKProverError);
}

i += 1;
}

let mut a_x_hash = Sha256::new();
a_x_hash.input_str(&I::to_hex_str(&self.n));

let mut j : usize = 0;
while j < ZK_SECURITY_FACTOR {
a_x_hash.input_str(&I::to_hex_str(&challenge[j]));
a_x_hash.input_str(&I::to_hex_str(&a[j]));
j += 1;
}

if &I::from_hex_str(a_x_hash.result_str()) != e {
return Err(ZKProverError);
}

let dn = I::modinv(&self.n, &phi);
let dp = &dn % &(&self.p - &I::one());
let dq = &dn % &(&self.q - &I::one());

let mut y_tag_hash = Sha256::new();

let mut k : usize = 0;
while k < ZK_SECURITY_FACTOR {
let cp = &challenge[k] % &self.p;
let mp = I::modpow(&cp, &dp, &self.p);

let cq = &challenge[k] % &self.q;
let mq = I::modpow(&cq, &dq, &self.q);

let qinvp = I::modinv(&self.q, &self.p);
let mtag = &mq + (&self.q * I::modmul(&qinvp, &(&mp - &mq), &self.p));

y_tag_hash.input_str(&I::to_hex_str(&mtag));

k += 1;
}

Ok(I::from_hex_str(y_tag_hash.result_str()))
}
}

fn h<I>(p: &I, pp: &I, n: &I) -> I
where
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
extern crate test;
extern crate rand;
extern crate num_traits;
extern crate crypto;

#[macro_use]
mod macros;
Expand All @@ -12,9 +13,11 @@ pub mod arithimpl;
pub mod traits;
pub mod core;
pub mod coding;
pub mod zkproof;

pub use traits::*;
pub use coding::*;
pub use zkproof::*;
pub use core::Keypair;
pub use core::standard::EncryptionKey;
pub use core::crt::DecryptionKey;
Expand Down
19 changes: 19 additions & 0 deletions src/traits.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

//! Abstract operations exposed by the library.
pub const ZK_SECURITY_FACTOR : usize = 40;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move this closer to where it's used?


/// Marker trait for the Paillier scheme.
pub trait AbstractScheme
Expand Down Expand Up @@ -111,3 +112,21 @@ pub trait Decoder<T>
/// Decode `Source` types into `T` types.
fn decode(&self, y: &Self::Source) -> T;
}

#[derive(Debug)]
pub struct ZKVerifierError;

pub trait ZKVerifier<I>
{
fn generate_challenge(&self) -> (Vec<I>, I, Vec<I>, Vec<I>);
fn verify(&self, proof: &I, y: &Vec<I>) -> Result<(), ZKVerifierError>;
}

#[derive(Debug)]
pub struct ZKProverError;

pub trait ZKProver<I>
{
fn generate_proof(&self, challenge: &Vec<I>, e: &I, z: &Vec<I>) -> Result<I, ZKProverError>;
}

Loading