mirror of
https://github.com/tlsnotary/ole-protocols.git
synced 2026-01-09 14:37:54 -05:00
impl ole with rot
This commit is contained in:
227
src/e2f/mod.rs
227
src/e2f/mod.rs
@@ -1,227 +0,0 @@
|
||||
//! This module is a testing ground for the E2F protocol (page 33) from <https://eprint.iacr.org/2023/964>
|
||||
|
||||
mod prover;
|
||||
mod verifier;
|
||||
|
||||
use crate::func::ole::Ole;
|
||||
use mpz_share_conversion_core::fields::p256::P256;
|
||||
pub use prover::Prover;
|
||||
pub use verifier::Verifier;
|
||||
|
||||
/// Returns the x-coordinate shares of the sum of the two EC points
|
||||
pub fn e2f(
|
||||
prover_point: (P256, P256),
|
||||
prover: &mut Prover,
|
||||
verifier_point: (P256, P256),
|
||||
verifier: &mut Verifier,
|
||||
) -> (P256, P256) {
|
||||
let mut ole = Ole::default();
|
||||
|
||||
// Preprocessing
|
||||
prover.preprocess1();
|
||||
verifier.preprocess1();
|
||||
|
||||
prover.preprocess2_ole_input(&mut ole);
|
||||
verifier.preprocess2_ole_input(&mut ole);
|
||||
|
||||
prover.preprocess2_ole_output(&mut ole);
|
||||
verifier.preprocess2_ole_output(&mut ole);
|
||||
|
||||
prover.preprocess3();
|
||||
verifier.preprocess3();
|
||||
|
||||
prover.preprocess4();
|
||||
verifier.preprocess4();
|
||||
|
||||
// Handshake
|
||||
prover.handshake5_input_ec(prover_point);
|
||||
verifier.handshake5_input_ec(verifier_point);
|
||||
|
||||
let varespilon1_share_prover = prover.handshake5_varepsilon1_share_open();
|
||||
let varespilon1_share_verifier = verifier.handshake5_varepsilon1_share_open();
|
||||
let varepsilon1 = varespilon1_share_prover + varespilon1_share_verifier;
|
||||
|
||||
prover.handshake5_set_omega(varepsilon1);
|
||||
verifier.handshake5_set_omega(varepsilon1);
|
||||
|
||||
let omega_share_prover = prover.handshake6_omega_share_open();
|
||||
let omega_share_verifier = verifier.handshake6_omega_share_open();
|
||||
let omega = omega_share_prover + omega_share_verifier;
|
||||
|
||||
let varespilon2_share_prover = prover.handshake6_varepsilon2_share_open();
|
||||
let varespilon2_share_verifier = verifier.handshake6_varepsilon2_share_open();
|
||||
let varepsilon2 = varespilon2_share_prover + varespilon2_share_verifier;
|
||||
|
||||
prover.handshake6_set_eta(omega, varepsilon2);
|
||||
verifier.handshake6_set_eta(omega, varepsilon2);
|
||||
|
||||
let varepsilon3_share_prover = prover.handshake7_varepsilon3_share_open();
|
||||
let varepsilon3_share_verifier = verifier.handshake7_varepsilon3_share_open();
|
||||
let varepsilon3 = varepsilon3_share_prover + varepsilon3_share_verifier;
|
||||
|
||||
prover.handshake7_set_z1(varepsilon3);
|
||||
verifier.handshake7_set_z2(varepsilon3);
|
||||
|
||||
// Output
|
||||
let z1 = prover.handshake8_z1_open();
|
||||
let z2 = verifier.handshake8_z2_open();
|
||||
|
||||
(z1, z2)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use mpz_share_conversion_core::Field;
|
||||
use p256::{elliptic_curve::sec1::ToEncodedPoint, EncodedPoint, NonZeroScalar, PublicKey};
|
||||
use rand::thread_rng;
|
||||
|
||||
#[test]
|
||||
fn test_e2f() {
|
||||
let mut rng = thread_rng();
|
||||
let prover_scalar = NonZeroScalar::random(&mut rng);
|
||||
let verifier_scalar = NonZeroScalar::random(&mut rng);
|
||||
|
||||
let prover_ec = point_to_p256(scalar_to_encoded_point(prover_scalar));
|
||||
let mut prover = Prover::default();
|
||||
|
||||
let verifier_ec = point_to_p256(scalar_to_encoded_point(verifier_scalar));
|
||||
let mut verifier = Verifier::default();
|
||||
|
||||
let (z1, z2) = e2f(prover_ec, &mut prover, verifier_ec, &mut verifier);
|
||||
|
||||
let x_ec_expected = add_ec_points(prover_ec, verifier_ec);
|
||||
assert_eq!(z1 + z2, x_ec_expected.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sharing_sums() {
|
||||
let mut rng = thread_rng();
|
||||
let prover_scalar = NonZeroScalar::random(&mut rng);
|
||||
let verifier_scalar = NonZeroScalar::random(&mut rng);
|
||||
|
||||
let prover_ec = point_to_p256(scalar_to_encoded_point(prover_scalar));
|
||||
let mut prover = Prover::default();
|
||||
|
||||
let verifier_ec = point_to_p256(scalar_to_encoded_point(verifier_scalar));
|
||||
let mut verifier = Verifier::default();
|
||||
|
||||
let _ = e2f(prover_ec, &mut prover, verifier_ec, &mut verifier);
|
||||
|
||||
// Assertions
|
||||
|
||||
// c
|
||||
let c = prover.a1.unwrap() * prover.b1.unwrap()
|
||||
+ prover.a1_b2_share.unwrap()
|
||||
+ prover.a2_b1_share.unwrap()
|
||||
+ verifier.a2_b1_share.unwrap()
|
||||
+ verifier.a1_b2_share.unwrap()
|
||||
+ verifier.a2.unwrap() * verifier.b2.unwrap();
|
||||
assert_eq!(prover.c1.unwrap() + verifier.c2.unwrap(), c);
|
||||
|
||||
// c_prime
|
||||
let c_prime = prover.a1.unwrap() * prover.b1_prime.unwrap()
|
||||
+ prover.a1_b2_prime_share.unwrap()
|
||||
+ prover.a2_b1_prime_share.unwrap()
|
||||
+ verifier.a2_b1_prime_share.unwrap()
|
||||
+ verifier.a1_b2_prime_share.unwrap()
|
||||
+ verifier.a2.unwrap() * verifier.b2_prime.unwrap();
|
||||
assert_eq!(
|
||||
prover.c1_prime.unwrap() + verifier.c2_prime.unwrap(),
|
||||
c_prime
|
||||
);
|
||||
|
||||
// r_squared
|
||||
let r_squared = prover.r1.unwrap() * prover.r1.unwrap()
|
||||
+ P256::new(2).unwrap() * (prover.r1_r2_share.unwrap() + verifier.r1_r2_share.unwrap())
|
||||
+ verifier.r2.unwrap() * verifier.r2.unwrap();
|
||||
assert_eq!(
|
||||
prover.r_squared_share.unwrap() + verifier.r_squared_share.unwrap(),
|
||||
r_squared
|
||||
);
|
||||
|
||||
// omega
|
||||
let b = prover.b1.unwrap() + verifier.b2.unwrap();
|
||||
let varepsilon1 = -prover.ec_point.unwrap().0 + verifier.ec_point.unwrap().0 + -b;
|
||||
let omega = varepsilon1 * (prover.a1.unwrap() + verifier.a2.unwrap())
|
||||
+ prover.c1.unwrap()
|
||||
+ verifier.c2.unwrap();
|
||||
assert_eq!(
|
||||
prover.omega_share.unwrap() + verifier.omega_share.unwrap(),
|
||||
omega
|
||||
);
|
||||
|
||||
// eta
|
||||
let b_prime = prover.b1_prime.unwrap() + verifier.b2_prime.unwrap();
|
||||
let varepsilon2 = -prover.ec_point.unwrap().1 + verifier.ec_point.unwrap().1 + -b_prime;
|
||||
let eta = (prover.omega_share.unwrap() + verifier.omega_share.unwrap()).inverse()
|
||||
* (varepsilon2 * (prover.a1.unwrap() + verifier.a2.unwrap())
|
||||
+ prover.c1_prime.unwrap()
|
||||
+ verifier.c2_prime.unwrap());
|
||||
assert_eq!(prover.eta_share.unwrap() + verifier.eta_share.unwrap(), eta);
|
||||
|
||||
// z
|
||||
let varepsilon3 = prover.eta_share.unwrap()
|
||||
+ verifier.eta_share.unwrap()
|
||||
+ -prover.r1.unwrap()
|
||||
+ -verifier.r2.unwrap();
|
||||
let z = varepsilon3 * varepsilon3
|
||||
+ P256::new(2).unwrap() * varepsilon3 * (prover.r1.unwrap() + verifier.r2.unwrap())
|
||||
+ prover.r_squared_share.unwrap()
|
||||
+ verifier.r_squared_share.unwrap()
|
||||
+ -prover.ec_point.unwrap().0
|
||||
+ -verifier.ec_point.unwrap().0;
|
||||
assert_eq!(prover.z1.unwrap() + verifier.z2.unwrap(), z);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_ec_points() {
|
||||
let mut rng = thread_rng();
|
||||
let scalar1 = p256::NonZeroScalar::random(&mut rng);
|
||||
let scalar2 = p256::NonZeroScalar::random(&mut rng);
|
||||
|
||||
let pk1 = PublicKey::from_secret_scalar(&scalar1);
|
||||
let pk2 = PublicKey::from_secret_scalar(&scalar2);
|
||||
let pr1 = pk1.to_projective();
|
||||
let pr2 = pk2.to_projective();
|
||||
|
||||
let ec_added_expected = point_to_p256((pr1 + pr2).to_affine().to_encoded_point(false));
|
||||
|
||||
let ec1 = pr1.to_affine().to_encoded_point(false);
|
||||
let ec2 = pr2.to_affine().to_encoded_point(false);
|
||||
let ec_added = add_ec_points(point_to_p256(ec1), point_to_p256(ec2));
|
||||
|
||||
assert_eq!(ec_added, ec_added_expected);
|
||||
}
|
||||
|
||||
fn add_ec_points((x1, y1): (P256, P256), (x2, y2): (P256, P256)) -> (P256, P256) {
|
||||
let nominator = y2 + -y1;
|
||||
let denominator = x2 + -x1;
|
||||
|
||||
let fraction = nominator * denominator.inverse();
|
||||
let squared = fraction * fraction;
|
||||
|
||||
let x_r = squared + -x1 + -x2;
|
||||
let y_r = fraction * (x1 + -x_r) + -y1;
|
||||
|
||||
(x_r, y_r)
|
||||
}
|
||||
|
||||
fn scalar_to_encoded_point(scalar: NonZeroScalar) -> EncodedPoint {
|
||||
PublicKey::from_secret_scalar(&scalar).to_encoded_point(false)
|
||||
}
|
||||
|
||||
fn point_to_p256(point: EncodedPoint) -> (P256, P256) {
|
||||
let mut x: [u8; 32] = (*point.x().unwrap()).into();
|
||||
let mut y: [u8; 32] = (*point.y().unwrap()).into();
|
||||
|
||||
// reverse to little endian
|
||||
x.reverse();
|
||||
y.reverse();
|
||||
|
||||
let x = P256::try_from(x).unwrap();
|
||||
let y = P256::try_from(y).unwrap();
|
||||
|
||||
(x, y)
|
||||
}
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
//! The prover implementation
|
||||
|
||||
use crate::func::ole::Ole;
|
||||
use crate::func::Role;
|
||||
use mpz_share_conversion_core::fields::{p256::P256, Field, UniformRand};
|
||||
use rand::thread_rng;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Prover {
|
||||
// Preprocess 1
|
||||
pub(crate) a1: Option<P256>,
|
||||
pub(crate) b1: Option<P256>,
|
||||
pub(crate) b1_prime: Option<P256>,
|
||||
pub(crate) r1: Option<P256>,
|
||||
|
||||
// Preprocess 2
|
||||
pub(crate) a1_b2_share: Option<P256>,
|
||||
pub(crate) a2_b1_share: Option<P256>,
|
||||
pub(crate) a1_b2_prime_share: Option<P256>,
|
||||
pub(crate) a2_b1_prime_share: Option<P256>,
|
||||
pub(crate) r1_r2_share: Option<P256>,
|
||||
|
||||
// Preprocess 3
|
||||
pub(crate) c1: Option<P256>,
|
||||
pub(crate) c1_prime: Option<P256>,
|
||||
|
||||
// Preprocess 4
|
||||
pub(crate) r_squared_share: Option<P256>,
|
||||
|
||||
// Handshake 5
|
||||
pub(crate) ec_point: Option<(P256, P256)>,
|
||||
pub(crate) omega_share: Option<P256>,
|
||||
|
||||
// Handshake 6
|
||||
pub(crate) eta_share: Option<P256>,
|
||||
|
||||
// Handshake 7
|
||||
pub(crate) z1: Option<P256>,
|
||||
}
|
||||
|
||||
impl Prover {
|
||||
pub fn preprocess1(&mut self) {
|
||||
let mut rng = thread_rng();
|
||||
|
||||
self.a1 = Some(P256::rand(&mut rng));
|
||||
self.b1 = Some(P256::rand(&mut rng));
|
||||
self.b1_prime = Some(P256::rand(&mut rng));
|
||||
self.r1 = Some(P256::rand(&mut rng));
|
||||
}
|
||||
|
||||
pub fn preprocess2_ole_input(&mut self, ole: &mut Ole<P256>) {
|
||||
let a1 = self.a1.unwrap();
|
||||
let b1 = self.b1.unwrap();
|
||||
let b1_prime = self.b1_prime.unwrap();
|
||||
let r1 = self.r1.unwrap();
|
||||
|
||||
ole.input(Role::Sender, vec![a1, b1, a1, b1_prime, r1]);
|
||||
}
|
||||
|
||||
pub fn preprocess2_ole_output(&mut self, ole: &mut Ole<P256>) {
|
||||
let output = ole.output(Role::Sender);
|
||||
|
||||
self.a1_b2_share = Some(output[0]);
|
||||
self.a2_b1_share = Some(output[1]);
|
||||
self.a1_b2_prime_share = Some(output[2]);
|
||||
self.a2_b1_prime_share = Some(output[3]);
|
||||
self.r1_r2_share = Some(output[4]);
|
||||
}
|
||||
|
||||
pub fn preprocess3(&mut self) {
|
||||
let a1_b1_share = self.a1.unwrap() * self.b1.unwrap();
|
||||
let a1_b2_share = self.a1_b2_share.unwrap();
|
||||
let a2_b1_share = self.a2_b1_share.unwrap();
|
||||
|
||||
self.c1 = Some(a1_b1_share + a1_b2_share + a2_b1_share);
|
||||
|
||||
let a1_b1_prime_share = self.a1.unwrap() * self.b1_prime.unwrap();
|
||||
let a1_b2_prime_share = self.a1_b2_prime_share.unwrap();
|
||||
let a2_b1_prime_share = self.a2_b1_prime_share.unwrap();
|
||||
|
||||
self.c1_prime = Some(a1_b1_prime_share + a1_b2_prime_share + a2_b1_prime_share);
|
||||
}
|
||||
|
||||
pub fn preprocess4(&mut self) {
|
||||
let r1_squared = self.r1.unwrap() * self.r1.unwrap();
|
||||
|
||||
let two = P256::new(2).unwrap();
|
||||
let r1_r2_share = self.r1_r2_share.unwrap();
|
||||
|
||||
self.r_squared_share = Some(r1_squared + two * r1_r2_share);
|
||||
}
|
||||
|
||||
pub fn handshake5_input_ec(&mut self, ec_point: (P256, P256)) {
|
||||
self.ec_point = Some(ec_point);
|
||||
}
|
||||
|
||||
pub fn handshake5_varepsilon1_share_open(&self) -> P256 {
|
||||
-self.ec_point.unwrap().0 + -self.b1.unwrap()
|
||||
}
|
||||
|
||||
pub fn handshake5_set_omega(&mut self, varepsilon1: P256) {
|
||||
self.omega_share = Some(varepsilon1 * self.a1.unwrap() + self.c1.unwrap());
|
||||
}
|
||||
|
||||
pub fn handshake6_omega_share_open(&self) -> P256 {
|
||||
self.omega_share.unwrap()
|
||||
}
|
||||
|
||||
pub fn handshake6_varepsilon2_share_open(&self) -> P256 {
|
||||
-self.ec_point.unwrap().1 + -self.b1_prime.unwrap()
|
||||
}
|
||||
|
||||
pub fn handshake6_set_eta(&mut self, omega: P256, varepsilon2: P256) {
|
||||
if omega == P256::new(0).unwrap() {
|
||||
panic!("omega is 0");
|
||||
}
|
||||
|
||||
let omega_inv = omega.inverse();
|
||||
let a1 = self.a1.unwrap();
|
||||
let c1_prime = self.c1_prime.unwrap();
|
||||
|
||||
self.eta_share = Some(omega_inv * (varepsilon2 * a1 + c1_prime));
|
||||
}
|
||||
|
||||
pub fn handshake7_varepsilon3_share_open(&self) -> P256 {
|
||||
self.eta_share.unwrap() + -self.r1.unwrap()
|
||||
}
|
||||
|
||||
pub fn handshake7_set_z1(&mut self, varepsilon3: P256) {
|
||||
let two = P256::new(2).unwrap();
|
||||
let r1 = self.r1.unwrap();
|
||||
let r_squared_share = self.r_squared_share.unwrap();
|
||||
let x1 = self.ec_point.unwrap().0;
|
||||
|
||||
self.z1 = Some(varepsilon3 * varepsilon3 + two * varepsilon3 * r1 + r_squared_share + -x1);
|
||||
}
|
||||
|
||||
pub fn handshake8_z1_open(&self) -> P256 {
|
||||
self.z1.unwrap()
|
||||
}
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
//! The verifier implementation
|
||||
|
||||
use crate::func::ole::Ole;
|
||||
use crate::func::Role;
|
||||
use mpz_share_conversion_core::fields::{p256::P256, Field, UniformRand};
|
||||
use rand::thread_rng;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Verifier {
|
||||
// Preprocess 1
|
||||
pub(crate) a2: Option<P256>,
|
||||
pub(crate) b2: Option<P256>,
|
||||
pub(crate) b2_prime: Option<P256>,
|
||||
pub(crate) r2: Option<P256>,
|
||||
|
||||
// Preprocess 2
|
||||
pub(crate) a1_b2_share: Option<P256>,
|
||||
pub(crate) a2_b1_share: Option<P256>,
|
||||
pub(crate) a1_b2_prime_share: Option<P256>,
|
||||
pub(crate) a2_b1_prime_share: Option<P256>,
|
||||
pub(crate) r1_r2_share: Option<P256>,
|
||||
|
||||
// Preprocess 3
|
||||
pub(crate) c2: Option<P256>,
|
||||
pub(crate) c2_prime: Option<P256>,
|
||||
|
||||
// Preprocess 4
|
||||
pub(crate) r_squared_share: Option<P256>,
|
||||
|
||||
// Handshake 5
|
||||
pub(crate) ec_point: Option<(P256, P256)>,
|
||||
pub(crate) omega_share: Option<P256>,
|
||||
|
||||
// Handshake 6
|
||||
pub(crate) eta_share: Option<P256>,
|
||||
|
||||
// Handshake 7
|
||||
pub(crate) z2: Option<P256>,
|
||||
}
|
||||
|
||||
impl Verifier {
|
||||
pub fn preprocess1(&mut self) {
|
||||
let mut rng = thread_rng();
|
||||
|
||||
self.a2 = Some(P256::rand(&mut rng));
|
||||
self.b2 = Some(P256::rand(&mut rng));
|
||||
self.b2_prime = Some(P256::rand(&mut rng));
|
||||
self.r2 = Some(P256::rand(&mut rng));
|
||||
}
|
||||
|
||||
pub fn preprocess2_ole_input(&mut self, ole: &mut Ole<P256>) {
|
||||
let a2 = self.a2.unwrap();
|
||||
let b2 = self.b2.unwrap();
|
||||
let b2_prime = self.b2_prime.unwrap();
|
||||
let r2 = self.r2.unwrap();
|
||||
|
||||
ole.input(Role::Receiver, vec![b2, a2, b2_prime, a2, r2]);
|
||||
}
|
||||
|
||||
pub fn preprocess2_ole_output(&mut self, ole: &mut Ole<P256>) {
|
||||
let output = ole.output(Role::Receiver);
|
||||
|
||||
self.a1_b2_share = Some(output[0]);
|
||||
self.a2_b1_share = Some(output[1]);
|
||||
self.a1_b2_prime_share = Some(output[2]);
|
||||
self.a2_b1_prime_share = Some(output[3]);
|
||||
self.r1_r2_share = Some(output[4]);
|
||||
}
|
||||
|
||||
pub fn preprocess3(&mut self) {
|
||||
let a2_b2_share = self.a2.unwrap() * self.b2.unwrap();
|
||||
let a1_b2_share = self.a1_b2_share.unwrap();
|
||||
let a2_b1_share = self.a2_b1_share.unwrap();
|
||||
|
||||
self.c2 = Some(a2_b2_share + a1_b2_share + a2_b1_share);
|
||||
|
||||
let a2_b2_prime_share = self.a2.unwrap() * self.b2_prime.unwrap();
|
||||
let a1_b2_prime_share = self.a1_b2_prime_share.unwrap();
|
||||
let a2_b1_prime_share = self.a2_b1_prime_share.unwrap();
|
||||
|
||||
self.c2_prime = Some(a2_b2_prime_share + a1_b2_prime_share + a2_b1_prime_share);
|
||||
}
|
||||
|
||||
pub fn preprocess4(&mut self) {
|
||||
let r2_squared = self.r2.unwrap() * self.r2.unwrap();
|
||||
|
||||
let two = P256::new(2).unwrap();
|
||||
let r1_r2_share = self.r1_r2_share.unwrap();
|
||||
|
||||
self.r_squared_share = Some(r2_squared + two * r1_r2_share);
|
||||
}
|
||||
|
||||
pub fn handshake5_input_ec(&mut self, ec_point: (P256, P256)) {
|
||||
self.ec_point = Some(ec_point);
|
||||
}
|
||||
|
||||
pub fn handshake5_varepsilon1_share_open(&self) -> P256 {
|
||||
self.ec_point.unwrap().0 + -self.b2.unwrap()
|
||||
}
|
||||
|
||||
pub fn handshake5_set_omega(&mut self, varepsilon1: P256) {
|
||||
self.omega_share = Some(varepsilon1 * self.a2.unwrap() + self.c2.unwrap());
|
||||
}
|
||||
|
||||
pub fn handshake6_omega_share_open(&self) -> P256 {
|
||||
self.omega_share.unwrap()
|
||||
}
|
||||
|
||||
pub fn handshake6_varepsilon2_share_open(&self) -> P256 {
|
||||
self.ec_point.unwrap().1 + -self.b2_prime.unwrap()
|
||||
}
|
||||
|
||||
pub fn handshake6_set_eta(&mut self, omega: P256, varepsilon2: P256) {
|
||||
if omega == P256::new(0).unwrap() {
|
||||
panic!("omega is 0");
|
||||
}
|
||||
|
||||
let omega_inv = omega.inverse();
|
||||
let a2 = self.a2.unwrap();
|
||||
let c2_prime = self.c2_prime.unwrap();
|
||||
|
||||
self.eta_share = Some(omega_inv * (varepsilon2 * a2 + c2_prime));
|
||||
}
|
||||
|
||||
pub fn handshake7_varepsilon3_share_open(&self) -> P256 {
|
||||
self.eta_share.unwrap() + -self.r2.unwrap()
|
||||
}
|
||||
|
||||
pub fn handshake7_set_z2(&mut self, varepsilon3: P256) {
|
||||
let two = P256::new(2).unwrap();
|
||||
let r2 = self.r2.unwrap();
|
||||
let r_squared_share = self.r_squared_share.unwrap();
|
||||
let x2 = self.ec_point.unwrap().0;
|
||||
|
||||
self.z2 = Some(two * varepsilon3 * r2 + r_squared_share + -x2);
|
||||
}
|
||||
|
||||
pub fn handshake8_z2_open(&self) -> P256 {
|
||||
self.z2.unwrap()
|
||||
}
|
||||
}
|
||||
106
src/f2.rs
106
src/f2.rs
@@ -1,106 +0,0 @@
|
||||
use itybity::{BitLength, FromBitIterator, GetBit, Lsb0, Msb0};
|
||||
use mpz_share_conversion_core::fields::Field;
|
||||
use rand::distributions::{Distribution, Standard};
|
||||
use std::ops::{Add, Mul, Neg};
|
||||
|
||||
/// A simple boolean field type
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct F2 {
|
||||
inner: u8,
|
||||
}
|
||||
|
||||
impl F2 {
|
||||
/// Create a new `F2` from a `bool`.
|
||||
///
|
||||
/// `False` encodes 0 and `true` encodes 1.
|
||||
pub fn new(value: bool) -> Self {
|
||||
Self { inner: value as u8 }
|
||||
}
|
||||
}
|
||||
|
||||
impl Field for F2 {
|
||||
const BIT_SIZE: u32 = 1;
|
||||
|
||||
fn zero() -> Self {
|
||||
Self::new(false)
|
||||
}
|
||||
|
||||
fn one() -> Self {
|
||||
Self::new(true)
|
||||
}
|
||||
|
||||
fn two_pow(_rhs: u32) -> Self {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn inverse(self) -> Self {
|
||||
if self.inner == 0 {
|
||||
panic!("No inverse for 0")
|
||||
}
|
||||
Self::one()
|
||||
}
|
||||
|
||||
fn to_le_bytes(&self) -> Vec<u8> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn to_be_bytes(&self) -> Vec<u8> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Distribution<F2> for Standard {
|
||||
fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> F2 {
|
||||
F2::new(rng.gen())
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for F2 {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self::new((self.inner ^ rhs.inner) != 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mul for F2 {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: Self) -> Self::Output {
|
||||
Self::new(self.inner & rhs.inner != 0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for F2 {
|
||||
type Output = Self;
|
||||
|
||||
fn neg(self) -> Self::Output {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl BitLength for F2 {
|
||||
const BITS: usize = 1;
|
||||
}
|
||||
|
||||
impl GetBit<Lsb0> for F2 {
|
||||
fn get_bit(&self, _index: usize) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl GetBit<Msb0> for F2 {
|
||||
fn get_bit(&self, _index: usize) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromBitIterator for F2 {
|
||||
fn from_lsb0_iter(_iter: impl IntoIterator<Item = bool>) -> Self {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn from_msb0_iter(_iter: impl IntoIterator<Item = bool>) -> Self {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
140
src/func/cot.rs
140
src/func/cot.rs
@@ -1,140 +0,0 @@
|
||||
//! This module implements the COT functionality (page 5) from <https://eprint.iacr.org/2015/546> without errors.
|
||||
|
||||
use mpz_share_conversion_core::fields::UniformRand;
|
||||
|
||||
use super::Role;
|
||||
use crate::f2::F2;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Cot {
|
||||
kappa: usize,
|
||||
l: usize,
|
||||
delta: Vec<F2>,
|
||||
t: Vec<Vec<F2>>,
|
||||
q: Vec<Vec<F2>>,
|
||||
}
|
||||
|
||||
impl Cot {
|
||||
pub fn new(kappa: usize, l: usize) -> Self {
|
||||
Self {
|
||||
kappa,
|
||||
l,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn initialize_input_delta(&mut self, delta: Vec<F2>) {
|
||||
assert_eq!(delta.len(), self.kappa);
|
||||
|
||||
self.delta = delta;
|
||||
}
|
||||
|
||||
pub fn extend_input_x(&mut self, x: Vec<Vec<F2>>) {
|
||||
assert!(self.t.is_empty());
|
||||
assert!(self.q.is_empty());
|
||||
assert_eq!(x.len(), self.l);
|
||||
|
||||
for vec in x.iter() {
|
||||
assert_eq!(vec.len(), self.kappa);
|
||||
}
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
for _ in 0..self.l {
|
||||
let inner = (0..self.kappa)
|
||||
.map(|_| F2::rand(&mut rng))
|
||||
.collect::<Vec<F2>>();
|
||||
self.t.push(inner);
|
||||
}
|
||||
|
||||
for (ti, xi) in self.t.iter().zip(x.iter()) {
|
||||
let xi_times_delta = self
|
||||
.delta
|
||||
.iter()
|
||||
.zip(xi.iter())
|
||||
.map(|(&deltai, &xi)| deltai * xi)
|
||||
.collect::<Vec<F2>>();
|
||||
|
||||
self.q.push(
|
||||
ti.iter()
|
||||
.zip(xi_times_delta.iter())
|
||||
.map(|(&tk, &xtdk)| tk + xtdk)
|
||||
.collect::<Vec<F2>>(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn output(&mut self, role: Role) -> Vec<Vec<F2>> {
|
||||
let out = if role == Role::Sender {
|
||||
std::mem::take(&mut self.q)
|
||||
} else {
|
||||
std::mem::take(&mut self.t)
|
||||
};
|
||||
|
||||
std::mem::take(self);
|
||||
out
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_cot() {
|
||||
let mut cot = Cot::new(5, 3);
|
||||
let delta = vec![
|
||||
F2::new(true),
|
||||
F2::new(false),
|
||||
F2::new(true),
|
||||
F2::new(false),
|
||||
F2::new(true),
|
||||
];
|
||||
|
||||
let x = vec![
|
||||
vec![
|
||||
F2::new(true),
|
||||
F2::new(false),
|
||||
F2::new(true),
|
||||
F2::new(false),
|
||||
F2::new(true),
|
||||
],
|
||||
vec![
|
||||
F2::new(false),
|
||||
F2::new(true),
|
||||
F2::new(false),
|
||||
F2::new(true),
|
||||
F2::new(true),
|
||||
],
|
||||
vec![
|
||||
F2::new(false),
|
||||
F2::new(true),
|
||||
F2::new(true),
|
||||
F2::new(false),
|
||||
F2::new(false),
|
||||
],
|
||||
];
|
||||
|
||||
cot.initialize_input_delta(delta.clone());
|
||||
cot.extend_input_x(x.clone());
|
||||
|
||||
let q = cot.output(Role::Sender);
|
||||
let t = cot.output(Role::Receiver);
|
||||
|
||||
for ((qi, ti), xi) in q.iter().zip(t.iter()).zip(x.iter()) {
|
||||
let qi_minus_ti = qi
|
||||
.iter()
|
||||
.zip(ti.iter())
|
||||
.map(|(&qij, &tij)| qij + -tij)
|
||||
.collect::<Vec<F2>>();
|
||||
|
||||
let xi_times_delta = xi
|
||||
.iter()
|
||||
.zip(delta.iter())
|
||||
.map(|(&xij, &deltai)| xij * deltai)
|
||||
.collect::<Vec<F2>>();
|
||||
|
||||
assert_eq!(qi_minus_ti, xi_times_delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
//! This module implements some functionalities.
|
||||
|
||||
pub mod cot;
|
||||
pub mod ole;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum Role {
|
||||
Sender,
|
||||
Receiver,
|
||||
}
|
||||
100
src/func/ole.rs
100
src/func/ole.rs
@@ -1,100 +0,0 @@
|
||||
//! This module implements an OLE functionality.
|
||||
|
||||
use super::Role;
|
||||
use mpz_share_conversion_core::Field;
|
||||
use rand::thread_rng;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Ole<T: Field> {
|
||||
input_sender: Vec<T>,
|
||||
input_receiver: Vec<T>,
|
||||
output: Vec<T>,
|
||||
}
|
||||
|
||||
impl<T: Field> Default for Ole<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
input_sender: vec![],
|
||||
input_receiver: vec![],
|
||||
output: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Field> Ole<T> {
|
||||
pub fn input(&mut self, role: Role, input: Vec<T>) {
|
||||
if role == Role::Sender {
|
||||
self.input_sender = input;
|
||||
} else {
|
||||
self.input_receiver = input;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn output(&mut self, role: Role) -> Vec<T> {
|
||||
assert!(self.input_sender.len() == self.input_receiver.len());
|
||||
|
||||
if !self.output.is_empty() {
|
||||
return std::mem::take(&mut self.output);
|
||||
}
|
||||
|
||||
let mut rng = thread_rng();
|
||||
let mut output = vec![];
|
||||
let mut output_cached = vec![];
|
||||
|
||||
for (s, r) in self.input_sender.iter().zip(self.input_receiver.iter()) {
|
||||
let s_out = T::rand(&mut rng);
|
||||
let r_out = *s * *r + -s_out;
|
||||
|
||||
if role == Role::Sender {
|
||||
output.push(s_out);
|
||||
output_cached.push(r_out);
|
||||
} else {
|
||||
output.push(r_out);
|
||||
output_cached.push(s_out);
|
||||
}
|
||||
}
|
||||
self.input_sender.clear();
|
||||
self.input_receiver.clear();
|
||||
|
||||
self.output = output_cached;
|
||||
output
|
||||
}
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use mpz_share_conversion_core::fields::{p256::P256, UniformRand};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_ole() {
|
||||
let mut ole = Ole::default();
|
||||
let mut rng = thread_rng();
|
||||
|
||||
let input_sender = vec![
|
||||
P256::rand(&mut rng),
|
||||
P256::rand(&mut rng),
|
||||
P256::rand(&mut rng),
|
||||
];
|
||||
let input_receiver = vec![
|
||||
P256::rand(&mut rng),
|
||||
P256::rand(&mut rng),
|
||||
P256::rand(&mut rng),
|
||||
];
|
||||
|
||||
ole.input(Role::Sender, input_sender.clone());
|
||||
ole.input(Role::Receiver, input_receiver.clone());
|
||||
|
||||
let output_sender = ole.output(Role::Sender);
|
||||
let output_receiver = ole.output(Role::Receiver);
|
||||
|
||||
for (((is, ir), os), or) in input_sender
|
||||
.into_iter()
|
||||
.zip(input_receiver)
|
||||
.zip(output_sender)
|
||||
.zip(output_receiver)
|
||||
{
|
||||
assert_eq!(is * ir, os + or);
|
||||
}
|
||||
}
|
||||
}
|
||||
138
src/ghash/mod.rs
138
src/ghash/mod.rs
@@ -1,138 +0,0 @@
|
||||
//! This module is a testing ground for the GHASH protocol (page 36) from <https://eprint.iacr.org/2023/964>
|
||||
|
||||
mod prover;
|
||||
mod verifier;
|
||||
|
||||
use crate::func::ole::Ole;
|
||||
use mpz_share_conversion_core::{fields::gf2_128::Gf2_128, Field};
|
||||
pub use prover::Prover;
|
||||
pub use verifier::Verifier;
|
||||
|
||||
pub fn ghash(blocks: &[Gf2_128], prover: &mut Prover, verifier: &mut Verifier) -> Gf2_128 {
|
||||
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_di(d);
|
||||
verifier.handshake_a_set_di(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
|
||||
}
|
||||
|
||||
fn pascal_tri<T: Field>(n: usize) -> Vec<Vec<T>> {
|
||||
let mut pascal = vec![vec![T::one()]];
|
||||
|
||||
for _ in 0..n {
|
||||
let last_row = pascal.last().unwrap();
|
||||
let mut new_row = vec![T::one()];
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use mpz_share_conversion_core::fields::{compute_product_repeated, UniformRand};
|
||||
use rand::thread_rng;
|
||||
|
||||
#[test]
|
||||
fn test_ghash() {
|
||||
let mut rng = thread_rng();
|
||||
let blocks: Vec<Gf2_128> = (0..10).map(|_| Gf2_128::rand(&mut rng)).collect();
|
||||
|
||||
let h1: Gf2_128 = Gf2_128::rand(&mut rng);
|
||||
let h2: Gf2_128 = Gf2_128::rand(&mut rng);
|
||||
let h = h1 + h2;
|
||||
|
||||
let mut prover = Prover::new(blocks.len(), h1);
|
||||
let mut verifier = Verifier::new(blocks.len(), h2);
|
||||
|
||||
let ghash = ghash(&blocks, &mut prover, &mut verifier);
|
||||
|
||||
let ghash_expected = {
|
||||
let mut hi = vec![h];
|
||||
compute_product_repeated(&mut hi, h, blocks.len());
|
||||
|
||||
blocks
|
||||
.iter()
|
||||
.zip(hi.iter())
|
||||
.fold(Gf2_128::zero(), |acc, (&b, &h)| acc + (b * h))
|
||||
};
|
||||
|
||||
assert_eq!(ghash, ghash_expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ghash_invariants() {
|
||||
let mut rng = thread_rng();
|
||||
let blocks: Vec<Gf2_128> = (0..1).map(|_| Gf2_128::rand(&mut rng)).collect();
|
||||
|
||||
let h1: Gf2_128 = Gf2_128::rand(&mut rng);
|
||||
let h2: Gf2_128 = Gf2_128::rand(&mut rng);
|
||||
|
||||
let mut prover = Prover::new(blocks.len(), h1);
|
||||
let mut verifier = Verifier::new(blocks.len(), h2);
|
||||
|
||||
let _ = ghash(&blocks, &mut prover, &mut verifier);
|
||||
|
||||
assert_eq!(prover.d_powers[0], Gf2_128::one());
|
||||
assert_eq!(verifier.d_powers[0], Gf2_128::one());
|
||||
assert_eq!(prover.d_powers[1], verifier.d_powers[1]);
|
||||
|
||||
assert_eq!(prover.ai[1] + verifier.bi[1], prover.r1 * verifier.r2);
|
||||
assert_eq!(prover.h1 + verifier.h2, prover.hi[0] + verifier.hi[0]);
|
||||
assert_eq!(prover.d_powers[1] + prover.ai[1] + verifier.bi[1], h1 + h2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pascal_tri() {
|
||||
// This is an extension field so no naive arithmetic!
|
||||
let pascal = pascal_tri::<Gf2_128>(4);
|
||||
|
||||
let expected0 = vec![Gf2_128::one()];
|
||||
let expected1 = vec![Gf2_128::one(), Gf2_128::one()];
|
||||
let expected2 = vec![Gf2_128::one(), Gf2_128::zero(), Gf2_128::one()];
|
||||
let expected3 = vec![
|
||||
Gf2_128::one(),
|
||||
Gf2_128::one(),
|
||||
Gf2_128::one(),
|
||||
Gf2_128::one(),
|
||||
];
|
||||
let expected4 = vec![
|
||||
Gf2_128::one(),
|
||||
Gf2_128::zero(),
|
||||
Gf2_128::zero(),
|
||||
Gf2_128::zero(),
|
||||
Gf2_128::one(),
|
||||
];
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
use super::pascal_tri;
|
||||
use crate::func::ole::Ole;
|
||||
use crate::func::Role;
|
||||
use mpz_share_conversion_core::{
|
||||
fields::{compute_product_repeated, gf2_128::Gf2_128, UniformRand},
|
||||
Field,
|
||||
};
|
||||
use rand::thread_rng;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Prover {
|
||||
pub(crate) block_num: usize,
|
||||
pub(crate) h1: Gf2_128,
|
||||
pub(crate) r1: Gf2_128,
|
||||
pub(crate) ai: Vec<Gf2_128>,
|
||||
pub(crate) d_powers: Vec<Gf2_128>,
|
||||
pub(crate) 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_powers: vec![],
|
||||
hi: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn preprocess_ole_input(&self, ole: &mut Ole<Gf2_128>) {
|
||||
let mut r1_powers = vec![Gf2_128::one()];
|
||||
|
||||
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.ai[1]
|
||||
}
|
||||
|
||||
pub fn handshake_a_set_di(&mut self, d: Gf2_128) {
|
||||
self.d_powers = vec![Gf2_128::one(), d];
|
||||
compute_product_repeated(&mut self.d_powers, d, self.block_num);
|
||||
}
|
||||
|
||||
pub fn handshake_a_set_hi(&mut self) {
|
||||
let pascal_tri = pascal_tri::<Gf2_128>(self.block_num);
|
||||
|
||||
for pascal_row in pascal_tri.iter().skip(1) {
|
||||
let h_pow_share = pascal_row
|
||||
.iter()
|
||||
.enumerate()
|
||||
.fold(Gf2_128::new(0), |acc, (i, &el)| {
|
||||
acc + el * self.d_powers[pascal_row.len() - 1 - i] * self.ai[i]
|
||||
});
|
||||
self.hi.push(h_pow_share);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handshake_output_ghash(&self, blocks: &[Gf2_128]) -> Gf2_128 {
|
||||
let mut res = Gf2_128::zero();
|
||||
|
||||
for (i, block) in blocks.iter().enumerate() {
|
||||
res = res + *block * self.hi[i];
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
use super::pascal_tri;
|
||||
use crate::func::ole::Ole;
|
||||
use crate::func::Role;
|
||||
use mpz_share_conversion_core::{
|
||||
fields::{compute_product_repeated, gf2_128::Gf2_128, UniformRand},
|
||||
Field,
|
||||
};
|
||||
use rand::thread_rng;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Verifier {
|
||||
pub(crate) block_num: usize,
|
||||
pub(crate) h2: Gf2_128,
|
||||
pub(crate) r2: Gf2_128,
|
||||
pub(crate) bi: Vec<Gf2_128>,
|
||||
pub(crate) d_powers: Vec<Gf2_128>,
|
||||
pub(crate) 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_powers: vec![],
|
||||
hi: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn preprocess_ole_input(&self, ole: &mut Ole<Gf2_128>) {
|
||||
let mut r2_powers = vec![Gf2_128::one()];
|
||||
|
||||
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.bi[1]
|
||||
}
|
||||
|
||||
pub fn handshake_a_set_di(&mut self, d: Gf2_128) {
|
||||
self.d_powers = vec![Gf2_128::one(), d];
|
||||
compute_product_repeated(&mut self.d_powers, d, self.block_num);
|
||||
}
|
||||
|
||||
pub fn handshake_a_set_hi(&mut self) {
|
||||
let pascal_tri = pascal_tri::<Gf2_128>(self.block_num);
|
||||
|
||||
for pascal_row in pascal_tri.iter().skip(1) {
|
||||
let h_pow_share = pascal_row
|
||||
.iter()
|
||||
.enumerate()
|
||||
.fold(Gf2_128::new(0), |acc, (i, &el)| {
|
||||
acc + el * self.d_powers[pascal_row.len() - 1 - i] * self.bi[i]
|
||||
});
|
||||
self.hi.push(h_pow_share);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handshake_output_ghash(&self, blocks: &[Gf2_128]) -> Gf2_128 {
|
||||
let mut res = Gf2_128::zero();
|
||||
|
||||
for (i, block) in blocks.iter().enumerate() {
|
||||
res = res + *block * self.hi[i];
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
57
src/lib.rs
57
src/lib.rs
@@ -1,7 +1,52 @@
|
||||
//! This crate is for testing TLSNotary sub protocols based on OLE, and check their security properties.
|
||||
#![feature(iter_map_windows)]
|
||||
use itybity::ToBits;
|
||||
use mpz_share_conversion_core::fields::gf2_128::Gf2_128;
|
||||
use mpz_share_conversion_core::Field;
|
||||
use rand::Rng;
|
||||
|
||||
pub mod e2f;
|
||||
mod f2;
|
||||
pub mod func;
|
||||
pub mod ghash;
|
||||
#[test]
|
||||
fn test() {
|
||||
let a: Gf2_128 = rand::thread_rng().gen();
|
||||
let b: Gf2_128 = rand::thread_rng().gen();
|
||||
|
||||
let mut ts = Vec::new();
|
||||
let mut ys = Vec::new();
|
||||
|
||||
for b_i in b.iter_lsb0() {
|
||||
let ((t_0, t_1), t_b) = rot(b_i);
|
||||
let u_i = t_0 + -t_1 + a;
|
||||
|
||||
let y_i = if b_i { t_b + u_i } else { t_b };
|
||||
|
||||
assert_eq!(y_i, if b_i { t_0 + a } else { t_0 });
|
||||
|
||||
ts.push(t_0);
|
||||
ys.push(y_i);
|
||||
}
|
||||
|
||||
let x = ts
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.fold(Gf2_128::zero(), |acc, (i, t_i)| {
|
||||
acc + (t_i * Gf2_128::two_pow(i as u32))
|
||||
});
|
||||
let y = -ys
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.fold(Gf2_128::zero(), |acc, (i, y_i)| {
|
||||
acc + (y_i * Gf2_128::two_pow(i as u32))
|
||||
});
|
||||
|
||||
assert_eq!(x + y, a * b);
|
||||
}
|
||||
|
||||
pub fn rot(x: bool) -> ((Gf2_128, Gf2_128), Gf2_128) {
|
||||
let t_0: Gf2_128 = rand::thread_rng().gen();
|
||||
let t_1: Gf2_128 = rand::thread_rng().gen();
|
||||
let t_x = if x { t_1 } else { t_0 };
|
||||
|
||||
((t_0, t_1), t_x)
|
||||
}
|
||||
|
||||
pub fn get_bit(a: u64, idx: usize) -> bool {
|
||||
(a >> idx) & 1 == 1
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user