Browse Source

add bool noise

par-agg-key-shares
Janmajaya Mall 1 year ago
parent
commit
5a54685737
6 changed files with 197 additions and 56 deletions
  1. +9
    -8
      src/bool/evaluator.rs
  2. +5
    -5
      src/bool/mod.rs
  3. +159
    -0
      src/bool/noise.rs
  4. +5
    -23
      src/bool/parameters.rs
  5. +15
    -16
      src/random.rs
  6. +4
    -4
      src/rgsw.rs

+ 9
- 8
src/bool/evaluator.rs

@ -1,4 +1,5 @@
use std::{
borrow::BorrowMut,
cell::{OnceCell, RefCell},
clone,
collections::HashMap,
@ -1808,11 +1809,11 @@ mod tests {
NttBackendU64,
ModularOpsU64<CiphertextModulus<u64>>,
ModularOpsU64<CiphertextModulus<u64>>,
>::new(MP_BOOL_PARAMS);
>::new(SP_BOOL_PARAMS);
// let (_, collective_pk, _, _, server_key_eval, ideal_client_key) =
// _multi_party_all_keygen(&bool_evaluator, 20);
let no_of_parties = 32;
let no_of_parties = 2;
let lwe_q = bool_evaluator.pbs_info.parameters.lwe_q();
let rlwe_q = bool_evaluator.pbs_info.parameters.rlwe_q();
let lwe_n = bool_evaluator.pbs_info.parameters.lwe_n().0;
@ -1938,7 +1939,7 @@ mod tests {
bool_evaluator.aggregate_multi_party_server_key_shares(&server_key_shares);
// Check noise in RGSW ciphertexts of ideal LWE secret elements
if true {
if false {
let mut check = Stats { samples: vec![] };
izip!(
ideal_client_key.sk_lwe().values.iter(),
@ -2040,7 +2041,7 @@ mod tests {
);
// check noise in RLWE x RGSW(X^{s_i}) where RGSW is accunulated RGSW ciphertext
if true {
if false {
let mut check = Stats { samples: vec![] };
izip!(
@ -2151,7 +2152,7 @@ mod tests {
}
// check noise in Auto key
if true {
if false {
let mut check = Stats { samples: vec![] };
let mut neg_s_poly =
@ -2219,7 +2220,7 @@ mod tests {
// auto key
if true {
let mut check = Stats { samples: vec![] };
let br_q = bool_evaluator.pbs_info.br_q();
let g = bool_evaluator.pbs_info.g();
let auto_element_dlogs = bool_evaluator.pbs_info.parameters.auto_element_dlogs();
for i in auto_element_dlogs.into_iter() {
@ -2252,8 +2253,8 @@ mod tests {
);
let auto_key = server_key_eval_domain.galois_key_for_auto(i);
let g_pow = if i == 0 { -g } else { g.pow(i as u32) };
let (auto_map_index, auto_map_sign) = generate_auto_map(rlwe_n, g_pow);
let (auto_map_index, auto_map_sign) =
bool_evaluator.pbs_info.rlwe_auto_map(i);
let mut scratch =
vec![vec![0u64; rlwe_n]; auto_decomposer.decomposition_count() + 2];
galois_auto(

+ 5
- 5
src/bool/mod.rs

@ -19,7 +19,7 @@ use crate::{
};
thread_local! {
static BOOL_EVALUATOR: RefCell<BoolEvaluator<Vec<Vec<u64>>, NttBackendU64, ModularOpsU64<CiphertextModulus<u64>>, ModularOpsU64<CiphertextModulus<u64>>>> = RefCell::new(BoolEvaluator::new(MP_BOOL_PARAMS));
static BOOL_EVALUATOR: RefCell<Option<BoolEvaluator<Vec<Vec<u64>>, NttBackendU64, ModularOpsU64<CiphertextModulus<u64>>, ModularOpsU64<CiphertextModulus<u64>>>>> = RefCell::new(None);
}
static BOOL_SERVER_KEY: OnceLock<
@ -29,7 +29,7 @@ static BOOL_SERVER_KEY: OnceLock<
static MULTI_PARTY_CRS: OnceLock<MultiPartyCrs<[u8; 32]>> = OnceLock::new();
pub fn set_parameter_set(parameter: &BoolParameters<u64>) {
BoolEvaluator::with_local_mut(|e| *e = BoolEvaluator::new(parameter.clone()))
BOOL_EVALUATOR.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(parameter.clone())));
}
pub fn set_mp_seed(seed: [u8; 32]) {
@ -158,20 +158,20 @@ impl WithLocal
where
F: Fn(&Self) -> R,
{
BOOL_EVALUATOR.with_borrow(|s| func(s))
BOOL_EVALUATOR.with_borrow(|s| func(s.as_ref().expect("Parameters not set")))
}
fn with_local_mut<F, R>(func: F) -> R
where
F: Fn(&mut Self) -> R,
{
BOOL_EVALUATOR.with_borrow_mut(|s| func(s))
BOOL_EVALUATOR.with_borrow_mut(|s| func(s.as_mut().expect("Parameters not set")))
}
fn with_local_mut_mut<F, R>(func: &mut F) -> R
where
F: FnMut(&mut Self) -> R,
{
BOOL_EVALUATOR.with_borrow_mut(|s| func(s))
BOOL_EVALUATOR.with_borrow_mut(|s| func(s.as_mut().expect("Parameters not set")))
}
}

+ 159
- 0
src/bool/noise.rs

@ -0,0 +1,159 @@
use std::cell::RefCell;
mod test {
use itertools::{izip, Itertools};
use crate::{
backend::{ArithmeticOps, ModularOpsU64, Modulus},
bool::{
set_parameter_set, BoolEncoding, BoolEvaluator, BooleanGates, CiphertextModulus,
ClientKey, PublicKey, ServerKeyEvaluationDomain, MP_BOOL_PARAMS, SMALL_MP_BOOL_PARAMS,
},
lwe::{decrypt_lwe, LweSecret},
ntt::NttBackendU64,
pbs::PbsInfo,
random::DefaultSecureRng,
rgsw::RlweSecret,
utils::Stats,
Secret,
};
#[test]
fn mp_noise() {
// set_parameter_set(&SMALL_MP_BOOL_PARAMS);
let mut evaluator = BoolEvaluator::<
Vec<Vec<u64>>,
NttBackendU64,
ModularOpsU64<CiphertextModulus<u64>>,
ModularOpsU64<CiphertextModulus<u64>>,
>::new(SMALL_MP_BOOL_PARAMS);
let parties = 16;
let mut rng = DefaultSecureRng::new();
let mut pk_cr_seed = [0u8; 32];
let mut bk_cr_seed = [0u8; 32];
rng.fill_bytes(&mut pk_cr_seed);
rng.fill_bytes(&mut bk_cr_seed);
let cks = (0..parties)
.into_iter()
.map(|_| evaluator.client_key())
.collect_vec();
// construct ideal rlwe sk for meauring noise
let ideal_client_key = {
let mut ideal_rlwe_sk = vec![0i32; evaluator.parameters().rlwe_n().0];
cks.iter().for_each(|k| {
izip!(ideal_rlwe_sk.iter_mut(), k.sk_rlwe().values()).for_each(|(ideal_i, s_i)| {
*ideal_i = *ideal_i + s_i;
});
});
let mut ideal_lwe_sk = vec![0i32; evaluator.parameters().lwe_n().0];
cks.iter().for_each(|k| {
izip!(ideal_lwe_sk.iter_mut(), k.sk_lwe().values()).for_each(|(ideal_i, s_i)| {
*ideal_i = *ideal_i + s_i;
});
});
ClientKey::new(
RlweSecret {
values: ideal_rlwe_sk,
},
LweSecret {
values: ideal_lwe_sk,
},
)
};
// round 1
let pk_shares = cks
.iter()
.map(|c| evaluator.multi_party_public_key_share(pk_cr_seed, c))
.collect_vec();
// public key
let pk = PublicKey::<Vec<Vec<u64>>, DefaultSecureRng, ModularOpsU64<CiphertextModulus<u64>>>::from(
pk_shares.as_slice(),
);
// round 2
let server_key_shares = cks
.iter()
.map(|c| evaluator.multi_party_server_key_share(bk_cr_seed, &pk.key(), c))
.collect_vec();
let server_key = evaluator.aggregate_multi_party_server_key_shares(&server_key_shares);
let server_key_eval_domain = ServerKeyEvaluationDomain::from(&server_key);
let mut m0 = false;
let mut m1 = true;
let mut c_m0 = evaluator.pk_encrypt(pk.key(), m0);
let mut c_m1 = evaluator.pk_encrypt(pk.key(), m1);
// println!(
// "Evaluator ciphertext modulus: {:?}",
// evaluator.parameters().rlwe_q()
// );
// {
// // let v = LWE_VEC.take();
// let added = decrypt_lwe(
// &c_m1,
// ideal_client_key.sk_rlwe().values(),
// evaluator.pbs_info().modop_rlweq(),
// );
// println!("Of interest {added}");
// }
let true_el_encoded = evaluator.parameters().rlwe_q().true_el();
let false_el_encoded = evaluator.parameters().rlwe_q().false_el();
let mut stats = Stats::new();
for _ in 0..1000 {
let c_out = evaluator.xor(&c_m0, &c_m1, &server_key_eval_domain);
// mp decrypt
let decryption_shares = cks
.iter()
.map(|c| evaluator.multi_party_decryption_share(&c_out, c))
.collect_vec();
let m_out = evaluator.multi_party_decrypt(&decryption_shares, &c_out);
let m_expected = (m0 ^ m1);
assert_eq!(m_expected, m_out, "Expected {m_expected} but got {m_out}");
// find noise update
{
let out = decrypt_lwe(
&c_out,
ideal_client_key.sk_rlwe().values(),
evaluator.pbs_info().modop_rlweq(),
);
let out_want = {
if m_expected == true {
true_el_encoded
} else {
false_el_encoded
}
};
let diff = evaluator.pbs_info().modop_rlweq().sub(&out, &out_want);
stats.add_more(&vec![evaluator
.pbs_info()
.rlwe_q()
.map_element_to_i64(&diff)]);
}
m1 = m0;
m0 = m_out;
c_m1 = c_m0;
c_m0 = c_out;
}
println!("log2 std dev {}", stats.std_dev().abs().log2());
}
}

+ 5
- 23
src/bool/parameters.rs

@ -177,7 +177,7 @@ impl AsRef for DecompositionCount {
pub(crate) struct LweDimension(pub(crate) usize);
#[derive(Clone, Copy, PartialEq)]
pub(crate) struct PolynomialSize(pub(crate) usize);
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Debug)]
/// T equals modulus when modulus is non-native. Otherwise T equals 0. bool is
/// true when modulus is native, false otherwise.
@ -328,38 +328,20 @@ pub(crate) const MP_BOOL_PARAMS: BoolParameters = BoolParameters:: {
w: 10,
};
// pub(crate) const SMALL_MP_BOOL_PARAMS: BoolParameters<u64> =
// BoolParameters::<u64> { rlwe_q:
// CiphertextModulus::new_non_native(36028797018820609), lwe_q:
// CiphertextModulus::new_non_native(1 << 20), br_q: 1 << 11,
// rlwe_n: PolynomialSize(1 << 11),
// lwe_n: LweDimension(600),
// lwe_decomposer_base: DecompostionLogBase(4),
// lwe_decomposer_count: DecompositionCount(5),
// rlrg_decomposer_base: DecompostionLogBase(11),
// rlrg_decomposer_count: (DecompositionCount(2), DecompositionCount(2)),
// rgrg_decomposer_base: DecompostionLogBase(11),
// rgrg_decomposer_count: (DecompositionCount(5), DecompositionCount(4)),
// auto_decomposer_base: DecompostionLogBase(11),
// auto_decomposer_count: DecompositionCount(2),
// g: 5,
// w: 10,
// };
pub(crate) const SMALL_MP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {
rlwe_q: CiphertextModulus::new_non_native(36028797018820609),
lwe_q: CiphertextModulus::new_non_native(1 << 20),
br_q: 1 << 11,
rlwe_n: PolynomialSize(1 << 11),
lwe_n: LweDimension(500),
lwe_n: LweDimension(600),
lwe_decomposer_base: DecompostionLogBase(4),
lwe_decomposer_count: DecompositionCount(5),
rlrg_decomposer_base: DecompostionLogBase(11),
rlrg_decomposer_count: (DecompositionCount(5), DecompositionCount(5)),
rlrg_decomposer_count: (DecompositionCount(2), DecompositionCount(2)),
rgrg_decomposer_base: DecompostionLogBase(11),
rgrg_decomposer_count: (DecompositionCount(5), DecompositionCount(5)),
rgrg_decomposer_count: (DecompositionCount(5), DecompositionCount(4)),
auto_decomposer_base: DecompostionLogBase(11),
auto_decomposer_count: DecompositionCount(5),
auto_decomposer_count: DecompositionCount(2),
g: 5,
w: 10,
};

+ 15
- 16
src/random.rs

@ -107,19 +107,19 @@ where
impl<T, C> RandomFillGaussianInModulus<[T], C> for DefaultSecureRng
where
T: PrimInt + SampleUniform,
T: PrimInt,
C: Modulus<Element = T>,
{
fn random_fill(&mut self, modulus: &C, 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 = modulus.map_element_from_f64(from);
// });
izip!(
rand_distr::Normal::new(0.0, 3.19f64)
.unwrap()
.sample_iter(&mut self.rng),
container.iter_mut()
)
.for_each(|(from, to)| {
*to = modulus.map_element_from_f64(from);
});
}
}
@ -173,12 +173,11 @@ where
impl<T, M: Modulus<Element = T>> RandomGaussianElementInModulus<T, M> for DefaultSecureRng {
fn random(&mut self, modulus: &M) -> T {
// modulus.map_element_from_f64(
// rand_distr::Normal::new(0.0, 3.19f64)
// .unwrap()
// .sample(&mut self.rng),
// )
modulus.map_element_from_f64(0.0)
modulus.map_element_from_f64(
rand_distr::Normal::new(0.0, 3.19f64)
.unwrap()
.sample(&mut self.rng),
)
}
}

+ 4
- 4
src/rgsw.rs

@ -1906,13 +1906,13 @@ pub(crate) mod tests {
#[test]
fn galois_auto_works() {
let logq = 50;
let ring_size = 1 << 8;
let logq = 55;
let ring_size = 1 << 11;
let q = generate_prime(logq, 2 * ring_size, 1u64 << logq).unwrap();
let logp = 3;
let p = 1u64 << logp;
let d_rgsw = 10;
let logb = 5;
let d_rgsw = 5;
let logb = 11;
let mut rng = DefaultSecureRng::new();
let s = RlweSecret::random((ring_size >> 1) as usize, ring_size as usize);

Loading…
Cancel
Save