Browse Source

change LWE secret distribution to Error distribution for all parameters

par-agg-key-shares
Janmajaya Mall 9 months ago
parent
commit
7cbe55691f
4 changed files with 116 additions and 18 deletions
  1. +34
    -7
      src/bool/keys.rs
  2. +21
    -10
      src/bool/ni_mp_api.rs
  3. +34
    -0
      src/bool/parameters.rs
  4. +27
    -1
      src/random.rs

+ 34
- 7
src/bool/keys.rs

@ -54,7 +54,8 @@ pub struct ClientKey {
mod impl_ck {
use crate::{
random::DefaultSecureRng,
parameters::SecretKeyDistribution,
random::{DefaultSecureRng, RandomFillGaussian},
utils::{fill_random_ternary_secret_with_hamming_weight, puncture_p_rng},
};
@ -76,15 +77,29 @@ mod impl_ck {
let lwe_seed = puncture_p_rng::<[u8; 32], DefaultSecureRng>(&mut p_rng, 2);
let mut lwe_prng = DefaultSecureRng::new_seeded(lwe_seed);
let mut out = vec![0i32; self.parameters.lwe_n().0];
fill_random_ternary_secret_with_hamming_weight(
&mut out,
self.parameters.lwe_n().0 >> 1,
&mut lwe_prng,
);
match self.parameters.lwe_secret_key_dist() {
&SecretKeyDistribution::ErrorDistribution => {
RandomFillGaussian::random_fill(&mut lwe_prng, &mut out);
}
&SecretKeyDistribution::TernaryDistribution => {
fill_random_ternary_secret_with_hamming_weight(
&mut out,
self.parameters.lwe_n().0 >> 1,
&mut lwe_prng,
);
}
}
out
}
fn sk_rlwe(&self) -> Vec<Self::Element> {
assert!(
self.parameters.rlwe_secret_key_dist()
== &SecretKeyDistribution::TernaryDistribution
);
let mut p_rng = DefaultSecureRng::new_seeded(self.seed);
let rlwe_seed = puncture_p_rng::<[u8; 32], DefaultSecureRng>(&mut p_rng, 1);
@ -120,6 +135,11 @@ mod impl_ck {
<Self as SinglePartyClientKey>::sk_rlwe(&self)
}
fn sk_u_rlwe(&self) -> Vec<Self::Element> {
assert!(
self.parameters.rlwe_secret_key_dist()
== &SecretKeyDistribution::TernaryDistribution
);
let mut p_rng = DefaultSecureRng::new_seeded(self.seed);
let rlwe_seed = puncture_p_rng::<[u8; 32], DefaultSecureRng>(&mut p_rng, 3);
@ -1486,7 +1506,7 @@ pub(super) mod tests {
bool::ClientKey,
decomposer::NumInfo,
lwe::decrypt_lwe,
parameters::CiphertextModulus,
parameters::{CiphertextModulus, I_2P},
utils::TryConvertFrom1,
ArithmeticOps, Row,
};
@ -1540,4 +1560,11 @@ pub(super) mod tests {
.unwrap()
.log2()
}
// #[test]
// fn trial() {
// let parameters = I_2P;
// let ck = ClientKey::new(parameters);
// let lwe = ck.sk_lwe();
// dbg!(lwe);
// }
}

+ 21
- 10
src/bool/ni_mp_api.rs

@ -447,23 +447,26 @@ mod tests {
use rand::{thread_rng, RngCore};
use crate::{
backend::Modulus,
bool::{
keys::tests::{ideal_sk_rlwe, measure_noise_lwe},
BooleanGates,
},
Encoder, Encryptor, KeySwitchWithId, MultiPartyDecryptor,
lwe::decrypt_lwe,
utils::tests::Stats,
ArithmeticOps, Encoder, Encryptor, KeySwitchWithId, MultiPartyDecryptor,
};
use super::*;
#[test]
fn non_interactive_mp_bool_nand() {
set_parameter_set(ParameterSelector::NonInteractiveLTE4Party);
set_parameter_set(ParameterSelector::NonInteractiveLTE2Party);
let mut seed = [0u8; 32];
thread_rng().fill_bytes(&mut seed);
set_common_reference_seed(seed);
let parties = 3;
let parties = 2;
let cks = (0..parties).map(|_| gen_client_key()).collect_vec();
@ -495,6 +498,8 @@ mod tests {
ct.extract(0)
};
let mut stats = Stats::new();
for _ in 0..1000 {
// let now = std::time::Instant::now();
let ct_out =
@ -510,13 +515,17 @@ mod tests {
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 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)]);
}
assert!(m_out == m_expected, "Expected {m_expected} but got {m_out}");
@ -527,5 +536,7 @@ mod tests {
ct1 = ct0;
ct0 = ct_out;
}
println!("Noise std dev log2: {}", stats.std_dev().abs().log2());
}
}

+ 34
- 0
src/bool/parameters.rs

@ -78,6 +78,16 @@ impl SingleDecomposerParams for (DecompostionLogBase, DecompositionCount) {
}
}
#[derive(Clone, PartialEq, Debug)]
pub(crate) enum SecretKeyDistribution {
/// Elements of secret key are sample from Gaussian distribitution with
/// \sigma = 3.19 and \mu = 0.0
ErrorDistribution,
/// Elements of secret key are chosen from the set {1,0,-1} with hamming
/// weight `floor(N/2)` where `N` is the secret dimension.
TernaryDistribution,
}
#[derive(Clone, PartialEq, Debug)]
pub(crate) enum ParameterVariant {
SingleParty,
@ -86,6 +96,10 @@ pub(crate) enum ParameterVariant {
}
#[derive(Clone, PartialEq)]
pub struct BoolParameters<El> {
/// RLWE secret key distribution
rlwe_secret_key_dist: SecretKeyDistribution,
/// LWE secret key distribtuion
lwe_secret_key_dist: SecretKeyDistribution,
/// RLWE ciphertext modulus Q
rlwe_q: CiphertextModulus<El>,
/// LWE ciphertext modulus q (usually referred to as Q_{ks})
@ -153,6 +167,14 @@ pub struct BoolParameters {
}
impl<El> BoolParameters<El> {
pub(crate) fn rlwe_secret_key_dist(&self) -> &SecretKeyDistribution {
&self.rlwe_secret_key_dist
}
pub(crate) fn lwe_secret_key_dist(&self) -> &SecretKeyDistribution {
&self.lwe_secret_key_dist
}
pub(crate) fn rlwe_q(&self) -> &CiphertextModulus<El> {
&self.rlwe_q
}
@ -502,6 +524,8 @@ where
}
pub(crate) const 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(1152921504606830593),
lwe_q: CiphertextModulus::new_non_native(1 << 20),
br_q: 1 << 11,
@ -524,6 +548,8 @@ pub(crate) const MP_BOOL_PARAMS: BoolParameters = BoolParameters:: {
};
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),
br_q: 1 << 11,
@ -546,6 +572,8 @@ pub(crate) const SMALL_MP_BOOL_PARAMS: BoolParameters = BoolParameters::
};
pub(crate) const I_2P: BoolParameters<u64> = BoolParameters::<u64> {
rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
lwe_secret_key_dist: SecretKeyDistribution::ErrorDistribution,
rlwe_q: CiphertextModulus::new_non_native(18014398509404161),
lwe_q: CiphertextModulus::new_non_native(1 << 15),
br_q: 1 << 11,
@ -568,6 +596,8 @@ pub(crate) const I_2P: BoolParameters = BoolParameters:: {
};
pub(crate) const NI_2P: BoolParameters<u64> = BoolParameters::<u64> {
rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
lwe_secret_key_dist: SecretKeyDistribution::ErrorDistribution,
rlwe_q: CiphertextModulus::new_non_native(18014398509404161),
lwe_q: CiphertextModulus::new_non_native(1 << 15),
br_q: 1 << 11,
@ -593,6 +623,8 @@ pub(crate) const NI_2P: BoolParameters = BoolParameters:: {
};
pub(crate) const NI_4P: BoolParameters<u64> = BoolParameters::<u64> {
rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
lwe_secret_key_dist: SecretKeyDistribution::ErrorDistribution,
rlwe_q: CiphertextModulus::new_non_native(18014398509404161),
lwe_q: CiphertextModulus::new_non_native(1 << 16),
br_q: 1 << 11,
@ -619,6 +651,8 @@ pub(crate) const NI_4P: BoolParameters = BoolParameters:: {
#[cfg(test)]
pub(crate) const SP_TEST_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {
rlwe_secret_key_dist: SecretKeyDistribution::TernaryDistribution,
lwe_secret_key_dist: SecretKeyDistribution::ErrorDistribution,
rlwe_q: CiphertextModulus::new_non_native(268369921u64),
lwe_q: CiphertextModulus::new_non_native(1 << 16),
br_q: 1 << 9,

+ 27
- 1
src/random.rs

@ -1,7 +1,7 @@
use std::cell::RefCell;
use itertools::izip;
use num_traits::{PrimInt, Zero};
use num_traits::{FromPrimitive, PrimInt, Zero};
use rand::{distributions::Uniform, Rng, RngCore, SeedableRng};
use rand_chacha::ChaCha8Rng;
use rand_distr::{uniform::SampleUniform, Distribution};
@ -36,6 +36,15 @@ where
fn random_fill(&mut self, container: &mut M);
}
pub trait RandomFillGaussian<M>
where
M: ?Sized,
{
/// Fill container with random elements sampled from normal distribtuion
/// with \mu = 0.0 and \sigma = 3.19.
fn random_fill(&mut self, container: &mut M);
}
pub trait RandomFillUniformInModulus<M, P>
where
M: ?Sized,
@ -133,6 +142,23 @@ where
}
}
impl<T> RandomFillGaussian<[T]> for DefaultSecureRng
where
T: FromPrimitive,
{
fn random_fill(&mut self, container: &mut [T]) {
izip!(
rand_distr::Normal::new(0.0, 3.19f64)
.unwrap()
.sample_iter(&mut self.rng),
container.iter_mut()
)
.for_each(|(from, to)| {
*to = T::from_f64(from).unwrap();
});
}
}
impl<T> RandomFill<[T; 32]> for DefaultSecureRng
where
T: PrimInt + SampleUniform,

Loading…
Cancel
Save