mirror of
https://github.com/arnaucube/phantom-zone.git
synced 2026-01-12 09:01:29 +01:00
clean lwe
This commit is contained in:
@@ -5,23 +5,18 @@ use std::{
|
||||
usize,
|
||||
};
|
||||
|
||||
use itertools::{izip, partition, Itertools};
|
||||
use num_traits::{
|
||||
zero, FromPrimitive, Num, One, Pow, PrimInt, ToPrimitive, WrappingAdd, WrappingSub, Zero,
|
||||
};
|
||||
use rand::Rng;
|
||||
use itertools::{izip, Itertools};
|
||||
use num_traits::{FromPrimitive, One, PrimInt, ToPrimitive, WrappingAdd, WrappingSub, Zero};
|
||||
use rand_distr::uniform::SampleUniform;
|
||||
|
||||
use crate::{
|
||||
backend::{
|
||||
ArithmeticOps, GetModulus, ModInit, ModularOpsU64, Modulus, ShoupMatrixFMA, VectorOps,
|
||||
},
|
||||
backend::{ArithmeticOps, GetModulus, ModInit, Modulus, ShoupMatrixFMA, VectorOps},
|
||||
bool::parameters::ParameterVariant,
|
||||
decomposer::{Decomposer, DefaultDecomposer, NumInfo, RlweDecomposer},
|
||||
lwe::{decrypt_lwe, encrypt_lwe, lwe_key_switch, lwe_ksk_keygen, measure_noise_lwe, LweSecret},
|
||||
lwe::{decrypt_lwe, encrypt_lwe, seeded_lwe_ksk_keygen},
|
||||
multi_party::{
|
||||
non_interactive_ksk_gen, non_interactive_ksk_zero_encryptions_for_other_party_i,
|
||||
non_interactive_rgsw_ct, public_key_share,
|
||||
public_key_share,
|
||||
},
|
||||
ntt::{self, Ntt, NttBackendU64, NttInit},
|
||||
pbs::{pbs, sample_extract, PbsInfo, PbsKey, WithShoupRepr},
|
||||
@@ -48,8 +43,7 @@ use super::{
|
||||
CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare,
|
||||
InteractiveMultiPartyClientKey, NonInteractiveMultiPartyClientKey,
|
||||
SeededMultiPartyServerKey, SeededNonInteractiveMultiPartyServerKey,
|
||||
SeededSinglePartyServerKey, ServerKeyEvaluationDomain, ShoupServerKeyEvaluationDomain,
|
||||
SinglePartyClientKey,
|
||||
SeededSinglePartyServerKey, SinglePartyClientKey,
|
||||
},
|
||||
parameters::{
|
||||
BoolParameters, CiphertextModulus, DecompositionCount, DecompostionLogBase,
|
||||
@@ -67,9 +61,8 @@ use super::{
|
||||
/// Initial Seed:
|
||||
/// Puncture 1 -> Public key share seed
|
||||
/// Puncture 2 -> Main server key share seed
|
||||
/// Puncture 1 -> RGSW cuphertexts seed
|
||||
/// Puncture 2 -> Auto keys cipertexts seed
|
||||
/// Puncture 3 -> LWE ksk seed
|
||||
/// Puncture 1 -> Auto keys cipertexts seed
|
||||
/// Puncture 2 -> LWE ksk seed
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct MultiPartyCrs<S> {
|
||||
pub(super) seed: S,
|
||||
@@ -97,19 +90,14 @@ impl<S: Default + Copy> MultiPartyCrs<S> {
|
||||
puncture_p_rng(&mut prng, 2)
|
||||
}
|
||||
|
||||
pub(super) fn rgsw_cts_seed<Rng: NewWithSeed<Seed = S> + RandomFill<S>>(&self) -> S {
|
||||
pub(super) fn auto_keys_cts_seed<Rng: NewWithSeed<Seed = S> + RandomFill<S>>(&self) -> S {
|
||||
let mut key_prng = Rng::new_with_seed(self.key_seed::<Rng>());
|
||||
puncture_p_rng(&mut key_prng, 1)
|
||||
}
|
||||
|
||||
pub(super) fn auto_keys_cts_seed<Rng: NewWithSeed<Seed = S> + RandomFill<S>>(&self) -> S {
|
||||
let mut key_prng = Rng::new_with_seed(self.key_seed::<Rng>());
|
||||
puncture_p_rng(&mut key_prng, 2)
|
||||
}
|
||||
|
||||
pub(super) fn lwe_ksk_cts_seed_seed<Rng: NewWithSeed<Seed = S> + RandomFill<S>>(&self) -> S {
|
||||
let mut key_prng = Rng::new_with_seed(self.key_seed::<Rng>());
|
||||
puncture_p_rng(&mut key_prng, 3)
|
||||
puncture_p_rng(&mut key_prng, 2)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +107,8 @@ impl<S: Default + Copy> MultiPartyCrs<S> {
|
||||
/// Puncture 1 -> Key Seed
|
||||
/// Puncture 1 -> Rgsw ciphertext seed
|
||||
/// Puncture l+1 -> Seed for zero encs and non-interactive
|
||||
/// multi-party RGSW ciphertext corresponding to l^th LWE index.
|
||||
/// multi-party RGSW ciphertexts of
|
||||
/// l^th LWE index.
|
||||
/// Puncture 2 -> auto keys seed
|
||||
/// Puncture 3 -> Lwe key switching key seed
|
||||
/// Puncture 2 -> user specific seed for u_j to s ksk
|
||||
@@ -931,12 +920,9 @@ where
|
||||
|
||||
// LWE KSK from RLWE secret s -> LWE secret z
|
||||
let d_lwe_gadget = self.pbs_info.lwe_decomposer.gadget_vector();
|
||||
let mut lwe_ksk =
|
||||
M::R::zeros(self.pbs_info.lwe_decomposer.decomposition_count() * ring_size);
|
||||
lwe_ksk_keygen(
|
||||
let lwe_ksk = seeded_lwe_ksk_keygen(
|
||||
&sk_rlwe,
|
||||
&sk_lwe,
|
||||
&mut lwe_ksk,
|
||||
&d_lwe_gadget,
|
||||
&self.pbs_info.lwe_modop,
|
||||
&mut main_prng,
|
||||
@@ -2049,21 +2035,16 @@ where
|
||||
) -> M::R {
|
||||
DefaultSecureRng::with_local_mut(|rng| {
|
||||
let mut p_rng = DefaultSecureRng::new_seeded(lwe_ksk_seed);
|
||||
let mut lwe_ksk = M::R::zeros(
|
||||
self.pbs_info.lwe_decomposer.decomposition_count() * self.parameters().rlwe_n().0,
|
||||
);
|
||||
let lwe_modop = &self.pbs_info.lwe_modop;
|
||||
let d_lwe_gadget_vec = self.pbs_info.lwe_decomposer.gadget_vector();
|
||||
lwe_ksk_keygen(
|
||||
seeded_lwe_ksk_keygen(
|
||||
sk_rlwe,
|
||||
sk_lwe,
|
||||
&mut lwe_ksk,
|
||||
&d_lwe_gadget_vec,
|
||||
lwe_modop,
|
||||
&mut p_rng,
|
||||
rng,
|
||||
);
|
||||
lwe_ksk
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2238,15 +2219,7 @@ where
|
||||
};
|
||||
|
||||
DefaultSecureRng::with_local_mut(|rng| {
|
||||
let mut lwe_out = M::R::zeros(self.pbs_info.parameters.rlwe_n().0 + 1);
|
||||
encrypt_lwe(
|
||||
&mut lwe_out,
|
||||
&m,
|
||||
&client_key.sk_rlwe(),
|
||||
&self.pbs_info.rlwe_modop,
|
||||
rng,
|
||||
);
|
||||
lwe_out
|
||||
encrypt_lwe(&m, &client_key.sk_rlwe(), &self.pbs_info.rlwe_modop, rng)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ use std::{collections::HashMap, hash::Hash, marker::PhantomData};
|
||||
|
||||
use crate::{
|
||||
backend::{ModInit, VectorOps},
|
||||
lwe::LweSecret,
|
||||
pbs::WithShoupRepr,
|
||||
random::{NewWithSeed, RandomFillUniformInModulus},
|
||||
rgsw::RlweSecret,
|
||||
|
||||
@@ -22,7 +22,8 @@ pub type ClientKey = keys::ClientKey<[u8; 32], u64>;
|
||||
pub enum ParameterSelector {
|
||||
HighCommunicationButFast2Party,
|
||||
MultiPartyLessThanOrEqualTo16,
|
||||
NonInteractiveMultiPartyLessThanOrEqualTo16,
|
||||
NonInteractiveLTE2Party,
|
||||
NonInteractiveLTE4Party,
|
||||
}
|
||||
|
||||
mod common_mp_enc_dec {
|
||||
|
||||
@@ -3,6 +3,7 @@ use std::{cell::RefCell, sync::OnceLock};
|
||||
use crate::{
|
||||
backend::ModulusPowerOf2,
|
||||
bool::parameters::ParameterVariant,
|
||||
parameters::NI_4P,
|
||||
random::DefaultSecureRng,
|
||||
utils::{Global, WithLocal},
|
||||
ModularOpsU64, NttBackendU64,
|
||||
@@ -38,9 +39,13 @@ static MULTI_PARTY_CRS: OnceLock<NonInteractiveMultiPartyCrs<[u8; 32]>> = OnceLo
|
||||
|
||||
pub fn set_parameter_set(select: ParameterSelector) {
|
||||
match select {
|
||||
ParameterSelector::NonInteractiveMultiPartyLessThanOrEqualTo16 => {
|
||||
ParameterSelector::NonInteractiveLTE2Party => {
|
||||
BOOL_EVALUATOR.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(NI_2P)));
|
||||
}
|
||||
ParameterSelector::NonInteractiveLTE4Party => {
|
||||
BOOL_EVALUATOR.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(NI_4P)));
|
||||
}
|
||||
|
||||
_ => {
|
||||
panic!("Paramerters not supported")
|
||||
}
|
||||
@@ -160,6 +165,13 @@ impl Global for RuntimeServerKey {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct NonInteractiveBatchedFheBools<C> {
|
||||
data: Vec<C>,
|
||||
}
|
||||
pub(super) struct BatchedFheBools<C> {
|
||||
pub(in super::super) data: Vec<C>,
|
||||
}
|
||||
|
||||
/// Non interactive multi-party specfic encryptor decryptor routines
|
||||
mod impl_enc_dec {
|
||||
use crate::{
|
||||
@@ -177,10 +189,6 @@ mod impl_enc_dec {
|
||||
|
||||
type Mat = Vec<Vec<u64>>;
|
||||
|
||||
pub(super) struct BatchedFheBools<C> {
|
||||
pub(super) data: Vec<C>,
|
||||
}
|
||||
|
||||
impl<C: MatrixMut<MatElement = u64>> BatchedFheBools<C>
|
||||
where
|
||||
C::R: RowEntity + RowMut,
|
||||
@@ -202,10 +210,6 @@ mod impl_enc_dec {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) struct NonInteractiveBatchedFheBools<C> {
|
||||
data: Vec<C>,
|
||||
}
|
||||
|
||||
impl<M: MatrixEntity + MatrixMut<MatElement = u64>> From<&(Vec<M::R>, [u8; 32])>
|
||||
for NonInteractiveBatchedFheBools<M>
|
||||
where
|
||||
@@ -349,10 +353,9 @@ mod impl_enc_dec {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use impl_enc_dec::NonInteractiveBatchedFheBools;
|
||||
use itertools::{izip, Itertools};
|
||||
use num_traits::{FromPrimitive, PrimInt, ToPrimitive, Zero};
|
||||
use rand::{thread_rng, RngCore};
|
||||
use rand::{thread_rng, Rng, RngCore};
|
||||
|
||||
use crate::{
|
||||
backend::{GetModulus, Modulus},
|
||||
@@ -374,7 +377,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn non_interactive_mp_bool_nand() {
|
||||
set_parameter_set(ParameterSelector::NonInteractiveMultiPartyLessThanOrEqualTo16);
|
||||
set_parameter_set(ParameterSelector::NonInteractiveLTE2Party);
|
||||
let mut seed = [0u8; 32];
|
||||
thread_rng().fill_bytes(&mut seed);
|
||||
set_common_reference_seed(seed);
|
||||
@@ -444,63 +447,4 @@ mod tests {
|
||||
ct0 = ct_out;
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trialtest() {
|
||||
set_parameter_set(ParameterSelector::NonInteractiveMultiPartyLessThanOrEqualTo16);
|
||||
set_common_reference_seed([2; 32]);
|
||||
|
||||
let parties = 2;
|
||||
|
||||
let cks = (0..parties).map(|_| gen_client_key()).collect_vec();
|
||||
|
||||
let key_shares = cks
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(user_index, ck)| gen_server_key_share(user_index, parties, ck))
|
||||
.collect_vec();
|
||||
|
||||
let seeded_server_key = aggregate_server_key_shares(&key_shares);
|
||||
seeded_server_key.set_server_key();
|
||||
|
||||
let m = vec![false, true];
|
||||
let ct: NonInteractiveBatchedFheBools<_> = cks[0].encrypt(m.as_slice());
|
||||
let ct = ct.key_switch(0);
|
||||
|
||||
let parameters = BoolEvaluator::with_local(|e| e.parameters().clone());
|
||||
let nttop = NttBackendU64::new(parameters.rlwe_q(), parameters.rlwe_n().0);
|
||||
let rlwe_q_modop = ModularOpsU64::new(*parameters.rlwe_q());
|
||||
|
||||
let mut ideal_rlwe_sk = vec![0i32; parameters.rlwe_n().0];
|
||||
cks.iter().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;
|
||||
});
|
||||
});
|
||||
|
||||
let message = m
|
||||
.iter()
|
||||
.map(|b| parameters.rlwe_q().encode(*b))
|
||||
.collect_vec();
|
||||
|
||||
let mut m_out = vec![0u64; parameters.rlwe_n().0];
|
||||
decrypt_rlwe(
|
||||
&ct.data[0],
|
||||
&ideal_rlwe_sk,
|
||||
&mut m_out,
|
||||
&nttop,
|
||||
&rlwe_q_modop,
|
||||
);
|
||||
|
||||
let mut diff = m_out;
|
||||
rlwe_q_modop.elwise_sub_mut(diff.as_mut_slice(), message.as_ref());
|
||||
|
||||
let mut stats = Stats::new();
|
||||
stats.add_more(&Vec::<i64>::try_convert_from(
|
||||
diff.as_slice(),
|
||||
parameters.rlwe_q(),
|
||||
));
|
||||
println!("Noise: {}", stats.std_dev().abs().log2());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -534,6 +534,31 @@ pub(crate) const NI_2P: BoolParameters<u64> = BoolParameters::<u64> {
|
||||
variant: ParameterVariant::NonInteractiveMultiParty,
|
||||
};
|
||||
|
||||
pub(crate) const NI_4P: BoolParameters<u64> = BoolParameters::<u64> {
|
||||
rlwe_q: CiphertextModulus::new_non_native(18014398509404161),
|
||||
lwe_q: CiphertextModulus::new_non_native(1 << 16),
|
||||
br_q: 1 << 11,
|
||||
rlwe_n: PolynomialSize(1 << 11),
|
||||
lwe_n: LweDimension(510),
|
||||
lwe_decomposer_params: (DecompostionLogBase(1), DecompositionCount(12)),
|
||||
rlrg_decomposer_params: (
|
||||
DecompostionLogBase(17),
|
||||
(DecompositionCount(1), DecompositionCount(1)),
|
||||
),
|
||||
rgrg_decomposer_params: Some((
|
||||
DecompostionLogBase(4),
|
||||
(DecompositionCount(10), DecompositionCount(9)),
|
||||
)),
|
||||
auto_decomposer_params: (DecompostionLogBase(24), DecompositionCount(1)),
|
||||
non_interactive_ui_to_s_key_switch_decomposer: Some((
|
||||
DecompostionLogBase(1),
|
||||
DecompositionCount(50),
|
||||
)),
|
||||
g: 5,
|
||||
w: 10,
|
||||
variant: ParameterVariant::NonInteractiveMultiParty,
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) const SP_TEST_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {
|
||||
rlwe_q: CiphertextModulus::new_non_native(268369921u64),
|
||||
|
||||
@@ -427,7 +427,7 @@ mod tests {
|
||||
NttBackendU64,
|
||||
};
|
||||
|
||||
set_parameter_set(crate::ParameterSelector::NonInteractiveMultiPartyLessThanOrEqualTo16);
|
||||
set_parameter_set(crate::ParameterSelector::NonInteractiveLTE2Party);
|
||||
set_common_reference_seed(NonInteractiveMultiPartyCrs::random().seed);
|
||||
let parties = 2;
|
||||
let cks = (0..parties).map(|i| gen_client_key()).collect_vec();
|
||||
@@ -469,4 +469,73 @@ mod tests {
|
||||
server_key_stats.post_lwe_key_switch.std_dev().abs().log2()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "non_interactive_mp")]
|
||||
fn enc_under_sk_and_key_switch() {
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use crate::{
|
||||
aggregate_server_key_shares,
|
||||
bool::{keys::tests::ideal_sk_rlwe, ni_mp_api::NonInteractiveBatchedFheBools},
|
||||
gen_client_key, gen_server_key_share,
|
||||
rgsw::decrypt_rlwe,
|
||||
set_common_reference_seed, set_parameter_set,
|
||||
utils::{tests::Stats, TryConvertFrom1, WithLocal},
|
||||
BoolEvaluator, Encoder, Encryptor, KeySwitchWithId, ModInit, ModularOpsU64,
|
||||
NttBackendU64, NttInit, ParameterSelector, VectorOps,
|
||||
};
|
||||
|
||||
set_parameter_set(ParameterSelector::NonInteractiveLTE2Party);
|
||||
set_common_reference_seed([2; 32]);
|
||||
|
||||
let parties = 2;
|
||||
|
||||
let cks = (0..parties).map(|_| gen_client_key()).collect_vec();
|
||||
|
||||
let key_shares = cks
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(user_index, ck)| gen_server_key_share(user_index, parties, ck))
|
||||
.collect_vec();
|
||||
|
||||
let seeded_server_key = aggregate_server_key_shares(&key_shares);
|
||||
seeded_server_key.set_server_key();
|
||||
|
||||
let parameters = BoolEvaluator::with_local(|e| e.parameters().clone());
|
||||
let nttop = NttBackendU64::new(parameters.rlwe_q(), parameters.rlwe_n().0);
|
||||
let rlwe_q_modop = ModularOpsU64::new(*parameters.rlwe_q());
|
||||
|
||||
let m = (0..parameters.rlwe_n().0)
|
||||
.map(|_| thread_rng().gen_bool(0.5))
|
||||
.collect_vec();
|
||||
let ct: NonInteractiveBatchedFheBools<_> = cks[0].encrypt(m.as_slice());
|
||||
let ct = ct.key_switch(0);
|
||||
|
||||
let ideal_rlwe_sk = ideal_sk_rlwe(&cks);
|
||||
|
||||
let message = m
|
||||
.iter()
|
||||
.map(|b| parameters.rlwe_q().encode(*b))
|
||||
.collect_vec();
|
||||
|
||||
let mut m_out = vec![0u64; parameters.rlwe_n().0];
|
||||
decrypt_rlwe(
|
||||
&ct.data[0],
|
||||
&ideal_rlwe_sk,
|
||||
&mut m_out,
|
||||
&nttop,
|
||||
&rlwe_q_modop,
|
||||
);
|
||||
|
||||
let mut diff = m_out;
|
||||
rlwe_q_modop.elwise_sub_mut(diff.as_mut_slice(), message.as_ref());
|
||||
|
||||
let mut stats = Stats::new();
|
||||
stats.add_more(&Vec::<i64>::try_convert_from(
|
||||
diff.as_slice(),
|
||||
parameters.rlwe_q(),
|
||||
));
|
||||
println!("Noise std log2: {}", stats.std_dev().abs().log2());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user