2018-02-24 00:12:58 -08:00
|
|
|
extern crate bn;
|
2018-02-24 23:46:52 -08:00
|
|
|
extern crate rand;
|
|
|
|
extern crate bincode;
|
|
|
|
extern crate sodiumoxide;
|
2018-03-24 06:44:45 -07:00
|
|
|
|
2018-02-24 23:46:52 -08:00
|
|
|
use std::fmt;
|
2018-03-24 06:44:45 -07:00
|
|
|
use std::str;
|
|
|
|
use std::default;
|
2018-02-24 23:46:52 -08:00
|
|
|
use bn::{Group, Fr, G1, G2, pairing};
|
|
|
|
use bincode::SizeLimit::Infinite;
|
|
|
|
use bincode::rustc_serialize::{encode, decode};
|
2018-04-08 00:46:17 -07:00
|
|
|
use sodiumoxide::randombytes;
|
2018-03-24 06:44:45 -07:00
|
|
|
use sodiumoxide::crypto::hash::sha512;
|
2018-02-24 00:12:58 -08:00
|
|
|
|
2018-04-07 12:01:27 -07:00
|
|
|
pub mod prf;
|
2018-04-02 07:47:19 -07:00
|
|
|
pub mod sym;
|
2018-04-07 12:01:27 -07:00
|
|
|
pub mod ote;
|
2018-04-02 07:47:19 -07:00
|
|
|
pub mod clsigs;
|
|
|
|
pub mod commit_scheme;
|
|
|
|
|
2018-02-24 23:46:52 -08:00
|
|
|
// Begin CL Signature scheme data structures
|
2018-02-24 00:12:58 -08:00
|
|
|
|
2018-02-24 23:46:52 -08:00
|
|
|
// End CL Signature scheme data structures
|
2018-02-24 00:12:58 -08:00
|
|
|
|
2018-03-24 06:44:45 -07:00
|
|
|
//pub fn hash_string(s: &str) -> String {
|
|
|
|
// let digest = sha256::hash(s.as_bytes());
|
|
|
|
// format!("{:X}", HexSlice::new(&digest))
|
|
|
|
//}
|
2018-02-24 23:46:52 -08:00
|
|
|
|
2018-03-24 06:44:45 -07:00
|
|
|
pub fn debug_elem_in_hex(prefix: &str, r: &Fr) {
|
|
|
|
let encoded: Vec<u8> = encode(&r, Infinite).unwrap();
|
|
|
|
print!("{} (hex) = 0x", prefix);
|
|
|
|
for e in encoded.iter() {
|
|
|
|
print!("{:x}", e);
|
|
|
|
}
|
|
|
|
print!("\n");
|
2018-02-24 00:12:58 -08:00
|
|
|
}
|
|
|
|
|
2018-03-24 06:44:45 -07:00
|
|
|
struct HexSlice<'a>(&'a [u8]);
|
|
|
|
|
|
|
|
impl<'a> HexSlice<'a> {
|
|
|
|
fn new<T>(data: &'a T) -> HexSlice<'a>
|
|
|
|
where T: ?Sized + AsRef<[u8]> + 'a
|
|
|
|
{
|
|
|
|
HexSlice(data.as_ref())
|
2018-02-24 23:46:52 -08:00
|
|
|
}
|
|
|
|
}
|
2018-02-24 00:12:58 -08:00
|
|
|
|
2018-03-24 06:44:45 -07:00
|
|
|
impl<'a> fmt::LowerHex for HexSlice<'a> {
|
2018-02-24 23:46:52 -08:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2018-03-24 06:44:45 -07:00
|
|
|
for byte in self.0 {
|
|
|
|
// Decide if you want upper- or lowercase results,
|
|
|
|
// padding the values to two characters, spaces
|
|
|
|
// between bytes, etc.
|
|
|
|
write!(f, "{:x}", byte)?;
|
2018-02-24 23:46:52 -08:00
|
|
|
}
|
2018-03-24 06:44:45 -07:00
|
|
|
Ok(())
|
2018-02-24 23:46:52 -08:00
|
|
|
}
|
2018-02-24 00:12:58 -08:00
|
|
|
}
|
|
|
|
|
2018-03-24 06:44:45 -07:00
|
|
|
impl<'a> fmt::UpperHex for HexSlice<'a> {
|
2018-02-24 23:46:52 -08:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
2018-03-24 06:44:45 -07:00
|
|
|
for byte in self.0 {
|
|
|
|
// Decide if you want upper- or lowercase results,
|
|
|
|
// padding the values to two characters, spaces
|
|
|
|
// between bytes, etc.
|
|
|
|
write!(f, "{:X}", byte)?;
|
2018-02-24 23:46:52 -08:00
|
|
|
}
|
2018-03-24 06:44:45 -07:00
|
|
|
Ok(())
|
2018-02-24 23:46:52 -08:00
|
|
|
}
|
2018-02-24 00:12:58 -08:00
|
|
|
}
|
2018-03-24 06:44:45 -07:00
|
|
|
// To hash this message structure, encode each element in the tuple
|
|
|
|
// as a byte stream, then apply a hash on it. Then, convert the output value into
|
|
|
|
// a Fr element.
|
2018-02-24 00:12:58 -08:00
|
|
|
|
2018-02-24 23:46:52 -08:00
|
|
|
pub fn misc_tests() {
|
|
|
|
let rng = &mut rand::thread_rng();
|
|
|
|
let a = Fr::random(rng);
|
|
|
|
// println!("crs = {}", stringify!(a));
|
|
|
|
// let limit = bincode::SizeLimit::Bounded(256);
|
|
|
|
let encoded: Vec<u8> = encode(&a, Infinite).unwrap();
|
|
|
|
println!("a length = {}", encoded.len());
|
|
|
|
println!("a = {:?}", encoded);
|
|
|
|
print!("a (hex) = 0x");
|
|
|
|
for x in encoded.iter() {
|
|
|
|
print!("{:x}", x);
|
|
|
|
}
|
|
|
|
print!("\n");
|
2018-02-24 00:12:58 -08:00
|
|
|
|
|
|
|
}
|
2018-02-24 23:46:52 -08:00
|
|
|
|
2018-04-07 12:01:27 -07:00
|
|
|
pub fn print(g: &G1) -> String {
|
|
|
|
let c_vec: Vec<u8> = encode(g, Infinite).unwrap();
|
|
|
|
let mut c_s = String::new();
|
|
|
|
for x in c_vec.iter() {
|
|
|
|
c_s = format!("{}{:x}", c_s, x);
|
|
|
|
}
|
|
|
|
|
|
|
|
return c_s;
|
|
|
|
}
|
|
|
|
|
2018-04-02 07:47:19 -07:00
|
|
|
////////////////////////////////// ZK proof compiler ///////////////////////////////////
|
|
|
|
|
|
|
|
//pub mod zkp {
|
|
|
|
//
|
|
|
|
//#[macro_export]
|
|
|
|
//macro_rules! log {
|
|
|
|
// ($msg:expr) => {{
|
|
|
|
// let state: i32 = get_log_state();
|
|
|
|
// if state > 0 {
|
|
|
|
// println!("log({}): {}", state, $msg);
|
|
|
|
// }
|
|
|
|
// }};
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//#[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))
|
|
|
|
// )
|
|
|
|
// ),+
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//#[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}
|
|
|
|
// 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 Fr,
|
|
|
|
// )+
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// #[derive(Copy, Clone)]
|
|
|
|
// pub struct Publics<'a> {
|
|
|
|
// // Create a parameter for each public value
|
|
|
|
// $(
|
|
|
|
// pub $public : &'a G1,
|
|
|
|
// )+
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// // 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: G1,)+ }
|
|
|
|
// struct Randomnesses {$($secret : Scalar,)+}
|
|
|
|
// #[derive(Serialize, Deserialize)]
|
|
|
|
// struct Responses {$($secret : Scalar,)+}
|
|
|
|
//
|
|
|
|
// #[derive(Serialize, Deserialize)]
|
|
|
|
// pub struct Proof {
|
|
|
|
// challenge: Fr,
|
|
|
|
// 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 : Fr::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.as_bytes());
|
|
|
|
// )+
|
|
|
|
// $(
|
|
|
|
// hash_state.update(commitments.$lhs.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.as_bytes());
|
|
|
|
// )+
|
|
|
|
// // Add each (recomputed) commitment into the hash
|
|
|
|
// $(
|
|
|
|
// hash_state.update(commitments.$lhs.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 : G1, )+ }
|
|
|
|
// let dummy_publics = DummyPublics {
|
|
|
|
// $( $public : G1::random(&mut rng) , )+
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
// let publics = Publics {
|
|
|
|
// $( $public : &dummy_publics.$public , )+
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
// struct DummySecrets { $( pub $secret : Fr, )+ }
|
|
|
|
// 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 : G1, )+ }
|
|
|
|
// let dummy_publics = DummyPublics {
|
|
|
|
// $( $public : G1::random(&mut rng) , )+
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
// let publics = Publics {
|
|
|
|
// $( $public : &dummy_publics.$public , )+
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
// struct DummySecrets { $( pub $secret : Fr, )+ }
|
|
|
|
// let dummy_secrets = DummySecrets {
|
|
|
|
// $( $secret : Fr::random(&mut rng) , )+
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
// let secrets = Secrets {
|
|
|
|
// $( $secret : &dummy_secrets.$secret , )+
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
// let p = Proof::create(&mut rng, publics, secrets);
|
|
|
|
//
|
|
|
|
// b.iter(|| p.verify(publics));
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
//}
|
|
|
|
//
|
|
|
|
//}
|
|
|
|
////////////////////////////////// ZK proof compiler ///////////////////////////////////
|
|
|
|
|
2018-03-24 21:03:59 -07:00
|
|
|
////////////////////////////////// SymKeyEnc ///////////////////////////////////
|
|
|
|
/*
|
|
|
|
Symmetric Key Encryption Scheme.
|
|
|
|
*/
|
2018-03-25 20:20:05 -07:00
|
|
|
//pub mod sym {
|
2018-03-24 21:03:59 -07:00
|
|
|
// use std::fmt;
|
2018-03-25 20:20:05 -07:00
|
|
|
// use sodiumoxide;
|
|
|
|
// use sodiumoxide::crypto::secretbox;
|
2018-03-24 21:03:59 -07:00
|
|
|
//
|
2018-03-25 20:20:05 -07:00
|
|
|
// pub struct SymCT {
|
|
|
|
// nonce: secretbox::Nonce,
|
|
|
|
// ciphertext: Vec<u8>
|
2018-03-24 21:03:59 -07:00
|
|
|
// }
|
|
|
|
//
|
|
|
|
//
|
2018-03-25 20:20:05 -07:00
|
|
|
// impl fmt::Display for SymCT {
|
2018-03-24 21:03:59 -07:00
|
|
|
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
// let mut y_s = String::new();
|
2018-03-25 20:20:05 -07:00
|
|
|
// for y in self.ciphertext.iter() {
|
2018-03-24 21:03:59 -07:00
|
|
|
// y_s = format!("{}{:x}", y_s, y);
|
|
|
|
// }
|
|
|
|
//
|
2018-03-25 20:20:05 -07:00
|
|
|
// write!(f, "CT : (ct=0x{})", y_s)
|
2018-03-24 21:03:59 -07:00
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// #[derive(Clone)]
|
2018-03-25 20:20:05 -07:00
|
|
|
// pub struct SymKey {
|
|
|
|
// key: secretbox::Key,
|
|
|
|
// l: i32
|
2018-03-24 21:03:59 -07:00
|
|
|
// }
|
|
|
|
//
|
2018-03-25 20:20:05 -07:00
|
|
|
// pub fn init() {
|
|
|
|
// sodiumoxide::init();
|
2018-03-24 21:03:59 -07:00
|
|
|
// }
|
|
|
|
//
|
2018-03-25 20:20:05 -07:00
|
|
|
// pub fn keygen(l: i32) -> SymKey {
|
|
|
|
// // TODO: make sure key is a l-bit key
|
|
|
|
// return SymKey { key: secretbox::gen_key(), l: l };
|
2018-03-24 21:03:59 -07:00
|
|
|
// }
|
|
|
|
//
|
2018-03-25 20:20:05 -07:00
|
|
|
// pub fn encrypt(key: &SymKey, plaintext: &String) -> SymCT {
|
|
|
|
// let nonce = secretbox::gen_nonce();
|
|
|
|
// let pt = plaintext.as_bytes();
|
|
|
|
// let ct = secretbox::seal(pt, &nonce, &key.key);
|
|
|
|
// return SymCT { nonce: nonce, ciphertext: ct };
|
2018-03-24 21:03:59 -07:00
|
|
|
// }
|
|
|
|
//
|
2018-03-25 20:20:05 -07:00
|
|
|
// pub fn decrypt(key: &SymKey, ciphertext: &SymCT) -> String {
|
|
|
|
// let nonce = ciphertext.nonce;
|
|
|
|
// let pt = secretbox::open(&ciphertext.ciphertext, &nonce, &key.key).unwrap();
|
|
|
|
// // TODO: investigate better error handling here
|
|
|
|
// let plaintext = String::from_utf8(pt).expect("Found invalid UTF-8");
|
|
|
|
// return plaintext;
|
2018-03-24 21:03:59 -07:00
|
|
|
// }
|
2018-03-25 20:20:05 -07:00
|
|
|
//}
|
|
|
|
|
|
|
|
////////////////////////////////// SymKeyEnc ///////////////////////////////////
|
|
|
|
|
|
|
|
////////////////////////////////// CL Sigs /////////////////////////////////////
|
|
|
|
|
2018-03-24 21:03:59 -07:00
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct RefundMessage<'a> {
|
|
|
|
prefix: &'a str, // string prefix for the prefix
|
|
|
|
c_id: Fr, // uniquely identifies the
|
|
|
|
index: i32, // index
|
|
|
|
// ck: Fr, // TODO: l-bit key (from SymKeyEnc)
|
|
|
|
}
|
2018-02-24 23:46:52 -08:00
|
|
|
|
2018-03-24 21:03:59 -07:00
|
|
|
impl<'a> RefundMessage<'a> {
|
|
|
|
pub fn new(_c_id: Fr, _index: i32) -> RefundMessage<'a> {
|
|
|
|
RefundMessage {
|
|
|
|
prefix: "refund", c_id: _c_id, index: _index,
|
2018-03-24 06:44:45 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-24 21:03:59 -07:00
|
|
|
pub fn hash(&self) -> Fr {
|
|
|
|
let mut input_buf = Vec::new();
|
|
|
|
input_buf.extend_from_slice(self.prefix.as_bytes());
|
|
|
|
let c_id_vec: Vec<u8> = encode(&self.c_id, Infinite).unwrap();
|
|
|
|
// encode cId in the vector
|
|
|
|
input_buf.extend(c_id_vec);
|
|
|
|
// encoee the balance as a hex string
|
|
|
|
let b = format!("{:x}", self.index);
|
|
|
|
input_buf.extend_from_slice(b.as_bytes());
|
|
|
|
// TODO: add the ck vector (l-bit key)
|
|
|
|
// let mut in_str = String::new();
|
|
|
|
// for y in input_buf.iter() {
|
|
|
|
// in_str = format!("{}{:x}", in_str, y);
|
|
|
|
// }
|
|
|
|
// println!("input_buf: {}", in_str);
|
|
|
|
|
|
|
|
// hash the inputs via SHA256
|
|
|
|
let sha2_digest = sha512::hash(input_buf.as_slice());
|
|
|
|
// println!("hash: {:?}", sha2_digest);
|
|
|
|
// let h = format!("{:x}", HexSlice::new(&sha2_digest));
|
|
|
|
let mut hash_buf: [u8; 64] = [0; 64];
|
|
|
|
hash_buf.copy_from_slice(&sha2_digest[0..64]);
|
|
|
|
return Fr::interpret(&hash_buf);
|
2018-03-24 06:44:45 -07:00
|
|
|
}
|
2018-03-24 21:03:59 -07:00
|
|
|
}
|
2018-03-24 06:44:45 -07:00
|
|
|
|
2018-03-24 21:03:59 -07:00
|
|
|
////////////////////////////////// CL Sigs /////////////////////////////////////
|
2018-03-24 06:44:45 -07:00
|
|
|
|
2018-03-24 21:03:59 -07:00
|
|
|
////////////////////////////////// COMMITMENT //////////////////////////////////
|
|
|
|
|
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
pub struct Message {
|
|
|
|
sk: clsigs::SecretKey, // the secret key for the signature scheme (Is it possible to make this a generic field?)
|
|
|
|
k1: Fr, // seed 1 for PRF
|
|
|
|
k2: Fr, // seed 2 for PRF
|
|
|
|
balance: i32 // the balance for the user
|
|
|
|
}
|
2018-03-24 06:44:45 -07:00
|
|
|
|
2018-03-24 21:03:59 -07:00
|
|
|
impl Message {
|
|
|
|
pub fn new(_sk: clsigs::SecretKey, _k1: Fr, _k2: Fr, _balance: i32) -> Message {
|
|
|
|
Message {
|
|
|
|
sk: _sk, k1: _k1, k2: _k2, balance: _balance,
|
2018-03-24 06:44:45 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-24 21:13:12 -07:00
|
|
|
pub fn hash(&self) -> Fr {
|
2018-03-24 21:03:59 -07:00
|
|
|
let mut input_buf = self.sk.encode();
|
|
|
|
// TODO: add sk_sigs to encode it
|
|
|
|
let k1_vec: Vec<u8> = encode(&self.k1, Infinite).unwrap();
|
|
|
|
let k2_vec: Vec<u8> = encode(&self.k2, Infinite).unwrap();
|
|
|
|
// encode k1 in the vector
|
|
|
|
input_buf.extend(k1_vec);
|
|
|
|
// encode k2 in the vector
|
|
|
|
input_buf.extend(k2_vec);
|
|
|
|
// encoee the balance as a hex string
|
|
|
|
let b = format!("{:x}", self.balance);
|
|
|
|
// println!("Balance: {}", b);
|
|
|
|
input_buf.extend_from_slice(b.as_bytes());
|
|
|
|
// let mut in_str = String::new();
|
|
|
|
// for y in input_buf.iter() {
|
|
|
|
// in_str = format!("{}{:x}", in_str, y);
|
|
|
|
// }
|
|
|
|
// println!("input_buf: {}", in_str);
|
|
|
|
|
|
|
|
// hash the inputs via SHA256
|
|
|
|
let sha2_digest = sha512::hash(input_buf.as_slice());
|
|
|
|
// println!("hash: {:?}", sha2_digest);
|
|
|
|
// let h = format!("{:x}", HexSlice::new(&sha2_digest));
|
|
|
|
let mut hash_buf: [u8; 64] = [0; 64];
|
|
|
|
hash_buf.copy_from_slice(&sha2_digest[0..64]);
|
|
|
|
return Fr::interpret(&hash_buf);
|
2018-03-24 06:44:45 -07:00
|
|
|
}
|
2018-03-24 21:03:59 -07:00
|
|
|
}
|
2018-03-24 06:44:45 -07:00
|
|
|
|
2018-03-25 20:20:05 -07:00
|
|
|
////////////////////////////////// COMMITMENT //////////////////////////////////
|
2018-03-24 06:44:45 -07:00
|
|
|
|
2018-03-25 20:20:05 -07:00
|
|
|
pub mod unidirectional {
|
|
|
|
use std::fmt;
|
|
|
|
use rand;
|
|
|
|
use bn::{Group, Fr};
|
2018-04-05 23:44:31 -07:00
|
|
|
use sym;
|
2018-03-25 20:20:05 -07:00
|
|
|
use commit_scheme;
|
|
|
|
use clsigs;
|
|
|
|
use Message;
|
2018-04-08 00:46:17 -07:00
|
|
|
use sodiumoxide::randombytes;
|
2018-03-25 20:20:05 -07:00
|
|
|
|
|
|
|
pub struct PublicParams {
|
|
|
|
cm_mpk: commit_scheme::PublicKey,
|
2018-04-05 23:44:31 -07:00
|
|
|
cl_mpk: clsigs::PublicParams,
|
|
|
|
l_bits: i32
|
2018-03-25 20:20:05 -07:00
|
|
|
// TODO: add NIZK proof system pub params
|
|
|
|
}
|
|
|
|
|
2018-04-05 23:44:31 -07:00
|
|
|
pub struct ChannelToken {
|
2018-03-25 20:20:05 -07:00
|
|
|
w_com: commit_scheme::Commitment,
|
|
|
|
pk: clsigs::PublicKey
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct CustSecretKey {
|
|
|
|
sk: clsigs::SecretKey, // the secret key for the signature scheme (Is it possible to make this a generic field?)
|
|
|
|
k1: Fr, // seed 1 for PRF
|
|
|
|
k2: Fr, // seed 2 for PRF
|
|
|
|
r: Fr, // random coins for commitment scheme
|
|
|
|
balance: i32, // the balance for the user
|
2018-04-05 23:44:31 -07:00
|
|
|
ck_vec: Vec<sym::SymKey>
|
2018-03-25 20:20:05 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
pub struct MerchSecretKey {
|
|
|
|
sk: clsigs::SecretKey,
|
|
|
|
balance: i32
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct InitCustomerData {
|
2018-04-05 23:44:31 -07:00
|
|
|
T: ChannelToken,
|
2018-03-25 20:20:05 -07:00
|
|
|
csk: CustSecretKey
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct InitMerchantData {
|
|
|
|
T: clsigs::PublicKey,
|
|
|
|
csk: MerchSecretKey
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn setup() -> PublicParams {
|
|
|
|
// TODO: provide option for generating CRS parameters
|
|
|
|
let cm_pk = commit_scheme::setup();
|
|
|
|
let cl_mpk = clsigs::setup();
|
2018-04-05 23:44:31 -07:00
|
|
|
let l = 256;
|
2018-03-25 20:20:05 -07:00
|
|
|
// let nizk = "nizk proof system";
|
2018-04-05 23:44:31 -07:00
|
|
|
let pp = PublicParams { cm_mpk: cm_pk, cl_mpk: cl_mpk, l_bits: l };
|
2018-03-25 20:20:05 -07:00
|
|
|
return pp;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn keygen(pp: &PublicParams) -> clsigs::KeyPair {
|
|
|
|
// TODO: figure out what we need from public params to generate keys
|
|
|
|
println!("Run Keygen...");
|
|
|
|
let keypair = clsigs::keygen(&pp.cl_mpk);
|
|
|
|
return keypair;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn init_customer(pp: &PublicParams, b0_customer: i32, keypair: &clsigs::KeyPair) -> InitCustomerData {
|
|
|
|
println!("Run Init customer...");
|
2018-04-05 23:44:31 -07:00
|
|
|
sym::init();
|
2018-03-25 20:20:05 -07:00
|
|
|
let rng = &mut rand::thread_rng();
|
|
|
|
// pick two distinct seeds
|
2018-04-05 23:44:31 -07:00
|
|
|
let l = 256;
|
2018-03-25 20:20:05 -07:00
|
|
|
let k1 = Fr::random(rng);
|
|
|
|
let k2 = Fr::random(rng);
|
|
|
|
let r = Fr::random(rng);
|
|
|
|
let msg = Message::new(keypair.sk, k1, k2, b0_customer).hash();
|
2018-04-05 23:44:31 -07:00
|
|
|
|
|
|
|
let mut ck_vec: Vec<sym::SymKey> = Vec::new();
|
|
|
|
// generate the vector ck of sym keys
|
|
|
|
for i in 1 .. b0_customer {
|
|
|
|
let ck = sym::keygen(l);
|
|
|
|
ck_vec.push(ck);
|
|
|
|
}
|
2018-03-25 20:20:05 -07:00
|
|
|
let w_com = commit_scheme::commit(&pp.cm_mpk, msg, Some(r));
|
2018-04-05 23:44:31 -07:00
|
|
|
let t_c = ChannelToken { w_com: w_com, pk: keypair.pk };
|
2018-03-25 20:20:05 -07:00
|
|
|
let csk_c = CustSecretKey { sk: keypair.sk, k1: k1, k2: k2, r: r, balance: b0_customer, ck_vec: ck_vec };
|
|
|
|
return InitCustomerData { T: t_c, csk: csk_c };
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn init_merchant(pp: &PublicParams, b0_merchant: i32, keypair: &clsigs::KeyPair) -> InitMerchantData {
|
|
|
|
println!("Run Init merchant...");
|
|
|
|
let csk_m = MerchSecretKey { sk: keypair.sk, balance: b0_merchant };
|
|
|
|
return InitMerchantData { T: keypair.pk, csk: csk_m };
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: requires NIZK proof system
|
2018-04-08 00:46:17 -07:00
|
|
|
pub fn establish_customer_send(pp: &PublicParams, t_m: &clsigs::PublicKey, csk_c: &CustSecretKey) {
|
2018-03-25 20:20:05 -07:00
|
|
|
println ! ("Run establish_customer algorithm...");
|
2018-04-05 23:44:31 -07:00
|
|
|
// set sk_0 to random bytes of length l
|
|
|
|
// let sk_0 = random_bytes(pp.l);
|
2018-04-08 00:46:17 -07:00
|
|
|
let buf_len: usize = pp.l_bits as usize;
|
|
|
|
let mut sk0 = vec![0; buf_len];
|
|
|
|
randombytes::randombytes_into(&mut sk0);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn estalibsh_mercahnt_send() {
|
2018-03-25 20:20:05 -07:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: requires NIZK proof system calls
|
|
|
|
pub fn pay() {
|
|
|
|
println!("Run pay algorithm...");
|
|
|
|
}
|
|
|
|
|
2018-04-02 07:47:19 -07:00
|
|
|
// pub fn refund(pp: &PublicParams, imd : &InitMerchantData, w: Wallet) {
|
2018-03-25 20:20:05 -07:00
|
|
|
// println!("Run Refund...");
|
2018-03-24 21:03:59 -07:00
|
|
|
// }
|
|
|
|
//
|
2018-03-25 20:20:05 -07:00
|
|
|
// pub fn refute() {
|
|
|
|
// println!("Run Refute...");
|
2018-03-24 21:03:59 -07:00
|
|
|
// }
|
|
|
|
//
|
2018-03-25 20:20:05 -07:00
|
|
|
// pub fn resolve() {
|
|
|
|
// println!("Run Resolve...");
|
2018-03-24 21:03:59 -07:00
|
|
|
// }
|
2018-03-25 20:20:05 -07:00
|
|
|
}
|