-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
570 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,3 +12,5 @@ pub mod fpre; | |
pub mod protocol; | ||
|
||
mod garble; | ||
|
||
mod otext; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
//! Block | ||
//Later look into replacing this to __m128i, e.g., using https://docs.rs/safe_arch/latest/src/safe_arch/x86_x64/m128i_.rs.html#19 | ||
|
||
/// Block type | ||
pub type Block = u128; | ||
|
||
/// Generate a 128-bit value from two 64-bit values | ||
pub fn make_block(high: u64, low: u64) -> u128 { | ||
let high = (high as u128) << 64; | ||
let low = low as u128; | ||
high | low | ||
} | ||
|
||
/// All zero block | ||
pub const ZERO_BLOCK: Block = 0; | ||
|
||
/// All one block | ||
pub const ALL_ONE_BLOCK: Block = u128::MAX; | ||
|
||
/// XOR blocks | ||
pub fn xor_blocks_arr(res: &mut [Block], x: &[Block], y: &[Block], nblocks: usize) { | ||
for i in 0..nblocks { | ||
res[i] = x[i] ^ y[i]; | ||
} | ||
} | ||
|
||
/// XOR single block | ||
pub fn xor_blocks_arr_single(res: &mut [Block], x: &[Block], y: Block, nblocks: usize) { | ||
for i in 0..nblocks { | ||
res[i] = x[i] ^ y; | ||
} | ||
} | ||
|
||
/// Compare blocks | ||
pub fn cmp_block(x: &[Block], y: &[Block], nblocks: usize) -> bool { | ||
for i in 0..nblocks { | ||
if x[i] != y[i] { | ||
return false; | ||
} | ||
} | ||
true | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn test_make_block() { | ||
let high = 0x0123456789ABCDEF; | ||
let low = 0xFEDCBA9876543210; | ||
let block = make_block(high, low); | ||
assert_eq!(block, 0x0123456789ABCDEF_FEDCBA9876543210); | ||
} | ||
|
||
#[test] | ||
fn test_xor_blocks_arr() { | ||
let x = vec![make_block(1, 2); 3]; | ||
let y = vec![make_block(3, 4); 3]; | ||
let mut res = vec![ZERO_BLOCK; 3]; | ||
|
||
xor_blocks_arr(&mut res, &x, &y, 3); | ||
|
||
for block in &res { | ||
assert_eq!(*block, make_block(1 ^ 3, 2 ^ 4)); | ||
} | ||
} | ||
|
||
#[test] | ||
fn test_xor_blocks_arr_single() { | ||
let x = vec![make_block(1, 2); 3]; | ||
let y = make_block(5, 6); | ||
let mut res = vec![ZERO_BLOCK; 3]; | ||
|
||
xor_blocks_arr_single(&mut res, &x, y, 3); | ||
|
||
for block in &res { | ||
assert_eq!(*block, make_block(1 ^ 5, 2 ^ 6)); | ||
} | ||
} | ||
|
||
#[test] | ||
fn test_cmp_block() { | ||
let x = vec![make_block(1, 2); 3]; | ||
let y = vec![make_block(1, 2); 3]; | ||
let z = vec![make_block(3, 4); 3]; | ||
|
||
assert!(cmp_block(&x, &y, 3)); // Should be true | ||
assert!(!cmp_block(&x, &z, 3)); // Should be false | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
//! Smaller crypto utilities | ||
use blake3::Hasher; | ||
use super::block::ZERO_BLOCK; | ||
|
||
use super::block::Block; | ||
|
||
/// Function to hash data using BLAKE3 and store the result in a Block[2] array | ||
pub fn hash_once(dgst: &mut [Block; 2], data: &Block) { | ||
let mut hasher = Hasher::new(); | ||
let data_bytes = data.to_le_bytes(); | ||
hasher.update(&data_bytes); | ||
let hash = hasher.finalize(); | ||
let hash_bytes = hash.as_bytes(); | ||
dgst[0] = Block::from_le_bytes(hash_bytes[0..16].try_into().unwrap()); | ||
dgst[1] = Block::from_le_bytes(hash_bytes[16..32].try_into().unwrap()); | ||
} | ||
|
||
/// Galois Field multiplication function for Block | ||
fn gfmul(a: Block, b: Block) -> Block { | ||
let mut p: Block = 0; | ||
let mut counter = 0; | ||
let mut hi = a; | ||
while hi != 0 { | ||
if (hi & 1) != 0 { | ||
p ^= b << counter; | ||
} | ||
hi >>= 1; | ||
counter += 1; | ||
} | ||
p | ||
} | ||
|
||
/// Function to generate coefficients for almost universal hash function | ||
pub fn uni_hash_coeff_gen(coeff: &mut [Block], seed: Block, sz: usize) { | ||
// Handle the case with small `sz` | ||
coeff[0] = seed; | ||
if sz == 1 { | ||
return; | ||
} | ||
|
||
coeff[1] = gfmul(seed, seed); | ||
if sz == 2 { | ||
return; | ||
} | ||
|
||
coeff[2] = gfmul(coeff[1], seed); | ||
if sz == 3 { | ||
return; | ||
} | ||
|
||
let multiplier = gfmul(coeff[2], seed); | ||
coeff[3] = multiplier; | ||
if sz == 4 { | ||
return; | ||
} | ||
|
||
// Computing the rest with a batch of 4 | ||
let mut i = 4; | ||
while i < sz - 3 { | ||
coeff[i] = gfmul(coeff[i - 4], multiplier); | ||
coeff[i + 1] = gfmul(coeff[i - 3], multiplier); | ||
coeff[i + 2] = gfmul(coeff[i - 2], multiplier); | ||
coeff[i + 3] = gfmul(coeff[i - 1], multiplier); | ||
i += 4; | ||
} | ||
|
||
// Cleaning up with the rest | ||
let remainder = sz % 4; | ||
if remainder != 0 { | ||
let start = sz - remainder; | ||
for j in start..sz { | ||
coeff[j] = gfmul(coeff[j - 1], seed); | ||
} | ||
} | ||
} | ||
|
||
/// Function to compute inner product of two Galois field vectors with reduction | ||
pub fn vector_inn_prdt_sum_red(a: &[Block], b: &[Block], sz: usize) -> Block { | ||
let mut r = ZERO_BLOCK; | ||
|
||
// Ensure both vectors have the same size | ||
assert_eq!(a.len(), b.len()); | ||
assert_eq!(a.len(), sz); | ||
|
||
for i in 0..sz { | ||
let r1 = gfmul(a[i], b[i]); | ||
r ^= r1; | ||
} | ||
r | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
pub mod block; | ||
pub mod crypto_utils; | ||
pub mod twokeyprp; | ||
pub mod spcot_recver; | ||
pub mod spcot_sender; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
//! SPCOT receiver implementation | ||
use super::block::ZERO_BLOCK; | ||
|
||
use super::block::{make_block, Block}; | ||
use crate::channel::SimpleChannel; | ||
use super::crypto_utils::{hash_once, uni_hash_coeff_gen, vector_inn_prdt_sum_red}; | ||
use super::twokeyprp::TwoKeyPRP; | ||
|
||
/// SPCOT Receiver | ||
struct SpcotRecver { | ||
ggm_tree: Vec<Block>, | ||
m: Vec<Block>, | ||
b: Vec<bool>, | ||
choice_pos: usize, | ||
depth: usize, | ||
leave_n: usize, | ||
secret_sum_f2: Block, | ||
channel: SimpleChannel, | ||
} | ||
|
||
///SPCOT Receiver | ||
impl SpcotRecver { | ||
fn new(channel: SimpleChannel, depth: usize) -> Self { | ||
let leave_n = 1 << (depth - 1); | ||
let m = vec![Block::default(); depth - 1]; | ||
let b = vec![false; depth - 1]; | ||
|
||
SpcotRecver { | ||
ggm_tree: vec![], | ||
m, | ||
b, | ||
choice_pos: 0, | ||
depth, | ||
leave_n, | ||
secret_sum_f2: Block::default(), | ||
channel, | ||
} | ||
} | ||
|
||
///Get index | ||
fn get_index(&mut self) -> usize { | ||
self.choice_pos = 0; | ||
for &bi in self.b.iter() { | ||
self.choice_pos <<= 1; | ||
if !bi { | ||
self.choice_pos += 1; | ||
} | ||
} | ||
self.choice_pos | ||
} | ||
|
||
// TODO OTs through channel | ||
|
||
// Receive the message and reconstruct the tree | ||
fn compute(&mut self, ggm_tree_mem: Vec<Block>) { | ||
self.ggm_tree = ggm_tree_mem; | ||
self.ggm_tree_reconstruction(); | ||
self.ggm_tree[self.choice_pos] = Block::default(); | ||
|
||
let mut nodes_sum = Block::default(); | ||
let one = make_block(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFE); | ||
for i in 0..self.leave_n { | ||
self.ggm_tree[i] &= one; | ||
nodes_sum ^= self.ggm_tree[i]; | ||
} | ||
self.ggm_tree[self.choice_pos] = nodes_sum ^ self.secret_sum_f2; | ||
} | ||
|
||
/// Tree reconstruct | ||
fn ggm_tree_reconstruction(&mut self) { | ||
let mut to_fill_idx = 0; | ||
let prp = TwoKeyPRP::new(ZERO_BLOCK, make_block(0, 1)); | ||
for i in 1..self.depth { | ||
to_fill_idx *= 2; | ||
self.ggm_tree[to_fill_idx] = ZERO_BLOCK; | ||
self.ggm_tree[to_fill_idx + 1] = ZERO_BLOCK; | ||
if !self.b[i - 1] { | ||
self.layer_recover(i, 0, to_fill_idx, self.m[i - 1], &prp); | ||
to_fill_idx += 1; | ||
} else { | ||
self.layer_recover(i, 1, to_fill_idx + 1, self.m[i - 1], &prp); | ||
} | ||
} | ||
} | ||
|
||
///Recover layer | ||
fn layer_recover( | ||
&mut self, | ||
depth: usize, | ||
lr: usize, | ||
to_fill_idx: usize, | ||
sum: Block, | ||
prp: &TwoKeyPRP, | ||
) { | ||
let layer_start = 0; | ||
let item_n = 1 << depth; | ||
let mut nodes_sum = ZERO_BLOCK; | ||
let lr_start = if lr == 0 { | ||
layer_start | ||
} else { | ||
layer_start + 1 | ||
}; | ||
for i in (lr_start..item_n).step_by(2) { | ||
nodes_sum ^= self.ggm_tree[i]; | ||
} | ||
self.ggm_tree[to_fill_idx] = nodes_sum ^ sum; | ||
if depth == self.depth - 1 { | ||
return; | ||
} | ||
if item_n == 2 { | ||
let parent: &mut [Block; 2] = &mut [self.ggm_tree[0], self.ggm_tree[1]]; | ||
self.ggm_tree = prp.node_expand_2to4(parent); | ||
} else { | ||
for _ in (0..item_n - 4).rev().step_by(4) { | ||
let parent: &mut [Block; 4] = &mut [ | ||
self.ggm_tree[0], | ||
self.ggm_tree[2], | ||
self.ggm_tree[4], | ||
self.ggm_tree[6], | ||
]; | ||
self.ggm_tree = prp.node_expand_4to8(parent); | ||
} | ||
} | ||
} | ||
|
||
//Check | ||
fn consistency_check_msg_gen(&mut self, chi_alpha: &mut Block) -> Block { | ||
let mut chi = vec![Block::default(); self.leave_n]; | ||
let mut digest: [u128; 2] = [Block::default(); 2]; | ||
hash_once(&mut digest, &self.secret_sum_f2); | ||
uni_hash_coeff_gen(&mut chi, digest[0], self.leave_n); | ||
*chi_alpha = chi[self.choice_pos]; | ||
vector_inn_prdt_sum_red(&chi, &self.ggm_tree, self.leave_n) | ||
} | ||
} |
Oops, something went wrong.