change LWE secret distribution to Error distribution for all parameters

This commit is contained in:
Janmajaya Mall
2024-07-02 16:15:09 +05:30
parent 4e6a9aa3a7
commit 7cbe55691f
4 changed files with 116 additions and 18 deletions

View File

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

View File

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

View File

@@ -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)] #[derive(Clone, PartialEq, Debug)]
pub(crate) enum ParameterVariant { pub(crate) enum ParameterVariant {
SingleParty, SingleParty,
@@ -86,6 +96,10 @@ pub(crate) enum ParameterVariant {
} }
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
pub struct BoolParameters<El> { 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 ciphertext modulus Q
rlwe_q: CiphertextModulus<El>, rlwe_q: CiphertextModulus<El>,
/// LWE ciphertext modulus q (usually referred to as Q_{ks}) /// LWE ciphertext modulus q (usually referred to as Q_{ks})
@@ -153,6 +167,14 @@ pub struct BoolParameters<El> {
} }
impl<El> BoolParameters<El> { 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> { pub(crate) fn rlwe_q(&self) -> &CiphertextModulus<El> {
&self.rlwe_q &self.rlwe_q
} }
@@ -502,6 +524,8 @@ where
} }
pub(crate) const MP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> { 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), rlwe_q: CiphertextModulus::new_non_native(1152921504606830593),
lwe_q: CiphertextModulus::new_non_native(1 << 20), lwe_q: CiphertextModulus::new_non_native(1 << 20),
br_q: 1 << 11, br_q: 1 << 11,
@@ -524,6 +548,8 @@ pub(crate) const MP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {
}; };
pub(crate) const SMALL_MP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> { 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), rlwe_q: CiphertextModulus::new_non_native(36028797018820609),
lwe_q: CiphertextModulus::new_non_native(1 << 20), lwe_q: CiphertextModulus::new_non_native(1 << 20),
br_q: 1 << 11, br_q: 1 << 11,
@@ -546,6 +572,8 @@ pub(crate) const SMALL_MP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u6
}; };
pub(crate) const I_2P: BoolParameters<u64> = BoolParameters::<u64> { 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), rlwe_q: CiphertextModulus::new_non_native(18014398509404161),
lwe_q: CiphertextModulus::new_non_native(1 << 15), lwe_q: CiphertextModulus::new_non_native(1 << 15),
br_q: 1 << 11, br_q: 1 << 11,
@@ -568,6 +596,8 @@ pub(crate) const I_2P: BoolParameters<u64> = BoolParameters::<u64> {
}; };
pub(crate) const NI_2P: BoolParameters<u64> = BoolParameters::<u64> { 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), rlwe_q: CiphertextModulus::new_non_native(18014398509404161),
lwe_q: CiphertextModulus::new_non_native(1 << 15), lwe_q: CiphertextModulus::new_non_native(1 << 15),
br_q: 1 << 11, br_q: 1 << 11,
@@ -593,6 +623,8 @@ pub(crate) const NI_2P: BoolParameters<u64> = BoolParameters::<u64> {
}; };
pub(crate) const NI_4P: BoolParameters<u64> = BoolParameters::<u64> { 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), 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 << 11,
@@ -619,6 +651,8 @@ pub(crate) const NI_4P: BoolParameters<u64> = BoolParameters::<u64> {
#[cfg(test)] #[cfg(test)]
pub(crate) const SP_TEST_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> { 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), rlwe_q: CiphertextModulus::new_non_native(268369921u64),
lwe_q: CiphertextModulus::new_non_native(1 << 16), lwe_q: CiphertextModulus::new_non_native(1 << 16),
br_q: 1 << 9, br_q: 1 << 9,

View File

@@ -1,7 +1,7 @@
use std::cell::RefCell; use std::cell::RefCell;
use itertools::izip; use itertools::izip;
use num_traits::{PrimInt, Zero}; use num_traits::{FromPrimitive, PrimInt, Zero};
use rand::{distributions::Uniform, Rng, RngCore, SeedableRng}; use rand::{distributions::Uniform, Rng, RngCore, SeedableRng};
use rand_chacha::ChaCha8Rng; use rand_chacha::ChaCha8Rng;
use rand_distr::{uniform::SampleUniform, Distribution}; use rand_distr::{uniform::SampleUniform, Distribution};
@@ -36,6 +36,15 @@ where
fn random_fill(&mut self, container: &mut M); 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> pub trait RandomFillUniformInModulus<M, P>
where where
M: ?Sized, 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 impl<T> RandomFill<[T; 32]> for DefaultSecureRng
where where
T: PrimInt + SampleUniform, T: PrimInt + SampleUniform,