moved hash implementation into block

This commit is contained in:
sinuio
2022-02-12 17:57:50 -08:00
parent 7ca9d898dc
commit aed4c855fe
12 changed files with 81 additions and 153 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,3 @@
pub mod circuit;
pub mod evaluator;
pub mod generator;
pub mod hash;
pub mod generator;

View File

@@ -8,4 +8,3 @@ pub mod element;
pub mod errors;
pub mod garble;
mod gate;
pub mod ot;

View File

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