pub mod alsz;
pub mod chou_orlandi;
pub mod dummy;
pub mod kos;
pub mod kos_delta;
pub mod naor_pinkas;
use crate::errors::Error;
use rand::{CryptoRng, Rng};
use scuttlebutt::AbstractChannel;
pub type ChouOrlandiSender = chou_orlandi::Sender;
pub type ChouOrlandiReceiver = chou_orlandi::Receiver;
pub type DummySender = dummy::Sender;
pub type DummyReceiver = dummy::Receiver;
pub type NaorPinkasSender = naor_pinkas::Sender;
pub type NaorPinkasReceiver = naor_pinkas::Receiver;
pub type AlszSender = alsz::Sender<ChouOrlandiReceiver>;
pub type AlszReceiver = alsz::Receiver<ChouOrlandiSender>;
pub type KosSender = kos::Sender<ChouOrlandiReceiver>;
pub type KosReceiver = kos::Receiver<ChouOrlandiSender>;
pub type KosDeltaSender = kos_delta::Sender<ChouOrlandiReceiver>;
pub type KosDeltaReceiver = kos_delta::Receiver<ChouOrlandiSender>;
pub trait Sender
where
Self: Sized,
{
type Msg: Sized + AsMut<[u8]>;
fn init<C: AbstractChannel, RNG: CryptoRng + Rng>(
channel: &mut C,
rng: &mut RNG,
) -> Result<Self, Error>;
fn send<C: AbstractChannel, RNG: CryptoRng + Rng>(
&mut self,
channel: &mut C,
inputs: &[(Self::Msg, Self::Msg)],
rng: &mut RNG,
) -> Result<(), Error>;
}
pub trait FixedKeyInitializer
where
Self: Sized,
{
fn init_fixed_key<C: AbstractChannel, RNG: CryptoRng + Rng>(
channel: &mut C,
s_: [u8; 16],
rng: &mut RNG,
) -> Result<Self, Error>;
}
pub trait Receiver
where
Self: Sized,
{
type Msg: Sized + AsMut<[u8]>;
fn init<C: AbstractChannel, RNG: CryptoRng + Rng>(
channel: &mut C,
rng: &mut RNG,
) -> Result<Self, Error>;
fn receive<C: AbstractChannel, RNG: CryptoRng + Rng>(
&mut self,
channel: &mut C,
inputs: &[bool],
rng: &mut RNG,
) -> Result<Vec<Self::Msg>, Error>;
}
pub trait CorrelatedSender: Sender
where
Self: Sized,
{
fn send_correlated<C: AbstractChannel, RNG: CryptoRng + Rng>(
&mut self,
channel: &mut C,
deltas: &[Self::Msg],
rng: &mut RNG,
) -> Result<Vec<(Self::Msg, Self::Msg)>, Error>;
}
pub trait CorrelatedReceiver: Receiver
where
Self: Sized,
{
fn receive_correlated<C: AbstractChannel, RNG: CryptoRng + Rng>(
&mut self,
channel: &mut C,
inputs: &[bool],
rng: &mut RNG,
) -> Result<Vec<Self::Msg>, Error>;
}
pub trait RandomSender: Sender
where
Self: Sized,
{
fn send_random<C: AbstractChannel, RNG: CryptoRng + Rng>(
&mut self,
channel: &mut C,
m: usize,
rng: &mut RNG,
) -> Result<Vec<(Self::Msg, Self::Msg)>, Error>;
}
pub trait RandomReceiver: Receiver
where
Self: Sized,
{
fn receive_random<C: AbstractChannel, RNG: CryptoRng + Rng>(
&mut self,
channel: &mut C,
deltas: &[bool],
rng: &mut RNG,
) -> Result<Vec<Self::Msg>, Error>;
}
#[cfg(test)]
mod tests {
use super::*;
use scuttlebutt::{AesRng, Block, Channel};
use std::{
fmt::Display,
io::{BufReader, BufWriter},
os::unix::net::UnixStream,
sync::{Arc, Mutex},
};
fn rand_block_vec(size: usize) -> Vec<Block> {
(0..size).map(|_| rand::random::<Block>()).collect()
}
fn rand_bool_vec(size: usize) -> Vec<bool> {
(0..size).map(|_| rand::random::<bool>()).collect()
}
fn test_ot<OTSender: Sender<Msg = Block>, OTReceiver: Receiver<Msg = Block> + Display>() {
let m0s = rand_block_vec(128);
let m1s = rand_block_vec(128);
let bs = rand_bool_vec(128);
let m0s_ = m0s.clone();
let m1s_ = m1s.clone();
let (sender, receiver) = UnixStream::pair().unwrap();
let handle = std::thread::spawn(move || {
let mut rng = AesRng::new();
let reader = BufReader::new(sender.try_clone().unwrap());
let writer = BufWriter::new(sender);
let mut channel = Channel::new(reader, writer);
let mut ot = OTSender::init(&mut channel, &mut rng).unwrap();
let ms = m0s
.into_iter()
.zip(m1s.into_iter())
.collect::<Vec<(Block, Block)>>();
ot.send(&mut channel, &ms, &mut rng).unwrap();
ot.send(&mut channel, &ms, &mut rng).unwrap();
});
let mut rng = AesRng::new();
let reader = BufReader::new(receiver.try_clone().unwrap());
let writer = BufWriter::new(receiver);
let mut channel = Channel::new(reader, writer);
let mut ot = OTReceiver::init(&mut channel, &mut rng).unwrap();
let result = ot.receive(&mut channel, &bs, &mut rng).unwrap();
for j in 0..128 {
assert_eq!(result[j], if bs[j] { m1s_[j] } else { m0s_[j] });
}
let result = ot.receive(&mut channel, &bs, &mut rng).unwrap();
for j in 0..128 {
assert_eq!(result[j], if bs[j] { m1s_[j] } else { m0s_[j] });
}
handle.join().unwrap();
}
fn test_otext<OTSender: Sender<Msg = Block>, OTReceiver: Receiver<Msg = Block> + Display>(
ninputs: usize,
) {
let m0s = rand_block_vec(ninputs);
let m1s = rand_block_vec(ninputs);
let bs = rand_bool_vec(ninputs);
let m0s_ = m0s.clone();
let m1s_ = m1s.clone();
let (sender, receiver) = UnixStream::pair().unwrap();
let handle = std::thread::spawn(move || {
let mut rng = AesRng::new();
let reader = BufReader::new(sender.try_clone().unwrap());
let writer = BufWriter::new(sender);
let mut channel = Channel::new(reader, writer);
let mut otext = OTSender::init(&mut channel, &mut rng).unwrap();
let ms = m0s
.into_iter()
.zip(m1s.into_iter())
.collect::<Vec<(Block, Block)>>();
otext.send(&mut channel, &ms, &mut rng).unwrap();
});
let mut rng = AesRng::new();
let reader = BufReader::new(receiver.try_clone().unwrap());
let writer = BufWriter::new(receiver);
let mut channel = Channel::new(reader, writer);
let mut otext = OTReceiver::init(&mut channel, &mut rng).unwrap();
let results = otext.receive(&mut channel, &bs, &mut rng).unwrap();
handle.join().unwrap();
for j in 0..ninputs {
assert_eq!(results[j], if bs[j] { m1s_[j] } else { m0s_[j] })
}
}
fn test_cotext<
OTSender: CorrelatedSender<Msg = Block>,
OTReceiver: CorrelatedReceiver<Msg = Block> + Display,
>(
ninputs: usize,
) {
let deltas = rand_block_vec(ninputs);
let bs = rand_bool_vec(ninputs);
let out = Arc::new(Mutex::new(vec![]));
let out_ = out.clone();
let (sender, receiver) = UnixStream::pair().unwrap();
let handle = std::thread::spawn(move || {
let mut rng = AesRng::new();
let reader = BufReader::new(sender.try_clone().unwrap());
let writer = BufWriter::new(sender);
let mut channel = Channel::new(reader, writer);
let mut otext = OTSender::init(&mut channel, &mut rng).unwrap();
let mut out = out.lock().unwrap();
*out = otext
.send_correlated(&mut channel, &deltas, &mut rng)
.unwrap();
});
let mut rng = AesRng::new();
let reader = BufReader::new(receiver.try_clone().unwrap());
let writer = BufWriter::new(receiver);
let mut channel = Channel::new(reader, writer);
let mut otext = OTReceiver::init(&mut channel, &mut rng).unwrap();
let results = otext
.receive_correlated(&mut channel, &bs, &mut rng)
.unwrap();
handle.join().unwrap();
let out_ = out_.lock().unwrap();
for j in 0..ninputs {
assert_eq!(results[j], if bs[j] { out_[j].1 } else { out_[j].0 })
}
}
fn test_rotext<
OTSender: RandomSender<Msg = Block>,
OTReceiver: RandomReceiver<Msg = Block> + Display,
>(
ninputs: usize,
) {
let bs = rand_bool_vec(ninputs);
let out = Arc::new(Mutex::new(vec![]));
let out_ = out.clone();
let (sender, receiver) = UnixStream::pair().unwrap();
let handle = std::thread::spawn(move || {
let mut rng = AesRng::new();
let reader = BufReader::new(sender.try_clone().unwrap());
let writer = BufWriter::new(sender);
let mut channel = Channel::new(reader, writer);
let mut otext = OTSender::init(&mut channel, &mut rng).unwrap();
let mut out = out.lock().unwrap();
*out = otext.send_random(&mut channel, ninputs, &mut rng).unwrap();
});
let mut rng = AesRng::new();
let reader = BufReader::new(receiver.try_clone().unwrap());
let writer = BufWriter::new(receiver);
let mut channel = Channel::new(reader, writer);
let mut otext = OTReceiver::init(&mut channel, &mut rng).unwrap();
let results = otext.receive_random(&mut channel, &bs, &mut rng).unwrap();
handle.join().unwrap();
let out_ = out_.lock().unwrap();
for j in 0..ninputs {
assert_eq!(results[j], if bs[j] { out_[j].1 } else { out_[j].0 })
}
}
fn test_rotext_fixed_key<
OTSender: RandomSender<Msg = Block> + FixedKeyInitializer,
OTReceiver: RandomReceiver<Msg = Block> + Display,
>(
ninputs: usize,
) {
let bs = rand_bool_vec(ninputs);
let out = Arc::new(Mutex::new(vec![]));
let out_ = out.clone();
let (sender, receiver) = UnixStream::pair().unwrap();
let key = [1u8; 16];
let key_ = key.clone();
let handle = std::thread::spawn(move || {
let mut rng = AesRng::new();
let reader = BufReader::new(sender.try_clone().unwrap());
let writer = BufWriter::new(sender);
let mut channel = Channel::new(reader, writer);
let mut otext = OTSender::init_fixed_key(&mut channel, key_, &mut rng).unwrap();
let mut out = out.lock().unwrap();
*out = otext.send_random(&mut channel, ninputs, &mut rng).unwrap();
});
let mut rng = AesRng::new();
let reader = BufReader::new(receiver.try_clone().unwrap());
let writer = BufWriter::new(receiver);
let mut channel = Channel::new(reader, writer);
let mut otext = OTReceiver::init(&mut channel, &mut rng).unwrap();
let results = otext.receive_random(&mut channel, &bs, &mut rng).unwrap();
handle.join().unwrap();
let out_ = out_.lock().unwrap();
for j in 0..ninputs {
assert_eq!(results[j], if bs[j] { out_[j].1 } else { out_[j].0 })
}
}
#[test]
fn test_dummy() {
test_ot::<DummySender, DummyReceiver>();
}
#[test]
fn test_naor_pinkas() {
test_ot::<NaorPinkasSender, NaorPinkasReceiver>();
}
#[test]
fn test_chou_orlandi() {
test_ot::<ChouOrlandiSender, ChouOrlandiReceiver>();
}
#[test]
fn test_alsz() {
let ninputs = 1 << 10;
test_otext::<AlszSender, AlszReceiver>(ninputs);
test_cotext::<AlszSender, AlszReceiver>(ninputs);
test_rotext::<AlszSender, AlszReceiver>(ninputs);
let ninputs = (1 << 10) + 1;
test_otext::<AlszSender, AlszReceiver>(ninputs);
test_cotext::<AlszSender, AlszReceiver>(ninputs);
test_rotext::<AlszSender, AlszReceiver>(ninputs);
}
#[test]
fn test_kos() {
let ninputs = 1 << 10;
test_otext::<KosSender, KosReceiver>(ninputs);
test_cotext::<KosSender, KosReceiver>(ninputs);
test_rotext::<KosSender, KosReceiver>(ninputs);
let ninputs = (1 << 10) + 1;
test_otext::<KosSender, KosReceiver>(ninputs);
test_cotext::<KosSender, KosReceiver>(ninputs);
test_rotext::<KosSender, KosReceiver>(ninputs);
}
#[test]
fn test_kos_delta() {
let ninputs = 1 << 10;
test_otext::<KosDeltaSender, KosDeltaReceiver>(ninputs);
test_cotext::<KosDeltaSender, KosDeltaReceiver>(ninputs);
test_rotext::<KosDeltaSender, KosDeltaReceiver>(ninputs);
test_rotext_fixed_key::<KosDeltaSender, KosDeltaReceiver>(ninputs);
let ninputs = (1 << 10) + 1;
test_otext::<KosDeltaSender, KosDeltaReceiver>(ninputs);
test_cotext::<KosDeltaSender, KosDeltaReceiver>(ninputs);
test_rotext::<KosDeltaSender, KosDeltaReceiver>(ninputs);
test_rotext_fixed_key::<KosDeltaSender, KosDeltaReceiver>(ninputs);
}
}