Browse Source

add more MP params

par-agg-key-shares
Janmajaya Mall 9 months ago
parent
commit
56c4276cba
8 changed files with 386 additions and 207 deletions
  1. +5
    -16
      src/bool/keys.rs
  2. +32
    -14
      src/bool/mp_api.rs
  3. +16
    -21
      src/bool/ni_mp_api.rs
  4. +63
    -81
      src/bool/parameters.rs
  5. +250
    -68
      src/bool/print_noise.rs
  6. +1
    -0
      src/lib.rs
  7. +2
    -2
      src/rgsw/mod.rs
  8. +17
    -5
      src/utils.rs

+ 5
- 16
src/bool/keys.rs

@ -1499,16 +1499,11 @@ pub(crate) mod key_size {
pub(super) mod tests { pub(super) mod tests {
use itertools::izip; use itertools::izip;
use num_traits::{FromPrimitive, PrimInt, ToPrimitive, Zero};
use num_traits::{FromPrimitive, PrimInt, Zero};
use crate::{ use crate::{
backend::{GetModulus, Modulus},
bool::ClientKey,
decomposer::NumInfo,
lwe::decrypt_lwe,
parameters::{CiphertextModulus, I_2P},
utils::TryConvertFrom1,
ArithmeticOps, Row,
backend::GetModulus, bool::ClientKey, decomposer::NumInfo, lwe::decrypt_lwe,
parameters::CiphertextModulus, utils::TryConvertFrom1, ArithmeticOps, Row,
}; };
use super::SinglePartyClientKey; use super::SinglePartyClientKey;
@ -1545,20 +1540,14 @@ pub(super) mod tests {
m_expected: R::Element, m_expected: R::Element,
sk: &[S], sk: &[S],
modop: &Modop, modop: &Modop,
) -> f64
) -> R::Element
where where
R: TryConvertFrom1<[S], CiphertextModulus<R::Element>>, R: TryConvertFrom1<[S], CiphertextModulus<R::Element>>,
R::Element: Zero + FromPrimitive + PrimInt + NumInfo, R::Element: Zero + FromPrimitive + PrimInt + NumInfo,
{ {
let noisy_m = decrypt_lwe(lwe_ct, &sk, modop); let noisy_m = decrypt_lwe(lwe_ct, &sk, modop);
let noise = modop.sub(&m_expected, &noisy_m); let noise = modop.sub(&m_expected, &noisy_m);
modop
.modulus()
.map_element_to_i64(&noise)
.abs()
.to_f64()
.unwrap()
.log2()
noise
} }
// #[test] // #[test]
// fn trial() { // fn trial() {

+ 32
- 14
src/bool/mp_api.rs

@ -35,13 +35,13 @@ pub enum ParameterSelector {
pub fn set_parameter_set(select: ParameterSelector) { pub fn set_parameter_set(select: ParameterSelector) {
match select { match select {
ParameterSelector::InteractiveLTE2Party => { ParameterSelector::InteractiveLTE2Party => {
BOOL_EVALUATOR.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(I_2P)));
BOOL_EVALUATOR.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(I_2P_LB_SR)));
} }
ParameterSelector::InteractiveLTE4Party => { ParameterSelector::InteractiveLTE4Party => {
BOOL_EVALUATOR.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(I_4P))); BOOL_EVALUATOR.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(I_4P)));
} }
ParameterSelector::InteractiveLTE8Party => { ParameterSelector::InteractiveLTE8Party => {
BOOL_EVALUATOR.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(I_8P_LB_SR)));
BOOL_EVALUATOR.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(I_8P)));
} }
_ => { _ => {
panic!("Paramerter not supported") panic!("Paramerter not supported")
@ -311,24 +311,27 @@ mod tests {
use rand::{thread_rng, Rng, RngCore}; use rand::{thread_rng, Rng, RngCore};
use crate::{ use crate::{
backend::Modulus,
bool::{ bool::{
evaluator::BoolEncoding, evaluator::BoolEncoding,
keys::tests::{ideal_sk_rlwe, measure_noise_lwe}, keys::tests::{ideal_sk_rlwe, measure_noise_lwe},
BooleanGates, BooleanGates,
}, },
Encryptor, MultiPartyDecryptor, SampleExtractor,
lwe::decrypt_lwe,
utils::tests::Stats,
Encoder, Encryptor, MultiPartyDecryptor, SampleExtractor,
}; };
use super::*; use super::*;
#[test] #[test]
fn multi_party_bool_gates() { fn multi_party_bool_gates() {
set_parameter_set(ParameterSelector::InteractiveLTE2Party);
set_parameter_set(ParameterSelector::InteractiveLTE8Party);
let mut seed = [0u8; 32]; let mut seed = [0u8; 32];
thread_rng().fill_bytes(&mut seed); thread_rng().fill_bytes(&mut seed);
set_common_reference_seed(seed); set_common_reference_seed(seed);
let parties = 2;
let parties = 8;
let cks = (0..parties).map(|_| gen_client_key()).collect_vec(); let cks = (0..parties).map(|_| gen_client_key()).collect_vec();
// round 1 // round 1
@ -361,7 +364,9 @@ mod tests {
let parameters = BoolEvaluator::with_local(|e| e.parameters().clone()); let parameters = BoolEvaluator::with_local(|e| e.parameters().clone());
let rlwe_modop = parameters.default_rlwe_modop(); let rlwe_modop = parameters.default_rlwe_modop();
for _ in 0..500 {
let mut stats = Stats::new();
for _ in 0..1000 {
let now = std::time::Instant::now(); let now = std::time::Instant::now();
let ct_out = let ct_out =
BoolEvaluator::with_local_mut(|e| e.nand(&ct0, &ct1, RuntimeServerKey::global())); BoolEvaluator::with_local_mut(|e| e.nand(&ct0, &ct1, RuntimeServerKey::global()));
@ -376,14 +381,15 @@ mod tests {
let m_out = cks[0].aggregate_decryption_shares(&ct_out, &decryption_shares); let m_out = cks[0].aggregate_decryption_shares(&ct_out, &decryption_shares);
assert!(m_out == m_expected, "Expected {m_expected}, got {m_out}"); 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}");
let noise = measure_noise_lwe(
&ct_out,
parameters.rlwe_q().encode(m_expected),
&ideal_sk_rlwe,
&rlwe_modop,
);
stats.add_sample(parameters.rlwe_q().map_element_to_i64(&noise));
} }
m1 = m0; m1 = m0;
@ -393,7 +399,7 @@ mod tests {
ct0 = ct_out; ct0 = ct_out;
} }
for _ in 0..500 {
for _ in 0..1000 {
let ct_out = let ct_out =
BoolEvaluator::with_local_mut(|e| e.xnor(&ct0, &ct1, RuntimeServerKey::global())); BoolEvaluator::with_local_mut(|e| e.xnor(&ct0, &ct1, RuntimeServerKey::global()));
@ -407,12 +413,24 @@ mod tests {
assert!(m_out == m_expected, "Expected {m_expected}, got {m_out}"); assert!(m_out == m_expected, "Expected {m_expected}, got {m_out}");
{
let noise = measure_noise_lwe(
&ct_out,
parameters.rlwe_q().encode(m_expected),
&ideal_sk_rlwe,
&rlwe_modop,
);
stats.add_sample(parameters.rlwe_q().map_element_to_i64(&noise));
}
m1 = m0; m1 = m0;
m0 = m_expected; m0 = m_expected;
ct1 = ct0; ct1 = ct0;
ct0 = ct_out; ct0 = ct_out;
} }
println!("Noise std_dev log2: {}", stats.std_dev().abs().log2());
} }
#[test] #[test]

+ 16
- 21
src/bool/ni_mp_api.rs

@ -3,7 +3,6 @@ use std::{cell::RefCell, sync::OnceLock};
use crate::{ use crate::{
backend::ModulusPowerOf2, backend::ModulusPowerOf2,
bool::parameters::ParameterVariant, bool::parameters::ParameterVariant,
parameters::NI_4P,
random::DefaultSecureRng, random::DefaultSecureRng,
utils::{Global, WithLocal}, utils::{Global, WithLocal},
ModularOpsU64, NttBackendU64, ModularOpsU64, NttBackendU64,
@ -16,7 +15,7 @@ use super::{
NonInteractiveServerKeyEvaluationDomain, SeededNonInteractiveMultiPartyServerKey, NonInteractiveServerKeyEvaluationDomain, SeededNonInteractiveMultiPartyServerKey,
ShoupNonInteractiveServerKeyEvaluationDomain, ShoupNonInteractiveServerKeyEvaluationDomain,
}, },
parameters::{BoolParameters, CiphertextModulus, NI_2P},
parameters::{BoolParameters, CiphertextModulus, NI_2P, NI_4P_HB_FR, NI_8P},
ClientKey, ClientKey,
}; };
@ -40,6 +39,7 @@ static MULTI_PARTY_CRS: OnceLock> = OnceLo
pub enum ParameterSelector { pub enum ParameterSelector {
NonInteractiveLTE2Party, NonInteractiveLTE2Party,
NonInteractiveLTE4Party, NonInteractiveLTE4Party,
NonInteractiveLTE8Party,
} }
pub fn set_parameter_set(select: ParameterSelector) { pub fn set_parameter_set(select: ParameterSelector) {
@ -48,11 +48,10 @@ pub fn set_parameter_set(select: ParameterSelector) {
BOOL_EVALUATOR.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(NI_2P))); BOOL_EVALUATOR.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(NI_2P)));
} }
ParameterSelector::NonInteractiveLTE4Party => { ParameterSelector::NonInteractiveLTE4Party => {
BOOL_EVALUATOR.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(NI_4P)));
BOOL_EVALUATOR.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(NI_4P_HB_FR)));
} }
_ => {
panic!("Paramerters not supported")
ParameterSelector::NonInteractiveLTE8Party => {
BOOL_EVALUATOR.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(NI_8P)));
} }
} }
} }
@ -461,12 +460,12 @@ mod tests {
#[test] #[test]
fn non_interactive_mp_bool_nand() { fn non_interactive_mp_bool_nand() {
set_parameter_set(ParameterSelector::NonInteractiveLTE2Party);
set_parameter_set(ParameterSelector::NonInteractiveLTE8Party);
let mut seed = [0u8; 32]; let mut seed = [0u8; 32];
thread_rng().fill_bytes(&mut seed); thread_rng().fill_bytes(&mut seed);
set_common_reference_seed(seed); set_common_reference_seed(seed);
let parties = 2;
let parties = 8;
let cks = (0..parties).map(|_| gen_client_key()).collect_vec(); let cks = (0..parties).map(|_| gen_client_key()).collect_vec();
@ -501,10 +500,10 @@ mod tests {
let mut stats = Stats::new(); let mut stats = Stats::new();
for _ in 0..1000 { for _ in 0..1000 {
// let now = std::time::Instant::now();
let now = std::time::Instant::now();
let ct_out = let ct_out =
BoolEvaluator::with_local_mut(|e| e.xor(&ct0, &ct1, RuntimeServerKey::global())); BoolEvaluator::with_local_mut(|e| e.xor(&ct0, &ct1, RuntimeServerKey::global()));
// println!("Time: {:?}", now.elapsed());
println!("Time: {:?}", now.elapsed());
let decryption_shares = cks let decryption_shares = cks
.iter() .iter()
@ -515,17 +514,13 @@ mod tests {
let m_expected = m0 ^ m1; let m_expected = m0 ^ m1;
{ {
// let noise = measure_noise_lwe(
// &ct_out,
// parameters.rlwe_q().encode(m_expected),
// &ideal_sk_rlwe,
// &rlwe_modop,
// );
// println!("Noise: {noise}");
let noisy_m = decrypt_lwe(&ct_out, &ideal_sk_rlwe, &rlwe_modop);
let noise = rlwe_modop.sub(&parameters.rlwe_q().encode(m_expected), &noisy_m);
stats.add_more(&vec![parameters.rlwe_q().map_element_to_i64(&noise)]);
let noise = measure_noise_lwe(
&ct_out,
parameters.rlwe_q().encode(m_expected),
&ideal_sk_rlwe,
&rlwe_modop,
);
stats.add_sample(parameters.rlwe_q().map_element_to_i64(&noise));
} }
assert!(m_out == m_expected, "Expected {m_expected} but got {m_out}"); assert!(m_out == m_expected, "Expected {m_expected} but got {m_out}");

+ 63
- 81
src/bool/parameters.rs

@ -523,70 +523,46 @@ where
} }
} }
pub(crate) const MP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {
pub(crate) const I_2P_LB_SR: BoolParameters<u64> = BoolParameters::<u64> {
rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution, rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
lwe_secret_key_dist: SecretKeyDistribution::ErrorDistribution,
rlwe_q: CiphertextModulus::new_non_native(1152921504606830593),
lwe_q: CiphertextModulus::new_non_native(1 << 20),
br_q: 1 << 11,
rlwe_n: PolynomialSize(1 << 11),
lwe_n: LweDimension(500),
lwe_decomposer_params: (DecompostionLogBase(4), DecompositionCount(5)),
rlrg_decomposer_params: (
DecompostionLogBase(12),
(DecompositionCount(5), DecompositionCount(5)),
),
rgrg_decomposer_params: Some((
DecompostionLogBase(12),
(DecompositionCount(5), DecompositionCount(5)),
)),
auto_decomposer_params: (DecompostionLogBase(12), DecompositionCount(5)),
non_interactive_ui_to_s_key_switch_decomposer: None,
g: 5,
w: 10,
variant: ParameterVariant::InteractiveMultiParty,
};
pub(crate) const SMALL_MP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {
rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
lwe_secret_key_dist: SecretKeyDistribution::ErrorDistribution,
rlwe_q: CiphertextModulus::new_non_native(36028797018820609),
lwe_q: CiphertextModulus::new_non_native(1 << 20),
lwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
rlwe_q: CiphertextModulus::new_non_native(18014398509404161),
lwe_q: CiphertextModulus::new_non_native(1 << 15),
br_q: 1 << 11, br_q: 1 << 11,
rlwe_n: PolynomialSize(1 << 11), rlwe_n: PolynomialSize(1 << 11),
lwe_n: LweDimension(600),
lwe_decomposer_params: (DecompostionLogBase(4), DecompositionCount(5)),
lwe_n: LweDimension(580),
lwe_decomposer_params: (DecompostionLogBase(1), DecompositionCount(12)),
rlrg_decomposer_params: ( rlrg_decomposer_params: (
DecompostionLogBase(11),
(DecompositionCount(2), DecompositionCount(1)),
DecompostionLogBase(17),
(DecompositionCount(1), DecompositionCount(1)),
), ),
rgrg_decomposer_params: Some(( rgrg_decomposer_params: Some((
DecompostionLogBase(11),
(DecompositionCount(5), DecompositionCount(4)),
DecompostionLogBase(7),
(DecompositionCount(6), DecompositionCount(5)),
)), )),
auto_decomposer_params: (DecompostionLogBase(11), DecompositionCount(2)),
auto_decomposer_params: (DecompostionLogBase(24), DecompositionCount(1)),
non_interactive_ui_to_s_key_switch_decomposer: None, non_interactive_ui_to_s_key_switch_decomposer: None,
g: 5, g: 5,
w: 10, w: 10,
variant: ParameterVariant::InteractiveMultiParty, variant: ParameterVariant::InteractiveMultiParty,
}; };
pub(crate) const I_2P: BoolParameters<u64> = BoolParameters::<u64> {
pub(crate) const I_4P: BoolParameters<u64> = BoolParameters::<u64> {
rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution, rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
lwe_secret_key_dist: SecretKeyDistribution::ErrorDistribution,
lwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
rlwe_q: CiphertextModulus::new_non_native(18014398509404161), rlwe_q: CiphertextModulus::new_non_native(18014398509404161),
lwe_q: CiphertextModulus::new_non_native(1 << 15),
lwe_q: CiphertextModulus::new_non_native(1 << 16),
br_q: 1 << 11, br_q: 1 << 11,
rlwe_n: PolynomialSize(1 << 11), rlwe_n: PolynomialSize(1 << 11),
lwe_n: LweDimension(480),
lwe_decomposer_params: (DecompostionLogBase(1), DecompositionCount(12)),
lwe_n: LweDimension(620),
lwe_decomposer_params: (DecompostionLogBase(1), DecompositionCount(13)),
rlrg_decomposer_params: ( rlrg_decomposer_params: (
DecompostionLogBase(17), DecompostionLogBase(17),
(DecompositionCount(1), DecompositionCount(1)), (DecompositionCount(1), DecompositionCount(1)),
), ),
rgrg_decomposer_params: Some(( rgrg_decomposer_params: Some((
DecompostionLogBase(7),
(DecompositionCount(6), DecompositionCount(5)),
DecompostionLogBase(6),
(DecompositionCount(7), DecompositionCount(6)),
)), )),
auto_decomposer_params: (DecompostionLogBase(24), DecompositionCount(1)), auto_decomposer_params: (DecompostionLogBase(24), DecompositionCount(1)),
non_interactive_ui_to_s_key_switch_decomposer: None, non_interactive_ui_to_s_key_switch_decomposer: None,
@ -595,22 +571,22 @@ pub(crate) const I_2P: BoolParameters = BoolParameters:: {
variant: ParameterVariant::InteractiveMultiParty, variant: ParameterVariant::InteractiveMultiParty,
}; };
pub(crate) const I_4P: BoolParameters<u64> = BoolParameters::<u64> {
pub(crate) const I_8P: BoolParameters<u64> = BoolParameters::<u64> {
rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution, rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
lwe_secret_key_dist: SecretKeyDistribution::ErrorDistribution,
lwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
rlwe_q: CiphertextModulus::new_non_native(18014398509404161), rlwe_q: CiphertextModulus::new_non_native(18014398509404161),
lwe_q: CiphertextModulus::new_non_native(1 << 16),
br_q: 1 << 11,
lwe_q: CiphertextModulus::new_non_native(1 << 17),
br_q: 1 << 12,
rlwe_n: PolynomialSize(1 << 11), rlwe_n: PolynomialSize(1 << 11),
lwe_n: LweDimension(520),
lwe_decomposer_params: (DecompostionLogBase(1), DecompositionCount(13)),
lwe_n: LweDimension(660),
lwe_decomposer_params: (DecompostionLogBase(1), DecompositionCount(14)),
rlrg_decomposer_params: ( rlrg_decomposer_params: (
DecompostionLogBase(17), DecompostionLogBase(17),
(DecompositionCount(1), DecompositionCount(1)), (DecompositionCount(1), DecompositionCount(1)),
), ),
rgrg_decomposer_params: Some(( rgrg_decomposer_params: Some((
DecompostionLogBase(6),
(DecompositionCount(7), DecompositionCount(6)),
DecompostionLogBase(5),
(DecompositionCount(9), DecompositionCount(8)),
)), )),
auto_decomposer_params: (DecompostionLogBase(24), DecompositionCount(1)), auto_decomposer_params: (DecompostionLogBase(24), DecompositionCount(1)),
non_interactive_ui_to_s_key_switch_decomposer: None, non_interactive_ui_to_s_key_switch_decomposer: None,
@ -619,12 +595,12 @@ pub(crate) const I_4P: BoolParameters = BoolParameters:: {
variant: ParameterVariant::InteractiveMultiParty, variant: ParameterVariant::InteractiveMultiParty,
}; };
pub(crate) const I_8P_HB_FR: BoolParameters<u64> = BoolParameters::<u64> {
pub(crate) const NI_2P: BoolParameters<u64> = BoolParameters::<u64> {
rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution, rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
lwe_secret_key_dist: SecretKeyDistribution::ErrorDistribution, lwe_secret_key_dist: SecretKeyDistribution::ErrorDistribution,
rlwe_q: CiphertextModulus::new_non_native(18014398509404161), rlwe_q: CiphertextModulus::new_non_native(18014398509404161),
lwe_q: CiphertextModulus::new_non_native(1 << 16), lwe_q: CiphertextModulus::new_non_native(1 << 16),
br_q: 1 << 11,
br_q: 1 << 12,
rlwe_n: PolynomialSize(1 << 11), rlwe_n: PolynomialSize(1 << 11),
lwe_n: LweDimension(520), lwe_n: LweDimension(520),
lwe_decomposer_params: (DecompostionLogBase(1), DecompositionCount(13)), lwe_decomposer_params: (DecompostionLogBase(1), DecompositionCount(13)),
@ -634,55 +610,61 @@ pub(crate) const I_8P_HB_FR: BoolParameters = BoolParameters:: {
), ),
rgrg_decomposer_params: Some(( rgrg_decomposer_params: Some((
DecompostionLogBase(4), DecompostionLogBase(4),
(DecompositionCount(12), DecompositionCount(11)),
(DecompositionCount(10), DecompositionCount(9)),
)), )),
auto_decomposer_params: (DecompostionLogBase(24), DecompositionCount(1)), auto_decomposer_params: (DecompostionLogBase(24), DecompositionCount(1)),
non_interactive_ui_to_s_key_switch_decomposer: None,
non_interactive_ui_to_s_key_switch_decomposer: Some((
DecompostionLogBase(1),
DecompositionCount(50),
)),
g: 5, g: 5,
w: 10, w: 10,
variant: ParameterVariant::InteractiveMultiParty,
variant: ParameterVariant::NonInteractiveMultiParty,
}; };
pub(crate) const I_8P_LB_SR: BoolParameters<u64> = BoolParameters::<u64> {
pub(crate) const NI_4P_HB_FR: BoolParameters<u64> = BoolParameters::<u64> {
rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution, rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
lwe_secret_key_dist: SecretKeyDistribution::ErrorDistribution,
lwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
rlwe_q: CiphertextModulus::new_non_native(18014398509404161), rlwe_q: CiphertextModulus::new_non_native(18014398509404161),
lwe_q: CiphertextModulus::new_non_native(1 << 17),
lwe_q: CiphertextModulus::new_non_native(1 << 16),
br_q: 1 << 11, br_q: 1 << 11,
rlwe_n: PolynomialSize(1 << 11), rlwe_n: PolynomialSize(1 << 11),
lwe_n: LweDimension(560),
lwe_decomposer_params: (DecompostionLogBase(1), DecompositionCount(14)),
lwe_n: LweDimension(620),
lwe_decomposer_params: (DecompostionLogBase(1), DecompositionCount(13)),
rlrg_decomposer_params: ( rlrg_decomposer_params: (
DecompostionLogBase(17), DecompostionLogBase(17),
(DecompositionCount(1), DecompositionCount(1)), (DecompositionCount(1), DecompositionCount(1)),
), ),
rgrg_decomposer_params: Some(( rgrg_decomposer_params: Some((
DecompostionLogBase(5),
(DecompositionCount(8), DecompositionCount(7)),
DecompostionLogBase(3),
(DecompositionCount(13), DecompositionCount(12)),
)), )),
auto_decomposer_params: (DecompostionLogBase(24), DecompositionCount(1)), auto_decomposer_params: (DecompostionLogBase(24), DecompositionCount(1)),
non_interactive_ui_to_s_key_switch_decomposer: None,
non_interactive_ui_to_s_key_switch_decomposer: Some((
DecompostionLogBase(1),
DecompositionCount(50),
)),
g: 5, g: 5,
w: 10, w: 10,
variant: ParameterVariant::InteractiveMultiParty,
variant: ParameterVariant::NonInteractiveMultiParty,
}; };
pub(crate) const NI_2P: BoolParameters<u64> = BoolParameters::<u64> {
pub(crate) const NI_4P_LB_SR: BoolParameters<u64> = BoolParameters::<u64> {
rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution, rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
lwe_secret_key_dist: SecretKeyDistribution::ErrorDistribution,
lwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
rlwe_q: CiphertextModulus::new_non_native(18014398509404161), rlwe_q: CiphertextModulus::new_non_native(18014398509404161),
lwe_q: CiphertextModulus::new_non_native(1 << 15),
br_q: 1 << 11,
lwe_q: CiphertextModulus::new_non_native(1 << 16),
br_q: 1 << 12,
rlwe_n: PolynomialSize(1 << 11), rlwe_n: PolynomialSize(1 << 11),
lwe_n: LweDimension(480),
lwe_decomposer_params: (DecompostionLogBase(1), DecompositionCount(12)),
lwe_n: LweDimension(620),
lwe_decomposer_params: (DecompostionLogBase(1), DecompositionCount(13)),
rlrg_decomposer_params: ( rlrg_decomposer_params: (
DecompostionLogBase(16),
DecompostionLogBase(17),
(DecompositionCount(1), DecompositionCount(1)), (DecompositionCount(1), DecompositionCount(1)),
), ),
rgrg_decomposer_params: Some(( rgrg_decomposer_params: Some((
DecompostionLogBase(6),
(DecompositionCount(7), DecompositionCount(7)),
DecompostionLogBase(4),
(DecompositionCount(10), DecompositionCount(9)),
)), )),
auto_decomposer_params: (DecompostionLogBase(24), DecompositionCount(1)), auto_decomposer_params: (DecompostionLogBase(24), DecompositionCount(1)),
non_interactive_ui_to_s_key_switch_decomposer: Some(( non_interactive_ui_to_s_key_switch_decomposer: Some((
@ -694,22 +676,22 @@ pub(crate) const NI_2P: BoolParameters = BoolParameters:: {
variant: ParameterVariant::NonInteractiveMultiParty, variant: ParameterVariant::NonInteractiveMultiParty,
}; };
pub(crate) const NI_4P: BoolParameters<u64> = BoolParameters::<u64> {
pub(crate) const NI_8P: BoolParameters<u64> = BoolParameters::<u64> {
rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution, rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
lwe_secret_key_dist: SecretKeyDistribution::ErrorDistribution,
lwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
rlwe_q: CiphertextModulus::new_non_native(18014398509404161), rlwe_q: CiphertextModulus::new_non_native(18014398509404161),
lwe_q: CiphertextModulus::new_non_native(1 << 16),
br_q: 1 << 11,
lwe_q: CiphertextModulus::new_non_native(1 << 17),
br_q: 1 << 12,
rlwe_n: PolynomialSize(1 << 11), rlwe_n: PolynomialSize(1 << 11),
lwe_n: LweDimension(510),
lwe_decomposer_params: (DecompostionLogBase(1), DecompositionCount(12)),
lwe_n: LweDimension(660),
lwe_decomposer_params: (DecompostionLogBase(1), DecompositionCount(14)),
rlrg_decomposer_params: ( rlrg_decomposer_params: (
DecompostionLogBase(17), DecompostionLogBase(17),
(DecompositionCount(1), DecompositionCount(1)), (DecompositionCount(1), DecompositionCount(1)),
), ),
rgrg_decomposer_params: Some(( rgrg_decomposer_params: Some((
DecompostionLogBase(4),
(DecompositionCount(10), DecompositionCount(9)),
DecompostionLogBase(2),
(DecompositionCount(20), DecompositionCount(18)),
)), )),
auto_decomposer_params: (DecompostionLogBase(24), DecompositionCount(1)), auto_decomposer_params: (DecompostionLogBase(24), DecompositionCount(1)),
non_interactive_ui_to_s_key_switch_decomposer: Some(( non_interactive_ui_to_s_key_switch_decomposer: Some((

+ 250
- 68
src/bool/print_noise.rs

@ -23,7 +23,7 @@ use super::keys::tests::{ideal_sk_lwe, ideal_sk_rlwe};
pub(crate) trait CollectRuntimeServerKeyStats { pub(crate) trait CollectRuntimeServerKeyStats {
type M; type M;
/// RGSW ciphertext X^{s[s_index]} in evaluation domain where s the LWE
/// RGSW ciphertext X^{s[s_index]} in evaluation domain where `s` the LWE
/// secret /// secret
fn rgsw_cts_lwe_si(&self, s_index: usize) -> &Self::M; fn rgsw_cts_lwe_si(&self, s_index: usize) -> &Self::M;
/// Auto key in evaluation domain for automorphism g^k. For auto key for /// Auto key in evaluation domain for automorphism g^k. For auto key for
@ -33,9 +33,20 @@ pub(crate) trait CollectRuntimeServerKeyStats {
fn lwe_ksk(&self) -> &Self::M; fn lwe_ksk(&self) -> &Self::M;
} }
#[derive(Default)]
struct ServerKeyStats<T> { struct ServerKeyStats<T> {
/// Distribution of noise in RGSW ciphertexts
///
/// We collect statistics for RLWE'(-sm) separately from RLWE'(m) because
/// non-interactive protocol differents between the two. Although we expect
/// the distribution of noise in both to be the same.
brk_rgsw_cts: (Stats<T>, Stats<T>), brk_rgsw_cts: (Stats<T>, Stats<T>),
/// Distribtion of noise added to RLWE ciphertext after automorphism using
/// Server auto keys.
post_1_auto: Stats<T>, post_1_auto: Stats<T>,
/// Distribution of noise added in LWE key switching from LWE_{q, s} to
/// LWE_{q, z} where `z` is ideal LWE secret and `s` is ideal RLWE secret
/// using Server's LWE key switching key.
post_lwe_key_switch: Stats<T>, post_lwe_key_switch: Stats<T>,
} }
@ -52,19 +63,28 @@ where
} }
fn add_noise_brk_rgsw_cts_nsm(&mut self, noise: &[T]) { fn add_noise_brk_rgsw_cts_nsm(&mut self, noise: &[T]) {
self.brk_rgsw_cts.0.add_more(noise);
self.brk_rgsw_cts.0.add_many_samples(noise);
} }
fn add_noise_brk_rgsw_cts_m(&mut self, noise: &[T]) { fn add_noise_brk_rgsw_cts_m(&mut self, noise: &[T]) {
self.brk_rgsw_cts.1.add_more(noise);
self.brk_rgsw_cts.1.add_many_samples(noise);
} }
fn add_noise_post_1_auto(&mut self, noise: &[T]) { fn add_noise_post_1_auto(&mut self, noise: &[T]) {
self.post_1_auto.add_more(&noise);
self.post_1_auto.add_many_samples(&noise);
} }
fn add_noise_post_kwe_key_switch(&mut self, noise: &[T]) { fn add_noise_post_kwe_key_switch(&mut self, noise: &[T]) {
self.post_lwe_key_switch.add_more(&noise);
self.post_lwe_key_switch.add_many_samples(&noise);
}
fn merge_in(&mut self, other: &Self) {
self.brk_rgsw_cts.0.merge_in(&other.brk_rgsw_cts.0);
self.brk_rgsw_cts.1.merge_in(&other.brk_rgsw_cts.1);
self.post_1_auto.merge_in(&other.post_1_auto);
self.post_lwe_key_switch
.merge_in(&other.post_lwe_key_switch);
} }
} }
@ -363,8 +383,6 @@ where
mod tests { mod tests {
use itertools::Itertools; use itertools::Itertools;
use super::collect_server_key_stats;
#[test] #[test]
#[cfg(feature = "interactive_mp")] #[cfg(feature = "interactive_mp")]
fn interactive_key_noise() { fn interactive_key_noise() {
@ -382,64 +400,82 @@ mod tests {
BoolEvaluator, DefaultDecomposer, ModularOpsU64, NttBackendU64, BoolEvaluator, DefaultDecomposer, ModularOpsU64, NttBackendU64,
}; };
set_parameter_set(crate::ParameterSelector::InteractiveLTE2Party);
set_common_reference_seed(InteractiveMultiPartyCrs::random().seed);
let parties = 2;
let cks = (0..parties).map(|_| gen_client_key()).collect_vec();
let pk_shares = cks
.iter()
.map(|k| interactive_multi_party_round1_share(k))
.collect_vec();
use super::*;
let pk = aggregate_public_key_shares(&pk_shares);
let server_key_shares = cks
.iter()
.enumerate()
.map(|(index, k)| gen_mp_keys_phase2(k, index, parties, &pk))
.collect_vec();
set_parameter_set(crate::ParameterSelector::InteractiveLTE8Party);
set_common_reference_seed(InteractiveMultiPartyCrs::random().seed);
let parties = 8;
let mut server_key_stats = ServerKeyStats::default();
let mut server_key_share_size = 0usize;
for i in 0..2 {
let cks = (0..parties).map(|_| gen_client_key()).collect_vec();
let pk_shares = cks
.iter()
.map(|k| interactive_multi_party_round1_share(k))
.collect_vec();
let pk = aggregate_public_key_shares(&pk_shares);
let server_key_shares = cks
.iter()
.enumerate()
.map(|(index, k)| gen_mp_keys_phase2(k, index, parties, &pk))
.collect_vec();
// In 0th iteration measure server key size
if i == 0 {
// Server key share size of user with last id may not equal server key share
// sizes of other users if LWE dimension does not divides number of parties.
server_key_share_size = std::cmp::max(
server_key_shares.first().unwrap().size(),
server_key_shares.last().unwrap().size(),
);
}
// println!("Size: {}", server_key_shares[0].size());
let seeded_server_key = aggregate_server_key_shares(&server_key_shares);
let server_key_eval =
ServerKeyEvaluationDomain::<_, _, DefaultSecureRng, NttBackendU64>::from(
&seeded_server_key,
);
// println!("Size: {}", server_key_shares[0].size());
let seeded_server_key = aggregate_server_key_shares(&server_key_shares);
let server_key_eval =
ServerKeyEvaluationDomain::<_, _, DefaultSecureRng, NttBackendU64>::from(
&seeded_server_key,
);
let parameters = BoolEvaluator::with_local(|e| e.parameters().clone());
let server_key_stats = collect_server_key_stats::<
_,
DefaultDecomposer<u64>,
NttBackendU64,
ModularOpsU64<CiphertextModulus<u64>>,
_,
>(parameters, &cks, &server_key_eval);
let parameters = BoolEvaluator::with_local(|e| e.parameters().clone());
server_key_stats.merge_in(&collect_server_key_stats::<
_,
DefaultDecomposer<u64>,
NttBackendU64,
ModularOpsU64<CiphertextModulus<u64>>,
_,
>(parameters, &cks, &server_key_eval));
}
println!( println!(
"Common reference seeded server key share key size size: {} Bits",
server_key_shares[0].size()
"Common reference seeded server key share key size: {} Bits",
server_key_share_size
); );
println!( println!(
"Rgsw nsm std log2 {}", "Rgsw nsm std log2 {}",
server_key_stats.brk_rgsw_cts.0.std_dev().abs().log2()
server_key_stats.brk_rgsw_cts.0.std_dev().log2()
); );
println!( println!(
"Rgsw m std log2 {}", "Rgsw m std log2 {}",
server_key_stats.brk_rgsw_cts.1.std_dev().abs().log2()
server_key_stats.brk_rgsw_cts.1.std_dev().log2()
); );
println!( println!(
"rlwe post 1 auto std log2 {}", "rlwe post 1 auto std log2 {}",
server_key_stats.post_1_auto.std_dev().abs().log2()
server_key_stats.post_1_auto.std_dev().log2()
); );
println!( println!(
"key switching noise rlwe secret s to lwe secret z std log2 {}", "key switching noise rlwe secret s to lwe secret z std log2 {}",
server_key_stats.post_lwe_key_switch.std_dev().abs().log2()
server_key_stats.post_lwe_key_switch.std_dev().log2()
); );
} }
#[test] #[test]
#[cfg(feature = "non_interactive_mp")] #[cfg(feature = "non_interactive_mp")]
fn querty2() {
fn non_interactive_key_noise() {
use crate::{ use crate::{
aggregate_server_key_shares, aggregate_server_key_shares,
bool::{ bool::{
@ -455,35 +491,55 @@ mod tests {
BoolEvaluator, ModularOpsU64, NttBackendU64, BoolEvaluator, ModularOpsU64, NttBackendU64,
}; };
set_parameter_set(crate::ParameterSelector::NonInteractiveLTE2Party);
set_common_reference_seed(NonInteractiveMultiPartyCrs::random().seed);
let parties = 2;
let cks = (0..parties).map(|_| gen_client_key()).collect_vec();
let server_key_shares = cks
.iter()
.enumerate()
.map(|(user_id, k)| gen_server_key_share(user_id, parties, k))
.collect_vec();
let server_key = aggregate_server_key_shares(&server_key_shares);
use super::*;
let server_key_eval =
NonInteractiveServerKeyEvaluationDomain::<_, _, DefaultSecureRng, NttBackendU64>::from(
&server_key,
);
set_parameter_set(crate::ParameterSelector::NonInteractiveLTE8Party);
set_common_reference_seed(NonInteractiveMultiPartyCrs::random().seed);
let parties = 8;
let mut server_key_stats = ServerKeyStats::default();
let mut server_key_share_size = 0;
for i in 0..2 {
let cks = (0..parties).map(|_| gen_client_key()).collect_vec();
let server_key_shares = cks
.iter()
.enumerate()
.map(|(user_id, k)| gen_server_key_share(user_id, parties, k))
.collect_vec();
// Collect server key size in the 0th iteration
if i == 0 {
// Server key share size may differ for user with last id from
// the share size of other users if the LWE dimension `n` is not
// divisible by no. of parties.
server_key_share_size = std::cmp::max(
server_key_shares.first().unwrap().size(),
server_key_shares.last().unwrap().size(),
);
}
let parameters = BoolEvaluator::with_local(|e| e.parameters().clone());
let server_key_stats = collect_server_key_stats::<
_,
DefaultDecomposer<u64>,
NttBackendU64,
ModularOpsU64<CiphertextModulus<u64>>,
_,
>(parameters, &cks, &server_key_eval);
let server_key = aggregate_server_key_shares(&server_key_shares);
let server_key_eval = NonInteractiveServerKeyEvaluationDomain::<
_,
_,
DefaultSecureRng,
NttBackendU64,
>::from(&server_key);
let parameters = BoolEvaluator::with_local(|e| e.parameters().clone());
server_key_stats.merge_in(&collect_server_key_stats::<
_,
DefaultDecomposer<u64>,
NttBackendU64,
ModularOpsU64<CiphertextModulus<u64>>,
_,
>(parameters, &cks, &server_key_eval));
}
println!( println!(
"Common reference seeded server key share key size size: {} Bits",
server_key_shares[0].size()
"Common reference seeded server key share key size: {} Bits",
server_key_share_size
); );
println!( println!(
"Rgsw nsm std log2 {}", "Rgsw nsm std log2 {}",
@ -565,10 +621,136 @@ mod tests {
rlwe_q_modop.elwise_sub_mut(diff.as_mut_slice(), message.as_ref()); rlwe_q_modop.elwise_sub_mut(diff.as_mut_slice(), message.as_ref());
let mut stats = Stats::new(); let mut stats = Stats::new();
stats.add_more(&Vec::<i64>::try_convert_from(
stats.add_many_samples(&Vec::<i64>::try_convert_from(
diff.as_slice(), diff.as_slice(),
parameters.rlwe_q(), parameters.rlwe_q(),
)); ));
println!("Noise std log2: {}", stats.std_dev().abs().log2()); println!("Noise std log2: {}", stats.std_dev().abs().log2());
} }
#[test]
fn mod_switch_noise() {
// Experiment to check mod switch noise using different secret dist in
// multi-party setting
use itertools::izip;
use num_traits::ToPrimitive;
use crate::{
backend::{Modulus, ModulusPowerOf2},
parameters::SecretKeyDistribution,
random::{DefaultSecureRng, RandomFillGaussian, RandomFillUniformInModulus},
utils::{fill_random_ternary_secret_with_hamming_weight, tests::Stats},
ArithmeticOps, ModInit,
};
fn mod_switch(v: u64, q_from: u64, q_to: u64) -> f64 {
(v as f64) * (q_to as f64) / q_from as f64
}
fn mod_switch_round(v: u64, q_from: u64, q_to: u64) -> u64 {
mod_switch(v, q_from, q_to).round().to_u64().unwrap()
}
fn mod_switch_odd(v: u64, q_from: u64, q_to: u64) -> u64 {
let odd_v = mod_switch(v, q_from, q_to).floor().to_u64().unwrap();
odd_v + ((odd_v & 1) ^ 1)
}
fn sample_secret(n: usize, dist: &SecretKeyDistribution) -> Vec<i32> {
let mut s = vec![0i32; n];
let mut rng = DefaultSecureRng::new();
match dist {
SecretKeyDistribution::ErrorDistribution => {
RandomFillGaussian::random_fill(&mut rng, s.as_mut_slice());
}
SecretKeyDistribution::TernaryDistribution => {
fill_random_ternary_secret_with_hamming_weight(&mut s, n >> 1, &mut rng);
}
}
s
}
let parties = 2;
let q_from = 1 << 40;
let q_to = 1 << 20;
let n = 480;
let lweq_in_modop = ModulusPowerOf2::new(q_from);
let lweq_out_modop = ModulusPowerOf2::new(q_to);
let secret_dist = SecretKeyDistribution::ErrorDistribution;
let mut stats_ms_noise = Stats::new();
let mut stats_ms_rounding_err = Stats::new();
for _ in 0..1000000 {
let mut rng = DefaultSecureRng::new();
// sample secrets
let s = {
let mut s = vec![0i32; n];
for _ in 0..parties {
let temp = sample_secret(n, &secret_dist);
izip!(s.iter_mut(), temp.iter()).for_each(|(si, ti)| {
*si = *si + *ti;
});
}
s
};
let m = 10;
// LWE encryption without noise
let mut lwe_in = vec![0u64; n + 1];
{
RandomFillUniformInModulus::random_fill(&mut rng, &q_from, &mut lwe_in[1..]);
let mut b = m;
izip!(lwe_in.iter().skip(1), s.iter()).for_each(|(ai, si)| {
b = lweq_in_modop.add(
&b,
&lweq_in_modop.mul(ai, &q_from.map_element_from_i64(*si as i64)),
);
});
lwe_in[0] = b;
}
// Mod switch
let lwe_out = lwe_in
.iter()
.map(|v| {
// mod_switch_round(*v, q_from, q_to)
mod_switch_odd(*v, q_from, q_to)
})
.collect_vec();
let rounding_errors = izip!(lwe_out.iter(), lwe_in.iter())
.map(|(v_out, v_in)| {
let r_i = mod_switch(*v_in, q_from, q_to) - (*v_out as f64);
r_i
})
.collect_vec();
stats_ms_rounding_err.add_many_samples(&rounding_errors);
// LWE decrypt and calculate ms noise
let mut m_back = 0;
izip!(lwe_out.iter().skip(1), s.iter()).for_each(|(ai, si)| {
m_back = lweq_out_modop.add(
&m_back,
&lweq_out_modop.mul(ai, &q_from.map_element_from_i64(*si as i64)),
);
});
m_back = lweq_out_modop.sub(&lwe_out[0], &m_back);
let noise = lweq_out_modop.sub(&m_back, &m);
stats_ms_noise.add_many_samples(&vec![q_to.map_element_to_i64(&noise)]);
}
println!("ms noise variance: {}", stats_ms_noise.variance());
println!("ms rounding errors mean: {}", stats_ms_rounding_err.mean());
println!(
"ms rounding errors variance: {}",
stats_ms_rounding_err.variance()
);
}
} }

+ 1
- 0
src/lib.rs

@ -194,6 +194,7 @@ trait SizeInBitsWithLogModulus {
/// 2^{log_modulus-1} < Q <= `2^log_modulus` /// 2^{log_modulus-1} < Q <= `2^log_modulus`
fn size(&self, log_modulus: usize) -> usize; fn size(&self, log_modulus: usize) -> usize;
} }
impl SizeInBitsWithLogModulus for Vec<Vec<u64>> { impl SizeInBitsWithLogModulus for Vec<Vec<u64>> {
fn size(&self, log_modulus: usize) -> usize { fn size(&self, log_modulus: usize) -> usize {
let mut total = 0; let mut total = 0;

+ 2
- 2
src/rgsw/mod.rs

@ -878,7 +878,7 @@ pub(crate) mod tests {
let mut diff = want_m; let mut diff = want_m;
mod_op.elwise_sub_mut(diff.as_mut(), got_m.as_ref()); mod_op.elwise_sub_mut(diff.as_mut(), got_m.as_ref());
stats.add_more(&Vec::<i64>::try_convert_from(&diff, q));
stats.add_many_samples(&Vec::<i64>::try_convert_from(&diff, q));
} }
// RLWE(\beta^j m) // RLWE(\beta^j m)
@ -899,7 +899,7 @@ pub(crate) mod tests {
let mut diff = want_m; let mut diff = want_m;
mod_op.elwise_sub_mut(diff.as_mut(), got_m.as_ref()); mod_op.elwise_sub_mut(diff.as_mut(), got_m.as_ref());
stats.add_more(&Vec::<i64>::try_convert_from(&diff, q));
stats.add_many_samples(&Vec::<i64>::try_convert_from(&diff, q));
} }
stats stats

+ 17
- 5
src/utils.rs

@ -271,7 +271,7 @@ impl TryConvertFrom1<[P::Element], P> for Vec {
pub(crate) mod tests { pub(crate) mod tests {
use std::fmt::Debug; use std::fmt::Debug;
use num_traits::{FromPrimitive, PrimInt};
use num_traits::ToPrimitive;
use crate::random::DefaultSecureRng; use crate::random::DefaultSecureRng;
@ -288,7 +288,7 @@ pub(crate) mod tests {
} }
} }
impl<T: PrimInt + FromPrimitive + Debug> Stats<T>
impl<T: Copy + ToPrimitive + Debug> Stats<T>
where where
// T: for<'a> Sum<&'a T>, // T: for<'a> Sum<&'a T>,
T: for<'a> std::iter::Sum<&'a T> + std::iter::Sum<T>, T: for<'a> std::iter::Sum<&'a T> + std::iter::Sum<T>,
@ -301,7 +301,7 @@ pub(crate) mod tests {
self.samples.iter().sum::<T>().to_f64().unwrap() / (self.samples.len() as f64) self.samples.iter().sum::<T>().to_f64().unwrap() / (self.samples.len() as f64)
} }
pub(crate) fn std_dev(&self) -> f64 {
pub(crate) fn variance(&self) -> f64 {
let mean = self.mean(); let mean = self.mean();
// diff // diff
@ -315,12 +315,24 @@ pub(crate) mod tests {
.into_iter() .into_iter()
.sum::<f64>(); .sum::<f64>();
(diff_sq / (self.samples.len() as f64)).sqrt()
diff_sq / (self.samples.len() as f64 - 1.0)
}
pub(crate) fn std_dev(&self) -> f64 {
self.variance().sqrt()
} }
pub(crate) fn add_more(&mut self, values: &[T]) {
pub(crate) fn add_many_samples(&mut self, values: &[T]) {
self.samples.extend(values.iter()); self.samples.extend(values.iter());
} }
pub(crate) fn add_sample(&mut self, value: T) {
self.samples.push(value)
}
pub(crate) fn merge_in(&mut self, other: &Self) {
self.samples.extend(other.samples.iter());
}
} }
#[test] #[test]

Loading…
Cancel
Save