This commit is contained in:
Michael Rosenberg
2022-06-28 02:54:51 -04:00
parent b4c46e1cb7
commit ec8250a72e
24 changed files with 601 additions and 732 deletions

5
.gitignore vendored
View File

@@ -13,7 +13,4 @@ Cargo.lock
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
# macOS puts these everywhere
.DS_Store
tlsn-mpc-circuits/compiled/*
tlsn-mpc-circuits/compiled/*

View File

@@ -4,7 +4,7 @@ use futures::{AsyncRead, AsyncWrite};
use mpc_aio::ot::{
ExtOTReceive, ExtOTSend, ExtReceiver, ExtSender, OTReceive, OTSend, Receiver, Sender,
};
use mpc_core::ot::{DhOtSender, ExtReceiverCore, ExtSenderCore, ReceiverCore};
use mpc_core::ot::{ExtReceiverCore, ExtSenderCore, ReceiverCore, SenderCore};
use mpc_core::Block;
use rand::{thread_rng, Rng};
use tokio;
@@ -83,7 +83,7 @@ async fn send<S: AsyncWrite + AsyncRead + Send + Unpin>(
let mut sender = ExtSender::new(ExtSenderCore::new(values.len()), stream);
let _ = sender.send(&values).await;
} else {
let mut sender = Sender::new(DhOtSender::new(values.len()), stream);
let mut sender = Sender::new(SenderCore::new(values.len()), stream);
let _ = sender.send(&values).await;
}

View File

@@ -56,10 +56,10 @@ where
let setup = self.ot.setup(choice, setup)?;
trace!("Sending ReceiverSetup: {:?}", &setup);
self.stream.send(Message::ReceiverChoices(setup)).await?;
self.stream.send(Message::ReceiverSetup(setup)).await?;
let payload = match self.stream.next().await {
Some(Ok(Message::SenderOutput(m))) => m,
Some(Ok(Message::SenderPayload(m))) => m,
Some(Ok(m)) => return Err(OTError::Unexpected(m)),
Some(Err(e)) => return Err(e)?,
None => return Err(IOError::new(ErrorKind::UnexpectedEof, ""))?,

View File

@@ -51,7 +51,7 @@ where
self.stream.send(Message::SenderSetup(setup)).await?;
let setup = match self.stream.next().await {
Some(Ok(Message::ReceiverChoices(m))) => m,
Some(Ok(Message::ReceiverSetup(m))) => m,
Some(Ok(m)) => return Err(OTError::Unexpected(m)),
Some(Err(e)) => return Err(e)?,
None => return Err(IOError::new(ErrorKind::UnexpectedEof, ""))?,
@@ -61,7 +61,7 @@ where
let payload = self.ot.send(payload, setup)?;
trace!("Sending SenderPayload: {:?}", &payload);
self.stream.send(Message::SenderOutput(payload)).await?;
self.stream.send(Message::SenderPayload(payload)).await?;
Ok(())
}

View File

@@ -33,7 +33,6 @@ anyhow = "1.0.55"
elliptic-curve = { version = "0.11.12", optional = true }
p256 = { version = "0.10.1", optional = true }
derive_builder = "0.11.2"
merlin = "3.0.0"
[dependencies.paillier]
package = "kzen-paillier"

View File

@@ -1,8 +1,8 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use mpc_core::block::{Block, BLOCK_ONES};
use mpc_core::ot::{
DhOtSender, ExtReceiveCore, ExtReceiverCore, ExtSendCore, ExtSenderCore, ReceiveCore,
ReceiverCore, SendCore,
ExtReceiveCore, ExtReceiverCore, ExtSendCore, ExtSenderCore, ReceiveCore, ReceiverCore,
SendCore, SenderCore,
};
use mpc_core::utils::u8vec_to_boolvec;
use rand::RngCore;
@@ -15,7 +15,7 @@ fn criterion_benchmark(c: &mut Criterion) {
let choice = [false; 1024];
bench.iter(|| {
let mut sender = DhOtSender::new(1024);
let mut sender = SenderCore::new(1024);
let sender_setup = sender.setup();
let mut receiver = ReceiverCore::new(1024);

View File

@@ -3,12 +3,9 @@
// For simplicity, this example shows how to use OT components in memory.
use mpc_core::block::Block;
use mpc_core::ot::dh_ot::{DhOtReceiver, DhOtSender};
use rand::thread_rng;
use mpc_core::ot::{ReceiveCore, ReceiverCore, SendCore, SenderCore};
pub fn main() {
let mut rng = thread_rng();
// Receiver choice bits
let choice = vec![false, true, false, false, true, true, false, true];
@@ -29,12 +26,12 @@ pub fn main() {
println!("Sender inputs: {:?}", &inputs);
// First the sender creates a setup message and passes it to sender
let mut sender = DhOtSender::default();
let setup = sender.setup(&mut rng);
let mut sender = SenderCore::new(inputs.len());
let setup = sender.setup();
// Receiver takes sender's setup and creates its own setup message
let mut receiver = DhOtReceiver::default();
let setup = receiver.setup(&mut rng, &choice, setup).unwrap();
let mut receiver = ReceiverCore::new(choice.len());
let setup = receiver.setup(&choice, setup).unwrap();
// Finally, sender encrypts their inputs and sends them to receiver
let payload = sender.send(&inputs, setup).unwrap();

View File

@@ -3,10 +3,7 @@
// For simplicity, this example shows how to use OT components in memory.
use mpc_core::block::Block;
use mpc_core::ot::extension::{
kos15::{Kos15Receiver, Kos15Sender},
ExtReceiveCore, ExtSendCore,
};
use mpc_core::ot::{ExtReceiveCore, ExtReceiverCore, ExtSendCore, ExtSenderCore};
pub fn main() {
// Receiver choice bits
@@ -29,11 +26,11 @@ pub fn main() {
println!("Sender inputs: {:?}", &inputs);
// First the receiver creates a setup message and passes it to sender
let mut receiver = Kos15Receiver::new(inputs.len());
let mut receiver = ExtReceiverCore::new(inputs.len());
let base_sender_setup = receiver.base_setup().unwrap();
// Sender takes receiver's setup and creates its own setup message
let mut sender = Kos15Sender::new(inputs.len());
let mut sender = ExtSenderCore::new(inputs.len());
let base_receiver_setup = sender.base_setup(base_sender_setup).unwrap();
// Now the receiver generates some seeds from sender's setup and uses OT to transfer them

View File

@@ -6,10 +6,7 @@
// For simplicity, this example shows how to use OT components in memory.
use mpc_core::block::Block;
use mpc_core::ot::extension::{
kos15::{Kos15Receiver, Kos15Sender},
ExtRandomReceiveCore, ExtRandomSendCore, ExtReceiveCore, ExtSendCore,
};
use mpc_core::ot::{ExtRandomReceiveCore, ExtRandomSendCore, ExtReceiverCore, ExtSenderCore};
pub fn main() {
// Sender messages the receiver chooses from
@@ -27,11 +24,11 @@ pub fn main() {
println!("Sender inputs: {:?}", &inputs);
// First the receiver creates a setup message and passes it to sender
let mut receiver = Kos15Receiver::new(inputs.len());
let mut receiver = ExtReceiverCore::new(inputs.len());
let base_sender_setup = receiver.base_setup().unwrap();
// Sender takes receiver's setup and creates its own setup message
let mut sender = Kos15Sender::new(inputs.len());
let mut sender = ExtSenderCore::new(inputs.len());
let base_receiver_setup = sender.base_setup(base_sender_setup).unwrap();
// Now the receiver generates some seeds from sender's setup and uses OT to transfer them
@@ -39,7 +36,7 @@ pub fn main() {
sender.base_receive(base_payload).unwrap();
// Receiver generates OT extension setup and passes it to sender
let receiver_setup = receiver.rand_extension_setup().unwrap();
let receiver_setup = receiver.extension_setup().unwrap();
// Sender takes receiver's setup and runs its own extension setup
sender.extension_setup(receiver_setup).unwrap();
@@ -50,13 +47,13 @@ pub fn main() {
// their choices depending on what they received in earlier batches
let initial_choices = vec![false, true];
let derandomize = receiver.derandomize(&initial_choices).unwrap();
let initial_payload = sender.rand_send(&inputs[..2], derandomize).unwrap();
received.append(&mut receiver.rand_receive(initial_payload).unwrap());
let initial_payload = sender.send(&inputs[..2], derandomize).unwrap();
received.append(&mut receiver.receive(initial_payload).unwrap());
for chunk in inputs[2..].chunks(2) {
let received_sum: u128 = received.iter().map(|b| b.inner()).sum();
let choice = received_sum % 2 == 0;
let derandomize = receiver.derandomize(&[choice, !choice]).unwrap();
let payload = sender.rand_send(&chunk, derandomize).unwrap();
let payload = sender.send(&chunk, derandomize).unwrap();
received.append(&mut receiver.receive(payload).unwrap());
}

View File

@@ -13,13 +13,13 @@ message SenderSetup {
// Message sent by OT Sender containing encrypted values
message SenderPayload {
// Encrypted values
repeated core.LabelPair ciphertexts = 1;
repeated core.LabelPair encrypted_values = 1;
}
// Setup message sent by Base OT Receiver
message ReceiverSetup {
// The blinded choice bit sent by the receiver
repeated core.RistrettoPoint blinded_choices = 1;
// Keys used to encrypt values by Sender
repeated core.RistrettoPoint keys = 1;
}
// Setup message sent by OT Receiver
@@ -38,7 +38,7 @@ message ExtDerandomize {
message ExtSenderPayload {
// Encrypted values
repeated core.LabelPair ciphertexts = 1;
repeated core.LabelPair encrypted_values = 1;
}
// Setup message sent by Base OT Sender in preparation for the OT extension
@@ -75,4 +75,4 @@ message Message {
BaseReceiverSetup base_receiver_setup = 8;
BaseSenderPayload base_sender_payload = 9;
}
}
}

View File

@@ -1,7 +1,9 @@
use cipher::{consts::U16, generic_array::GenericArray, BlockCipher, BlockEncrypt};
use core::ops::{BitAnd, BitXor};
use curve25519_dalek::ristretto::RistrettoPoint;
use rand::{CryptoRng, Rng};
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use std::convert::{From, TryInto};
#[repr(transparent)]
@@ -42,7 +44,7 @@ impl Block {
// hash, i.e. instead of Hash(x, i) we must do C(C(x) xor i) xor C(x).
pub fn hash_tweak<C: BlockCipher<BlockSize = U16> + BlockEncrypt>(
&self,
c: &C,
c: &mut C,
tweak: usize,
) -> Self {
let gid: [u8; 16] = (tweak as u128).to_be_bytes();
@@ -66,6 +68,17 @@ impl Block {
Self::new(h)
}
#[inline]
pub fn hash_point(point: &RistrettoPoint, tweak: u32) -> Self {
let mut hasher = Sha256::new();
hasher.update(point.compress().as_bytes());
hasher.update(tweak.to_be_bytes());
let h: [u8; 16] = hasher.finalize()[..16]
.try_into()
.expect("Unable to convert hash to block");
Self::from(h)
}
#[inline]
pub fn zero() -> Self {
Self(0)

View File

@@ -1,96 +0,0 @@
//! This module implements the CO15 Oblivious Transfer protocol from
//! [ref1] https://eprint.iacr.org/2015/267.pdf (see Figure 1)
pub mod receiver;
pub mod sender;
pub use receiver::*;
pub use sender::*;
use crate::{ot::base::ReceiverCoreError, Block};
use curve25519_dalek::ristretto::RistrettoPoint;
use sha2::{Digest, Sha256};
pub(crate) const DOMAIN_SEP: &[u8] = b"CO15 DH-OT";
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct SenderSetup {
pub public_key: RistrettoPoint,
}
/// The final output of the sender to the receiver
#[derive(Clone, Debug, PartialEq)]
pub struct SenderPayload {
/// The pairs of ciphertexts output by the sender. At most one of these can be decrypted by the
/// receiver.
pub ciphertexts: Vec<[DhOtCiphertext; 2]>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct ReceiverChoices {
pub blinded_choices: Vec<RistrettoPoint>,
}
/// Hashes a ristretto point to a symmetric key
pub(crate) fn hash_point(point: &RistrettoPoint, tweak: &[u8]) -> Block {
// Compute H(tweak || point)
let mut h = Sha256::new();
h.update(&tweak);
h.update(point.compress().as_bytes());
let digest = h.finalize();
// Copy the first 16 bytes into a Block
let mut block = [0u8; 16];
block.copy_from_slice(&digest[..16]);
block.into()
}
// We just do block encryption the ordinary way
pub(crate) type DhOtCiphertext = Block;
// Encrypts an input: E_k(m) = k ⊕ m
fn encrypt_input(key: Block, input: Block) -> DhOtCiphertext {
key ^ input
}
// Decrypts an input: D_k(c) = k ⊕ c
fn decrypt_input(key: Block, ct: DhOtCiphertext) -> Result<Block, ReceiverCoreError> {
Ok(key ^ ct)
}
// Unclear if we need to do quasi-authenticated encryption as below. Relevant Github issue:
// https://github.com/emp-toolkit/emp-ot/issues/74#issuecomment-1151550188
/*
// The encryption scheme in CO15 produces a ciphertext and a tag, both 16 bytes
pub(crate) type DhOtCiphertext = [Block; 2];
// Encrypts an input according to CO15: E_k(m) = (k[:16] ⊕ m, k[16:])
fn encrypt_input(key: &[u8; 32], input: Block) -> DhOtCiphertext {
// Break the key into two blocks, α and β
let mut alpha_buf = [0u8; 16];
let mut beta_buf = [0u8; 16];
alpha_buf.copy_from_slice(&key[..16]);
beta_buf.copy_from_slice(&key[16..]);
let alpha = Block::from(alpha_buf);
let beta = Block::from(beta_buf);
[input ^ alpha, beta]
}
// Decrypts an input according to CO15: D_k(c) = k[:16] ⊕ c[:16] if k[16:] == c[:16], else ⊥
fn decrypt_input(key: &[u8; 32], ct: &DhOtCiphertext) -> Result<Block, ReceiverCoreError> {
// Break the key into two blocks, α and β
let mut alpha_buf = [0u8; 16];
let mut beta_buf = [0u8; 16];
alpha_buf.copy_from_slice(&key[..16]);
beta_buf.copy_from_slice(&key[16..]);
let alpha = Block::from(alpha_buf);
let beta = Block::from(beta_buf);
if !bool::from(beta.ct_eq(&ct[1])) {
Err(ReceiverCoreError::MalformedCiphertext)
} else {
Ok(alpha ^ ct[0])
}
}
*/

View File

@@ -1,127 +0,0 @@
use crate::{
ot::base::{
dh_ot::{
decrypt_input, hash_point, ReceiverChoices, ReceiverCoreError, SenderPayload,
SenderSetup, DOMAIN_SEP,
},
ReceiverState,
},
Block,
};
use curve25519_dalek::{
constants::RISTRETTO_BASEPOINT_TABLE,
ristretto::{RistrettoBasepointTable, RistrettoPoint},
scalar::Scalar,
};
use merlin::Transcript;
use rand::{CryptoRng, RngCore};
pub struct DhOtReceiver {
/// The current state of the protocol
state: ReceiverState,
/// The transcript of the protocol so far
transcript: Transcript,
/// The keys used to decrypt the sender's responses
decryption_keys: Option<Vec<Block>>,
/// The bits that this receiver picked
choices: Option<Vec<bool>>,
}
impl Default for DhOtReceiver {
fn default() -> Self {
DhOtReceiver {
state: ReceiverState::Initialized,
transcript: Transcript::new(DOMAIN_SEP),
decryption_keys: None,
choices: None,
}
}
}
impl DhOtReceiver {
/// Returns current state of this OT protocol
pub fn state(&self) -> ReceiverState {
self.state
}
/// Constructs all the blinded choices, given the sender's pubkey
pub fn setup<R: CryptoRng + RngCore>(
&mut self,
rng: &mut R,
choices: &[bool],
sender_setup: SenderSetup,
) -> Result<ReceiverChoices, ReceiverCoreError> {
// Log the sending of the pubkey
self.transcript
.append_message(b"pubkey", sender_setup.public_key.compress().as_bytes());
// point_table is A in [ref1]
let public_key = sender_setup.public_key;
let point_table = RistrettoBasepointTable::create(&public_key);
// Construct the return value and compute the decryption keys in advance for the sender's
// response ciphertexts
let (blinded_choices, decryption_keys): (Vec<RistrettoPoint>, Vec<Block>) = choices
.iter()
.map(|c| {
let b = Scalar::random(rng);
// blinded_choice is B in [ref1]
let blinded_choice = if *c {
public_key + &b * &RISTRETTO_BASEPOINT_TABLE
} else {
&b * &RISTRETTO_BASEPOINT_TABLE
};
// Witness the blinded choice in the transcript
self.transcript
.append_message(b"B", blinded_choice.compress().as_bytes());
// Construct a tweak to domain-separate the ristretto point hashes
let mut tweak = [0u8; 16];
self.transcript.challenge_bytes(b"tweak", &mut tweak);
// dec_key is k_r in [ref1] == hash(A^b)
let dec_key = hash_point(&(&b * &point_table), &tweak);
// we send the choice values to the Sender and keep the h values
(blinded_choice, dec_key)
})
.unzip();
// Update the state
self.decryption_keys = Some(decryption_keys);
self.choices = Some(Vec::from(choices));
self.state = ReceiverState::Initialized;
// Return the blinded choices
Ok(ReceiverChoices { blinded_choices })
}
/// Decrypts the OT sender's ciphertexts
pub fn receive(&mut self, payload: SenderPayload) -> Result<Vec<Block>, ReceiverCoreError> {
if self.state != ReceiverState::Initialized {
return Err(ReceiverCoreError::NotSetup);
}
let keys = self.decryption_keys.as_ref().unwrap();
let selected_inputs: Result<Vec<Block>, ReceiverCoreError> = self
.choices
.as_ref()
.unwrap()
.iter()
.zip(keys)
.zip(payload.ciphertexts.iter())
.map(|((&c, &key), [ct0, ct1])| {
// Select an encrypted value based on the choices bit
let ct = if c { ct1 } else { ct0 };
// Decrypt it with the corresponding key
decrypt_input(key, *ct)
})
.collect();
// Update the state regardless of whether this OT succeeded or not
self.state = ReceiverState::Complete;
selected_inputs
}
}

View File

@@ -1,106 +0,0 @@
use crate::{
ot::base::{
dh_ot::{
encrypt_input, hash_point, DhOtCiphertext, ReceiverChoices, SenderPayload, SenderSetup,
DOMAIN_SEP,
},
SenderCoreError, SenderState,
},
Block,
};
use curve25519_dalek::{
constants::RISTRETTO_BASEPOINT_TABLE, ristretto::RistrettoPoint, scalar::Scalar,
};
use merlin::Transcript;
use rand::{CryptoRng, RngCore};
pub struct DhOtSender {
/// The current state of the protocol
state: SenderState,
/// The transcript of the protocol so far
transcript: Transcript,
/// The private_key is random `a` in [ref1]
private_key: Option<Scalar>,
// The public_key is `A == g^a` in [ref1]
public_key: Option<RistrettoPoint>,
}
impl Default for DhOtSender {
fn default() -> Self {
DhOtSender {
private_key: None,
public_key: None,
state: SenderState::Initialized,
transcript: Transcript::new(DOMAIN_SEP),
}
}
}
impl DhOtSender {
/// Generates the keypair to be used by the sender for this OT
pub fn setup<R: CryptoRng + RngCore>(&mut self, rng: &mut R) -> SenderSetup {
// Randomly sample a
let private_key = Scalar::random(rng);
// Compute the pubkey A = aG where G is a generator
let public_key = &private_key * &RISTRETTO_BASEPOINT_TABLE;
// Update the state
self.private_key = Some(private_key);
self.public_key = Some(public_key);
self.state = SenderState::ReadyToSend;
// Log the sending of the pubkey
self.transcript
.append_message(b"pubkey", public_key.compress().as_bytes());
// Return the pubkey
SenderSetup { public_key }
}
/// For each i, sends `inputs[i][0]` or `inputs[i][1]` base on the corresponding receiver's
/// choices. Panics if `inputs.len() != receivers_choices.blinded_choices.len()`.
pub fn send(
&mut self,
inputs: &[[Block; 2]],
receivers_choices: ReceiverChoices,
) -> Result<SenderPayload, SenderCoreError> {
// This sender needs to be ready to send, and the number of inputs needs to be equal to the
// number of choices
if self.state != SenderState::ReadyToSend {
return Err(SenderCoreError::NotSetup);
}
let private_key = self.private_key.unwrap();
// ys is A^a in [ref1]
let ys = private_key * self.public_key.unwrap();
// Compute and collect all the OT ciphertexts
let ciphertexts: Vec<[DhOtCiphertext; 2]> = inputs
.iter()
.zip(receivers_choices.blinded_choices)
.map(|(input, receivers_choice)| {
// Witness the receiver's choice in the transcript
self.transcript
.append_message(b"B", &*receivers_choice.compress().as_bytes());
// Construct a tweak to domain-separate the ristretto point hashes
let mut tweak = [0u8; 16];
self.transcript.challenge_bytes(b"tweak", &mut tweak);
// yr is B^a in [ref1]
let yr = private_key * receivers_choice;
let k0 = hash_point(&yr, &tweak).into();
// yr - ys == (B/A)^a in [ref1]
let k1 = hash_point(&(yr - ys), &tweak).into();
[encrypt_input(k0, input[0]), encrypt_input(k1, input[1])]
})
.collect();
// Update the state and return the ciphertexts
self.state = SenderState::Complete;
Ok(SenderPayload { ciphertexts })
}
}

View File

@@ -16,6 +16,4 @@ pub enum ReceiverCoreError {
NotSetup,
#[error("Provided incorrect number of choice bits")]
InvalidChoiceLength,
#[error("Sender's ciphertext is malformed")]
MalformedCiphertext,
}

View File

@@ -1,24 +1,37 @@
//! This crate implements types and imple
//! this crate implements the CO15 Oblivious Transfer protocol from
//! [ref1] https://eprint.iacr.org/2015/267.pdf (see Figure 1)
pub mod dh_ot;
pub mod errors;
pub mod receiver;
pub mod sender;
pub use errors::*;
/// The state of an OT sender
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum SenderState {
Initialized,
ReadyToSend,
Complete,
pub use receiver::{ReceiverCore, ReceiverSetup};
pub use sender::{SenderCore, SenderPayload, SenderSetup};
pub trait SendCore {
fn state(&self) -> sender::State;
fn setup(&mut self) -> SenderSetup;
fn send(
&mut self,
inputs: &[[crate::Block; 2]],
receiver_setup: ReceiverSetup,
) -> Result<SenderPayload, SenderCoreError>;
}
/// The state of an OT receiver
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ReceiverState {
Initialized,
Setup,
Complete,
pub trait ReceiveCore {
fn state(&self) -> receiver::State;
fn setup(
&mut self,
choice: &[bool],
sender_setup: SenderSetup,
) -> Result<ReceiverSetup, ReceiverCoreError>;
fn receive(&mut self, payload: SenderPayload) -> Result<Vec<crate::Block>, ReceiverCoreError>;
}
#[cfg(test)]
@@ -29,15 +42,12 @@ pub mod tests {
use rand::{thread_rng, RngCore};
use rstest::*;
// We test the CO15 scheme only
use dh_ot::*;
pub mod fixtures {
use super::*;
pub struct Data {
pub sender_setup: SenderSetup,
pub receiver_setup: ReceiverChoices,
pub receiver_setup: ReceiverSetup,
pub sender_payload: SenderPayload,
pub receiver_values: Vec<Block>,
}
@@ -62,14 +72,11 @@ pub mod tests {
#[fixture]
#[once]
pub fn ot_core_data(choice: &Vec<bool>, values: &Vec<[Block; 2]>) -> Data {
let mut rng = thread_rng();
let mut sender = DhOtSender::default();
let sender_setup = sender.setup(&mut rng);
let mut receiver = DhOtReceiver::default();
let receiver_setup = receiver.setup(&mut rng, choice, sender_setup).unwrap();
let mut sender = SenderCore::new(values.len());
let sender_setup = sender.setup();
let mut receiver = ReceiverCore::new(choice.len());
let receiver_setup = receiver.setup(choice, sender_setup).unwrap();
let sender_payload = sender.send(values, receiver_setup.clone()).unwrap();
let receiver_values = receiver.receive(sender_payload.clone()).unwrap();
@@ -97,13 +104,13 @@ pub mod tests {
.map(|(input, choice)| input[*choice as usize])
.collect();
let mut sender = DhOtSender::default();
let sender_setup = sender.setup(&mut rng);
let mut sender = SenderCore::new(s_inputs.len());
let sender_setup = sender.setup();
let mut receiver = DhOtReceiver::default();
let receiver_choices = receiver.setup(&mut rng, &choice, sender_setup).unwrap();
let mut receiver = ReceiverCore::new(choice.len());
let receiver_setup = receiver.setup(&choice, sender_setup).unwrap();
let send = sender.send(&s_inputs, receiver_choices).unwrap();
let send = sender.send(&s_inputs, receiver_setup).unwrap();
let receive = receiver.receive(send).unwrap();
assert_eq!(expected, receive);
}

View File

@@ -0,0 +1,120 @@
use curve25519_dalek::{
constants::RISTRETTO_BASEPOINT_TABLE,
ristretto::{RistrettoBasepointTable, RistrettoPoint},
scalar::Scalar,
};
use rand::{CryptoRng, Rng, SeedableRng};
use rand_chacha::ChaCha12Rng;
use super::{ReceiveCore, ReceiverCoreError, SenderPayload, SenderSetup};
use crate::Block;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
pub enum State {
Initialized,
Setup,
Complete,
}
pub struct ReceiverCore<R = ChaCha12Rng> {
rng: R,
count: usize,
hashes: Option<Vec<Block>>,
choice: Option<Vec<bool>>,
state: State,
}
#[derive(Clone, Debug, PartialEq)]
pub struct ReceiverSetup {
pub keys: Vec<RistrettoPoint>,
}
impl ReceiverCore {
pub fn new(count: usize) -> Self {
Self {
rng: ChaCha12Rng::from_entropy(),
count,
hashes: None,
choice: None,
state: State::Initialized,
}
}
}
impl<R: Rng + CryptoRng> ReceiverCore<R> {
pub fn new_from_rng(rng: R, count: usize) -> Self {
Self {
rng,
count,
hashes: None,
choice: None,
state: State::Initialized,
}
}
}
impl<R: Rng + CryptoRng> ReceiveCore for ReceiverCore<R> {
fn state(&self) -> State {
self.state
}
fn setup(
&mut self,
choice: &[bool],
sender_setup: SenderSetup,
) -> Result<ReceiverSetup, ReceiverCoreError> {
if choice.len() != self.count {
return Err(ReceiverCoreError::InvalidChoiceLength);
}
// point_table is A in [ref1]
let point_table = RistrettoBasepointTable::create(&sender_setup.public_key);
let zero = &Scalar::zero() * &point_table;
let one = &Scalar::one() * &point_table;
let (keys, hashes): (Vec<RistrettoPoint>, Vec<Block>) = choice
.iter()
.enumerate()
.map(|(i, b)| {
// x is b in [ref1]
let x = Scalar::random(&mut self.rng);
let c = if *b { one } else { zero };
// k is B in [ref1]
let k = c + &x * &RISTRETTO_BASEPOINT_TABLE;
// h is k_r in [ref1] == hash(A^b)
let h = Block::hash_point(&(&x * &point_table), i as u32);
// we send the k values to the Sender and keep the h values
(k, h)
})
.unzip();
self.hashes = Some(hashes);
self.choice = Some(Vec::from(choice));
self.state = State::Setup;
Ok(ReceiverSetup { keys })
}
fn receive(&mut self, payload: SenderPayload) -> Result<Vec<Block>, ReceiverCoreError> {
if self.state < State::Setup {
return Err(ReceiverCoreError::NotSetup);
}
let hashes = self.hashes.as_ref().unwrap();
let values: Vec<Block> = self
.choice
.as_ref()
.unwrap()
.iter()
.zip(hashes)
.zip(payload.encrypted_values.iter())
.map(|((c, h), v)| {
// select an encrypted value based on the choice bit
let b = if *c { v[1] } else { v[0] };
// decrypt it with the corresponding key (the key is a hash)
*h ^ b
})
.collect();
self.state = State::Complete;
Ok(values)
}
}

View File

@@ -0,0 +1,106 @@
use crate::Block;
use curve25519_dalek::{
constants::RISTRETTO_BASEPOINT_TABLE, ristretto::RistrettoPoint, scalar::Scalar,
};
use rand::{CryptoRng, Rng};
use rand_chacha::ChaCha12Rng;
use rand_core::SeedableRng;
use super::{ReceiverSetup, SendCore, SenderCoreError};
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
pub enum State {
Initialized,
Setup,
Complete,
}
pub struct SenderCore<R = ChaCha12Rng> {
rng: R,
count: usize,
// private_key is random "a" in [ref1]
private_key: Option<Scalar>,
// public_key is A == g^a in [ref1]
public_key: Option<RistrettoPoint>,
state: State,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct SenderSetup {
pub public_key: RistrettoPoint,
}
#[derive(Clone, Debug, PartialEq)]
pub struct SenderPayload {
pub encrypted_values: Vec<[Block; 2]>,
}
impl SenderCore {
pub fn new(count: usize) -> Self {
Self {
rng: ChaCha12Rng::from_entropy(),
count,
private_key: None,
public_key: None,
state: State::Initialized,
}
}
}
impl<R: Rng + CryptoRng> SenderCore<R> {
pub fn new_from_rng(rng: R, count: usize) -> Self {
Self {
rng,
count,
private_key: None,
public_key: None,
state: State::Initialized,
}
}
}
impl<R: Rng + CryptoRng> SendCore for SenderCore<R> {
fn state(&self) -> State {
self.state
}
fn setup(&mut self) -> SenderSetup {
let private_key = Scalar::random(&mut self.rng);
self.public_key = Some(&private_key * &RISTRETTO_BASEPOINT_TABLE);
self.private_key = Some(private_key);
self.state = State::Setup;
SenderSetup {
public_key: self.public_key.unwrap(),
}
}
fn send(
&mut self,
inputs: &[[Block; 2]],
receiver_setup: ReceiverSetup,
) -> Result<SenderPayload, SenderCoreError> {
if self.state < State::Setup {
return Err(SenderCoreError::NotSetup);
} else if inputs.len() != self.count {
return Err(SenderCoreError::InvalidInputLength);
}
let private_key = self.private_key.unwrap();
let ninputs = inputs.len();
// ys is A^a in [ref1]
let ys = private_key * self.public_key.unwrap();
let mut encrypted_values: Vec<[Block; 2]> = Vec::with_capacity(ninputs);
for (i, (input, receiver_key)) in inputs.iter().zip(receiver_setup.keys).enumerate() {
// yr is B^a in [ref1]
let yr = private_key * receiver_key;
let k0 = Block::hash_point(&yr, i as u32);
// yr - ys == (B/A)^a in [ref1]
let k1 = Block::hash_point(&(yr - ys), i as u32);
encrypted_values.push([k0 ^ input[0], k1 ^ input[1]]);
}
self.state = State::Complete;
Ok(SenderPayload { encrypted_values })
}
}

View File

@@ -1,27 +0,0 @@
use crate::Block;
mod receiver;
mod sender;
pub use receiver::*;
pub use sender::*;
// We instantiate KOS15 w.r.t the DH-OT defined in CO15
pub(crate) use crate::ot::base::dh_ot::{
DhOtReceiver as BaseReceiver, DhOtSender as BaseSender, ReceiverChoices as ReceiverSetup,
SenderPayload, SenderSetup,
};
/// OT extension Sender plays the role of base OT Receiver and sends the
/// second message containing base OT setup and cointoss share
#[derive(Debug, Clone, PartialEq)]
pub struct BaseReceiverSetup {
pub setup: ReceiverSetup,
// Cointoss protocol's 2nd message: Receiver reveals share
pub cointoss_share: [u8; 32],
}
#[derive(Clone, Debug, PartialEq)]
pub struct ExtSenderPayload {
pub ciphertexts: Vec<[Block; 2]>,
}

View File

@@ -1,11 +1,17 @@
//! This crate implements the KOS15 Oblivious Transfer extension protocol.
pub mod errors;
pub mod kos15;
pub mod receiver;
pub mod sender;
pub use crate::ot::base::{ReceiverSetup, SenderPayload, SenderSetup};
pub use crate::Block;
pub use clmul::Clmul;
pub use errors::*;
pub use receiver::{
BaseSenderPayload, BaseSenderSetup, ExtDerandomize, ExtReceiverCore, ExtReceiverSetup,
};
pub use sender::{BaseReceiverSetup, ExtSenderCore, ExtSenderPayload};
pub const BASE_COUNT: usize = 128;
@@ -14,100 +20,119 @@ pub const BASE_COUNT: usize = 128;
const K: usize = 40;
pub trait ExtSendCore {
type State;
type BaseSenderSetup;
type BaseSenderPayload;
type BaseReceiverSetup;
type ExtSenderPayload;
type ExtReceiverSetup;
fn state(&self) -> &Self::State;
fn state(&self) -> sender::State;
//
fn base_setup(
&mut self,
base_sender_setup: Self::BaseSenderSetup,
) -> Result<Self::BaseReceiverSetup, ExtSenderCoreError>;
base_sender_setup: BaseSenderSetup,
) -> Result<BaseReceiverSetup, ExtSenderCoreError>;
fn base_receive(&mut self, payload: Self::BaseSenderPayload) -> Result<(), ExtSenderCoreError>;
fn base_receive(&mut self, payload: BaseSenderPayload) -> Result<(), ExtSenderCoreError>;
fn extension_setup(
&mut self,
receiver_setup: Self::ExtReceiverSetup,
receiver_setup: ExtReceiverSetup,
) -> Result<(), ExtSenderCoreError>;
fn send(&mut self, inputs: &[[Block; 2]])
-> Result<Self::ExtSenderPayload, ExtSenderCoreError>;
fn send(&mut self, inputs: &[[Block; 2]]) -> Result<ExtSenderPayload, ExtSenderCoreError>;
fn is_complete(&self) -> bool;
}
pub trait ExtRandomSendCore: ExtSendCore {
type ExtDerandomize;
fn state(&self) -> sender::State {
ExtSendCore::state(self)
}
fn rand_send(
// Sender in OT extension acts as Receiver in base OT and receives a setup
// message from base OT Sender and responds with its own setup message.
fn base_setup(
&mut self,
base_sender_setup: BaseSenderSetup,
) -> Result<BaseReceiverSetup, ExtSenderCoreError> {
ExtSendCore::base_setup(self, base_sender_setup)
}
fn base_receive(&mut self, payload: BaseSenderPayload) -> Result<(), ExtSenderCoreError> {
ExtSendCore::base_receive(self, payload)
}
fn extension_setup(
&mut self,
receiver_setup: ExtReceiverSetup,
) -> Result<(), ExtSenderCoreError> {
ExtSendCore::extension_setup(self, receiver_setup)
}
fn send(
&mut self,
inputs: &[[Block; 2]],
derandomize: Self::ExtDerandomize,
) -> Result<Self::ExtSenderPayload, ExtSenderCoreError>;
derandomize: ExtDerandomize,
) -> Result<ExtSenderPayload, ExtSenderCoreError>;
fn is_complete(&self) -> bool {
ExtSendCore::is_complete(self)
}
}
pub trait ExtReceiveCore {
type State;
type BaseSenderSetup;
type BaseSenderPayload;
type BaseReceiverSetup;
type ExtSenderPayload;
type ExtReceiverSetup;
fn state(&self) -> &Self::State;
fn state(&self) -> &receiver::State;
// Receiver in OT extension acts as Sender in base OT and sends the first
// base OT setup message.
fn base_setup(&mut self) -> Result<Self::BaseSenderSetup, ExtReceiverCoreError>;
fn base_setup(&mut self) -> Result<BaseSenderSetup, ExtReceiverCoreError>;
fn base_send(
&mut self,
base_receiver_setup: Self::BaseReceiverSetup,
) -> Result<Self::BaseSenderPayload, ExtReceiverCoreError>;
base_receiver_setup: BaseReceiverSetup,
) -> Result<BaseSenderPayload, ExtReceiverCoreError>;
fn extension_setup(
&mut self,
choice: &[bool],
) -> Result<Self::ExtReceiverSetup, ExtReceiverCoreError>;
) -> Result<ExtReceiverSetup, ExtReceiverCoreError>;
fn receive(
&mut self,
payload: Self::ExtSenderPayload,
) -> Result<Vec<Block>, ExtReceiverCoreError>;
fn receive(&mut self, payload: ExtSenderPayload) -> Result<Vec<Block>, ExtReceiverCoreError>;
fn is_complete(&self) -> bool;
}
pub trait ExtRandomReceiveCore: ExtReceiveCore {
type ExtDerandomize;
fn state(&self) -> &receiver::State {
ExtReceiveCore::state(self)
}
fn rand_extension_setup(&mut self) -> Result<Self::ExtReceiverSetup, ExtReceiverCoreError>;
// Receiver in OT extension acts as Sender in base OT and sends the first
// base OT setup message.
fn base_setup(&mut self) -> Result<BaseSenderSetup, ExtReceiverCoreError> {
ExtReceiveCore::base_setup(self)
}
fn rand_receive(
fn base_send(
&mut self,
payload: Self::ExtSenderPayload,
) -> Result<Vec<Block>, ExtReceiverCoreError>;
base_receiver_setup: BaseReceiverSetup,
) -> Result<BaseSenderPayload, ExtReceiverCoreError> {
ExtReceiveCore::base_send(self, base_receiver_setup)
}
fn derandomize(
&mut self,
choice: &[bool],
) -> Result<Self::ExtDerandomize, ExtReceiverCoreError>;
fn extension_setup(&mut self) -> Result<ExtReceiverSetup, ExtReceiverCoreError>;
fn derandomize(&mut self, choice: &[bool]) -> Result<ExtDerandomize, ExtReceiverCoreError>;
fn receive(&mut self, payload: ExtSenderPayload) -> Result<Vec<Block>, ExtReceiverCoreError>;
fn is_complete(&self) -> bool {
ExtReceiveCore::is_complete(self)
}
}
#[cfg(test)]
pub mod tests {
use super::errors::{ExtReceiverCoreError, ExtSenderCoreError};
use super::{
errors::{ExtReceiverCoreError, ExtSenderCoreError},
kos15::{
BaseReceiverSetup, BaseSenderPayload, BaseSenderSetup, ExtDerandomize,
ExtSenderPayload, Kos15Receiver, Kos15Sender,
},
ExtReceiveCore, ExtSendCore,
BaseReceiverSetup, BaseSenderPayload, BaseSenderSetup, ExtDerandomize, ExtReceiverCore,
ExtSenderCore, ExtSenderPayload,
};
use crate::utils::u8vec_to_boolvec;
use crate::Block;
@@ -132,12 +157,11 @@ pub mod tests {
#[once]
pub fn ot_ext_core_data(choice: &Vec<bool>, values: &Vec<[Block; 2]>) -> Data {
use crate::ot::extension::{
kos15::{Kos15Receiver, Kos15Sender},
ExtReceiveCore, ExtSendCore,
ExtReceiveCore, ExtReceiverCore, ExtSendCore, ExtSenderCore,
};
let mut sender = Kos15Sender::new(values.len());
let mut receiver = Kos15Receiver::new(choice.len());
let mut sender = ExtSenderCore::new(values.len());
let mut receiver = ExtReceiverCore::new(choice.len());
let base_sender_setup = receiver.base_setup().unwrap();
let base_receiver_setup = sender.base_setup(base_sender_setup).unwrap();
let base_sender_payload = receiver.base_send(base_receiver_setup.clone()).unwrap();
@@ -151,20 +175,20 @@ pub mod tests {
}
#[fixture]
fn receiver() -> Kos15Receiver {
Kos15Receiver::new(16)
fn receiver() -> ExtReceiverCore {
ExtReceiverCore::new(16)
}
#[fixture]
fn sender() -> Kos15Sender {
Kos15Sender::new(16)
fn sender() -> ExtSenderCore {
ExtSenderCore::new(16)
}
#[fixture]
fn pair_base_setup(
mut sender: Kos15Sender,
mut receiver: Kos15Receiver,
) -> (Kos15Sender, Kos15Receiver) {
mut sender: ExtSenderCore,
mut receiver: ExtReceiverCore,
) -> (ExtSenderCore, ExtReceiverCore) {
use super::{ExtReceiveCore, ExtSendCore};
let base_sender_setup = receiver.base_setup().unwrap();
let base_receiver_setup = sender.base_setup(base_sender_setup).unwrap();
@@ -175,9 +199,10 @@ pub mod tests {
#[fixture]
fn random_pair_base_setup(
mut sender: Kos15Sender,
mut receiver: Kos15Receiver,
) -> (Kos15Sender, Kos15Receiver) {
mut sender: ExtSenderCore,
mut receiver: ExtReceiverCore,
) -> (ExtSenderCore, ExtReceiverCore) {
use super::{ExtRandomReceiveCore, ExtRandomSendCore};
let base_sender_setup = receiver.base_setup().unwrap();
let base_receiver_setup = sender.base_setup(base_sender_setup).unwrap();
let send_seeds = receiver.base_send(base_receiver_setup).unwrap();
@@ -186,7 +211,7 @@ pub mod tests {
}
#[rstest]
fn test_ext_ot(pair_base_setup: (Kos15Sender, Kos15Receiver)) {
fn test_ext_ot(pair_base_setup: (ExtSenderCore, ExtReceiverCore)) {
use super::{ExtReceiveCore, ExtSendCore};
let (mut sender, mut receiver) = pair_base_setup;
@@ -216,7 +241,7 @@ pub mod tests {
#[rstest]
// Test that the cointoss check fails on wrong data
fn test_ext_ot_cointoss_failure(mut sender: Kos15Sender, mut receiver: Kos15Receiver) {
fn test_ext_ot_cointoss_failure(mut sender: ExtSenderCore, mut receiver: ExtReceiverCore) {
use super::{ExtReceiveCore, ExtSendCore};
let mut base_sender_setup = receiver.base_setup().unwrap();
@@ -229,7 +254,7 @@ pub mod tests {
#[rstest]
// Test that the KOS15 check fails on wrong data
fn test_ext_ot_kos_failure(pair_base_setup: (Kos15Sender, Kos15Receiver)) {
fn test_ext_ot_kos_failure(pair_base_setup: (ExtSenderCore, ExtReceiverCore)) {
use super::{ExtReceiveCore, ExtSendCore};
let (mut sender, mut receiver) = pair_base_setup;
@@ -246,7 +271,7 @@ pub mod tests {
}
#[rstest]
fn test_ext_ot_batch(pair_base_setup: (Kos15Sender, Kos15Receiver)) {
fn test_ext_ot_batch(pair_base_setup: (ExtSenderCore, ExtReceiverCore)) {
use super::{ExtReceiveCore, ExtSendCore};
let (mut sender, mut receiver) = pair_base_setup;
@@ -276,7 +301,7 @@ pub mod tests {
let res = sender.send(&[[Block::random(&mut rng), Block::random(&mut rng)]]);
assert_eq!(res, Err(ExtSenderCoreError::InvalidInputLength));
let p = ExtSenderPayload {
ciphertexts: vec![[Block::random(&mut rng), Block::random(&mut rng)]],
encrypted_values: vec![[Block::random(&mut rng), Block::random(&mut rng)]],
};
let res = receiver.receive(p);
assert_eq!(res, Err(ExtReceiverCoreError::AlreadyComplete));
@@ -291,7 +316,7 @@ pub mod tests {
}
#[rstest]
fn test_ext_random_ot(random_pair_base_setup: (Kos15Sender, Kos15Receiver)) {
fn test_ext_random_ot(random_pair_base_setup: (ExtSenderCore, ExtReceiverCore)) {
use super::{ExtRandomReceiveCore, ExtRandomSendCore};
let (mut sender, mut receiver) = random_pair_base_setup;
@@ -304,13 +329,13 @@ pub mod tests {
.map(|_| [Block::random(&mut rng), Block::random(&mut rng)])
.collect();
let receiver_setup = receiver.rand_extension_setup().unwrap();
let receiver_setup = receiver.extension_setup().unwrap();
sender.extension_setup(receiver_setup).unwrap();
let derandomize = receiver.derandomize(&choice).unwrap();
let payload = sender.rand_send(&inputs, derandomize).unwrap();
let receive = receiver.rand_receive(payload).unwrap();
let payload = sender.send(&inputs, derandomize).unwrap();
let receive = receiver.receive(payload).unwrap();
let expected: Vec<Block> = inputs
.iter()
@@ -322,7 +347,7 @@ pub mod tests {
}
#[rstest]
fn test_ext_random_ot_batch(random_pair_base_setup: (Kos15Sender, Kos15Receiver)) {
fn test_ext_random_ot_batch(random_pair_base_setup: (ExtSenderCore, ExtReceiverCore)) {
use super::{ExtRandomReceiveCore, ExtRandomSendCore};
let (mut sender, mut receiver) = random_pair_base_setup;
@@ -335,7 +360,7 @@ pub mod tests {
.map(|_| [Block::random(&mut rng), Block::random(&mut rng)])
.collect();
let receiver_setup = receiver.rand_extension_setup().unwrap();
let receiver_setup = receiver.extension_setup().unwrap();
sender.extension_setup(receiver_setup).unwrap();
let mut received: Vec<Block> = Vec::new();
@@ -343,18 +368,18 @@ pub mod tests {
assert!(!sender.is_complete());
assert!(!receiver.is_complete());
let derandomize = receiver.derandomize(&choice).unwrap();
let payload = sender.rand_send(&input, derandomize).unwrap();
received.append(&mut receiver.rand_receive(payload).unwrap());
let payload = sender.send(&input, derandomize).unwrap();
received.append(&mut receiver.receive(payload).unwrap());
}
assert!(sender.is_complete());
assert!(receiver.is_complete());
// Trying to send/receive more OTs should return an error
let d = ExtDerandomize { flip: vec![true] };
let res = sender.rand_send(&[[Block::random(&mut rng); 2]], d);
let res = sender.send(&[[Block::random(&mut rng); 2]], d);
assert_eq!(res, Err(ExtSenderCoreError::InvalidInputLength));
let p = ExtSenderPayload {
ciphertexts: vec![[Block::random(&mut rng); 2]],
encrypted_values: vec![[Block::random(&mut rng); 2]],
};
let res = receiver.receive(p);
assert_eq!(res, Err(ExtReceiverCoreError::AlreadyComplete));

View File

@@ -4,18 +4,14 @@ use rand::{CryptoRng, Rng, RngCore, SeedableRng};
use rand_chacha::ChaCha12Rng;
use std::convert::TryInto;
use super::BaseSender;
use crate::{
ot::extension::{
kos15::{
sender::{BaseSenderPayload, BaseSenderSetup},
BaseReceiverSetup, ExtSenderPayload,
},
ExtRandomReceiveCore, ExtReceiveCore, ExtReceiverCoreError, BASE_COUNT,
},
utils::{self, sha256, u8vec_to_boolvec, xor},
Block,
use super::{
BaseReceiverSetup, ExtRandomReceiveCore, ExtReceiveCore, ExtReceiverCoreError,
ExtSenderPayload, BASE_COUNT,
};
use crate::block::Block;
use crate::ot::base::{SenderPayload, SenderSetup};
use crate::ot::{SendCore, SenderCore};
use crate::utils::{self, sha256, u8vec_to_boolvec, xor};
use clmul::Clmul;
#[derive(Clone, Debug, PartialEq)]
@@ -33,10 +29,26 @@ pub enum State {
Complete,
}
pub struct Kos15Receiver<R = ChaCha12Rng, C = Aes128> {
/// OT extension Receiver plays the role of base OT Sender and sends the
/// first message containing base OT setup and cointoss commitment
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct BaseSenderSetup {
pub setup: SenderSetup,
// Cointoss protocol's 1st message: sha256 commitment
pub cointoss_commit: [u8; 32],
}
#[derive(Debug, Clone, PartialEq)]
pub struct BaseSenderPayload {
pub payload: SenderPayload,
// Cointoss protocol's 3rd message: Sender reveals share
pub cointoss_share: [u8; 32],
}
pub struct ExtReceiverCore<R = ChaCha12Rng, C = Aes128, OT = SenderCore<ChaCha12Rng>> {
rng: R,
cipher: C,
base: BaseSender,
base: OT,
state: State,
count: usize,
// seeds are the result of running base OT setup. They are used to seed the
@@ -66,14 +78,14 @@ pub struct ExtDerandomize {
pub flip: Vec<bool>,
}
impl Kos15Receiver {
impl ExtReceiverCore {
pub fn new(count: usize) -> Self {
let mut rng = ChaCha12Rng::from_entropy();
let cointoss_share = rng.gen();
Self {
rng,
cipher: Aes128::new_from_slice(&[0u8; 16]).unwrap(),
base: BaseSender::default(),
base: SenderCore::new(BASE_COUNT),
state: State::Initialized,
count,
seeds: None,
@@ -87,7 +99,7 @@ impl Kos15Receiver {
fn decrypt_values<C: BlockCipher<BlockSize = U16> + BlockEncrypt>(
cipher: &mut C,
ciphertexts: &[[Block; 2]],
encrypted_values: &[[Block; 2]],
table: &[Vec<u8>],
choice: &[bool],
) -> Vec<Block> {
@@ -96,9 +108,9 @@ fn decrypt_values<C: BlockCipher<BlockSize = U16> + BlockEncrypt>(
let t: [u8; 16] = table[j].clone().try_into().unwrap();
let t = Block::from(t);
let y = if *b {
ciphertexts[j][1]
encrypted_values[j][1]
} else {
ciphertexts[j][0]
encrypted_values[j][0]
};
let y = y ^ t.hash_tweak(cipher, j);
values.push(y);
@@ -106,12 +118,13 @@ fn decrypt_values<C: BlockCipher<BlockSize = U16> + BlockEncrypt>(
values
}
impl<R, C> Kos15Receiver<R, C>
impl<R, C, OT> ExtReceiverCore<R, C, OT>
where
R: Rng + CryptoRng,
C: BlockCipher<BlockSize = U16> + BlockEncrypt,
OT: SendCore,
{
pub fn new_with_custom(mut rng: R, cipher: C, base: BaseSender, count: usize) -> Self {
pub fn new_with_custom(mut rng: R, cipher: C, base: OT, count: usize) -> Self {
let cointoss_share = rng.gen();
Self {
rng,
@@ -149,18 +162,12 @@ where
}
}
impl<R, C> ExtReceiveCore for Kos15Receiver<R, C>
impl<R, C, OT> ExtReceiveCore for ExtReceiverCore<R, C, OT>
where
R: Rng + CryptoRng + SeedableRng,
C: BlockCipher<BlockSize = U16> + BlockEncrypt,
OT: SendCore,
{
type State = State;
type BaseSenderSetup = BaseSenderSetup;
type BaseSenderPayload = BaseSenderPayload;
type BaseReceiverSetup = BaseReceiverSetup;
type ExtSenderPayload = ExtSenderPayload;
type ExtReceiverSetup = ExtReceiverSetup;
fn state(&self) -> &State {
&self.state
}
@@ -175,7 +182,7 @@ where
}
self.state = State::BaseSetup;
Ok(BaseSenderSetup {
setup: self.base.setup(&mut self.rng),
setup: self.base.setup(),
cointoss_commit: sha256(&self.cointoss_share),
})
}
@@ -192,7 +199,9 @@ where
seeds.push([Block::random(&mut self.rng), Block::random(&mut self.rng)]);
}
let base_send = self.base.send(&seeds, base_receiver_setup.setup)?;
let base_send = self
.base
.send(seeds.as_slice(), base_receiver_setup.setup)?;
self.set_seeds(seeds);
let mut result = [0u8; 32];
@@ -213,7 +222,6 @@ where
&mut self,
choice: &[bool],
) -> Result<ExtReceiverSetup, ExtReceiverCoreError> {
println!("Doing extension setup with {} choices", choice.len());
if State::BaseSend != self.state {
return Err(ExtReceiverCoreError::BaseOTNotSetup);
}
@@ -300,14 +308,6 @@ where
choice: Vec::from(choice),
derandomized: Vec::new(),
});
println!(
"self.state.choice.len() == {}",
if let State::Setup(ChoiceState { choice, .. }) = &self.state {
choice.len()
} else {
0
}
);
// remove the last 256 elements which were sacrificed
ts.drain(ts.len() - 256..);
self.table = Some(ts);
@@ -327,23 +327,18 @@ where
_ => return Err(ExtReceiverCoreError::NotSetup),
};
if payload.ciphertexts.len() > choice_state.choice.len() {
println!(
"Got {} payload ciphertexts with {} choices",
payload.ciphertexts.len(),
choice_state.choice.len()
);
if payload.encrypted_values.len() > choice_state.choice.len() {
return Err(ExtReceiverCoreError::InvalidPayloadSize);
}
let choice: Vec<bool> = choice_state
.choice
.drain(..payload.ciphertexts.len())
.drain(..payload.encrypted_values.len())
.collect();
let table = self.table.as_mut().ok_or(ExtReceiverCoreError::NotSetup)?;
let table: Vec<Vec<u8>> = table.drain(..choice.len()).collect();
let values = decrypt_values(&mut self.cipher, &payload.ciphertexts, &table, &choice);
let values = decrypt_values(&mut self.cipher, &payload.encrypted_values, &table, &choice);
if (choice_state.choice.len() == 0) && (choice_state.derandomized.len() == 0) {
self.state = State::Complete;
@@ -353,14 +348,13 @@ where
}
}
impl<R, C> ExtRandomReceiveCore for Kos15Receiver<R, C>
impl<R, C, OT> ExtRandomReceiveCore for ExtReceiverCore<R, C, OT>
where
R: Rng + CryptoRng + SeedableRng,
C: BlockCipher<BlockSize = U16> + BlockEncrypt,
OT: SendCore,
{
type ExtDerandomize = ExtDerandomize;
fn rand_extension_setup(&mut self) -> Result<ExtReceiverSetup, ExtReceiverCoreError> {
fn extension_setup(&mut self) -> Result<ExtReceiverSetup, ExtReceiverCoreError> {
let n = self.count;
// For random OT we generate random choice bits during setup then derandomize later
let mut choice = vec![0u8; if n % 8 != 0 { n + (8 - n % 8) } else { n } / 8];
@@ -368,7 +362,6 @@ where
let mut choice = u8vec_to_boolvec(&choice);
choice.resize(n, false);
println!("In rand_extension_setup");
ExtReceiveCore::extension_setup(self, &choice)
}
@@ -394,27 +387,24 @@ where
Ok(ExtDerandomize { flip })
}
fn rand_receive(
&mut self,
payload: ExtSenderPayload,
) -> Result<Vec<Block>, ExtReceiverCoreError> {
fn receive(&mut self, payload: ExtSenderPayload) -> Result<Vec<Block>, ExtReceiverCoreError> {
let choice_state = match &mut self.state {
State::Setup(state) => state,
State::Complete => return Err(ExtReceiverCoreError::AlreadyComplete),
_ => return Err(ExtReceiverCoreError::NotSetup),
};
if payload.ciphertexts.len() > choice_state.derandomized.len() {
if payload.encrypted_values.len() > choice_state.derandomized.len() {
return Err(ExtReceiverCoreError::NotDerandomized);
}
let choice: Vec<bool> = choice_state
.derandomized
.drain(..payload.ciphertexts.len())
.drain(..payload.encrypted_values.len())
.collect();
let table = self.table.as_mut().ok_or(ExtReceiverCoreError::NotSetup)?;
let table: Vec<Vec<u8>> = table.drain(..choice.len()).collect();
let values = decrypt_values(&mut self.cipher, &payload.ciphertexts, &table, &choice);
let values = decrypt_values(&mut self.cipher, &payload.encrypted_values, &table, &choice);
if (choice_state.choice.len() == 0) && (choice_state.derandomized.len() == 0) {
self.state = State::Complete;

View File

@@ -1,20 +1,19 @@
use crate::block::Block;
use crate::ot::extension::{
kos15::{
BaseReceiver, BaseReceiverSetup, ExtDerandomize, ExtReceiverSetup, ExtSenderPayload,
SenderPayload, SenderSetup,
},
ExtRandomSendCore, ExtSendCore, ExtSenderCoreError, BASE_COUNT,
};
use crate::utils::{self, sha256, xor};
use aes::{Aes128, BlockCipher, BlockEncrypt, NewBlockCipher};
use cipher::consts::U16;
use clmul::Clmul;
use rand::{Rng, RngCore, SeedableRng};
use rand::{thread_rng, Rng, RngCore, SeedableRng};
use rand_chacha::ChaCha12Rng;
use std::convert::TryInto;
use super::{
BaseSenderPayload, BaseSenderSetup, ExtDerandomize, ExtRandomSendCore, ExtReceiverSetup,
ExtSendCore, ExtSenderCoreError, BASE_COUNT,
};
use crate::block::Block;
use crate::ot::base::ReceiverSetup;
use crate::ot::{ReceiveCore, ReceiverCore};
use crate::utils::{self, sha256, xor};
use clmul::Clmul;
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
pub enum State {
Initialized,
@@ -24,10 +23,18 @@ pub enum State {
Complete,
}
pub struct Kos15Sender<C = Aes128> {
rng: ChaCha12Rng,
/// OT extension Sender plays the role of base OT Receiver and sends the
/// second message containing base OT setup and cointoss share
#[derive(Debug, Clone, std::cmp::PartialEq)]
pub struct BaseReceiverSetup {
pub setup: ReceiverSetup,
// Cointoss protocol's 2nd message: Receiver reveals share
pub cointoss_share: [u8; 32],
}
pub struct ExtSenderCore<C = Aes128, OT = ReceiverCore<ChaCha12Rng>> {
cipher: C,
base: BaseReceiver,
base: OT,
state: State,
count: usize,
sent: usize,
@@ -52,20 +59,9 @@ pub struct Kos15Sender<C = Aes128> {
cointoss_random: Option<[u8; 32]>,
}
/// OT extension Receiver plays the role of base OT Sender and sends the
/// first message containing base OT setup and cointoss commitment
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct BaseSenderSetup {
pub setup: SenderSetup,
// Cointoss protocol's 1st message: sha256 commitment
pub cointoss_commit: [u8; 32],
}
#[derive(Debug, Clone, PartialEq)]
pub struct BaseSenderPayload {
pub payload: SenderPayload,
// Cointoss protocol's 3rd message: Sender reveals share
pub cointoss_share: [u8; 32],
#[derive(Clone, Debug, PartialEq)]
pub struct ExtSenderPayload {
pub encrypted_values: Vec<[Block; 2]>,
}
// Having 2 messages that Receiver chooses from, we encrypt each message with
@@ -78,7 +74,7 @@ fn encrypt_values<C: BlockCipher<BlockSize = U16> + BlockEncrypt>(
base_choice: &[bool],
flip: Option<Vec<bool>>,
) -> Vec<[Block; 2]> {
let mut ciphertexts: Vec<[Block; 2]> = Vec::with_capacity(table.len());
let mut encrypted_values: Vec<[Block; 2]> = Vec::with_capacity(table.len());
let base_choice: [u8; 16] = utils::boolvec_to_u8vec(base_choice).try_into().unwrap();
let delta = Block::from(base_choice);
// If Receiver used *random* choice bits during OT extension setup, he will now
@@ -90,26 +86,22 @@ fn encrypt_values<C: BlockCipher<BlockSize = U16> + BlockEncrypt>(
let q = Block::from(q);
let masks = [q.hash_tweak(cipher, j), (q ^ delta).hash_tweak(cipher, j)];
if flip {
ciphertexts.push([input[0] ^ masks[1], input[1] ^ masks[0]]);
encrypted_values.push([input[0] ^ masks[1], input[1] ^ masks[0]]);
} else {
ciphertexts.push([input[0] ^ masks[0], input[1] ^ masks[1]]);
encrypted_values.push([input[0] ^ masks[0], input[1] ^ masks[1]]);
}
}
ciphertexts
encrypted_values
}
impl Kos15Sender {
impl ExtSenderCore {
pub fn new(count: usize) -> Self {
let mut rng = ChaCha12Rng::from_entropy();
let cointoss_share = rng.gen();
let mut base_choice = vec![0u8; BASE_COUNT / 8];
rng.fill_bytes(&mut base_choice);
Self {
rng,
cipher: Aes128::new_from_slice(&[0u8; 16]).unwrap(),
base: BaseReceiver::default(),
base: ReceiverCore::new(BASE_COUNT),
state: State::Initialized,
count,
sent: 0,
@@ -117,26 +109,23 @@ impl Kos15Sender {
seeds: None,
rngs: None,
table: None,
cointoss_share,
cointoss_share: rng.gen(),
receiver_cointoss_commit: None,
cointoss_random: None,
}
}
}
impl<C> Kos15Sender<C>
impl<C, OT> ExtSenderCore<C, OT>
where
C: BlockCipher<BlockSize = U16> + BlockEncrypt,
OT: ReceiveCore,
{
pub fn new_from_custom(cipher: C, base: BaseReceiver, count: usize) -> Self {
let mut rng = ChaCha12Rng::from_entropy();
let cointoss_share = rng.gen();
pub fn new_from_custom(cipher: C, base: OT, count: usize) -> Self {
let mut rng = thread_rng();
let mut base_choice = vec![0u8; BASE_COUNT / 8];
rng.fill_bytes(&mut base_choice);
Self {
rng,
cipher,
base,
state: State::Initialized,
@@ -146,7 +135,7 @@ where
seeds: None,
rngs: None,
table: None,
cointoss_share,
cointoss_share: rng.gen(),
receiver_cointoss_commit: None,
cointoss_random: None,
}
@@ -169,19 +158,13 @@ where
}
}
impl<C> ExtSendCore for Kos15Sender<C>
impl<C, OT> ExtSendCore for ExtSenderCore<C, OT>
where
C: BlockCipher<BlockSize = U16> + BlockEncrypt,
OT: ReceiveCore,
{
type State = State;
type BaseSenderSetup = BaseSenderSetup;
type BaseSenderPayload = BaseSenderPayload;
type BaseReceiverSetup = BaseReceiverSetup;
type ExtSenderPayload = ExtSenderPayload;
type ExtReceiverSetup = ExtReceiverSetup;
fn state(&self) -> &State {
&self.state
fn state(&self) -> State {
self.state
}
fn is_complete(&self) -> bool {
@@ -200,7 +183,7 @@ where
Ok(BaseReceiverSetup {
setup: self
.base
.setup(&mut self.rng, &self.base_choice, base_sender_setup.setup)?,
.setup(&self.base_choice, base_sender_setup.setup)?,
cointoss_share: self.cointoss_share,
})
}
@@ -308,7 +291,7 @@ where
// KOS check
qs.drain(qs.len() - 256..);
self.table = Some(qs);
self.state = State::Initialized;
self.state = State::Setup;
Ok(())
}
@@ -317,31 +300,31 @@ where
return Err(ExtSenderCoreError::InvalidInputLength);
}
match self.state {
State::Initialized => {}
State::Setup => {}
State::Complete => return Err(ExtSenderCoreError::AlreadyComplete),
_ => return Err(ExtSenderCoreError::NotSetup),
};
let table = self.table.as_mut().ok_or(ExtSenderCoreError::NotSetup)?;
let table: Vec<Vec<u8>> = table.drain(..inputs.len()).collect();
let ciphertexts = encrypt_values(&mut self.cipher, inputs, &table, &self.base_choice, None);
let encrypted_values =
encrypt_values(&mut self.cipher, inputs, &table, &self.base_choice, None);
self.sent += inputs.len();
if self.sent == self.count {
self.state = State::Complete;
}
Ok(ExtSenderPayload { ciphertexts })
Ok(ExtSenderPayload { encrypted_values })
}
}
impl<C> ExtRandomSendCore for Kos15Sender<C>
impl<C, OT> ExtRandomSendCore for ExtSenderCore<C, OT>
where
C: BlockCipher<BlockSize = U16> + BlockEncrypt,
OT: ReceiveCore,
{
type ExtDerandomize = ExtDerandomize;
fn rand_send(
fn send(
&mut self,
inputs: &[[Block; 2]],
derandomize: ExtDerandomize,
@@ -350,14 +333,14 @@ where
return Err(ExtSenderCoreError::InvalidInputLength);
}
match self.state {
State::Initialized => {}
State::Setup => {}
State::Complete => return Err(ExtSenderCoreError::AlreadyComplete),
_ => return Err(ExtSenderCoreError::NotSetup),
};
let table = self.table.as_mut().ok_or(ExtSenderCoreError::NotSetup)?;
let table: Vec<Vec<u8>> = table.drain(..inputs.len()).collect();
let ciphertexts = encrypt_values(
let encrypted_values = encrypt_values(
&mut self.cipher,
inputs,
&table,
@@ -370,6 +353,6 @@ where
self.state = State::Complete;
}
Ok(ExtSenderPayload { ciphertexts })
Ok(ExtSenderPayload { encrypted_values })
}
}

View File

@@ -5,14 +5,14 @@ pub use base::*;
pub use extension::*;
#[derive(Debug, Clone)]
pub enum Kos15Message {
SenderSetup(dh_ot::SenderSetup),
BaseSenderSetup(kos15::BaseSenderSetup),
SenderPayload(dh_ot::SenderPayload),
BaseSenderPayload(kos15::BaseSenderPayload),
ReceiverSetup(dh_ot::ReceiverChoices),
BaseReceiverSetup(kos15::BaseReceiverSetup),
ExtReceiverSetup(kos15::ExtReceiverSetup),
ExtDerandomize(kos15::ExtDerandomize),
ExtSenderPayload(kos15::ExtSenderPayload),
pub enum Message {
SenderSetup(SenderSetup),
BaseSenderSetup(BaseSenderSetup),
SenderPayload(SenderPayload),
BaseSenderPayload(BaseSenderPayload),
ReceiverSetup(ReceiverSetup),
BaseReceiverSetup(BaseReceiverSetup),
ExtReceiverSetup(ExtReceiverSetup),
ExtDerandomize(ExtDerandomize),
ExtSenderPayload(ExtSenderPayload),
}

View File

@@ -1,6 +1,6 @@
#![cfg(feature = "ot")]
pub use crate::ot::{self, dh_ot, kos15};
pub use crate::ot;
use crate::utils::parse_ristretto_key;
use std::convert::{TryFrom, TryInto};
use std::io::{Error, ErrorKind};
@@ -9,36 +9,34 @@ include!(concat!(env!("OUT_DIR"), "/core.ot.rs"));
pub use message::Msg;
impl From<ot::Kos15Message> for Message {
impl From<ot::Message> for Message {
#[inline]
fn from(m: ot::Kos15Message) -> Self {
fn from(m: ot::Message) -> Self {
Self {
msg: Some(match m {
ot::Kos15Message::ReceiverSetup(msg) => {
ot::Message::ReceiverSetup(msg) => {
message::Msg::ReceiverSetup(ReceiverSetup::from(msg))
}
ot::Kos15Message::SenderSetup(msg) => {
message::Msg::SenderSetup(SenderSetup::from(msg))
}
ot::Kos15Message::SenderPayload(msg) => {
ot::Message::SenderSetup(msg) => message::Msg::SenderSetup(SenderSetup::from(msg)),
ot::Message::SenderPayload(msg) => {
message::Msg::SenderPayload(SenderPayload::from(msg))
}
ot::Kos15Message::ExtReceiverSetup(msg) => {
ot::Message::ExtReceiverSetup(msg) => {
message::Msg::ExtReceiverSetup(ExtReceiverSetup::from(msg))
}
ot::Kos15Message::ExtDerandomize(msg) => {
ot::Message::ExtDerandomize(msg) => {
message::Msg::ExtDerandomize(ExtDerandomize::from(msg))
}
ot::Kos15Message::ExtSenderPayload(msg) => {
ot::Message::ExtSenderPayload(msg) => {
message::Msg::ExtSenderPayload(ExtSenderPayload::from(msg))
}
ot::Kos15Message::BaseSenderSetup(msg) => {
ot::Message::BaseSenderSetup(msg) => {
message::Msg::BaseSenderSetup(BaseSenderSetup::from(msg))
}
ot::Kos15Message::BaseReceiverSetup(msg) => {
ot::Message::BaseReceiverSetup(msg) => {
message::Msg::BaseReceiverSetup(BaseReceiverSetup::from(msg))
}
ot::Kos15Message::BaseSenderPayload(msg) => {
ot::Message::BaseSenderPayload(msg) => {
message::Msg::BaseSenderPayload(BaseSenderPayload::from(msg))
}
}),
@@ -46,38 +44,38 @@ impl From<ot::Kos15Message> for Message {
}
}
impl TryFrom<Message> for ot::Kos15Message {
impl TryFrom<Message> for ot::Message {
type Error = std::io::Error;
#[inline]
fn try_from(m: Message) -> Result<Self, Self::Error> {
if let Some(msg) = m.msg {
let m = match msg {
message::Msg::ReceiverSetup(msg) => {
ot::Kos15Message::ReceiverSetup(dh_ot::ReceiverChoices::try_from(msg)?)
ot::Message::ReceiverSetup(ot::ReceiverSetup::try_from(msg)?)
}
message::Msg::SenderSetup(msg) => {
ot::Kos15Message::SenderSetup(dh_ot::SenderSetup::try_from(msg)?)
ot::Message::SenderSetup(ot::SenderSetup::try_from(msg)?)
}
message::Msg::SenderPayload(msg) => {
ot::Kos15Message::SenderPayload(dh_ot::SenderPayload::from(msg))
ot::Message::SenderPayload(ot::SenderPayload::from(msg))
}
message::Msg::ExtReceiverSetup(msg) => {
ot::Kos15Message::ExtReceiverSetup(kos15::ExtReceiverSetup::try_from(msg)?)
ot::Message::ExtReceiverSetup(ot::ExtReceiverSetup::try_from(msg)?)
}
message::Msg::ExtDerandomize(msg) => {
ot::Kos15Message::ExtDerandomize(kos15::ExtDerandomize::from(msg))
ot::Message::ExtDerandomize(ot::ExtDerandomize::from(msg))
}
message::Msg::ExtSenderPayload(msg) => {
ot::Kos15Message::ExtSenderPayload(kos15::ExtSenderPayload::from(msg))
ot::Message::ExtSenderPayload(ot::ExtSenderPayload::from(msg))
}
message::Msg::BaseSenderSetup(msg) => {
ot::Kos15Message::BaseSenderSetup(kos15::BaseSenderSetup::try_from(msg)?)
ot::Message::BaseSenderSetup(ot::BaseSenderSetup::try_from(msg)?)
}
message::Msg::BaseReceiverSetup(msg) => {
ot::Kos15Message::BaseReceiverSetup(kos15::BaseReceiverSetup::try_from(msg)?)
ot::Message::BaseReceiverSetup(ot::BaseReceiverSetup::try_from(msg)?)
}
message::Msg::BaseSenderPayload(msg) => {
ot::Kos15Message::BaseSenderPayload(kos15::BaseSenderPayload::try_from(msg)?)
ot::Message::BaseSenderPayload(ot::BaseSenderPayload::try_from(msg)?)
}
};
Ok(m)
@@ -87,16 +85,16 @@ impl TryFrom<Message> for ot::Kos15Message {
}
}
impl From<dh_ot::SenderSetup> for SenderSetup {
impl From<ot::SenderSetup> for SenderSetup {
#[inline]
fn from(s: dh_ot::SenderSetup) -> Self {
fn from(s: ot::SenderSetup) -> Self {
Self {
public_key: super::RistrettoPoint::from(s.public_key),
}
}
}
impl TryFrom<SenderSetup> for dh_ot::SenderSetup {
impl TryFrom<SenderSetup> for ot::SenderSetup {
type Error = Error;
#[inline]
@@ -107,12 +105,12 @@ impl TryFrom<SenderSetup> for dh_ot::SenderSetup {
}
}
impl From<dh_ot::SenderPayload> for SenderPayload {
impl From<ot::SenderPayload> for SenderPayload {
#[inline]
fn from(p: dh_ot::SenderPayload) -> Self {
fn from(p: ot::SenderPayload) -> Self {
Self {
ciphertexts: p
.ciphertexts
encrypted_values: p
.encrypted_values
.into_iter()
.map(|b| super::LabelPair {
low: super::Block::from(b[0]),
@@ -123,12 +121,12 @@ impl From<dh_ot::SenderPayload> for SenderPayload {
}
}
impl From<SenderPayload> for dh_ot::SenderPayload {
impl From<SenderPayload> for ot::SenderPayload {
#[inline]
fn from(p: SenderPayload) -> Self {
Self {
ciphertexts: p
.ciphertexts
encrypted_values: p
.encrypted_values
.into_iter()
.map(|pair| [crate::Block::from(pair.low), crate::Block::from(pair.high)])
.collect(),
@@ -136,12 +134,12 @@ impl From<SenderPayload> for dh_ot::SenderPayload {
}
}
impl From<dh_ot::ReceiverChoices> for ReceiverSetup {
impl From<ot::ReceiverSetup> for ReceiverSetup {
#[inline]
fn from(s: dh_ot::ReceiverChoices) -> Self {
fn from(s: ot::ReceiverSetup) -> Self {
Self {
blinded_choices: s
.blinded_choices
keys: s
.keys
.into_iter()
.map(super::RistrettoPoint::from)
.collect(),
@@ -149,23 +147,23 @@ impl From<dh_ot::ReceiverChoices> for ReceiverSetup {
}
}
impl TryFrom<ReceiverSetup> for dh_ot::ReceiverChoices {
impl TryFrom<ReceiverSetup> for ot::ReceiverSetup {
type Error = Error;
#[inline]
fn try_from(s: ReceiverSetup) -> Result<Self, Self::Error> {
let mut blinded_choices: Vec<curve25519_dalek::ristretto::RistrettoPoint> =
Vec::with_capacity(s.blinded_choices.len());
for key in s.blinded_choices.into_iter() {
blinded_choices.push(parse_ristretto_key(key.point)?);
let mut keys: Vec<curve25519_dalek::ristretto::RistrettoPoint> =
Vec::with_capacity(s.keys.len());
for key in s.keys.into_iter() {
keys.push(parse_ristretto_key(key.point)?);
}
Ok(Self { blinded_choices })
Ok(Self { keys })
}
}
impl From<kos15::ExtReceiverSetup> for ExtReceiverSetup {
impl From<ot::ExtReceiverSetup> for ExtReceiverSetup {
#[inline]
fn from(s: kos15::ExtReceiverSetup) -> Self {
fn from(s: ot::ExtReceiverSetup) -> Self {
Self {
ncols: s.ncols as u32,
table: s.table,
@@ -176,7 +174,7 @@ impl From<kos15::ExtReceiverSetup> for ExtReceiverSetup {
}
}
impl TryFrom<ExtReceiverSetup> for kos15::ExtReceiverSetup {
impl TryFrom<ExtReceiverSetup> for ot::ExtReceiverSetup {
type Error = Error;
#[inline]
@@ -191,26 +189,26 @@ impl TryFrom<ExtReceiverSetup> for kos15::ExtReceiverSetup {
}
}
impl From<kos15::ExtDerandomize> for ExtDerandomize {
impl From<ot::ExtDerandomize> for ExtDerandomize {
#[inline]
fn from(d: kos15::ExtDerandomize) -> Self {
fn from(d: ot::ExtDerandomize) -> Self {
Self { flip: d.flip }
}
}
impl From<ExtDerandomize> for kos15::ExtDerandomize {
impl From<ExtDerandomize> for ot::ExtDerandomize {
#[inline]
fn from(d: ExtDerandomize) -> Self {
Self { flip: d.flip }
}
}
impl From<kos15::ExtSenderPayload> for ExtSenderPayload {
impl From<ot::ExtSenderPayload> for ExtSenderPayload {
#[inline]
fn from(p: kos15::ExtSenderPayload) -> Self {
fn from(p: ot::ExtSenderPayload) -> Self {
Self {
ciphertexts: p
.ciphertexts
encrypted_values: p
.encrypted_values
.into_iter()
.map(|b| super::LabelPair {
low: super::Block::from(b[0]),
@@ -221,12 +219,12 @@ impl From<kos15::ExtSenderPayload> for ExtSenderPayload {
}
}
impl From<ExtSenderPayload> for kos15::ExtSenderPayload {
impl From<ExtSenderPayload> for ot::ExtSenderPayload {
#[inline]
fn from(p: ExtSenderPayload) -> Self {
Self {
ciphertexts: p
.ciphertexts
encrypted_values: p
.encrypted_values
.into_iter()
.map(|pair| [crate::Block::from(pair.low), crate::Block::from(pair.high)])
.collect(),
@@ -234,9 +232,9 @@ impl From<ExtSenderPayload> for kos15::ExtSenderPayload {
}
}
impl From<kos15::BaseSenderSetup> for BaseSenderSetup {
impl From<ot::BaseSenderSetup> for BaseSenderSetup {
#[inline]
fn from(s: kos15::BaseSenderSetup) -> Self {
fn from(s: ot::BaseSenderSetup) -> Self {
Self {
setup: SenderSetup::from(s.setup),
cointoss_commit: s.cointoss_commit.to_vec(),
@@ -244,7 +242,7 @@ impl From<kos15::BaseSenderSetup> for BaseSenderSetup {
}
}
impl TryFrom<BaseSenderSetup> for kos15::BaseSenderSetup {
impl TryFrom<BaseSenderSetup> for ot::BaseSenderSetup {
type Error = Error;
#[inline]
@@ -259,9 +257,9 @@ impl TryFrom<BaseSenderSetup> for kos15::BaseSenderSetup {
}
}
impl From<kos15::BaseReceiverSetup> for BaseReceiverSetup {
impl From<ot::BaseReceiverSetup> for BaseReceiverSetup {
#[inline]
fn from(s: kos15::BaseReceiverSetup) -> Self {
fn from(s: ot::BaseReceiverSetup) -> Self {
Self {
setup: ReceiverSetup::from(s.setup),
cointoss_share: s.cointoss_share.to_vec(),
@@ -269,7 +267,7 @@ impl From<kos15::BaseReceiverSetup> for BaseReceiverSetup {
}
}
impl TryFrom<BaseReceiverSetup> for kos15::BaseReceiverSetup {
impl TryFrom<BaseReceiverSetup> for ot::BaseReceiverSetup {
type Error = Error;
#[inline]
@@ -284,9 +282,9 @@ impl TryFrom<BaseReceiverSetup> for kos15::BaseReceiverSetup {
}
}
impl From<kos15::BaseSenderPayload> for BaseSenderPayload {
impl From<ot::BaseSenderPayload> for BaseSenderPayload {
#[inline]
fn from(s: kos15::BaseSenderPayload) -> Self {
fn from(s: ot::BaseSenderPayload) -> Self {
Self {
payload: SenderPayload::from(s.payload),
cointoss_share: s.cointoss_share.to_vec(),
@@ -294,7 +292,7 @@ impl From<kos15::BaseSenderPayload> for BaseSenderPayload {
}
}
impl TryFrom<BaseSenderPayload> for kos15::BaseSenderPayload {
impl TryFrom<BaseSenderPayload> for ot::BaseSenderPayload {
type Error = Error;
#[inline]
@@ -356,7 +354,7 @@ pub mod tests {
#[rstest]
fn test_proto_ot(proto_base_core_data: &fixtures::ProtoData, ot_core_data: &Data) {
let sender_setup: crate::ot::base::dh_ot::SenderSetup = proto_base_core_data
let sender_setup: crate::ot::base::SenderSetup = proto_base_core_data
.sender_setup
.clone()
.try_into()
@@ -364,7 +362,7 @@ pub mod tests {
assert_eq!(sender_setup, ot_core_data.sender_setup);
let receiver_setup: crate::ot::base::dh_ot::ReceiverChoices = proto_base_core_data
let receiver_setup: crate::ot::base::ReceiverSetup = proto_base_core_data
.receiver_setup
.clone()
.try_into()
@@ -372,7 +370,7 @@ pub mod tests {
assert_eq!(receiver_setup, ot_core_data.receiver_setup);
let sender_payload: crate::ot::base::dh_ot::SenderPayload = proto_base_core_data
let sender_payload: crate::ot::base::SenderPayload = proto_base_core_data
.sender_payload
.clone()
.try_into()
@@ -383,7 +381,7 @@ pub mod tests {
#[rstest]
fn test_proto_ext(proto_ext_core_data: &fixtures::ProtoExtData, ot_ext_core_data: &ExtData) {
let base_sender_setup: crate::ot::extension::kos15::BaseSenderSetup = proto_ext_core_data
let base_sender_setup: crate::ot::extension::BaseSenderSetup = proto_ext_core_data
.base_sender_setup
.clone()
.try_into()
@@ -391,21 +389,19 @@ pub mod tests {
assert_eq!(base_sender_setup, ot_ext_core_data.base_sender_setup);
let base_receiver_setup: crate::ot::extension::kos15::BaseReceiverSetup =
proto_ext_core_data
.base_receiver_setup
.clone()
.try_into()
.unwrap();
let base_receiver_setup: crate::ot::extension::BaseReceiverSetup = proto_ext_core_data
.base_receiver_setup
.clone()
.try_into()
.unwrap();
assert_eq!(base_receiver_setup, ot_ext_core_data.base_receiver_setup);
let base_sender_payload: crate::ot::extension::kos15::BaseSenderPayload =
proto_ext_core_data
.base_sender_payload
.clone()
.try_into()
.unwrap();
let base_sender_payload: crate::ot::extension::BaseSenderPayload = proto_ext_core_data
.base_sender_payload
.clone()
.try_into()
.unwrap();
assert_eq!(base_sender_payload, ot_ext_core_data.base_sender_payload);
}