mirror of
https://github.com/tlsnotary/ole-protocols.git
synced 2026-01-08 22:18:07 -05:00
Added ghash protocol
This commit is contained in:
137
src/ghash/mod.rs
137
src/ghash/mod.rs
@@ -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
71
src/ghash/prover.rs
Normal 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
71
src/ghash/verifier.rs
Normal 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
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user