Skip to content

Commit

Permalink
Base OT & OTe implementation started
Browse files Browse the repository at this point in the history
  • Loading branch information
kisakishy committed Jul 22, 2024
1 parent e2a9e70 commit 9351a38
Show file tree
Hide file tree
Showing 9 changed files with 318 additions and 50 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ tokio = { version = "1.35.1", features = ["full"] }
trait-variant = "0.1.1"
async-trait = "0.1.77"
aes = "0.8.4"
block-modes = "0.9.1"
block-modes = "0.9.1"
curve25519-dalek = { version = "4.1.3", features = ["rand_core", "serde"] }
47 changes: 11 additions & 36 deletions src/otext/base_cot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,13 @@ use rand::Rng;
use crate::{
channel::{MsgChannel, Channel},
otext::{
block::{make_block, Block, ZERO_BLOCK, cmp_block, block_to_bool, get_lsb},
block::{make_block, Block, ZERO_BLOCK, cmp_block, get_lsb},
constants::{ALICE, BOB},
preot::OTPre,
iknp::Iknp,
}
};

pub struct Iknp {
malicious: bool,
}

impl Iknp {
pub fn new(malicious: bool) -> Self {
Self { malicious }
}

pub fn setup_send(&self, delta_bool: &[bool]) {
// Implement setup_send logic
}

pub fn setup_recv(&self) {
// Implement setup_recv logic
}

pub fn send_cot(&self, ot_data: &mut [Block], size: usize) {
// Implement send_cot logic
}

pub fn recv_cot(&self, ot_data: &mut [Block], pre_bool_ini: &[bool], size: usize) {
// Implement recv_cot logic
}
}

pub struct BaseCot {
party: usize,
one: Block,
Expand All @@ -46,7 +21,7 @@ pub struct BaseCot {

impl BaseCot {
pub fn new(party: usize, malicious: bool) -> Self {
let iknp = Iknp::new(malicious);
let iknp = Iknp::new(ZERO_BLOCK, malicious); //TODO Set this delta right later???
let minusone = make_block(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFE);
let one = make_block(0, 1);
Self {
Expand All @@ -62,10 +37,10 @@ impl BaseCot {
pub fn cot_gen_pre_delta(&mut self, deltain: Block) {
if self.party == ALICE {
self.ot_delta = deltain;
let delta_bool = block_to_bool(self.ot_delta);
self.iknp.setup_send(&delta_bool);
//let delta_bool = block_to_bool(self.ot_delta);
//self.iknp.setup_send(&delta_bool);
} else {
self.iknp.setup_recv();
//self.iknp.setup_recv();
}
}

Expand All @@ -74,10 +49,10 @@ impl BaseCot {
let mut prg = rand::thread_rng();
let delta: Block = prg.gen();
self.ot_delta = delta & self.minusone ^ self.one;
let delta_bool = block_to_bool(self.ot_delta);
self.iknp.setup_send(&delta_bool);
//let delta_bool = block_to_bool(self.ot_delta);
//self.iknp.setup_send(&delta_bool); //TODO If the implementation we take for IKNP includes the setup, this is not needed
} else {
self.iknp.setup_recv();
//self.iknp.setup_recv();
}
}

Expand All @@ -90,7 +65,7 @@ impl BaseCot {
} else {
let mut prg = rand::thread_rng();
let pre_bool_ini = vec![prg.gen(); size as usize];
self.iknp.recv_cot(ot_data, &pre_bool_ini, size);
self.iknp.recv_cot(ot_data, pre_bool_ini.clone(), size); //TODO Check: Is it ok to clone?
let ch = [ZERO_BLOCK, make_block(0, 1)];
for i in 0..size as usize {
ot_data[i] = (ot_data[i] & self.minusone) ^ ch[pre_bool_ini[i] as usize];
Expand All @@ -109,7 +84,7 @@ impl BaseCot {
} else {
let mut prg = rand::thread_rng();
let pre_bool_ini = vec![prg.gen(); size];
self.iknp.recv_cot(&mut ot_data, &pre_bool_ini, size);
self.iknp.recv_cot(&mut ot_data, pre_bool_ini.clone(), size); //TODO Check: Is it ok to clone?
let ch = [ZERO_BLOCK, make_block(0, 1)];
for i in 0..size as usize {
ot_data[i] = (ot_data[i] & self.minusone) ^ ch[pre_bool_ini[i] as usize];
Expand Down
77 changes: 77 additions & 0 deletions src/otext/baseot.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use curve25519_dalek::ristretto::RistrettoPoint;
use curve25519_dalek::scalar::Scalar;
use curve25519_dalek::constants::RISTRETTO_BASEPOINT_POINT;
use rand::rngs::OsRng;

use crate::otext::constants::{ALICE, BOB};
use crate::channel::{MsgChannel, Channel};
use crate::otext::block::Block;
use crate::otext::utils::kdf;

use super::block::ZERO_BLOCK;

// Chou-Orlandi OT
pub struct OTCO{}

impl OTCO {
pub async fn send(&mut self, channel: &mut MsgChannel<impl Channel>, data0: & Vec<Block>, data1: & Vec<Block>, length: usize) {
let mut rng = OsRng;
let a = Scalar::random(&mut rng);
let aa = RISTRETTO_BASEPOINT_POINT * a;
let aa_inv = aa * -a;

let mut b = Vec::with_capacity(length);
let mut ba = Vec::with_capacity(length);


channel.send_to(ALICE, "asend", &aa).await.unwrap(); //NOT SURE WHICH PARTY IT IS HERE

for i in 0..length {
b[i] = channel.recv_from(ALICE, "bsend").await.unwrap();
b[i] = b[i] * a;
ba[i] = b[i] + aa_inv;
}

let mut res: [Block; 2] = [ZERO_BLOCK; 2];
for i in 0..length {
res[0] = kdf(&b[i], i) ^ data0[i];
res[1] = kdf(&ba[i], i) ^ data1[i];
channel.send_to(ALICE, "res", &res).await.unwrap();
}
}

pub async fn recv(&mut self, channel: &mut MsgChannel<impl Channel>, data: &mut Vec<Block>, b: Vec<bool>, length: usize) {
let mut rng = OsRng;

let mut bb = Vec::with_capacity(length);
for _ in 0..length {
bb.push(Scalar::random(&mut rng));
}

let a: RistrettoPoint = channel.recv_from(BOB, "asend").await.unwrap();
let mut bigb = Vec::with_capacity(length);
let mut a_s = Vec::with_capacity(length);

for i in 0..length {
bigb[i] = RISTRETTO_BASEPOINT_POINT * bb[i];
if b[i] {
bigb[i] += a;
}
channel.send_to(BOB, "bsend", &bigb[i]).await.unwrap();
}

for i in 0..length {
a_s[i] = a * bb[i];
}

for i in 0..length {
let res: [Block; 2] = channel.recv_from(BOB, "res").await.unwrap();
let kdf_result = kdf(&a_s[i], i);
if b[i] {
data[i] = kdf_result ^ res[1];
} else {
data[i] = kdf_result ^ res[0];
}
}
}
}
30 changes: 30 additions & 0 deletions src/otext/block.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
//! 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

use rand::rngs::OsRng;
use rand::RngCore;

/// Block type
pub type Block = u128;

Expand Down Expand Up @@ -57,3 +60,30 @@ pub fn block_to_bool(mut b: Block) -> Vec<bool> {
}
res
}

fn bool_to_int(data: &[bool]) -> u64 {
let mut ret: u64 = 0;

for i in 0..std::mem::size_of::<u64>() * 8 {
let s: u64 = (data[i] as u8).into();
let s = s << i;
ret |= s;
}

ret
}

pub fn bool_to_block(data: &[bool]) -> Block {
assert_eq!(data.len(), 128); // Ensure data has exactly 128 elements

let lo = bool_to_int(&data[64..]);
let hi = bool_to_int(&data[..64]);

make_block(hi, lo)
}

pub fn random_block(rng: &mut OsRng) -> Block {
let upper = rng.next_u64() as u128;
let lower = rng.next_u64() as u128;
(upper << 64) | lower
}
16 changes: 9 additions & 7 deletions src/otext/ferret_cot.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rand::{
rngs::{OsRng, StdRng},
Rng, SeedableRng,
rngs::{StdRng, OsRng},
};

use crate::{
Expand All @@ -12,7 +12,7 @@ use crate::{
lpn_f2::LpnF2,
mpcot::MpcotReg,
preot::OTPre,
}
},
};

pub struct FerretCOT {
Expand Down Expand Up @@ -263,12 +263,14 @@ impl FerretCOT {
}
if round_memcpy {
self.extend_f2k(channel).await;
data2[..self.ot_limit as usize].copy_from_slice(&self.ot_data[..self.ot_limit as usize]);
data2 = &mut data2[self.ot_limit as usize..]; //TODO CHECK pt+=ot_limit ???
data2[..self.ot_limit as usize]
.copy_from_slice(&self.ot_data[..self.ot_limit as usize]);
data2 = &mut data2[self.ot_limit as usize..]; //TODO CHECK pt+=ot_limit ???
}
if last_round_ot > 0 {
self.extend_f2k(channel).await;
data2[..last_round_ot as usize].copy_from_slice(&self.ot_data[..last_round_ot as usize]);
data2[..last_round_ot as usize]
.copy_from_slice(&self.ot_data[..last_round_ot as usize]);
self.ot_used = last_round_ot;
}
}
Expand All @@ -287,9 +289,9 @@ mod tests {

#[tokio::test]
async fn test_ferret() {
let party = 1; // Example party value
let mut channels = SimpleChannel::channels(2);
let mut msgchannel1 = MsgChannel(channels.pop().unwrap());
FerretCOT::new(party, true, FERRET_B13, &mut msgchannel1).await;
//FerretCOT::new(1, true, FERRET_B13, &mut msgchannel1).await;
//FerretCOT::new(0, true, FERRET_B13, &mut msgchannel1).await;
}
}
125 changes: 125 additions & 0 deletions src/otext/iknp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
use crate::channel::{Channel, MsgChannel};
use crate::otext::baseot::OTCO;
use crate::otext::block::{bool_to_block, Block, ZERO_BLOCK};
use rand::prelude::*;
use rand::rngs::OsRng;
use rand::{RngCore, SeedableRng};

use super::block::random_block;

const BLOCK_SIZE: usize = 1024 * 2;

pub struct Iknp {
pub ot_delta: Block,
base_ot: OTCO,
setup: bool,
local_out: [Block; BLOCK_SIZE],
s: [bool; 128],
local_r: [bool; 256],
prg: OsRng,
g0: [OsRng; 128],
g1: [OsRng; 128],
malicious: bool,
k0: [Block; 128],
k1: [Block; 128],
}

impl Iknp {
pub fn new(delta: Block, malicious: bool) -> Self {
Iknp {
ot_delta: delta,
base_ot: OTCO {},
setup: false,
local_out: [ZERO_BLOCK; BLOCK_SIZE],
s: [false; 128],
local_r: [false; 256],
prg: OsRng,
g0: [OsRng; 128],
g1: [OsRng; 128],
malicious,
k0: [ZERO_BLOCK; 128],
k1: [ZERO_BLOCK; 128],
}
}

async fn setup_send_delta(&mut self, channel: &mut MsgChannel<impl Channel>, in_s: [bool; 128]) {
self.setup = true;

self.s.copy_from_slice(&in_s);

self.base_ot
.recv(channel, &mut self.k0.to_vec(), self.s.to_vec(), 128).await;

//for i in 0..128 {
//self.g0[i].reseed(&self.k0[i]);
//TODO figure out reseeding here!
//}
self.ot_delta = bool_to_block(&self.s);
}

async fn setup_send(&mut self, channel: &mut MsgChannel<impl Channel>) {
self.setup = true;
for i in 0..128 {
self.s[i] = self.prg.next_u32() % 2 == 1;
}

self.base_ot
.recv(channel, &mut self.k0.to_vec(), self.s.to_vec(), 128).await;

//for i in 0..128 {
//self.g0[i].reseed(&self.k0[i]);
//TODO figure out reseeding here!
//}
self.ot_delta = bool_to_block(&self.s);
}

async fn setup_recv(&mut self, channel: &mut MsgChannel<impl Channel>) {
self.setup = true;

for i in 0..128 {
self.k0[i] = random_block(&mut self.prg);
self.k1[i] = random_block(&mut self.prg);
}
self.base_ot.send(channel, &mut self.k0.to_vec(), &self.k1.to_vec(), 128).await;

/*for i in 0..128 {
self.g0[i].reseed(&self.k0[i]); // Assuming PRG has a reseed method
self.g1[i].reseed(&self.k1[i]); // Assuming PRG has a reseed method
}*/
}

pub fn recv_pre(&self, data: &mut Vec<Block>, b: Vec<bool>, length: usize) {
// implement ALSZ OT
}

pub fn send_pre(&self, out: &mut Vec<Block>, length: usize) {
// implement ALSZ OT
}

pub fn send_check(&self, out: &mut Vec<Block>, length: usize) -> bool {
//implement KOS check
true
}

pub fn recv_check(&self, out: &mut Vec<Block>, r: Vec<bool>, length: usize) {
// implement KOS check
}

pub fn send_cot(&self, data: &mut Vec<Block>, length: usize) {
self.send_pre(data, length);

if self.malicious {
if !self.send_check(data, length) {
panic!("OT Extension check failed");
}
}
}

pub fn recv_cot(&self, data: &mut Vec<Block>, b: Vec<bool>, length: usize) {
self.recv_pre(data, b.clone(), length);

if self.malicious {
self.recv_check(data, b, length);
}
}
}
Loading

0 comments on commit 9351a38

Please sign in to comment.