From 53a0ec49af624bd5e166cb71c9b2a2818097ef4b Mon Sep 17 00:00:00 2001 From: Janmajaya Mall Date: Mon, 24 Jun 2024 16:13:17 +0700 Subject: [PATCH] add high but fast communication for 2pc --- src/bool/keys.rs | 53 +++++++++++++++++++++++++++++++++++++++++++ src/bool/mod.rs | 1 + src/bool/mp_api.rs | 30 ++++++++++++++++++++++-- src/bool/ni_mp_api.rs | 37 +----------------------------- src/utils.rs | 1 - 5 files changed, 83 insertions(+), 39 deletions(-) diff --git a/src/bool/keys.rs b/src/bool/keys.rs index 03b8911..1d2774a 100644 --- a/src/bool/keys.rs +++ b/src/bool/keys.rs @@ -1243,3 +1243,56 @@ impl WithShoupRepr for NormalAndShoup { &self.1 } } + +pub(super) mod tests { + use itertools::izip; + use num_traits::{FromPrimitive, PrimInt, ToPrimitive, Zero}; + + use crate::{ + backend::{GetModulus, Modulus}, + bool::ClientKey, + lwe::decrypt_lwe, + parameters::CiphertextModulus, + utils::TryConvertFrom1, + ArithmeticOps, Row, + }; + + use super::SinglePartyClientKey; + + pub(crate) fn ideal_sk_rlwe(cks: &[ClientKey]) -> Vec { + let mut ideal_rlwe_sk = cks[0].sk_rlwe(); + cks.iter().skip(1).for_each(|k| { + let sk_rlwe = k.sk_rlwe(); + izip!(ideal_rlwe_sk.iter_mut(), sk_rlwe.iter()).for_each(|(a, b)| { + *a = *a + b; + }); + }); + ideal_rlwe_sk + } + + pub(crate) fn measure_noise_lwe< + R: Row, + S, + Modop: ArithmeticOps + + GetModulus, Element = R::Element>, + >( + lwe_ct: &R, + m_expected: R::Element, + sk: &[S], + modop: &Modop, + ) -> f64 + where + R: TryConvertFrom1<[S], CiphertextModulus>, + R::Element: Zero + FromPrimitive + PrimInt, + { + let noisy_m = decrypt_lwe(lwe_ct, &sk, modop); + let noise = modop.sub(&m_expected, &noisy_m); + modop + .modulus() + .map_element_to_i64(&noise) + .abs() + .to_f64() + .unwrap() + .log2() + } +} diff --git a/src/bool/mod.rs b/src/bool/mod.rs index e6b5672..6f30238 100644 --- a/src/bool/mod.rs +++ b/src/bool/mod.rs @@ -21,6 +21,7 @@ pub use mp_api::*; pub type ClientKey = keys::ClientKey<[u8; 32], u64>; pub enum ParameterSelector { + HighCommunicationButFast2Party, MultiPartyLessThanOrEqualTo16, NonInteractiveMultiPartyLessThanOrEqualTo16, } diff --git a/src/bool/mp_api.rs b/src/bool/mp_api.rs index 4dd7279..db2055f 100644 --- a/src/bool/mp_api.rs +++ b/src/bool/mp_api.rs @@ -30,6 +30,10 @@ pub fn set_parameter_set(select: ParameterSelector) { ParameterSelector::MultiPartyLessThanOrEqualTo16 => { BOOL_EVALUATOR.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(SMALL_MP_BOOL_PARAMS))); } + ParameterSelector::HighCommunicationButFast2Party => { + BOOL_EVALUATOR + .with_borrow_mut(|v| *v = Some(BoolEvaluator::new(OPTIMISED_SMALL_MP_BOOL_PARAMS))); + } _ => { panic!("Paramerters not supported") } @@ -234,16 +238,25 @@ mod impl_enc_dec { #[cfg(test)] mod tests { + use std::thread::panicking; + use itertools::Itertools; use rand::{thread_rng, RngCore}; - use crate::{bool::evaluator::BooleanGates, Encryptor, MultiPartyDecryptor}; + use crate::{ + bool::{ + evaluator::BooleanGates, + keys::tests::{ideal_sk_rlwe, measure_noise_lwe}, + }, + evaluator::{BoolEncoding, BoolEvaluator}, + Encryptor, MultiPartyDecryptor, + }; use super::*; #[test] fn multi_party_bool_gates() { - set_parameter_set(ParameterSelector::MultiPartyLessThanOrEqualTo16); + set_parameter_set(ParameterSelector::HighCommunicationButFast2Party); let mut seed = [0u8; 32]; thread_rng().fill_bytes(&mut seed); set_mp_seed(seed); @@ -274,6 +287,10 @@ mod tests { let mut ct0 = pk.encrypt(&m0); let mut ct1 = pk.encrypt(&m1); + let ideal_sk_rlwe = ideal_sk_rlwe(&cks); + let parameters = BoolEvaluator::with_local(|e| e.parameters().clone()); + let rlwe_modop = parameters.default_rlwe_modop(); + for _ in 0..500 { let ct_out = BoolEvaluator::with_local_mut(|e| e.nand(&ct0, &ct1, RuntimeServerKey::global())); @@ -287,6 +304,15 @@ mod tests { let m_out = cks[0].aggregate_decryption_shares(&ct_out, &decryption_shares); assert!(m_out == m_expected, "Expected {m_expected}, got {m_out}"); + { + let m_expected_el = if m_expected == true { + parameters.rlwe_q().true_el() + } else { + parameters.rlwe_q().false_el() + }; + let noise = measure_noise_lwe(&ct_out, m_expected_el, &ideal_sk_rlwe, &rlwe_modop); + println!("NAND Noise: {noise}"); + } m1 = m0; m0 = m_expected; diff --git a/src/bool/ni_mp_api.rs b/src/bool/ni_mp_api.rs index 108ac03..86961df 100644 --- a/src/bool/ni_mp_api.rs +++ b/src/bool/ni_mp_api.rs @@ -368,42 +368,7 @@ mod tests { use super::*; - pub(crate) fn ideal_sk_rlwe(cks: &[ClientKey]) -> Vec { - let mut ideal_rlwe_sk = cks[0].sk_rlwe(); - cks.iter().skip(1).for_each(|k| { - let sk_rlwe = k.sk_rlwe(); - izip!(ideal_rlwe_sk.iter_mut(), sk_rlwe.iter()).for_each(|(a, b)| { - *a = *a + b; - }); - }); - ideal_rlwe_sk - } - - pub(crate) fn measure_noise_lwe< - R: Row, - S, - Modop: ArithmeticOps - + GetModulus, Element = R::Element>, - >( - lwe_ct: &R, - m_expected: R::Element, - sk: &[S], - modop: &Modop, - ) -> f64 - where - R: TryConvertFrom1<[S], CiphertextModulus>, - R::Element: Zero + FromPrimitive + PrimInt, - { - let noisy_m = decrypt_lwe(lwe_ct, &sk, modop); - let noise = modop.sub(&m_expected, &noisy_m); - modop - .modulus() - .map_element_to_i64(&noise) - .abs() - .to_f64() - .unwrap() - .log2() - } + #[test] fn non_interactive_mp_bool_nand() { diff --git a/src/utils.rs b/src/utils.rs index aad1144..0b7c137 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -262,7 +262,6 @@ pub(crate) mod tests { use std::fmt::Debug; use num_traits::{FromPrimitive, PrimInt}; - use rand::thread_rng; use crate::random::DefaultSecureRng;