Added ghash protocol

This commit is contained in:
th4s
2023-12-13 02:02:35 +01:00
parent 7ed549569e
commit 589cdfd55b
4 changed files with 225 additions and 55 deletions

View File

@@ -1,73 +1,100 @@
//! This module is a testing ground for the GHASH protocol (page 36) from <https://eprint.iacr.org/2023/964>
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<Gf2_128>,
use crate::ole::Ole;
pub fn ghash(blocks: Vec<Gf2_128>) -> 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<T: Field>(n: usize) -> Vec<Vec<T>> {
let mut pascal = vec![vec![T::one()]];
pub fn preprocess_ole_input(&self, ole: &mut Ole<Gf2_128>) {
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<Gf2_128>) {
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<Gf2_128>,
}
#[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<Gf2_128>) {
let mut r2_powers = vec![Gf2_128::new(1)];
#[test]
fn test_pascal_tri() {
let pascal = pascal_tri::<P256>(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<Gf2_128>) {
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);
}
}

71
src/ghash/prover.rs Normal file
View File

@@ -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<Gf2_128>,
d: Option<Gf2_128>,
hi: Vec<Gf2_128>,
}
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<Gf2_128>) {
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<Gf2_128>) {
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::<Gf2_128>(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
}
}

71
src/ghash/verifier.rs Normal file
View File

@@ -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<Gf2_128>,
d: Option<Gf2_128>,
hi: Vec<Gf2_128>,
}
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<Gf2_128>) {
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<Gf2_128>) {
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::<Gf2_128>(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
}
}

View File

@@ -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;