diff --git a/.idea/libraries/Cargo__libbolt_.xml b/.idea/libraries/Cargo__libbolt_.xml index 9732714..d3fb7a5 100644 --- a/.idea/libraries/Cargo__libbolt_.xml +++ b/.idea/libraries/Cargo__libbolt_.xml @@ -1,34 +1,34 @@ - - - - - - - - - + - + + + + + + + + + + + + + + + - + + - - - - + + - - - - - diff --git a/bin/bolt.rs b/bin/bolt.rs index b3fc900..bca1464 100644 --- a/bin/bolt.rs +++ b/bin/bolt.rs @@ -6,11 +6,14 @@ extern crate bincode; extern crate serde_derive; extern crate serde; +use std::fmt; use bn::{Group, Fr, G1, G2, pairing}; use bincode::SizeLimit::Infinite; use bincode::rustc_serialize::{encode, decode}; +use libbolt::prf; use libbolt::sym; +use libbolt::ote; use libbolt::clsigs; use libbolt::commit_scheme; @@ -315,6 +318,14 @@ fn main() { println!("******************************************"); + let s = Fr::random(rng); + let key = prf::initPRF(s, None); + + let x = Fr::random(rng); + let y = prf::compute(&key, x); + + println!("Compute y = 0x{}", libbolt::print(&y)); + // let rng = &mut rand::thread_rng(); // let G = G1::random(rng); // &dalek_constants::RISTRETTO_BASEPOINT_POINT; // let H = G1::random(rng); // RistrettoPoint::hash_from_bytes::(G.compress().as_bytes()); diff --git a/docs/bolt_design.tex b/docs/bolt_design.tex index 206158a..7d1b68a 100644 --- a/docs/bolt_design.tex +++ b/docs/bolt_design.tex @@ -243,20 +243,20 @@ ${\sf KeyGen}(PP) \rightarrow (pk, sk)$. \end{itemize} \medskip \noindent -${\sf Init_{C}}(PP, BC_{0}, BM_{0}, pk_c, sk_c) \rightarrow (T_c, csk_c)$. On input a keypair $(pk_c, sk_c)$, perform the following: +${\sf Init_{C}}(PP, BC_{0}, BM_{0}, pk_c, sk_c) \rightarrow ({\sf T}_c, csk_c)$. On input a keypair $(pk_c, sk_c)$, perform the following: \begin{itemize} \item Uniformly sample two distinct PRF seeds $k_1, k_2$ and random coins $r$ for the commitment scheme. \item Compute ${\sf wCom} = {\sf Commit}(sk_c, k_1, k_2, BC_{0}; r)$ -\item For $i = 1$ to $BC_0$, sample $ck_i \rightarrow {\sf SymKeyGen}(1^\lambda)$ to form the vector $ck$. -\item Output $T_c = ({\sf wCom}, pk_c)$ and $csk_c = (sk_c, k_1, k_2, r, BC_{0}, ck)$. +\item For $i = 1$ to $BC_0$, sample $ck_i \rightarrow {\sf SymKeyGen}(1^\lambda)$ to form the vector $\vec{ck}$. +\item Output ${\sf T}_c = ({\sf wCom}, pk_c)$ and $csk_c = (sk_c, k_1, k_2, r, BC_{0}, \vec{ck})$. \end{itemize} \medskip \noindent -${\sf Init_{M}}(PP, BC_{0}, BM_{0}, pk_m, sk_m) \rightarrow T_m, csk_m$. On input a keypair $(pk_m, sk_m)$, perform the following: +${\sf Init_{M}}(PP, BC_{0}, BM_{0}, pk_m, sk_m) \rightarrow {\sf T}_m, csk_m$. On input a keypair $(pk_m, sk_m)$, perform the following: \begin{itemize} -\item Output $T_m = pk_m$ and $csk_m = (sk_m, BC_{0})$. +\item Output ${\sf T}_m = pk_m$ and $csk_m = (sk_m, BC_{0})$. \end{itemize} diff --git a/src/clsigs.rs b/src/clsigs.rs index f099975..e426b42 100644 --- a/src/clsigs.rs +++ b/src/clsigs.rs @@ -111,7 +111,7 @@ pub fn keygen(mpk : &PublicParams) -> KeyPair { pub fn sign(sk: &SecretKey, m: Fr) -> Signature { let rng = &mut rand::thread_rng(); let a = G2::random(rng); - //let m = msg.hash(); + let b = a * sk.y; let c = a * (sk.x + (m * sk.x * sk.y)); let sig = Signature { a: a, b: b, c: c }; @@ -119,7 +119,6 @@ pub fn sign(sk: &SecretKey, m: Fr) -> Signature { } pub fn verify(mpk: &PublicParams, pk: &PublicKey, m: Fr, sig: &Signature) -> bool { - //let m = msg.hash(); let lhs1 = pairing(pk.Y, sig.a); let rhs1 = pairing(mpk.g, sig.b); let lhs2 = pairing(pk.X, sig.a) * (pairing(pk.X, sig.b).pow(m)); diff --git a/src/commit_scheme.rs b/src/commit_scheme.rs index 73d31bc..1b62558 100644 --- a/src/commit_scheme.rs +++ b/src/commit_scheme.rs @@ -85,7 +85,7 @@ pub fn commit(pk: &PublicKey, m: Fr, R: Option) -> Commitment { //let m = msg.hash(); let p = "commit -> m"; debug_elem_in_hex(p, &m); - + // c = g^m * h^r let c = (pk.g * m) + (pk.h * r); // return (c, r) <- d=r let commitment = Commitment { c: c, d: r }; diff --git a/src/lib.rs b/src/lib.rs index e01302c..e554d2d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,7 +11,9 @@ use bincode::SizeLimit::Infinite; use bincode::rustc_serialize::{encode, decode}; use sodiumoxide::crypto::hash::sha512; +pub mod prf; pub mod sym; +pub mod ote; pub mod clsigs; pub mod commit_scheme; @@ -86,6 +88,16 @@ pub fn misc_tests() { } +pub fn print(g: &G1) -> String { + let c_vec: Vec = 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; +} + ////////////////////////////////// ZK proof compiler /////////////////////////////////// //pub mod zkp { @@ -429,44 +441,6 @@ pub fn misc_tests() { ////////////////////////////////// SymKeyEnc /////////////////////////////////// -////////////////////////////////// OTEnc /////////////////////////////////////// - -// TODO: implement this next -pub mod ot { - use std::fmt; - use rand; - use bn::{Group, Fr, G1, G2}; - - pub fn keygen() { - - } - - // encryption scheme can be implemented by encoding the plaintext as an element in a cyclic group G - // and multiplying by a random group element. - - // Our schemes additionally require a one-time encryption algorithm OTEnc where the keyspace - // of the algorithm is also the range of the pseudorandom function F. -// pub fn encrypt(pk: G1, plaintext: String) { -// let rng = &mut rand::thread_rng(); -// r = G1::random(rng); -// // TODO: encode plaintext as a group element -// -// } - - pub fn decrypt() { - - } -} - -////////////////////////////////// OTEnc /////////////////////////////////////// - -pub mod prf { - use std::fmt; - use bn::{Group, Fr, G1, G2}; - - -} - ////////////////////////////////// CL Sigs ///////////////////////////////////// #[derive(Clone)] diff --git a/src/ote.rs b/src/ote.rs new file mode 100644 index 0000000..81af44f --- /dev/null +++ b/src/ote.rs @@ -0,0 +1,38 @@ +/* + One-time encryption - keyspace of the OTE is also the range of the pseudo-random function +*/ + +use std::fmt; +use bn::{Group, Fr, G1}; +use rand; + +pub struct OTMessage { + m1: G1, + m2: G1 +} + +pub struct OTCiphertext { + c1: G1, + c2: G1 +} + +pub fn keygen() -> G1 { + let rng = &mut rand::thread_rng(); + let k = G1::random(rng); + return k; +} + +// encryption scheme can be implemented by encoding the plaintext as an element in a cyclic group G +// and multiplying by a random group element. +pub fn otenc(k: G1, m: &OTMessage) -> OTCiphertext { + let c1 = k + m.m1; + let c2 = k + m.m2; + assert!(c1 != c2); + return OTCiphertext { c1: c1, c2: c2 }; +} + +pub fn otdec(k: G1, c: &OTCiphertext) -> OTMessage { + let X = c.c1 - k; + let Y = c.c2 - k; + return OTMessage { m1: X, m2: Y}; +} diff --git a/src/prf.rs b/src/prf.rs new file mode 100644 index 0000000..cd1f195 --- /dev/null +++ b/src/prf.rs @@ -0,0 +1,25 @@ +/* + Pseudo-random Function (PRF) using Dodis-Yampolskiy PRF to support proofs of knowledge. + Properties: + - strong pr-image resistance +*/ +use rand; +use bn::{Group, Fr, G1}; + +pub struct PRFKey { + s: Fr, + g: G1 +} + +// initialize the PRF with a seed and an optional generator +pub fn initPRF(s: Fr, G: Option) -> PRFKey { + let rng = &mut rand::thread_rng(); + let g = G.unwrap_or(G1::random(rng)); + return PRFKey { s: s, g: g }; +} + +// compute the PRF given the key and an input +pub fn compute(key: &PRFKey, x: Fr) -> G1 { + let r = key.s + x; + return key.g * r.inverse().unwrap(); +} \ No newline at end of file