Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

offline-phase: lowgear: shared-random: Generate shared random values #73

Merged
merged 1 commit into from
Apr 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions mp-spdz-rs/src/fhe/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,13 @@ impl<C: CurveGroup> BGVParams<C> {
}

/// Get the number of plaintext slots the given parameters support
pub fn plaintext_slots(&self) -> u32 {
self.as_ref().n_plaintext_slots()
pub fn plaintext_slots(&self) -> usize {
self.as_ref().n_plaintext_slots() as usize
}

/// Get the number of ciphertexts that may be proven together
pub fn ciphertext_pok_batch_size(&self) -> usize {
(self.plaintext_slots() as usize) * (DEFAULT_DROWN_SEC as usize)
self.plaintext_slots() * (DEFAULT_DROWN_SEC as usize)
}
}

Expand Down
39 changes: 39 additions & 0 deletions mp-spdz-rs/src/fhe/plaintext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ impl<C: CurveGroup> Plaintext<C> {
self.inner.num_slots() as usize
}

/// Get a vector of scalars from the plaintext slots
pub fn to_scalars(&self) -> Vec<Scalar<C>> {
let mut scalars = Vec::with_capacity(self.num_slots());
for i in 0..self.num_slots() {
scalars.push(self.get_element(i));
}

scalars
}

/// Set each slot with the given value
pub fn set_all<T: Into<Scalar<C>>>(&mut self, value: T) {
let val_bigint = scalar_to_ffi_bigint(value.into());
Expand Down Expand Up @@ -155,6 +165,35 @@ impl<C: CurveGroup> PlaintextVector<C> {
Self { inner, _phantom: PhantomData }
}

/// Create a plaintext vector from a vector of scalars, packing them into
/// slots
pub fn from_scalars(scalars: &[Scalar<C>], params: &BGVParams<C>) -> Self {
let n_plaintexts = scalars.len() / params.plaintext_slots() + 1;
let mut pt = Self::new(n_plaintexts, params);

for chunk in scalars.chunks(params.plaintext_slots()) {
let mut plaintext = Plaintext::new(params);
for (i, scalar) in chunk.iter().enumerate() {
plaintext.set_element(i, *scalar);
}

pt.push(&plaintext);
}

pt
}

/// Create a vector of scalars from the plaintext vector
pub fn to_scalars(&self) -> Vec<Scalar<C>> {
let mut scalars = Vec::with_capacity(self.total_slots());
for i in 0..self.len() {
let plaintext = self.get(i);
scalars.extend(plaintext.to_scalars());
}

scalars
}

/// Create a new empty `PlaintextVector`
pub fn empty() -> Self {
Self { inner: ffi::new_empty_plaintext_vector(), _phantom: PhantomData }
Expand Down
23 changes: 23 additions & 0 deletions offline-phase/src/lowgear/inverse_tuples.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//! Defines the subprotocol for generating tuples (a, a^{-1}) for a random value
//! a

use ark_ec::CurveGroup;
use ark_mpc::network::MpcNetwork;

use crate::error::LowGearError;

use super::LowGear;

impl<C: CurveGroup, N: MpcNetwork<C> + Unpin + Send> LowGear<C, N> {
/// Generate a set of inverse tuples
pub async fn generate_inverse_tuples(&mut self, n: usize) -> Result<(), LowGearError> {
// We use one triplet per tuple, so we need at least n triples
assert!(self.triples.len() >= n, "not enough triplets for {n} inverse tuples");
let random_values = self.get_authenticated_randomness_vec(2 * n).await?;

// Split into halves that we will multiply using the Beaver trick
let (random_values1, random_values2) = random_values.split_at(n);

Ok(())
}
}
5 changes: 5 additions & 0 deletions offline-phase/src/lowgear/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
//! keys, authenticating inputs, etc

pub mod commit_reveal;
pub mod inverse_tuples;
pub mod mac_check;
pub mod multiplication;
pub mod setup;
pub mod shared_random;
pub mod triplets;
Expand Down Expand Up @@ -43,6 +45,8 @@ pub struct LowGear<C: CurveGroup, N: MpcNetwork<C>> {
pub other_mac_enc: Option<Ciphertext<C>>,
/// The Beaver triples generated during the offline phase
pub triples: Vec<(ValueMac<C>, ValueMac<C>, ValueMac<C>)>,
/// The inverse tuples generated during the offline phase
pub inverse_tuples: Vec<(ValueMac<C>, ValueMac<C>)>,
/// A reference to the underlying network connection
pub network: N,
}
Expand All @@ -63,6 +67,7 @@ impl<C: CurveGroup, N: MpcNetwork<C> + Unpin> LowGear<C, N> {
other_pk: None,
other_mac_enc: None,
triples: Default::default(),
inverse_tuples: Default::default(),
network,
}
}
Expand Down
1 change: 1 addition & 0 deletions offline-phase/src/lowgear/multiplication.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//! Multiplication sub-protocol using the Beaver trick
45 changes: 43 additions & 2 deletions offline-phase/src/lowgear/shared_random.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
use ark_ec::CurveGroup;
use ark_mpc::{algebra::Scalar, network::MpcNetwork};
use itertools::Itertools;
use mp_spdz_rs::fhe::plaintext::PlaintextVector;
use rand::rngs::OsRng;

use crate::error::LowGearError;
use crate::{beaver_source::ValueMac, error::LowGearError};

use super::LowGear;

Expand Down Expand Up @@ -38,14 +39,39 @@ impl<C: CurveGroup, N: MpcNetwork<C> + Unpin + Send> LowGear<C, N> {
.collect_vec();
Ok(final_shares)
}

/// Generate secret shared, authenticated random values
pub async fn get_authenticated_randomness_vec(
&mut self,
n: usize,
) -> Result<Vec<ValueMac<C>>, LowGearError> {
// Each party generates shares locally with the represented value implicitly
// defined as the sum of the shares
let mut rng = OsRng;
let my_shares = (0..n).map(|_| Scalar::<C>::random(&mut rng)).collect_vec();

let pt_vec = PlaintextVector::from_scalars(&my_shares, &self.params);
let mut macs = self.authenticate_vec(&pt_vec).await?.to_scalars();

// Recombine into ValueMac pairs
macs.truncate(n);
let res =
my_shares.into_iter().zip(macs.into_iter()).map(|(v, m)| ValueMac::new(v, m)).collect();

Ok(res)
}
}

#[cfg(test)]
mod tests {
use crate::test_helpers::mock_lowgear;
use crate::{
beaver_source::ValueMacBatch,
test_helpers::{mock_lowgear, mock_lowgear_with_keys},
};

use super::*;

/// Tests creating a shared vector of public randomness values
#[tokio::test]
async fn test_get_shared_randomness_vec() {
mock_lowgear(|mut lowgear| async move {
Expand All @@ -62,4 +88,19 @@ mod tests {
})
.await;
}

/// Tests creating a shared vector of authenticated random values
#[tokio::test]
async fn test_get_authenticated_randomness_vec() {
const N: usize = 100;

mock_lowgear_with_keys(|mut lowgear| async move {
let shares = lowgear.get_authenticated_randomness_vec(N).await.unwrap();
assert_eq!(shares.len(), N);

// Check the macs on the shares
lowgear.open_and_check_macs(ValueMacBatch::new(shares)).await.unwrap();
})
.await;
}
}
4 changes: 2 additions & 2 deletions offline-phase/src/lowgear/triplets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ impl<C: CurveGroup, N: MpcNetwork<C> + Unpin> LowGear<C, N> {
}

/// Authenticate a plaintext vector with the counterparty
async fn authenticate_vec(
pub async fn authenticate_vec(
&mut self,
a: &PlaintextVector<C>,
) -> Result<PlaintextVector<C>, LowGearError> {
Expand Down Expand Up @@ -416,7 +416,7 @@ mod test {
// The number of plaintext vectors to test
mock_lowgear_with_keys(|mut lowgear| async move {
// Generate values for the triplets
let n_slots = lowgear.params.plaintext_slots() as usize;
let n_slots = lowgear.params.plaintext_slots();
let my_a = random_scalars(n_slots);
let my_b = random_scalars(n_slots);
let my_c = random_scalars(n_slots);
Expand Down
Loading