mirror of
https://github.com/tlsnotary/tlsn.git
synced 2026-01-08 22:28:15 -05:00
moved hash implementation into block
This commit is contained in:
@@ -7,6 +7,7 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
aes = { version="0.7.5", features=[]}
|
||||
cipher = "0.3"
|
||||
rand = "0.7"
|
||||
rand_core = "0.5"
|
||||
rand_chacha = "0.2"
|
||||
|
||||
@@ -3,15 +3,18 @@ use pop_mpc::block::Block;
|
||||
use pop_mpc::circuit::Circuit;
|
||||
use pop_mpc::garble::{
|
||||
evaluator::HalfGateEvaluator, generator::half_gate::*, generator::GarbledCircuitGenerator,
|
||||
hash::aes::Aes,
|
||||
};
|
||||
use aes::cipher::{
|
||||
generic_array::GenericArray, NewBlockCipher,
|
||||
};
|
||||
use aes::Aes128;
|
||||
use rand::SeedableRng;
|
||||
use rand_chacha::ChaCha12Rng;
|
||||
|
||||
fn criterion_benchmark(c: &mut Criterion) {
|
||||
c.bench_function("half_gate_garble_and", move |bench| {
|
||||
let mut rng = ChaCha12Rng::from_entropy();
|
||||
let h = Aes::new(&[0u8; 16]);
|
||||
let mut cipher = Aes128::new(GenericArray::from_slice(&[0u8; 16]));
|
||||
let gen = HalfGateGenerator;
|
||||
|
||||
let mut delta = Block::random(&mut rng);
|
||||
@@ -23,14 +26,14 @@ fn criterion_benchmark(c: &mut Criterion) {
|
||||
let gid: usize = 1;
|
||||
|
||||
bench.iter(|| {
|
||||
let res = gen.and_gate(&h, x, y, delta, gid);
|
||||
let res = gen.and_gate(&mut cipher, x, y, delta, gid);
|
||||
black_box(res);
|
||||
});
|
||||
});
|
||||
|
||||
c.bench_function("half_gate_eval_and", move |bench| {
|
||||
let mut rng = ChaCha12Rng::from_entropy();
|
||||
let h = Aes::new(&[0u8; 16]);
|
||||
let mut cipher = Aes128::new(GenericArray::from_slice(&[0u8; 16]));
|
||||
let gen = HalfGateGenerator;
|
||||
let ev = HalfGateEvaluator;
|
||||
|
||||
@@ -42,21 +45,21 @@ fn criterion_benchmark(c: &mut Criterion) {
|
||||
let y = [y_0, y_0 ^ delta];
|
||||
let gid: usize = 1;
|
||||
|
||||
let (_, table) = gen.and_gate(&h, x, y, delta, gid);
|
||||
let (_, table) = gen.and_gate(&mut cipher, x, y, delta, gid);
|
||||
|
||||
bench.iter(|| {
|
||||
let res = ev.and_gate(&h, x[0], y[0], table, gid);
|
||||
let res = ev.and_gate(&mut cipher, x[0], y[0], table, gid);
|
||||
black_box(res);
|
||||
});
|
||||
});
|
||||
|
||||
c.bench_function("half_gate_aes", move |bench| {
|
||||
let mut rng = ChaCha12Rng::from_entropy();
|
||||
let h = Aes::new(&[0u8; 16]);
|
||||
let mut cipher = Aes128::new(GenericArray::from_slice(&[0u8; 16]));
|
||||
let circ = Circuit::parse("circuits/aes_128_reverse.txt").unwrap();
|
||||
let half_gate = HalfGateGenerator;
|
||||
bench.iter(|| {
|
||||
let gb = half_gate.garble(&h, &mut rng, &circ).unwrap();
|
||||
let gb = half_gate.garble(&mut cipher, &mut rng, &circ).unwrap();
|
||||
black_box(gb);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use core::ops::{BitAnd, BitXor, BitXorAssign};
|
||||
use rand::{CryptoRng, Rng, SeedableRng};
|
||||
use std::convert::From;
|
||||
use std::convert::{From, TryInto};
|
||||
use cipher::{BlockCipher, BlockEncrypt, consts::U16, generic_array::GenericArray};
|
||||
|
||||
#[repr(transparent)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
@@ -20,6 +21,28 @@ impl Block {
|
||||
Self::new(rng.gen())
|
||||
}
|
||||
|
||||
pub fn hash_tweak<C: BlockCipher<BlockSize = U16> + BlockEncrypt>(&self, c: &mut C, tweak: usize) -> Self {
|
||||
let gid: [u8; 16] = (tweak as u128).to_be_bytes();
|
||||
let label: [u8; 16] = self.to_be_bytes();
|
||||
|
||||
let mut h1: GenericArray<u8, U16> = GenericArray::from(label);
|
||||
c.encrypt_block(&mut h1);
|
||||
|
||||
let h2: GenericArray<u8, U16> = GenericArray::clone_from_slice(h1.as_slice());
|
||||
let mut h2: GenericArray<u8, U16> = h2.into_iter().zip(gid).map(|(a, b)| a ^ b).collect();
|
||||
c.encrypt_block(&mut h2);
|
||||
|
||||
let h3: GenericArray<u8, U16> = GenericArray::clone_from_slice(h2.as_slice());
|
||||
let h3: GenericArray<u8, U16> = h3.into_iter().zip(h1).map(|(a, b)| a ^ b).collect();
|
||||
|
||||
let b: [u8; 16] = h3
|
||||
.as_slice()
|
||||
.try_into()
|
||||
.expect("Expected array to have length 16");
|
||||
let h: u128 = u128::from_be_bytes(b);
|
||||
Self::new(h)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn zero() -> Self {
|
||||
Self(0)
|
||||
|
||||
@@ -3,16 +3,16 @@ use crate::block::{Block, SELECT_MASK};
|
||||
use crate::circuit::Circuit;
|
||||
use crate::errors::EvaluatorError;
|
||||
use crate::garble::circuit::GarbledCircuit;
|
||||
use crate::garble::hash::WireLabelHasher;
|
||||
use cipher::{BlockCipher, BlockEncrypt, consts::U16, generic_array::GenericArray};
|
||||
use crate::gate::Gate;
|
||||
|
||||
pub struct HalfGateEvaluator;
|
||||
|
||||
impl HalfGateEvaluator {
|
||||
#[inline]
|
||||
pub fn and_gate<H: WireLabelHasher>(
|
||||
pub fn and_gate<C: BlockCipher<BlockSize = U16> + BlockEncrypt>(
|
||||
&self,
|
||||
h: &H,
|
||||
c: &mut C,
|
||||
x: Block,
|
||||
y: Block,
|
||||
table: [Block; 2],
|
||||
@@ -24,8 +24,8 @@ impl HalfGateEvaluator {
|
||||
let j = gid;
|
||||
let k = gid + 1;
|
||||
|
||||
let hx = h.hash(x, j);
|
||||
let hy = h.hash(y, k);
|
||||
let hx = x.hash_tweak(c, j);
|
||||
let hy = y.hash_tweak(c, k);
|
||||
|
||||
let w_g = hx ^ (table[0] & SELECT_MASK[s_a]);
|
||||
let w_e = hy ^ (SELECT_MASK[s_b] & (table[1] ^ x));
|
||||
@@ -45,9 +45,9 @@ impl HalfGateEvaluator {
|
||||
}
|
||||
|
||||
impl GarbledCircuitEvaluator for HalfGateEvaluator {
|
||||
fn eval<H: WireLabelHasher>(
|
||||
fn eval<C: BlockCipher<BlockSize = U16> + BlockEncrypt>(
|
||||
&self,
|
||||
h: &H,
|
||||
c: &mut C,
|
||||
circ: &Circuit,
|
||||
gc: &GarbledCircuit,
|
||||
input_labels: Vec<Block>,
|
||||
@@ -86,7 +86,7 @@ impl GarbledCircuitEvaluator for HalfGateEvaluator {
|
||||
} => {
|
||||
let x = cache[xref].ok_or_else(|| EvaluatorError::UninitializedLabel(xref))?;
|
||||
let y = cache[yref].ok_or_else(|| EvaluatorError::UninitializedLabel(yref))?;
|
||||
let z = self.and_gate(h, x, y, gc.table[gid - 1], gid);
|
||||
let z = self.and_gate(c, x, y, gc.table[gid - 1], gid);
|
||||
cache[zref] = Some(z);
|
||||
gid += 1;
|
||||
}
|
||||
|
||||
@@ -6,12 +6,12 @@ use crate::block::Block;
|
||||
use crate::circuit::Circuit;
|
||||
use crate::errors::EvaluatorError;
|
||||
use crate::garble::circuit::GarbledCircuit;
|
||||
use crate::garble::hash::WireLabelHasher;
|
||||
use cipher::{BlockCipher, BlockEncrypt, consts::U16, generic_array::GenericArray};
|
||||
|
||||
pub trait GarbledCircuitEvaluator {
|
||||
fn eval<H: WireLabelHasher>(
|
||||
fn eval<C: BlockCipher<BlockSize = U16> + BlockEncrypt>(
|
||||
&self,
|
||||
h: &H,
|
||||
c: &mut C,
|
||||
circ: &Circuit,
|
||||
gc: &GarbledCircuit,
|
||||
input_labels: Vec<Block>,
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::block::{Block, SELECT_MASK};
|
||||
use crate::circuit::Circuit;
|
||||
use crate::errors::GeneratorError;
|
||||
use crate::garble::circuit::GarbledCircuit;
|
||||
use crate::garble::hash::WireLabelHasher;
|
||||
use cipher::{BlockCipher, BlockEncrypt, consts::U16, generic_array::GenericArray};
|
||||
use crate::gate::Gate;
|
||||
use rand::{CryptoRng, Rng, SeedableRng};
|
||||
|
||||
@@ -11,9 +11,9 @@ pub struct HalfGateGenerator;
|
||||
|
||||
impl HalfGateGenerator {
|
||||
#[inline]
|
||||
pub fn and_gate<H: WireLabelHasher>(
|
||||
pub fn and_gate<C: BlockCipher<BlockSize = U16> + BlockEncrypt>(
|
||||
&self,
|
||||
h: &H,
|
||||
c: &mut C,
|
||||
x: [Block; 2],
|
||||
y: [Block; 2],
|
||||
delta: Block,
|
||||
@@ -24,13 +24,13 @@ impl HalfGateGenerator {
|
||||
let j = gid;
|
||||
let k = gid + 1;
|
||||
|
||||
let hx_0 = h.hash(x[0], j);
|
||||
let hy_0 = h.hash(y[0], k);
|
||||
let hx_0 = x[0].hash_tweak(c, j);
|
||||
let hy_0 = y[0].hash_tweak(c, k);
|
||||
|
||||
let t_g = hx_0 ^ h.hash(x[1], j) ^ (SELECT_MASK[p_b] & delta);
|
||||
let t_g = hx_0 ^ x[1].hash_tweak(c, j) ^ (SELECT_MASK[p_b] & delta);
|
||||
let w_g = hx_0 ^ (SELECT_MASK[p_a] & t_g);
|
||||
|
||||
let t_e = hy_0 ^ h.hash(y[1], k) ^ x[0];
|
||||
let t_e = hy_0 ^ y[1].hash_tweak(c, k) ^ x[0];
|
||||
let w_e = hy_0 ^ (SELECT_MASK[p_b] & (t_e ^ x[0]));
|
||||
|
||||
let z_0 = w_g ^ w_e;
|
||||
@@ -53,9 +53,9 @@ impl HalfGateGenerator {
|
||||
}
|
||||
|
||||
impl GarbledCircuitGenerator for HalfGateGenerator {
|
||||
fn garble<R: Rng + CryptoRng, H: WireLabelHasher>(
|
||||
fn garble<R: Rng + CryptoRng, C: BlockCipher<BlockSize = U16> + BlockEncrypt>(
|
||||
&self,
|
||||
h: &H,
|
||||
c: &mut C,
|
||||
rng: &mut R,
|
||||
circ: &Circuit,
|
||||
) -> Result<GarbledCircuit, GeneratorError> {
|
||||
@@ -97,7 +97,7 @@ impl GarbledCircuitGenerator for HalfGateGenerator {
|
||||
} => {
|
||||
let x = cache[xref].ok_or_else(|| GeneratorError::UninitializedLabel(xref))?;
|
||||
let y = cache[yref].ok_or_else(|| GeneratorError::UninitializedLabel(yref))?;
|
||||
let (z, t) = self.and_gate(h, x, y, delta, gid);
|
||||
let (z, t) = self.and_gate(c, x, y, delta, gid);
|
||||
table.push(t);
|
||||
cache[zref] = Some(z);
|
||||
gid += 1;
|
||||
@@ -124,16 +124,19 @@ impl GarbledCircuitGenerator for HalfGateGenerator {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::garble::hash::aes::Aes;
|
||||
use aes::cipher::{
|
||||
generic_array::GenericArray, NewBlockCipher,
|
||||
};
|
||||
use aes::Aes128;
|
||||
use rand_chacha::ChaCha12Rng;
|
||||
|
||||
#[test]
|
||||
fn test_encode_wire_labels() {
|
||||
let mut cipher = Aes128::new(GenericArray::from_slice(&[0u8; 16]));
|
||||
let mut rng = ChaCha12Rng::from_entropy();
|
||||
let h = Aes::new(&[0u8; 16]);
|
||||
let circ = Circuit::parse("circuits/aes_128_reverse.txt").unwrap();
|
||||
let half_gate = HalfGateGenerator;
|
||||
|
||||
let gc = half_gate.garble(&h, &mut rng, &circ);
|
||||
let gc = half_gate.garble(&mut cipher, &mut rng, &circ);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,13 @@ pub use half_gate::*;
|
||||
use crate::circuit::Circuit;
|
||||
use crate::errors::GeneratorError;
|
||||
use crate::garble::circuit::GarbledCircuit;
|
||||
use crate::garble::hash::WireLabelHasher;
|
||||
use cipher::{BlockCipher, BlockEncrypt, consts::U16, generic_array::GenericArray};
|
||||
use rand::{CryptoRng, Rng};
|
||||
|
||||
pub trait GarbledCircuitGenerator {
|
||||
fn garble<R: Rng + CryptoRng, H: WireLabelHasher>(
|
||||
fn garble<R: Rng + CryptoRng, C: BlockCipher<BlockSize = U16> + BlockEncrypt>(
|
||||
&self,
|
||||
h: &H,
|
||||
c: &mut C,
|
||||
rng: &mut R,
|
||||
circ: &Circuit,
|
||||
) -> Result<GarbledCircuit, GeneratorError>;
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
use super::WireLabelHasher;
|
||||
use crate::block::Block;
|
||||
use aes::cipher::{
|
||||
generic_array::GenericArray, BlockCipher, BlockDecrypt, BlockEncrypt, NewBlockCipher,
|
||||
};
|
||||
use aes::{Aes128, Block as AesBlock, ParBlocks};
|
||||
use std::convert::TryInto;
|
||||
use std::ops::BitXor;
|
||||
|
||||
pub struct Aes {
|
||||
cipher: Aes128,
|
||||
}
|
||||
|
||||
impl Aes {
|
||||
pub fn new(key: &[u8; 16]) -> Self {
|
||||
Aes {
|
||||
cipher: Aes128::new(GenericArray::from_slice(key)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn xor_blocks(a: AesBlock, b: AesBlock) -> AesBlock {
|
||||
a.into_iter().zip(b).map(|(_a, _b)| _a ^ _b).collect()
|
||||
}
|
||||
|
||||
impl WireLabelHasher for Aes {
|
||||
/// π(π(x) ⊕ i) ⊕ π(x)
|
||||
fn hash(&self, label: Block, gid: usize) -> Block {
|
||||
let gid: [u8; 16] = (gid as u128).to_be_bytes();
|
||||
let label: [u8; 16] = label.to_be_bytes();
|
||||
|
||||
let mut h1 = AesBlock::from(label);
|
||||
self.cipher.encrypt_block(&mut h1);
|
||||
|
||||
let h2 = AesBlock::clone_from_slice(h1.as_slice());
|
||||
let mut h2 = h2.into_iter().zip(gid).map(|(a, b)| a ^ b).collect();
|
||||
self.cipher.encrypt_block(&mut h2);
|
||||
|
||||
let h3 = AesBlock::clone_from_slice(h2.as_slice());
|
||||
let h3: AesBlock = h3.into_iter().zip(h1).map(|(a, b)| a ^ b).collect();
|
||||
|
||||
let b: [u8; 16] = h3
|
||||
.as_slice()
|
||||
.try_into()
|
||||
.expect("Expected array to have length 16");
|
||||
let h: u128 = u128::from_be_bytes(b);
|
||||
Block::new(h)
|
||||
}
|
||||
|
||||
// fn hash_many(&mut self, labels: Vec<Block>, gids: Vec<usize>) -> Vec<Block> {
|
||||
// let gids: Vec<AesBlock> = gids
|
||||
// .into_iter()
|
||||
// .map(|gid| AesBlock::clone_from_slice((gid as u128).to_ne_bytes().as_ref()))
|
||||
// .collect();
|
||||
|
||||
// // π(x)
|
||||
// let mut h1: ParBlocks = labels
|
||||
// .into_iter()
|
||||
// .map(|label| AesBlock::from(label))
|
||||
// .collect();
|
||||
// self.cipher.encrypt_par_blocks(&mut h1);
|
||||
|
||||
// // π(π(x) ⊕ i)
|
||||
// let h2: ParBlocks = h1.iter().map(|b| AesBlock::clone_from_slice(b)).collect();
|
||||
// let mut h2: ParBlocks = h2
|
||||
// .into_iter()
|
||||
// .zip(gids)
|
||||
// .map(|(h, gid)| xor_blocks(h, gid))
|
||||
// .collect();
|
||||
// self.cipher.encrypt_par_blocks(&mut h2);
|
||||
|
||||
// // π(π(x) ⊕ i) ⊕ π(x)
|
||||
// let h: Vec<Block> = h1
|
||||
// .into_iter()
|
||||
// .zip(h2)
|
||||
// .map(|(h1, h2)| {
|
||||
// let h = xor_blocks(h1, h2);
|
||||
// let bytes: [u8; 16] = h.try_into().expect("Expected array to be length 16");
|
||||
// Block::from(bytes)
|
||||
// })
|
||||
// .collect();
|
||||
// h
|
||||
// }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_aes() {
|
||||
let key = [0u8; 16];
|
||||
let aes = Aes::new(&key);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
pub mod aes;
|
||||
|
||||
use crate::block::Block;
|
||||
|
||||
pub trait WireLabelHasher {
|
||||
fn hash(&self, label: Block, gid: usize) -> Block;
|
||||
|
||||
//fn hash_many(&mut self, labels: Vec<Block>, gids: Vec<usize>) -> Vec<Block>;
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
pub mod circuit;
|
||||
pub mod evaluator;
|
||||
pub mod generator;
|
||||
pub mod hash;
|
||||
pub mod generator;
|
||||
@@ -8,4 +8,3 @@ pub mod element;
|
||||
pub mod errors;
|
||||
pub mod garble;
|
||||
mod gate;
|
||||
pub mod ot;
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
use pop_mpc::{
|
||||
block::Block,
|
||||
circuit::Circuit,
|
||||
garble::{evaluator::*, generator::*, hash::aes::Aes},
|
||||
garble::{evaluator::*, generator::*},
|
||||
};
|
||||
use aes::cipher::{
|
||||
generic_array::GenericArray, NewBlockCipher,
|
||||
};
|
||||
use aes::Aes128;
|
||||
use rand::SeedableRng;
|
||||
use rand_chacha::ChaCha12Rng;
|
||||
|
||||
#[test]
|
||||
fn test_and_gate() {
|
||||
let mut rng = ChaCha12Rng::from_entropy();
|
||||
let h = Aes::new(&[0u8; 16]);
|
||||
let mut cipher = Aes128::new(GenericArray::from_slice(&[0u8; 16]));
|
||||
let gen = HalfGateGenerator;
|
||||
let ev = HalfGateEvaluator;
|
||||
|
||||
@@ -21,12 +25,12 @@ fn test_and_gate() {
|
||||
let y = [y_0, y_0 ^ delta];
|
||||
let gid: usize = 1;
|
||||
|
||||
let (z, table) = gen.and_gate(&h, x, y, delta, gid);
|
||||
let (z, table) = gen.and_gate(&mut cipher, x, y, delta, gid);
|
||||
|
||||
assert_eq!(ev.and_gate(&h, x[0], y[0], table, gid), z[0]);
|
||||
assert_eq!(ev.and_gate(&h, x[0], y[1], table, gid), z[0]);
|
||||
assert_eq!(ev.and_gate(&h, x[1], y[0], table, gid), z[0]);
|
||||
assert_eq!(ev.and_gate(&h, x[1], y[1], table, gid), z[1]);
|
||||
assert_eq!(ev.and_gate(&mut cipher, x[0], y[0], table, gid), z[0]);
|
||||
assert_eq!(ev.and_gate(&mut cipher, x[0], y[1], table, gid), z[0]);
|
||||
assert_eq!(ev.and_gate(&mut cipher, x[1], y[0], table, gid), z[0]);
|
||||
assert_eq!(ev.and_gate(&mut cipher, x[1], y[1], table, gid), z[1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -70,12 +74,12 @@ fn test_inv_gate() {
|
||||
#[test]
|
||||
fn test_aes_128() {
|
||||
let mut rng = ChaCha12Rng::from_entropy();
|
||||
let h = Aes::new(&[0u8; 16]);
|
||||
let mut cipher = Aes128::new(GenericArray::from_slice(&[0u8; 16]));
|
||||
let circ = Circuit::parse("circuits/aes_128_reverse.txt").unwrap();
|
||||
let gen = HalfGateGenerator;
|
||||
let ev = HalfGateEvaluator;
|
||||
|
||||
let gc = gen.garble(&h, &mut rng, &circ).unwrap();
|
||||
let gc = gen.garble(&mut cipher, &mut rng, &circ).unwrap();
|
||||
|
||||
let a: Vec<u8> = vec![1; 128];
|
||||
|
||||
@@ -89,7 +93,7 @@ fn test_aes_128() {
|
||||
.map(|(label, input)| label[input as usize])
|
||||
.collect();
|
||||
|
||||
let output_labels = ev.eval(&h, &circ, &gc, input_labels).unwrap();
|
||||
let output_labels = ev.eval(&mut cipher, &circ, &gc, input_labels).unwrap();
|
||||
let mut outputs: Vec<u8> = Vec::with_capacity(circ.noutput_wires);
|
||||
for (i, label) in output_labels.iter().enumerate() {
|
||||
outputs.push((label.lsb() ^ gc.output_bits[i]) as u8);
|
||||
|
||||
Reference in New Issue
Block a user