diff --git a/src/ghash/mod.rs b/src/ghash/mod.rs index 41031ea..7f1ace7 100644 --- a/src/ghash/mod.rs +++ b/src/ghash/mod.rs @@ -1,73 +1,100 @@ //! This module is a testing ground for the GHASH protocol (page 36) from -use mpz_share_conversion_core::fields::{gf2_128::Gf2_128, UniformRand}; -use rand::thread_rng; +mod prover; +mod verifier; -use crate::ole::{Ole, Role}; +use mpz_share_conversion_core::{ + fields::{gf2_128::Gf2_128, UniformRand}, + Field, +}; +pub use prover::Prover; +pub use verifier::Verifier; -#[derive(Debug)] -pub struct Prover { - block_num: usize, - h1: Gf2_128, - r1: Gf2_128, - ai: Vec, +use crate::ole::Ole; + +pub fn ghash(blocks: Vec) -> Gf2_128 { + let mut rng = rand::thread_rng(); + let mut prover = Prover::new(blocks.len(), Gf2_128::rand(&mut rng)); + let mut verifier = Verifier::new(blocks.len(), Gf2_128::rand(&mut rng)); + + let mut ole = Ole::default(); + + prover.preprocess_ole_input(&mut ole); + verifier.preprocess_ole_input(&mut ole); + + prover.preprocess_ole_output(&mut ole); + verifier.preprocess_ole_output(&mut ole); + + let d1 = prover.handshake_a_open_d(); + let d2 = verifier.handshake_a_open_d(); + let d = d1 + d2; + + prover.handshake_a_set_d(d); + verifier.handshake_a_set_d(d); + + prover.handshake_a_set_hi(); + verifier.handshake_a_set_hi(); + + let ghash1 = prover.handshake_output_ghash(&blocks); + let ghash2 = verifier.handshake_output_ghash(&blocks); + + ghash1 + ghash2 } -impl Prover { - pub fn new(block_num: usize, h1: Gf2_128) -> Self { - let mut rng = thread_rng(); - let r1 = Gf2_128::rand(&mut rng); - Self { - block_num, - h1, - r1, - ai: vec![], - } - } +fn pascal_tri(n: usize) -> Vec> { + let mut pascal = vec![vec![T::one()]]; - pub fn preprocess_ole_input(&self, ole: &mut Ole) { - let mut r1_powers = vec![Gf2_128::new(1)]; + for _ in 0..n { + let last_row = pascal.last().unwrap(); + let mut new_row = vec![T::one()]; - for k in 0..self.block_num { - r1_powers.push(self.r1 * r1_powers[k]); - } - ole.input(Role::Sender, r1_powers) - } - - pub fn preprocess_ole_output(&mut self, ole: &mut Ole) { - self.ai = ole.output(Role::Sender); + last_row + .iter() + .map_windows(|[&a, &b]| a + b) + .for_each(|el| { + new_row.push(el); + }); + new_row.push(T::one()); + pascal.push(new_row); } + pascal } -pub struct Verifier { - block_num: usize, - h2: Gf2_128, - r2: Gf2_128, - bi: Vec, -} +#[cfg(test)] +mod tests { + use super::*; + use mpz_share_conversion_core::fields::p256::P256; -impl Verifier { - pub fn new(block_num: usize, h2: Gf2_128) -> Self { - let mut rng = thread_rng(); - let r2 = Gf2_128::rand(&mut rng); - Self { - block_num, - h2, - r2, - bi: vec![], - } + #[test] + fn test_ghash() { + todo!() } - pub fn preprocess_ole_input(&self, ole: &mut Ole) { - let mut r2_powers = vec![Gf2_128::new(1)]; + #[test] + fn test_pascal_tri() { + let pascal = pascal_tri::(4); - for k in 0..self.block_num { - r2_powers.push(self.r2 * r2_powers[k]); - } - ole.input(Role::Receiver, r2_powers) - } + let expected0 = vec![P256::one()]; + let expected1 = vec![P256::one(), P256::one()]; + let expected2 = vec![P256::one(), P256::new(2).unwrap(), P256::one()]; + let expected3 = vec![ + P256::one(), + P256::new(3).unwrap(), + P256::new(3).unwrap(), + P256::one(), + ]; + let expected4 = vec![ + P256::one(), + P256::new(4).unwrap(), + P256::new(6).unwrap(), + P256::new(4).unwrap(), + P256::one(), + ]; - pub fn preprocess_ole_output(&mut self, ole: &mut Ole) { - self.bi = ole.output(Role::Receiver); + assert_eq!(pascal[0], expected0); + assert_eq!(pascal[1], expected1); + assert_eq!(pascal[2], expected2); + assert_eq!(pascal[3], expected3); + assert_eq!(pascal[4], expected4); } } diff --git a/src/ghash/prover.rs b/src/ghash/prover.rs new file mode 100644 index 0000000..2888343 --- /dev/null +++ b/src/ghash/prover.rs @@ -0,0 +1,71 @@ +use super::pascal_tri; +use crate::ole::{Ole, Role}; +use mpz_share_conversion_core::fields::{compute_product_repeated, gf2_128::Gf2_128, UniformRand}; +use rand::thread_rng; + +#[derive(Debug)] +pub struct Prover { + block_num: usize, + h1: Gf2_128, + r1: Gf2_128, + ai: Vec, + d: Option, + hi: Vec, +} + +impl Prover { + pub fn new(block_num: usize, h1: Gf2_128) -> Self { + let mut rng = thread_rng(); + let r1 = Gf2_128::rand(&mut rng); + + Self { + block_num, + h1, + r1, + ai: vec![], + d: None, + hi: vec![], + } + } + + pub fn preprocess_ole_input(&self, ole: &mut Ole) { + let mut r1_powers = vec![Gf2_128::new(1)]; + + compute_product_repeated(&mut r1_powers, self.r1, self.block_num); + ole.input(Role::Sender, r1_powers) + } + + pub fn preprocess_ole_output(&mut self, ole: &mut Ole) { + self.ai = ole.output(Role::Sender); + } + + pub fn handshake_a_open_d(&self) -> Gf2_128 { + self.h1 + -self.r1 + } + + pub fn handshake_a_set_d(&mut self, d: Gf2_128) { + self.d = Some(d); + } + + pub fn handshake_a_set_hi(&mut self) { + let mut di = vec![Gf2_128::new(1)]; + compute_product_repeated(&mut di, self.d.unwrap(), self.block_num); + + let pascal_tri = pascal_tri::(self.block_num); + + for k in 0..self.block_num { + for el in pascal_tri[k].iter() { + self.hi.push(*el * di[k] * self.ai[self.block_num - k]); + } + } + } + + pub fn handshake_output_ghash(&self, blocks: &[Gf2_128]) -> Gf2_128 { + let mut res = Gf2_128::new(0); + + for (i, block) in blocks.iter().enumerate() { + res = res + *block * self.hi[i]; + } + res + } +} diff --git a/src/ghash/verifier.rs b/src/ghash/verifier.rs new file mode 100644 index 0000000..ceb7712 --- /dev/null +++ b/src/ghash/verifier.rs @@ -0,0 +1,71 @@ +use super::pascal_tri; +use crate::ole::{Ole, Role}; +use mpz_share_conversion_core::fields::{compute_product_repeated, gf2_128::Gf2_128, UniformRand}; +use rand::thread_rng; + +#[derive(Debug)] +pub struct Verifier { + block_num: usize, + h2: Gf2_128, + r2: Gf2_128, + bi: Vec, + d: Option, + hi: Vec, +} + +impl Verifier { + pub fn new(block_num: usize, h2: Gf2_128) -> Self { + let mut rng = thread_rng(); + let r2 = Gf2_128::rand(&mut rng); + + Self { + block_num, + h2, + r2, + bi: vec![], + d: None, + hi: vec![], + } + } + + pub fn preprocess_ole_input(&self, ole: &mut Ole) { + let mut r2_powers = vec![Gf2_128::new(1)]; + + compute_product_repeated(&mut r2_powers, self.r2, self.block_num); + ole.input(Role::Receiver, r2_powers) + } + + pub fn preprocess_ole_output(&mut self, ole: &mut Ole) { + self.bi = ole.output(Role::Receiver); + } + + pub fn handshake_a_open_d(&self) -> Gf2_128 { + self.h2 + -self.r2 + } + + pub fn handshake_a_set_d(&mut self, d: Gf2_128) { + self.d = Some(d); + } + + pub fn handshake_a_set_hi(&mut self) { + let mut di = vec![Gf2_128::new(1)]; + compute_product_repeated(&mut di, self.d.unwrap(), self.block_num); + + let pascal_tri = pascal_tri::(self.block_num); + + for k in 0..self.block_num { + for el in pascal_tri[k].iter() { + self.hi.push(*el * di[k] * self.bi[self.block_num - k]); + } + } + } + + pub fn handshake_output_ghash(&self, blocks: &[Gf2_128]) -> Gf2_128 { + let mut res = Gf2_128::new(0); + + for (i, block) in blocks.iter().enumerate() { + res = res + *block * self.hi[i]; + } + res + } +} diff --git a/src/lib.rs b/src/lib.rs index aa7f06e..e121b1d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ //! This crate is for testing TLSNotary sub protocols based on OLE, and check their security properties. +#![feature(iter_map_windows)] pub mod e2f; pub mod ghash;