finally adding initial zkp.rs (not working yet)

This commit is contained in:
J. Ayo Akinyele 2018-03-25 23:54:47 -04:00
parent c0694a98e9
commit 6550d5cf12
4 changed files with 523 additions and 15 deletions

View File

@ -1,28 +1,34 @@
<component name="libraryTable">
<library name="Cargo &lt;libbolt&gt;">
<CLASSES>
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/unicode-xid-0.1.0" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/pkg-config-0.3.9" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/winapi-x86_64-pc-windows-gnu-0.4.0" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/winapi-i686-pc-windows-gnu-0.4.0" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/num-traits-0.1.43" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/syn-0.12.14" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/fuchsia-zircon-sys-0.3.3" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/quote-0.4.2" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/rustc-serialize-0.3.24" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-1.0.27" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/sodiumoxide-0.0.16" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/byteorder-1.2.1" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/fuchsia-zircon-0.3.3" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/bincode-0.5.9" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/libsodium-sys-0.0.16" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/winapi-x86_64-pc-windows-gnu-0.4.0" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/bn-0.4.3" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/bincode-0.6.1" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/fuchsia-zircon-sys-0.3.3" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/rustc-serialize-0.3.24" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/byteorder-0.5.3" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.4.2" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/bitflags-1.0.1" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/winapi-0.3.4" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/num-traits-0.1.43" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/pkg-config-0.3.9" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.36" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/fuchsia-zircon-0.3.3" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/num-traits-0.2.0" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.3.22" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/libc-0.2.36" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/bitflags-1.0.1" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/byteorder-0.5.3" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_derive_internals-0.22.1" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/serde_derive-1.0.35" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/serde-0.7.15" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/bincode-0.6.1" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/bincode-0.5.9" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/winapi-0.3.4" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/byteorder-1.2.1" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.3.22" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/proc-macro2-0.2.3" />
<root url="file://$USER_HOME$/.cargo/registry/src/github.com-1ecc6299db9ec823/rand-0.4.2" />
</CLASSES>
<SOURCES />
</library>

View File

@ -14,6 +14,8 @@ bn = "0.4.3"
rand = "~0.3.14"
bincode = "0.5.9"
sodiumoxide = "0.0.16"
serde = "1.0"
serde_derive = "1.0"
[dev-dependencies.bincode]
version = "~0.6.0"

View File

@ -181,6 +181,7 @@ pub mod prf {
////////////////////////////////// CL Sigs /////////////////////////////////////
pub mod zkp;
pub mod sym;
pub mod clsigs;
pub mod commit_scheme;

499
src/zkp.rs Normal file
View File

@ -0,0 +1,499 @@
// -*- coding: utf-8; mode: rust; -*-
//
// To the extent possible under law, the authors have waived all
// copyright and related or neighboring rights to zkp,
// using the Creative Commons "CC0" public domain dedication. See
// <http://creativecommons.org/publicdomain/zero/1.0/> for full
// details.
//
// Authors:
// - Henry de Valence <hdevalence@hdevalence.ca>
//! This crate has an experimental zero-knowledge proof compiler
//! implemented using Rust macros.
//!
//! It provides a DSL resembing Camenisch-Stadler notation for proving
//! statements about discrete logarithms in the Ristretto group on
//! BLS-381, as implemented in
//! [`bn module`](https://github.com/zcash-hackworks/bn).
#![allow(non_snake_case)]
#![feature(test)]
//extern crate serde;
//
//#[doc(hidden)]
//#[macro_use]
//pub extern crate serde_derive;
//#[doc(hidden)]
//pub extern crate bn;
//#[doc(hidden)]
//pub extern crate rand;
#[doc(hidden)]
#[macro_export]
macro_rules! __compute_formula_scalarlist {
// Unbracket a statement
(($publics:ident, $scalars:ident) ($($x:tt)*)) => {
// Add a trailing +
__compute_formula_scalarlist!(($publics,$scalars) $($x)* +)
};
// Inner part of the formula: give a list of &Scalars
// Since there's a trailing +, we can just generate the list as normal...
(($publics:ident, $scalars:ident)
$( $point:ident * $scalar:ident +)+ ) => {
&[ $( $scalars.$scalar ,)* ]
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __compute_formula_pointlist {
// Unbracket a statement
(($publics:ident, $scalars:ident) ($($x:tt)*)) => {
// Add a trailing +
__compute_formula_pointlist!(($publics,$scalars) $($x)* +)
};
// Inner part of the formula: give a list of &Scalars
// Since there's a trailing +, we can just generate the list as normal...
(($publics:ident, $scalars:ident)
$( $point:ident * $scalar:ident +)* ) => {
&[ $( *($publics.$point) ,)* ]
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __compute_commitments_consttime {
(($publics:ident, $scalars:ident) $($lhs:ident = $statement:tt),+) => {
Commitments {
$( $lhs :
multiscalar_mult(
__compute_formula_scalarlist!(($publics, $scalars) $statement),
__compute_formula_pointlist!(($publics, $scalars) $statement),
)
),+
}
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __recompute_commitments_vartime {
(($publics:ident, $scalars:ident, $minus_c:ident) $($lhs:ident = $statement:tt),+) => {
Commitments {
$( $lhs :
vartime::multiscalar_mult(
__compute_formula_scalarlist!(($publics, $scalars) $statement)
.into_iter()
.chain(iter::once(&($minus_c)))
,
__compute_formula_pointlist!(($publics, $scalars) $statement)
.into_iter()
.chain(iter::once($publics.$lhs))
)
),+
}
}
}
/// Creates a module with code required to produce a non-interactive
/// zero-knowledge proof statement, to serialize it to wire format, to
/// parse from wire format, and to verify the proof statement.
///
/// The statement is specified in an embedded DSL resembling
/// Camenisch-Stadler notation. For instance, a proof of knowledge of
/// two equal discrete logarithms ("DLEQ") is specified as:
///
/// ```rust,ignore
/// create_nipk!{dleq, (x), (A, B, G, H) : A = (G * x), B = (H * x) }
/// ```
///
/// This creates a module `dleq` with code for proving knowledge of a
/// secret `x: Scalar` such that `A = G*x`, `B = H*x` for public
/// parameters `A, B, G, H: RistrettoPoint`. In general the syntax is
///
/// ```rust,ignore
/// create_nipk!{
/// module_name, // used to label proof statements
/// (x,y,z,...), // secret variable names
/// (A,B,C,...) // public parameter names
/// :
/// LHS = (A * x + B * y + C * z + ... ), // comma-seperated statements
/// ...
/// }
/// ```
///
/// Statements have the form `LHS = (A * x + B * y + C * z + ... )`,
/// where `LHS` is one of the points listed as a public parameter, and
/// the right-hand side is a sum of public points multiplied by secret
/// scalars.
///
/// Inside the generated module `module_name`, the macro defines three
/// structs:
///
/// A `Publics` struct corresponding to the public parameters, of the
/// form
///
/// ```rust,ignore
/// pub struct Publics<'a> { pub A: &'a RistrettoPoint, ... }
/// ```
///
/// A `Secrets` struct corresponding to the secret parameters, of the
/// form
///
/// ```rust,ignore
/// pub struct Secrets<'a> { pub x: &'a Scalar, ... }
/// ```
///
/// A `Proof` struct, of the form
///
/// ```rust,ignore
/// #[derive(Serialize, Deserialize)]
/// pub struct Proof { ... }
///
/// impl Proof {
/// pub fn create<R: Rng>(
/// rng: &mut R,
/// publics: Publics,
/// secrets: Secrets,
/// ) -> Proof { ... }
///
/// pub fn verify(&self, publics: Publics) -> Result<(),()> { ... }
/// }
/// ```
///
/// The `Proof` struct derives the Serde traits, so it can be
/// serialized and deserialized to various wire formats.
///
/// The `Publics` and `Secrets` structs are used to fake named
/// arguments in the input to `create` and `verify`. Proof creation
/// is done in constant time. Proof verification uses variable-time
/// code.
///
/// As an example, we can create and verify a DLEQ proof as follows:
///
/// ```
/// #[macro_use]
/// extern crate serde_derive;
///
/// #[macro_use]
/// extern crate zkp;
///
/// extern crate curve25519_dalek;
/// use curve25519_dalek::constants as dalek_constants;
/// use curve25519_dalek::ristretto::RistrettoPoint;
/// use curve25519_dalek::scalar::Scalar;
///
/// extern crate rand;
/// use rand::OsRng;
///
/// extern crate sha2;
/// use sha2::Sha256;
///
/// extern crate bincode;
///
/// # fn main() {
/// let mut rng = OsRng::new().unwrap();
/// let G = &dalek_constants::RISTRETTO_BASEPOINT_POINT;
/// let H = RistrettoPoint::hash_from_bytes::<Sha256>(G.compress().as_bytes());
///
/// create_nipk!{dleq, (x), (A, B, G, H) : A = (G * x), B = (H * x) }
///
/// let x = Scalar::from_u64(89327492234);
/// let A = G * &x;
/// let B = &H * &x;
///
/// let publics = dleq::Publics{A: &A, B: &B, G: G, H: &H};
/// let secrets = dleq::Secrets{x: &x};
///
/// let proof = dleq::Proof::create(&mut rng, publics, secrets);
///
/// // Serialize to bincode representation
/// let proof_bytes = bincode::serialize(&proof, bincode::Infinite).unwrap();
///
/// // Send bytes over the wire here ...
///
/// // Parse bytes back to in-memory representation
/// let parsed_proof: dleq::Proof
/// = bincode::deserialize(&proof_bytes).unwrap();
///
/// // Check the proof.
/// assert!(parsed_proof.verify(publics).is_ok());
/// # }
/// ```
#[macro_export]
macro_rules! create_nipk {
(
$proof_module_name:ident // Name of the module to create
,
( $($secret:ident),+ ) // Secret variables, sep by commas
,
( $($public:ident),+ ) // Public variables, sep by commas
:
// List of statements to prove
// Format: LHS = ( ... RHS expr ... ),
$($lhs:ident = $statement:tt),+
) => {
mod $proof_module_name {
use $crate::{Group, Fr, G1, G2}
use $crate::sodiumoxide::crypto::hash;
// use $crate::sha2::{Digest, Sha512};
use $crate::rand::Rng;
use std::iter;
#[derive(Copy, Clone)]
pub struct Secrets<'a> {
// Create a parameter for each secret value
$(
pub $secret : &'a Scalar,
)+
}
#[derive(Copy, Clone)]
pub struct Publics<'a> {
// Create a parameter for each public value
$(
pub $public : &'a RistrettoPoint,
)+
}
// Hack because we can't concat identifiers,
// so do responses.x instead of responses_x
// rand.x instead of rand_x, etc.
struct Commitments {$($lhs: RistrettoPoint,)+ }
struct Randomnesses {$($secret : Scalar,)+}
#[derive(Serialize, Deserialize)]
struct Responses {$($secret : Scalar,)+}
#[derive(Serialize, Deserialize)]
pub struct Proof {
challenge: Scalar,
responses: Responses,
}
impl Proof {
/// Create a `Proof`, in constant time, from the given
/// `Publics` and `Secrets`.
#[allow(dead_code)]
pub fn create<R: Rng>(
rng: &mut R,
publics: Publics,
secrets: Secrets,
) -> Proof {
let rand = Randomnesses{
$(
$secret : Scalar::random(rng),
)+
};
// $statement_rhs = `X * x + Y * y + Z * z`
// should become
// `publics.X * rand.x + publics.Y * rand.y + publics.Z * rand.z`
let commitments: Commitments;
commitments = __compute_commitments_consttime!(
(publics, rand) $($lhs = $statement),*
);
let mut hash_state = hash::State::new();
$(
hash_state.update(publics.$public.compress().as_bytes());
)+
$(
hash_state.update(commitments.$lhs.compress().as_bytes());
)+
let digest = hash_state.finalize();
let mut digest_buf: [u8; 64] = [0; 64];
digest_buf.copy_from_slice(&digest[0..64]);
let challenge = Fr::interpret(&digest_buf); // Scalar::from_hash(hash);
let responses = Responses{
$(
$secret : &(&challenge * secrets.$secret) + &rand.$secret,
)+
};
Proof{ challenge: challenge, responses: responses }
}
/// Verify the `Proof` using the public parameters `Publics`.
#[allow(dead_code)]
pub fn verify(&self, publics: Publics) -> Result<(),()> {
// `A = X * x + Y * y`
// should become
// `publics.X * responses.x + publics.Y * responses.y - publics.A * self.challenge`
let responses = &self.responses;
let minus_c = -&self.challenge;
let commitments = __recompute_commitments_vartime!(
(publics, responses, minus_c) $($lhs = $statement),*
);
let mut hash_state = hash::State::new();
// Add each public point into the hash
$(
hash_state.update(publics.$public.compress().as_bytes());
)+
// Add each (recomputed) commitment into the hash
$(
hash_state.update(commitments.$lhs.compress().as_bytes());
)*
let digest = hash_state.finalize();
let mut digest_buf: [u8; 64] = [0; 64];
digest_buf.copy_from_slice(&digest[0..64]);
// Recompute challenge
let challenge = Fr::interpret(&digest_buf); // Scalar::from_hash(hash);
if challenge == self.challenge { Ok(()) } else { Err(()) }
}
}
#[cfg(test)]
mod bench {
extern crate test;
use $crate::rand;
use super::*;
use self::test::Bencher;
#[bench]
#[allow(dead_code)]
fn create(b: &mut Bencher) {
let rng = &mut rand::thread_rng();
//let mut rng = OsRng::new().unwrap();
// Need somewhere to actually put the public points
struct DummyPublics { $( pub $public : RistrettoPoint, )+ }
let dummy_publics = DummyPublics {
$( $public : G1::random(&mut rng) , )+
};
let publics = Publics {
$( $public : &dummy_publics.$public , )+
};
struct DummySecrets { $( pub $secret : Scalar, )+ }
let dummy_secrets = DummySecrets {
$( $secret : Fr::random(&mut rng) , )+
};
let secrets = Secrets {
$( $secret : &dummy_secrets.$secret , )+
};
b.iter(|| Proof::create(&mut rng, publics, secrets));
}
#[bench]
#[allow(dead_code)]
fn verify(b: &mut Bencher) {
let mut rng = OsRng::new().unwrap();
// Need somewhere to actually put the public points
struct DummyPublics { $( pub $public : RistrettoPoint, )+ }
let dummy_publics = DummyPublics {
$( $public : RistrettoPoint::random(&mut rng) , )+
};
let publics = Publics {
$( $public : &dummy_publics.$public , )+
};
struct DummySecrets { $( pub $secret : Scalar, )+ }
let dummy_secrets = DummySecrets {
$( $secret : Scalar::random(&mut rng) , )+
};
let secrets = Secrets {
$( $secret : &dummy_secrets.$secret , )+
};
let p = Proof::create(&mut rng, publics, secrets);
b.iter(|| p.verify(publics));
}
}
}
}
}
#[cfg(test)]
mod tests {
extern crate bincode;
extern crate test;
use rand;
use bn::{Group, Fr, G1, G2};
use sha2::Sha256;
use self::test::Bencher;
// use curve25519_dalek::constants as dalek_constants;
// use curve25519_dalek::ristretto::RistrettoPoint;
// use curve25519_dalek::scalar::Scalar;
#[bench]
fn create_gen_dleq(b: &mut Bencher) {
let rng = &mut rand::thread_rng(); // OsRng::new().unwrap();
let G = G1::random(rng); // &dalek_constants::RISTRETTO_BASEPOINT_POINT;
let H = G1::random(rng); // RistrettoPoint::hash_from_bytes::<Sha256>(G.compress().as_bytes());
create_nipk!{dleq, (x), (A, B, G, H) : A = (G * x), B = (H * x) }
let x = Fr::from_str("89327492234").unwrap();
let A = G * &x;
let B = &H * &x;
let publics = dleq::Publics{A: &A, B: &B, G: G, H: &H};
let secrets = dleq::Secrets{x: &x};
b.iter(|| dleq::Proof::create(&mut rng, publics, secrets));
}
// #[bench]
// fn verify_gen_dleq(b: &mut Bencher) {
// let mut rng = OsRng::new().unwrap();
// let G = &dalek_constants::RISTRETTO_BASEPOINT_POINT;
// let H = RistrettoPoint::hash_from_bytes::<Sha256>(G.compress().as_bytes());
//
// create_nipk!{dleq, (x), (A, B, G, H) : A = (G * x), B = (H * x) }
//
// let x = Scalar::from_u64(89327492234);
// let A = G * &x;
// let B = &H * &x;
//
// let publics = dleq::Publics{A: &A, B: &B, G: G, H: &H};
// let secrets = dleq::Secrets{x: &x};
//
// let proof = dleq::Proof::create(&mut rng, publics, secrets);
// b.iter(|| proof.verify(publics).is_ok());
// }
//
// #[test]
// fn create_and_verify_gen_dleq() {
// let mut rng = OsRng::new().unwrap();
// let G = &dalek_constants::RISTRETTO_BASEPOINT_POINT;
// let H = RistrettoPoint::hash_from_bytes::<Sha256>(G.compress().as_bytes());
//
// create_nipk!{dleq, (x), (A, B, G, H) : A = (G * x), B = (H * x) }
//
// let x = Scalar::from_u64(89327492234);
// let A = G * &x;
// let B = &H * &x;
//
// let publics = dleq::Publics{A: &A, B: &B, G: G, H: &H};
// let secrets = dleq::Secrets{x: &x};
//
// let proof = dleq::Proof::create(&mut rng, publics, secrets);
// // serialize to bincode representation
// let proof_bytes = bincode::serialize(&proof, bincode::Infinite).unwrap();
// // parse bytes back to memory
// let parsed_proof: dleq::Proof
// = bincode::deserialize(&proof_bytes).unwrap();
//
// assert!(parsed_proof.verify(publics).is_ok());
// }
}