Skip to content

Commit

Permalink
Move OT computation and random x generation into fabitn
Browse files Browse the repository at this point in the history
  • Loading branch information
kisakishy committed Oct 30, 2024
1 parent 597de5c commit e427a70
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 71 deletions.
37 changes: 21 additions & 16 deletions src/faand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ use smallvec::{smallvec, SmallVec};
use crate::{
channel::{self, recv_from, recv_vec_from, send_to, Channel},
fpre::{Auth, Delta, Key, Mac, Share},
ot::{kos_ot_receiver, kos_ot_sender, u128_to_block},
};

/// The statistical security parameter `RHO` used for cryptographic operations.
pub(crate) const RHO: usize = 40;
const RHO: usize = 40;

/// Errors occurring during preprocessing.
#[derive(Debug)]
Expand Down Expand Up @@ -133,27 +134,32 @@ pub(crate) async fn shared_rng(
/// parties.
async fn fabitn(
(channel, delta): (&mut impl Channel, Delta),
x: &mut Vec<bool>,
i: usize,
n: usize,
l: usize,
shared_rng: &mut ChaCha20Rng,
(sender_ot, receiver_ot): (Vec<Vec<u128>>, Vec<Vec<u128>>),
) -> Result<Vec<Share>, Error> {
// Step 1) Pick random bit-string x of length lprime [input parameter x].
// Step 1) Pick random bit-string x of length lprime.
let two_rho = 2 * RHO;
let lprime = l + two_rho;
if x.len() != lprime {
return Err(Error::InvalidLength);
}

let mut x: Vec<bool> = (0..lprime).map(|_| random()).collect();

// Steps 2) Use the output of the oblivious transfers between each pair of parties to generate keys and macs.
let mut keys = vec![vec![]; n];
let mut macs = vec![vec![]; n];
for k in (0..n).filter(|k| *k != i) {
macs[k] = receiver_ot[k].clone();
keys[k] = sender_ot[k].clone();
let mut keys = vec![vec![0; lprime]; n];
let mut macs = vec![vec![0; lprime]; n];

let deltas = vec![u128_to_block(delta.0); lprime];
for p in (0..n).filter(|p| *p != i) {
if i < p {
keys[p] = kos_ot_sender(channel, &deltas, i, p).await?;
macs[p] = kos_ot_receiver(channel, &x, i, p).await?;
} else {
macs[p] = kos_ot_receiver(channel, &x, i, p).await?;
keys[p] = kos_ot_sender(channel, &deltas, i, p).await?;
}
}
drop(deltas);

// Step 2) Run 2-party OTs to compute keys and MACs [input parameters mm and kk].

Expand Down Expand Up @@ -207,6 +213,7 @@ async fn fabitn(
}
}
}
drop(r);

// Step 4) Return first l objects.
x.truncate(l);
Expand All @@ -230,17 +237,15 @@ async fn fabitn(
/// Random bit strings are picked and random authenticated shares are distributed to the parties.
pub(crate) async fn fashare(
(channel, delta): (&mut impl Channel, Delta),
x: &mut Vec<bool>,
i: usize,
n: usize,
l: usize,
shared_rng: &mut ChaCha20Rng,
(keys, macs): (Vec<Vec<u128>>, Vec<Vec<u128>>),
) -> Result<Vec<Share>, Error> {
// Step 1) Pick random bit-string x (input).

// Step 2) Run Pi_aBit^n to compute shares.
let mut xishares = fabitn((channel, delta), x, i, n, l + RHO, shared_rng, (keys, macs)).await?;
let mut xishares = fabitn((channel, delta), i, n, l + RHO, shared_rng).await?;

// Step 3) Compute commitments and verify consistency.
// Step 3 a) Compute d0, d1, dm, c0, c1, cm and broadcast commitments to all parties.
Expand Down Expand Up @@ -318,7 +323,7 @@ pub(crate) async fn fashare(
if dmv.is_empty() {
return Err(Error::EmptyVector);
}
let dm = &dmv[r];
let dm = &dmv[r];
let start = if kk > k {
// here we compensate for not sending anything for own index
1 + (kk - 1) * 16
Expand Down
14 changes: 9 additions & 5 deletions src/fpre.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ pub async fn fpre(channel: &mut impl Channel, parties: usize) -> Result<(), Erro
for (i, (a, b)) in share.iter().enumerate() {
for (Share(bit, Auth(macs_i)), round) in [(a, 0), (b, 1)] {
for (j, (mac_i, _)) in macs_i.iter().enumerate() {
if *mac_i != Mac(0) { // Added when removed Option
if *mac_i != Mac(0) {
// Added when removed Option
let (a, b) = &share[j];
let Share(_, Auth(keys_j)) = if round == 0 { a } else { b };
let (_, key_j) = keys_j[i];
Expand Down Expand Up @@ -323,7 +324,7 @@ impl Auth {
mod tests {
use crate::{
channel::{recv_from, recv_vec_from, send_to, SimpleChannel},
fpre::{fpre, Auth, Delta, Error, Share, Mac, Key},
fpre::{fpre, Auth, Delta, Error, Key, Mac, Share},
};
use smallvec::smallvec;

Expand Down Expand Up @@ -449,7 +450,8 @@ mod tests {
assert_eq!(mac_s3, key_s3 ^ (s3 & delta_a));
} else if i == 1 {
// corrupted (r1 XOR s1) AND (r2 XOR s2):
let auth_r1_corrupted = Share(!r1, Auth(smallvec![(Mac(0), Key(0)), (mac_r1, key_s1)]));
let auth_r1_corrupted =
Share(!r1, Auth(smallvec![(Mac(0), Key(0)), (mac_r1, key_s1)]));
send_to(
&mut a,
fpre_party,
Expand All @@ -469,8 +471,10 @@ mod tests {
} else if i == 2 {
// A would need knowledge of B's key and delta to corrupt the shared secret:
let mac_r1_corrupted = key_r1 ^ (!r1 & delta_b);
let auth_r1_corrupted =
Share(!r1, Auth(smallvec![(Mac(0), Key(0)), (mac_r1_corrupted, key_s1)]));
let auth_r1_corrupted = Share(
!r1,
Auth(smallvec![(Mac(0), Key(0)), (mac_r1_corrupted, key_s1)]),
);
send_to(
&mut a,
fpre_party,
Expand Down
14 changes: 7 additions & 7 deletions src/ot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,34 +28,34 @@ pub fn u128_to_block(inp: u128) -> Block {

pub(crate) async fn kos_ot_sender(
channel: &mut impl Channel,
deltas: Vec<Block>,
deltas: &[Block],
p_own: usize,
p_to: usize,
) -> Result<Vec<(u128, u128)>, Error> {
) -> Result<Vec<u128>, Error> {
let mut rng = AesRng::new();
let mut ot = swankyot::KosSender::init(channel, &mut rng, p_own, p_to).await?;

let sender_out_block = ot
.send_correlated(channel, &deltas, &mut rng, p_own, p_to)
.send_correlated(channel, deltas, &mut rng, p_own, p_to)
.await?;
let mut sender_out = vec![];
for (i, j) in sender_out_block.iter() {
sender_out.push((block_to_u128(*i), block_to_u128(*j)));
for (i, _) in sender_out_block.iter() {
sender_out.push(block_to_u128(*i));
}
Ok(sender_out)
}

pub(crate) async fn kos_ot_receiver(
channel: &mut impl Channel,
bs: Vec<bool>,
bs: &[bool],
p_own: usize,
p_to: usize,
) -> Result<Vec<u128>, Error> {
let mut rng = AesRng::new();
let mut ot = swankyot::KosReceiver::init(channel, &mut rng, p_own, p_to).await?;

let recver_out_block = ot
.recv_correlated(channel, &bs, &mut rng, p_own, p_to)
.recv_correlated(channel, bs, &mut rng, p_own, p_to)
.await?;
let mut recver_out = vec![];
for i in recver_out_block.iter() {
Expand Down
61 changes: 18 additions & 43 deletions src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
use std::ops::BitXor;

use garble_lang::circuit::{Circuit, CircuitError, Wire};
use rand::random;
use rand::{random, SeedableRng};
use rand_chacha::ChaCha20Rng;
use serde::{Deserialize, Serialize};
use smallvec::smallvec;
use tokio::{runtime::Runtime, task::JoinSet};

use crate::{
channel::{self, recv_from, recv_vec_from, send_to, Channel, SimpleChannel},
faand::{self, beaver_aand, bucket_size, fashare, shared_rng, RHO},
faand::{self, beaver_aand, bucket_size, fashare, shared_rng},
fpre::{fpre, Auth, Delta, Key, Mac, Share},
garble::{self, decrypt, encrypt, GarblingKey},
ot::{kos_ot_receiver, kos_ot_sender, u128_to_block},
};

/// Preprocessed AND gates that need to be sent to the circuit evaluator.
Expand Down Expand Up @@ -328,64 +328,34 @@ pub async fn mpc(
let num_and_gates = circuit.and_gates();
let num_gates = num_input_gates + circuit.gates.len();
let secret_bits = num_input_gates + num_and_gates;
let secret_bits_ot = secret_bits + 3 * RHO;

let b = bucket_size(num_and_gates);
let lprime = num_and_gates * b;

let mut sender_ot = vec![vec![0; secret_bits_ot + 3 * lprime]; p_max];
let mut receiver_ot = vec![vec![0; secret_bits_ot + 3 * lprime]; p_max];

let delta: Delta;
let mut shared_rand = shared_rng(channel, p_own, (0..p_max).collect()).await?;
let mut x: Vec<bool> = (0..secret_bits_ot + 3 * lprime)
.map(|_| random())
.collect();
let mut shared_rand: rand_chacha::ChaCha20Rng = ChaCha20Rng::from_entropy();
let random_shares: Vec<Share>;
let mut xyz_shares = vec![];

if let Preprocessor::TrustedDealer(p_fpre) = p_fpre {
send_to::<()>(channel, p_fpre, "delta", &[]).await?;
delta = recv_from(channel, p_fpre, "delta")
.await?
.pop()
.ok_or(Error::EmptyMsg)?;
} else {
delta = Delta(random());
let deltas = vec![u128_to_block(delta.0); secret_bits_ot + 3 * lprime];
for p in (0..p_max).filter(|p| *p != p_own) {
let sender_out: Vec<(u128, u128)>;
let recver_out: Vec<u128>;
if p_own < p {
sender_out = kos_ot_sender(channel, deltas.clone(), p_own, p).await?;
recver_out = kos_ot_receiver(channel, x.clone(), p_own, p).await?;
} else {
recver_out = kos_ot_receiver(channel, x.clone(), p_own, p).await?;
sender_out = kos_ot_sender(channel, deltas.clone(), p_own, p).await?;
}

let sender = sender_out.iter().map(|(first, _)| *first).collect();
sender_ot[p] = sender;
receiver_ot[p] = recver_out;
}
}

let random_shares: Vec<Share>;
let rand_shares: Vec<Share>;
let auth_bits: Vec<Share>;
let mut shares = vec![Share(false, Auth(smallvec![])); num_gates];
let mut labels = vec![Label(0); num_gates];
let mut xyz_shares = vec![];

if let Preprocessor::TrustedDealer(p_fpre) = p_fpre {
send_to(channel, p_fpre, "random shares", &[secret_bits as u32]).await?;
random_shares = recv_from(channel, p_fpre, "random shares").await?;
} else {
rand_shares = fashare(
delta = Delta(random());
shared_rand = shared_rng(channel, p_own, (0..p_max).collect()).await?;

let rand_shares = fashare(
(channel, delta),
&mut x,
p_own,
p_max,
secret_bits + 3 * lprime,
&mut shared_rand,
(sender_ot, receiver_ot),
)
.await?;

Expand All @@ -395,6 +365,8 @@ pub async fn mpc(
}

let mut random_shares = random_shares.into_iter();
let mut shares = vec![Share(false, Auth(smallvec![])); num_gates];
let mut labels = vec![Label(0); num_gates];

for (w, gate) in circuit.wires().iter().enumerate() {
if let Wire::Input(_) | Wire::And(_, _) = gate {
Expand Down Expand Up @@ -428,6 +400,7 @@ pub async fn mpc(
}
}

let auth_bits: Vec<Share>;
if let Preprocessor::TrustedDealer(p_fpre) = p_fpre {
send_to(channel, p_fpre, "AND shares", &and_shares).await?;
auth_bits = recv_from(channel, p_fpre, "AND shares").await?;
Expand Down Expand Up @@ -560,7 +533,8 @@ pub async fn mpc(
let mut masked_input = *input ^ own_share;
for p in 0..p_max {
if let Some((_, key)) = own_macs_and_keys.get(p).copied() {
if key != Key(0) { //only needed for the trusted dealer version
if key != Key(0) {
//only needed for the trusted dealer version
let Some(other_shares) = wire_shares_from_others.get(p) else {
return Err(MpcError::InvalidInputMacOnWire(w).into());
};
Expand Down Expand Up @@ -667,7 +641,8 @@ pub async fn mpc(
let Auth(mac_s_key_r) = mac_s_key_r;
for (p, mac_s_key_r) in mac_s_key_r.iter().enumerate() {
let (_, key_r) = mac_s_key_r;
if *key_r == Key(0){ //only needed for the trusted dealer version
if *key_r == Key(0) {
//only needed for the trusted dealer version
continue;
}
let Some(GarbledGate(garbled_gate)) = &garbled_gates[p][w] else {
Expand Down

0 comments on commit e427a70

Please sign in to comment.