mirror of
https://github.com/arnaucube/phantom-zone.git
synced 2026-01-09 15:41:30 +01:00
make enc and dec variant specific
This commit is contained in:
@@ -38,23 +38,28 @@ use crate::{
|
||||
RlweCiphertext, RlweSecret,
|
||||
},
|
||||
utils::{
|
||||
fill_random_ternary_secret_with_hamming_weight, generate_prime, mod_exponent, Global,
|
||||
TryConvertFrom1, WithLocal,
|
||||
fill_random_ternary_secret_with_hamming_weight, generate_prime, mod_exponent,
|
||||
puncture_p_rng, Global, TryConvertFrom1, WithLocal,
|
||||
},
|
||||
Decryptor, Encryptor, Matrix, MatrixEntity, MatrixMut, MultiPartyDecryptor, Row, RowEntity,
|
||||
RowMut, Secret,
|
||||
};
|
||||
|
||||
use super::{
|
||||
parameters::{BoolParameters, CiphertextModulus},
|
||||
keys::{
|
||||
ClientKey, CommonReferenceSeededCollectivePublicKeyShare,
|
||||
CommonReferenceSeededMultiPartyServerKeyShare, DecompositionCount, DecompostionLogBase,
|
||||
DoubleDecomposerParams, SeededMultiPartyServerKey, SeededNonInteractiveMultiPartyServerKey,
|
||||
SeededSinglePartyServerKey, ServerKeyEvaluationDomain, ShoupServerKeyEvaluationDomain,
|
||||
ThrowMeAwayKey,
|
||||
CommonReferenceSeededMultiPartyServerKeyShare, InteractiveMultiPartyClientKey,
|
||||
NonInteractiveMultiPartyClientKey, SeededMultiPartyServerKey,
|
||||
SeededNonInteractiveMultiPartyServerKey, SeededSinglePartyServerKey,
|
||||
ServerKeyEvaluationDomain, ShoupServerKeyEvaluationDomain, SinglePartyClientKey,
|
||||
},
|
||||
parameters::{
|
||||
BoolParameters, CiphertextModulus, DecompositionCount, DecompostionLogBase,
|
||||
DoubleDecomposerParams,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct SeededNonInteractiveMultiPartyServerKeyShare<M: Matrix, S> {
|
||||
pub struct CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare<M: Matrix, S> {
|
||||
/// (ak*si + e + \beta ui, ak*si + e)
|
||||
ni_rgsw_cts: (Vec<M>, Vec<M>),
|
||||
ui_to_s_ksk: M,
|
||||
@@ -67,7 +72,7 @@ pub struct SeededNonInteractiveMultiPartyServerKeyShare<M: Matrix, S> {
|
||||
cr_seed: S,
|
||||
}
|
||||
|
||||
impl<M: Matrix, S> SeededNonInteractiveMultiPartyServerKeyShare<M, S> {
|
||||
impl<M: Matrix, S> CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare<M, S> {
|
||||
fn ui_to_s_ksk_zero_encs_for_user_i(&self, user_i: usize) -> &M {
|
||||
assert!(user_i != self.user_index);
|
||||
if user_i < self.user_index {
|
||||
@@ -82,12 +87,14 @@ pub struct MultiPartyCrs<S> {
|
||||
pub(super) seed: S,
|
||||
}
|
||||
|
||||
fn puncture_p_rng<S: Default + Copy, R: RandomFill<S>>(p_rng: &mut R, times: usize) -> S {
|
||||
let mut out = S::default();
|
||||
for _ in 0..times {
|
||||
RandomFill::<S>::random_fill(p_rng, &mut out);
|
||||
impl MultiPartyCrs<[u8; 32]> {
|
||||
pub(super) fn random() -> Self {
|
||||
DefaultSecureRng::with_local_mut(|rng| {
|
||||
let mut seed = [0u8; 32];
|
||||
rng.fill_bytes(&mut seed);
|
||||
Self { seed }
|
||||
})
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Common reference seed used for non-interactive multi-party.
|
||||
@@ -104,9 +111,6 @@ pub struct NonInteractiveMultiPartyCrs<S> {
|
||||
pub(super) seed: S,
|
||||
}
|
||||
|
||||
// impl<S: Clone> Clone for NonInteractiveMultiPartyCrs<S> where S: Clone {}
|
||||
// impl<S: Copy> Copy for NonInteractiveMultiPartyCrs<S> where S: Copy {}
|
||||
|
||||
impl<S: Default + Copy> NonInteractiveMultiPartyCrs<S> {
|
||||
fn key_seed<R: NewWithSeed<Seed = S> + RandomFill<S>>(&self) -> S {
|
||||
let mut p_rng = R::new_with_seed(self.seed);
|
||||
@@ -651,37 +655,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn client_key(&self) -> ClientKey {
|
||||
let sk_lwe = LweSecret::random(
|
||||
self.pbs_info.parameters.lwe_n().0 >> 1,
|
||||
self.pbs_info.parameters.lwe_n().0,
|
||||
);
|
||||
let sk_rlwe = RlweSecret::random(
|
||||
self.pbs_info.parameters.rlwe_n().0 >> 1,
|
||||
self.pbs_info.parameters.rlwe_n().0,
|
||||
);
|
||||
ClientKey::new(sk_rlwe, sk_lwe)
|
||||
}
|
||||
|
||||
pub(super) fn non_interactive_client_key(&self) -> ThrowMeAwayKey {
|
||||
let sk_lwe = LweSecret::random(
|
||||
self.pbs_info.parameters.lwe_n().0 >> 1,
|
||||
self.pbs_info.parameters.lwe_n().0,
|
||||
);
|
||||
let sk_rlwe = RlweSecret::random(
|
||||
self.pbs_info.parameters.rlwe_n().0 >> 1,
|
||||
self.pbs_info.parameters.rlwe_n().0,
|
||||
);
|
||||
let sk_u_rlwe = RlweSecret::random(
|
||||
self.pbs_info.parameters.rlwe_n().0 >> 1,
|
||||
self.pbs_info.parameters.rlwe_n().0,
|
||||
);
|
||||
ThrowMeAwayKey::new(sk_rlwe, sk_u_rlwe, sk_lwe)
|
||||
}
|
||||
|
||||
pub(super) fn single_party_server_key(
|
||||
pub(crate) fn client_key(
|
||||
&self,
|
||||
client_key: &ClientKey,
|
||||
) -> ClientKey<<DefaultSecureRng as NewWithSeed>::Seed, M::MatElement> {
|
||||
ClientKey::new(self.parameters().clone())
|
||||
}
|
||||
|
||||
pub(super) fn single_party_server_key<K: SinglePartyClientKey<Element = i32>>(
|
||||
&self,
|
||||
client_key: &K,
|
||||
) -> SeededSinglePartyServerKey<M, BoolParameters<M::MatElement>, [u8; 32]> {
|
||||
DefaultSecureRng::with_local_mut(|rng| {
|
||||
let mut main_seed = [0u8; 32];
|
||||
@@ -708,7 +690,7 @@ where
|
||||
let mut gk = M::zeros(self.pbs_info.auto_decomposer.decomposition_count(), rlwe_n);
|
||||
galois_key_gen(
|
||||
&mut gk,
|
||||
sk_rlwe.values(),
|
||||
&sk_rlwe,
|
||||
g_pow,
|
||||
&auto_gadget,
|
||||
&self.pbs_info.rlwe_modop,
|
||||
@@ -729,7 +711,6 @@ where
|
||||
let rlrg_gadget_a = self.pbs_info.rlwe_rgsw_decomposer.0.gadget_vector();
|
||||
let rlrg_gadget_b = self.pbs_info.rlwe_rgsw_decomposer.1.gadget_vector();
|
||||
let rgsw_cts = sk_lwe
|
||||
.values()
|
||||
.iter()
|
||||
.map(|si| {
|
||||
// X^{si}; assume |emebedding_factor * si| < N
|
||||
@@ -750,7 +731,7 @@ where
|
||||
m.as_ref(),
|
||||
&rlrg_gadget_a,
|
||||
&rlrg_gadget_b,
|
||||
sk_rlwe.values(),
|
||||
&sk_rlwe,
|
||||
&self.pbs_info.rlwe_modop,
|
||||
&self.pbs_info.rlwe_nttop,
|
||||
&mut main_prng,
|
||||
@@ -766,8 +747,8 @@ where
|
||||
let mut lwe_ksk =
|
||||
M::R::zeros(self.pbs_info.lwe_decomposer.decomposition_count() * ring_size);
|
||||
lwe_ksk_keygen(
|
||||
&sk_rlwe.values(),
|
||||
&sk_lwe.values(),
|
||||
&sk_rlwe,
|
||||
&sk_lwe,
|
||||
&mut lwe_ksk,
|
||||
&d_lwe_gadget,
|
||||
&self.pbs_info.lwe_modop,
|
||||
@@ -785,11 +766,11 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn multi_party_server_key_share(
|
||||
pub(super) fn multi_party_server_key_share<K: InteractiveMultiPartyClientKey<Element = i32>>(
|
||||
&self,
|
||||
cr_seed: [u8; 32],
|
||||
collective_pk: &M,
|
||||
client_key: &ClientKey,
|
||||
client_key: &K,
|
||||
) -> CommonReferenceSeededMultiPartyServerKeyShare<M, BoolParameters<M::MatElement>, [u8; 32]>
|
||||
{
|
||||
DefaultSecureRng::with_local_mut(|rng| {
|
||||
@@ -807,8 +788,8 @@ where
|
||||
let rlweq_nttop = &self.pbs_info.rlwe_nttop;
|
||||
|
||||
// sanity check
|
||||
assert!(sk_rlwe.values().len() == ring_size);
|
||||
assert!(sk_lwe.values().len() == self.pbs_info.parameters.lwe_n().0);
|
||||
assert!(sk_rlwe.len() == ring_size);
|
||||
assert!(sk_lwe.len() == self.pbs_info.parameters.lwe_n().0);
|
||||
|
||||
// auto keys
|
||||
let mut auto_keys = HashMap::new();
|
||||
@@ -828,7 +809,7 @@ where
|
||||
);
|
||||
galois_key_gen(
|
||||
&mut ksk_out,
|
||||
sk_rlwe.values(),
|
||||
&sk_rlwe,
|
||||
g_pow,
|
||||
&auto_gadget,
|
||||
rlweq_modop,
|
||||
@@ -853,7 +834,6 @@ where
|
||||
rgsw_rgsw_decomposer.1.gadget_vector(),
|
||||
);
|
||||
let rgsw_cts = sk_lwe
|
||||
.values()
|
||||
.iter()
|
||||
.map(|si| {
|
||||
let mut m = M::R::zeros(ring_size);
|
||||
@@ -893,8 +873,8 @@ where
|
||||
let lwe_modop = &self.pbs_info.lwe_modop;
|
||||
let d_lwe_gadget_vec = self.pbs_info.lwe_decomposer.gadget_vector();
|
||||
lwe_ksk_keygen(
|
||||
sk_rlwe.values(),
|
||||
sk_lwe.values(),
|
||||
&sk_rlwe,
|
||||
&sk_lwe,
|
||||
&mut lwe_ksk,
|
||||
&d_lwe_gadget_vec,
|
||||
lwe_modop,
|
||||
@@ -916,7 +896,7 @@ where
|
||||
&self,
|
||||
cr_seed: &NonInteractiveMultiPartyCrs<[u8; 32]>,
|
||||
total_users: usize,
|
||||
key_shares: &[SeededNonInteractiveMultiPartyServerKeyShare<
|
||||
key_shares: &[CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare<
|
||||
M,
|
||||
NonInteractiveMultiPartyCrs<[u8; 32]>,
|
||||
>],
|
||||
@@ -1432,21 +1412,29 @@ where
|
||||
)
|
||||
}
|
||||
|
||||
pub(super) fn non_interactive_multi_party_key_share(
|
||||
pub(super) fn non_interactive_multi_party_key_share<
|
||||
K: NonInteractiveMultiPartyClientKey<Element = i32>,
|
||||
>(
|
||||
&self,
|
||||
// TODO(Jay): Should get a common reference seed here and derive the rest.
|
||||
cr_seed: &NonInteractiveMultiPartyCrs<[u8; 32]>,
|
||||
self_index: usize,
|
||||
total_users: usize,
|
||||
client_key: &ThrowMeAwayKey,
|
||||
) -> SeededNonInteractiveMultiPartyServerKeyShare<M, NonInteractiveMultiPartyCrs<[u8; 32]>>
|
||||
{
|
||||
client_key: &K,
|
||||
) -> CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare<
|
||||
M,
|
||||
NonInteractiveMultiPartyCrs<[u8; 32]>,
|
||||
> {
|
||||
// TODO: check whether parameters support `total_users`
|
||||
let nttop = self.pbs_info().nttop_rlweq();
|
||||
let rlwe_modop = self.pbs_info().modop_rlweq();
|
||||
let ring_size = self.pbs_info().rlwe_n();
|
||||
let rlwe_q = self.parameters().rlwe_q();
|
||||
|
||||
let sk_rlwe = client_key.sk_rlwe();
|
||||
let sk_u_rlwe = client_key.sk_u_rlwe();
|
||||
let sk_lwe = client_key.sk_lwe();
|
||||
|
||||
let (ui_to_s_ksk, zero_encs_for_others) = DefaultSecureRng::with_local_mut(|rng| {
|
||||
// ui_to_s_ksk
|
||||
let non_interactive_decomposer = self
|
||||
@@ -1460,8 +1448,8 @@ where
|
||||
);
|
||||
|
||||
non_interactive_ksk_gen::<M, _, _, _, _, _>(
|
||||
client_key.sk_rlwe().values(),
|
||||
client_key.sk_u_rlwe().values(),
|
||||
&sk_rlwe,
|
||||
&sk_u_rlwe,
|
||||
&non_interactive_gadget_vec,
|
||||
&mut p_rng,
|
||||
rng,
|
||||
@@ -1479,7 +1467,7 @@ where
|
||||
);
|
||||
let zero_encs =
|
||||
non_interactive_ksk_zero_encryptions_for_other_party_i::<M, _, _, _, _, _>(
|
||||
client_key.sk_rlwe().values(),
|
||||
&sk_rlwe,
|
||||
&non_interactive_gadget_vec,
|
||||
&mut p_rng,
|
||||
rng,
|
||||
@@ -1511,9 +1499,7 @@ where
|
||||
rgsw_by_rgsw_decomposer.b().gadget_vector()
|
||||
}
|
||||
};
|
||||
let ni_rgsw_cts: (Vec<M>, Vec<M>) = client_key
|
||||
.sk_lwe()
|
||||
.values()
|
||||
let ni_rgsw_cts: (Vec<M>, Vec<M>) = sk_lwe
|
||||
.iter()
|
||||
.map(|s_i| {
|
||||
// X^{s[i]}
|
||||
@@ -1527,8 +1513,8 @@ where
|
||||
}
|
||||
|
||||
non_interactive_rgsw_ct::<M, _, _, _, _, _>(
|
||||
client_key.sk_rlwe().values(),
|
||||
client_key.sk_u_rlwe().values(),
|
||||
&sk_rlwe,
|
||||
&sk_u_rlwe,
|
||||
m.as_ref(),
|
||||
&ni_rgrg_gadget_vec,
|
||||
&mut rgsw_cts_prng,
|
||||
@@ -1544,20 +1530,16 @@ where
|
||||
// Auto key share
|
||||
let auto_keys_share = {
|
||||
let auto_seed = cr_seed.auto_keys_cts_seed::<DefaultSecureRng>();
|
||||
self._common_rountine_multi_party_auto_keys_share_gen(auto_seed, client_key.sk_rlwe())
|
||||
self._common_rountine_multi_party_auto_keys_share_gen(auto_seed, &sk_rlwe)
|
||||
};
|
||||
|
||||
// Lwe Ksk share
|
||||
let lwe_ksk_share = {
|
||||
let lwe_ksk_seed = cr_seed.lwe_ksk_cts_seed::<DefaultSecureRng>();
|
||||
self._common_rountine_multi_party_lwe_ksk_share_gen(
|
||||
lwe_ksk_seed,
|
||||
client_key.sk_rlwe(),
|
||||
client_key.sk_lwe(),
|
||||
)
|
||||
self._common_rountine_multi_party_lwe_ksk_share_gen(lwe_ksk_seed, &sk_rlwe, &sk_lwe)
|
||||
};
|
||||
|
||||
SeededNonInteractiveMultiPartyServerKeyShare {
|
||||
CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare {
|
||||
ni_rgsw_cts,
|
||||
ui_to_s_ksk,
|
||||
others_ksk_zero_encs: zero_encs_for_others,
|
||||
@@ -1571,7 +1553,7 @@ where
|
||||
fn _common_rountine_multi_party_auto_keys_share_gen(
|
||||
&self,
|
||||
auto_seed: <DefaultSecureRng as NewWithSeed>::Seed,
|
||||
sk_rlwe: &RlweSecret,
|
||||
sk_rlwe: &[i32],
|
||||
) -> HashMap<usize, M> {
|
||||
let g = self.pbs_info.parameters.g();
|
||||
let ring_size = self.pbs_info.parameters.rlwe_n().0;
|
||||
@@ -1599,7 +1581,7 @@ where
|
||||
);
|
||||
galois_key_gen(
|
||||
&mut ksk_out,
|
||||
sk_rlwe.values(),
|
||||
sk_rlwe,
|
||||
g_pow,
|
||||
&auto_gadget,
|
||||
rlweq_modop,
|
||||
@@ -1617,8 +1599,8 @@ where
|
||||
fn _common_rountine_multi_party_lwe_ksk_share_gen(
|
||||
&self,
|
||||
lwe_ksk_seed: <DefaultSecureRng as NewWithSeed>::Seed,
|
||||
sk_rlwe: &RlweSecret,
|
||||
sk_lwe: &LweSecret,
|
||||
sk_rlwe: &[i32],
|
||||
sk_lwe: &[i32],
|
||||
) -> M::R {
|
||||
DefaultSecureRng::with_local_mut(|rng| {
|
||||
let mut p_rng = DefaultSecureRng::new_seeded(lwe_ksk_seed);
|
||||
@@ -1628,8 +1610,8 @@ where
|
||||
let lwe_modop = &self.pbs_info.lwe_modop;
|
||||
let d_lwe_gadget_vec = self.pbs_info.lwe_decomposer.gadget_vector();
|
||||
lwe_ksk_keygen(
|
||||
sk_rlwe.values(),
|
||||
sk_lwe.values(),
|
||||
sk_rlwe,
|
||||
sk_lwe,
|
||||
&mut lwe_ksk,
|
||||
&d_lwe_gadget_vec,
|
||||
lwe_modop,
|
||||
@@ -1640,10 +1622,10 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn multi_party_public_key_share(
|
||||
pub(super) fn multi_party_public_key_share<K: InteractiveMultiPartyClientKey<Element = i32>>(
|
||||
&self,
|
||||
cr_seed: [u8; 32],
|
||||
client_key: &ClientKey,
|
||||
client_key: &K,
|
||||
) -> CommonReferenceSeededCollectivePublicKeyShare<
|
||||
<M as Matrix>::R,
|
||||
[u8; 32],
|
||||
@@ -1656,7 +1638,7 @@ where
|
||||
let mut main_prng = DefaultSecureRng::new_seeded(cr_seed);
|
||||
public_key_share(
|
||||
&mut share_out,
|
||||
client_key.sk_rlwe().values(),
|
||||
&client_key.sk_rlwe(),
|
||||
modop,
|
||||
nttop,
|
||||
&mut main_prng,
|
||||
@@ -1670,17 +1652,15 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn multi_party_decryption_share(
|
||||
pub(super) fn multi_party_decryption_share<K: InteractiveMultiPartyClientKey<Element = i32>>(
|
||||
&self,
|
||||
lwe_ct: &M::R,
|
||||
client_key: &ClientKey,
|
||||
client_key: &K,
|
||||
) -> <M as Matrix>::MatElement {
|
||||
assert!(lwe_ct.as_ref().len() == self.pbs_info.parameters.rlwe_n().0 + 1);
|
||||
let modop = &self.pbs_info.rlwe_modop;
|
||||
let mut neg_s = M::R::try_convert_from(
|
||||
client_key.sk_rlwe().values(),
|
||||
&self.pbs_info.parameters.rlwe_q(),
|
||||
);
|
||||
let mut neg_s =
|
||||
M::R::try_convert_from(&client_key.sk_rlwe(), &self.pbs_info.parameters.rlwe_q());
|
||||
modop.elwise_neg_mut(neg_s.as_mut());
|
||||
|
||||
let mut neg_sa = M::MatElement::zero();
|
||||
@@ -1798,7 +1778,11 @@ where
|
||||
}
|
||||
|
||||
/// TODO(Jay): Fetch client key from thread local
|
||||
pub fn sk_encrypt(&self, m: bool, client_key: &ClientKey) -> M::R {
|
||||
pub fn sk_encrypt<K: SinglePartyClientKey<Element = i32>>(
|
||||
&self,
|
||||
m: bool,
|
||||
client_key: &K,
|
||||
) -> M::R {
|
||||
//FIXME(Jay): Figure out a way to get Q/8 form modulus
|
||||
let m = if m {
|
||||
// Q/8
|
||||
@@ -1813,7 +1797,7 @@ where
|
||||
encrypt_lwe(
|
||||
&mut lwe_out,
|
||||
&m,
|
||||
client_key.sk_rlwe().values(),
|
||||
&client_key.sk_rlwe(),
|
||||
&self.pbs_info.rlwe_modop,
|
||||
rng,
|
||||
);
|
||||
@@ -1821,12 +1805,12 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
pub fn sk_decrypt(&self, lwe_ct: &M::R, client_key: &ClientKey) -> bool {
|
||||
let m = decrypt_lwe(
|
||||
lwe_ct,
|
||||
client_key.sk_rlwe().values(),
|
||||
&self.pbs_info.rlwe_modop,
|
||||
);
|
||||
pub fn sk_decrypt<K: SinglePartyClientKey<Element = i32>>(
|
||||
&self,
|
||||
lwe_ct: &M::R,
|
||||
client_key: &K,
|
||||
) -> bool {
|
||||
let m = decrypt_lwe(lwe_ct, &client_key.sk_rlwe(), &self.pbs_info.rlwe_modop);
|
||||
self.pbs_info.rlwe_q().decode(m)
|
||||
}
|
||||
|
||||
@@ -2159,17 +2143,21 @@ where
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use bool::parameters::{MP_BOOL_PARAMS, SP_BOOL_PARAMS};
|
||||
|
||||
use rand::{thread_rng, Rng};
|
||||
use rand_distr::Uniform;
|
||||
|
||||
use crate::{
|
||||
backend::ModulusPowerOf2,
|
||||
bool::{
|
||||
self, CommonReferenceSeededMultiPartyServerKeyShare,
|
||||
NonInteractiveServerKeyEvaluationDomain, PublicKey, SeededMultiPartyServerKey,
|
||||
ShoupNonInteractiveServerKeyEvaluationDomain, NON_INTERACTIVE_SMALL_MP_BOOL_PARAMS,
|
||||
SMALL_MP_BOOL_PARAMS,
|
||||
keys::{
|
||||
NonInteractiveServerKeyEvaluationDomain, PublicKey,
|
||||
ShoupNonInteractiveServerKeyEvaluationDomain,
|
||||
},
|
||||
parameters::{
|
||||
MP_BOOL_PARAMS, NON_INTERACTIVE_SMALL_MP_BOOL_PARAMS, SMALL_MP_BOOL_PARAMS,
|
||||
SP_BOOL_PARAMS,
|
||||
},
|
||||
},
|
||||
ntt::NttBackendU64,
|
||||
random::{RandomElementInModulus, DEFAULT_RNG},
|
||||
@@ -2306,7 +2294,11 @@ mod tests {
|
||||
|
||||
let mut ideal_rlwe_sk = vec![0i32; bool_evaluator.pbs_info.rlwe_n()];
|
||||
parties.iter().for_each(|k| {
|
||||
izip!(ideal_rlwe_sk.iter_mut(), k.sk_rlwe().values()).for_each(|(ideal_i, s_i)| {
|
||||
izip!(
|
||||
ideal_rlwe_sk.iter_mut(),
|
||||
InteractiveMultiPartyClientKey::sk_rlwe(k).iter()
|
||||
)
|
||||
.for_each(|(ideal_i, s_i)| {
|
||||
*ideal_i = *ideal_i + s_i;
|
||||
});
|
||||
});
|
||||
@@ -2354,131 +2346,6 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
fn _collecitve_public_key_gen(rlwe_q: u64, parties_rlwe_sk: &[RlweSecret]) -> Vec<Vec<u64>> {
|
||||
let ring_size = parties_rlwe_sk[0].values.len();
|
||||
assert!(ring_size.is_power_of_two());
|
||||
let mut rng = DefaultSecureRng::new();
|
||||
let nttop = NttBackendU64::new(&rlwe_q, ring_size);
|
||||
let modop = ModularOpsU64::new(rlwe_q);
|
||||
|
||||
// Generate Pk shares
|
||||
let pk_seed = [0u8; 32];
|
||||
let pk_shares = parties_rlwe_sk.iter().map(|sk| {
|
||||
let mut p_rng = DefaultSecureRng::new_seeded(pk_seed);
|
||||
let mut share_out = vec![0u64; ring_size];
|
||||
public_key_share(
|
||||
&mut share_out,
|
||||
sk.values(),
|
||||
&modop,
|
||||
&nttop,
|
||||
&mut p_rng,
|
||||
&mut rng,
|
||||
);
|
||||
share_out
|
||||
});
|
||||
|
||||
let mut pk_part_b = vec![0u64; ring_size];
|
||||
pk_shares.for_each(|share| modop.elwise_add_mut(&mut pk_part_b, &share));
|
||||
let mut pk_part_a = vec![0u64; ring_size];
|
||||
let mut p_rng = DefaultSecureRng::new_seeded(pk_seed);
|
||||
RandomFillUniformInModulus::random_fill(&mut p_rng, &rlwe_q, pk_part_a.as_mut_slice());
|
||||
|
||||
vec![pk_part_a, pk_part_b]
|
||||
}
|
||||
|
||||
fn _multi_party_all_keygen(
|
||||
bool_evaluator: &BoolEvaluator<
|
||||
Vec<Vec<u64>>,
|
||||
NttBackendU64,
|
||||
ModularOpsU64<CiphertextModulus<u64>>,
|
||||
ModularOpsU64<CiphertextModulus<u64>>,
|
||||
ShoupServerKeyEvaluationDomain<Vec<Vec<u64>>>,
|
||||
>,
|
||||
no_of_parties: usize,
|
||||
) -> (
|
||||
Vec<ClientKey>,
|
||||
PublicKey<Vec<Vec<u64>>, DefaultSecureRng, ModularOpsU64<CiphertextModulus<u64>>>,
|
||||
Vec<
|
||||
CommonReferenceSeededMultiPartyServerKeyShare<
|
||||
Vec<Vec<u64>>,
|
||||
BoolParameters<u64>,
|
||||
[u8; 32],
|
||||
>,
|
||||
>,
|
||||
SeededMultiPartyServerKey<Vec<Vec<u64>>, [u8; 32], BoolParameters<u64>>,
|
||||
ShoupServerKeyEvaluationDomain<Vec<Vec<u64>>>,
|
||||
ClientKey,
|
||||
) {
|
||||
let parties = (0..no_of_parties)
|
||||
.map(|_| bool_evaluator.client_key())
|
||||
.collect_vec();
|
||||
|
||||
let mut rng = DefaultSecureRng::new();
|
||||
|
||||
// Collective public key
|
||||
let mut pk_cr_seed = [0u8; 32];
|
||||
rng.fill_bytes(&mut pk_cr_seed);
|
||||
let public_key_share = parties
|
||||
.iter()
|
||||
.map(|k| bool_evaluator.multi_party_public_key_share(pk_cr_seed, k))
|
||||
.collect_vec();
|
||||
let collective_pk =
|
||||
PublicKey::<Vec<Vec<u64>>, DefaultSecureRng, _>::from(public_key_share.as_slice());
|
||||
|
||||
// Server key
|
||||
let mut pbs_cr_seed = [0u8; 32];
|
||||
rng.fill_bytes(&mut pbs_cr_seed);
|
||||
let server_key_shares = parties
|
||||
.iter()
|
||||
.map(|k| {
|
||||
bool_evaluator.multi_party_server_key_share(pbs_cr_seed, &collective_pk.key(), k)
|
||||
})
|
||||
.collect_vec();
|
||||
let seeded_server_key =
|
||||
bool_evaluator.aggregate_multi_party_server_key_shares(&server_key_shares);
|
||||
let runtime_server_key =
|
||||
ShoupServerKeyEvaluationDomain::from(ServerKeyEvaluationDomain::<
|
||||
_,
|
||||
_,
|
||||
DefaultSecureRng,
|
||||
NttBackendU64,
|
||||
>::from(&seeded_server_key));
|
||||
|
||||
// construct ideal rlwe sk for meauring noise
|
||||
let ideal_client_key = {
|
||||
let mut ideal_rlwe_sk = vec![0i32; bool_evaluator.pbs_info.rlwe_n()];
|
||||
parties.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; bool_evaluator.pbs_info.lwe_n()];
|
||||
parties.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,
|
||||
},
|
||||
)
|
||||
};
|
||||
|
||||
(
|
||||
parties,
|
||||
collective_pk,
|
||||
server_key_shares,
|
||||
seeded_server_key,
|
||||
runtime_server_key,
|
||||
ideal_client_key,
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interactive_multi_party_nand() {
|
||||
let mut bool_evaluator = BoolEvaluator::<
|
||||
@@ -2489,8 +2356,51 @@ mod tests {
|
||||
ShoupServerKeyEvaluationDomain<Vec<Vec<u64>>>,
|
||||
>::new(MP_BOOL_PARAMS);
|
||||
|
||||
let (parties, collective_pk, _, _, server_key_eval, ideal_client_key) =
|
||||
_multi_party_all_keygen(&bool_evaluator, 2);
|
||||
let multi_party_crs = MultiPartyCrs::random();
|
||||
|
||||
// let (parties, collective_pk, _, _, server_key_eval, ideal_client_key) =
|
||||
// _multi_party_all_keygen(&bool_evaluator, 2);
|
||||
|
||||
let no_of_parties = 2;
|
||||
let parties = (0..no_of_parties)
|
||||
.map(|_| bool_evaluator.client_key())
|
||||
.collect_vec();
|
||||
|
||||
// generate public key
|
||||
let pk_shares = parties
|
||||
.iter()
|
||||
.map(|k| {
|
||||
bool_evaluator.multi_party_public_key_share(
|
||||
multi_party_crs.public_key_share_seed::<DefaultSecureRng>(),
|
||||
k,
|
||||
)
|
||||
})
|
||||
.collect_vec();
|
||||
let collective_pk =
|
||||
PublicKey::<_, DefaultSecureRng, ModularOpsU64<CiphertextModulus<u64>>>::from(
|
||||
pk_shares.as_slice(),
|
||||
);
|
||||
|
||||
// generate server key
|
||||
let server_key_shares = parties
|
||||
.iter()
|
||||
.map(|k| {
|
||||
bool_evaluator.multi_party_server_key_share(
|
||||
multi_party_crs.server_key_share_seed::<DefaultSecureRng>(),
|
||||
collective_pk.key(),
|
||||
k,
|
||||
)
|
||||
})
|
||||
.collect_vec();
|
||||
let seeded_server_key =
|
||||
bool_evaluator.aggregate_multi_party_server_key_shares(&server_key_shares);
|
||||
let server_key_eval =
|
||||
ShoupServerKeyEvaluationDomain::from(ServerKeyEvaluationDomain::<
|
||||
_,
|
||||
_,
|
||||
DefaultSecureRng,
|
||||
NttBackendU64,
|
||||
>::from(&seeded_server_key));
|
||||
|
||||
let mut m0 = true;
|
||||
let mut m1 = false;
|
||||
@@ -2558,30 +2468,27 @@ mod tests {
|
||||
.map(|_| bool_evaluator.client_key())
|
||||
.collect_vec();
|
||||
|
||||
let ideal_client_key = {
|
||||
let mut ideal_rlwe_sk = vec![0i32; bool_evaluator.pbs_info.rlwe_n()];
|
||||
parties.iter().for_each(|k| {
|
||||
izip!(ideal_rlwe_sk.iter_mut(), k.sk_rlwe().values()).for_each(|(ideal_i, s_i)| {
|
||||
izip!(
|
||||
ideal_rlwe_sk.iter_mut(),
|
||||
InteractiveMultiPartyClientKey::sk_rlwe(k).iter()
|
||||
)
|
||||
.for_each(|(ideal_i, s_i)| {
|
||||
*ideal_i = *ideal_i + s_i;
|
||||
});
|
||||
});
|
||||
let mut ideal_lwe_sk = vec![0i32; bool_evaluator.pbs_info.lwe_n()];
|
||||
parties.iter().for_each(|k| {
|
||||
izip!(ideal_lwe_sk.iter_mut(), k.sk_lwe().values()).for_each(|(ideal_i, s_i)| {
|
||||
izip!(
|
||||
ideal_lwe_sk.iter_mut(),
|
||||
InteractiveMultiPartyClientKey::sk_lwe(k).iter()
|
||||
)
|
||||
.for_each(|(ideal_i, s_i)| {
|
||||
*ideal_i = *ideal_i + s_i;
|
||||
});
|
||||
});
|
||||
|
||||
ClientKey::new(
|
||||
RlweSecret {
|
||||
values: ideal_rlwe_sk,
|
||||
},
|
||||
LweSecret {
|
||||
values: ideal_lwe_sk,
|
||||
},
|
||||
)
|
||||
};
|
||||
|
||||
// check noise in freshly encrypted RLWE ciphertext (ie var_fresh)
|
||||
if true {
|
||||
let mut rng = DefaultSecureRng::new();
|
||||
@@ -2615,7 +2522,7 @@ mod tests {
|
||||
let mut m_back = vec![0u64; rlwe_n];
|
||||
decrypt_rlwe(
|
||||
&rlwe_ct,
|
||||
ideal_client_key.sk_rlwe().values(),
|
||||
&ideal_rlwe_sk,
|
||||
&mut m_back,
|
||||
rlwe_nttop,
|
||||
rlwe_modop,
|
||||
@@ -2659,11 +2566,8 @@ mod tests {
|
||||
// Check noise in RGSW ciphertexts of ideal LWE secret elements
|
||||
if false {
|
||||
let mut check = Stats { samples: vec![] };
|
||||
izip!(
|
||||
ideal_client_key.sk_lwe().values.iter(),
|
||||
seeded_server_key.rgsw_cts().iter()
|
||||
)
|
||||
.for_each(|(s_i, rgsw_ct_i)| {
|
||||
izip!(ideal_lwe_sk.iter(), seeded_server_key.rgsw_cts().iter()).for_each(
|
||||
|(s_i, rgsw_ct_i)| {
|
||||
// X^{s[i]}
|
||||
let mut m_si = vec![0u64; rlwe_n];
|
||||
let s_i = *s_i * (bool_evaluator.pbs_info.embedding_factor as i32);
|
||||
@@ -2675,7 +2579,7 @@ mod tests {
|
||||
|
||||
// RLWE'(-sm)
|
||||
let mut neg_s_eval =
|
||||
Vec::<u64>::try_convert_from(ideal_client_key.sk_rlwe().values(), rlwe_q);
|
||||
Vec::<u64>::try_convert_from(ideal_rlwe_sk.as_slice(), rlwe_q);
|
||||
rlwe_modop.elwise_neg_mut(&mut neg_s_eval);
|
||||
rlwe_nttop.forward(&mut neg_s_eval);
|
||||
for j in 0..rlwe_rgsw_decomposer.a().decomposition_count() {
|
||||
@@ -2684,10 +2588,13 @@ mod tests {
|
||||
// -s[X]*X^{s_lwe[i]}*B_j
|
||||
let mut m_ideal = m_si.clone();
|
||||
rlwe_nttop.forward(m_ideal.as_mut_slice());
|
||||
rlwe_modop.elwise_mul_mut(m_ideal.as_mut_slice(), neg_s_eval.as_slice());
|
||||
rlwe_nttop.backward(m_ideal.as_mut_slice());
|
||||
rlwe_modop
|
||||
.elwise_scalar_mul_mut(m_ideal.as_mut_slice(), &rlwe_rgsw_gadget_a[j]);
|
||||
.elwise_mul_mut(m_ideal.as_mut_slice(), neg_s_eval.as_slice());
|
||||
rlwe_nttop.backward(m_ideal.as_mut_slice());
|
||||
rlwe_modop.elwise_scalar_mul_mut(
|
||||
m_ideal.as_mut_slice(),
|
||||
&rlwe_rgsw_gadget_a[j],
|
||||
);
|
||||
|
||||
// RLWE(-s*X^{s_lwe[i]}*B_j)
|
||||
let mut rlwe_ct = vec![vec![0u64; rlwe_n]; 2];
|
||||
@@ -2699,7 +2606,7 @@ mod tests {
|
||||
let mut m_back = vec![0u64; rlwe_n];
|
||||
decrypt_rlwe(
|
||||
&rlwe_ct,
|
||||
ideal_client_key.sk_rlwe().values(),
|
||||
&ideal_rlwe_sk,
|
||||
&mut m_back,
|
||||
rlwe_nttop,
|
||||
rlwe_modop,
|
||||
@@ -2716,13 +2623,16 @@ mod tests {
|
||||
|
||||
// X^{s_lwe[i]}*B_j
|
||||
let mut m_ideal = m_si.clone();
|
||||
rlwe_modop
|
||||
.elwise_scalar_mul_mut(m_ideal.as_mut_slice(), &rlwe_rgsw_gadget_b[j]);
|
||||
rlwe_modop.elwise_scalar_mul_mut(
|
||||
m_ideal.as_mut_slice(),
|
||||
&rlwe_rgsw_gadget_b[j],
|
||||
);
|
||||
|
||||
// RLWE(X^{s_lwe[i]}*B_j)
|
||||
let mut rlwe_ct = vec![vec![0u64; rlwe_n]; 2];
|
||||
rlwe_ct[0].copy_from_slice(
|
||||
&rgsw_ct_i[j + (2 * rlwe_rgsw_decomposer.a().decomposition_count())],
|
||||
&rgsw_ct_i
|
||||
[j + (2 * rlwe_rgsw_decomposer.a().decomposition_count())],
|
||||
);
|
||||
rlwe_ct[1].copy_from_slice(
|
||||
&rgsw_ct_i[j
|
||||
@@ -2733,7 +2643,7 @@ mod tests {
|
||||
let mut m_back = vec![0u64; rlwe_n];
|
||||
decrypt_rlwe(
|
||||
&rlwe_ct,
|
||||
ideal_client_key.sk_rlwe().values(),
|
||||
&ideal_rlwe_sk,
|
||||
&mut m_back,
|
||||
rlwe_nttop,
|
||||
rlwe_modop,
|
||||
@@ -2743,7 +2653,8 @@ mod tests {
|
||||
rlwe_modop.elwise_sub_mut(&mut m_back, &m_ideal);
|
||||
check.add_more(&Vec::<i64>::try_convert_from(&m_back, rlwe_q));
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
println!(
|
||||
"RGSW Std: {} {} ;; max={}",
|
||||
check.mean(),
|
||||
@@ -2765,12 +2676,7 @@ mod tests {
|
||||
if false {
|
||||
let mut check = Stats { samples: vec![] };
|
||||
|
||||
ideal_client_key
|
||||
.sk_lwe()
|
||||
.values()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.for_each(|(index, s_i)| {
|
||||
ideal_lwe_sk.iter().enumerate().for_each(|(index, s_i)| {
|
||||
let rgsw_ct_i = runtime_server_key.rgsw_ct_lwe_si(index).as_ref();
|
||||
|
||||
let mut m = vec![0u64; rlwe_n];
|
||||
@@ -2819,7 +2725,7 @@ mod tests {
|
||||
let mut m_plus_e_times_m1 = vec![0u64; rlwe_n];
|
||||
decrypt_rlwe(
|
||||
&rlwe_ct,
|
||||
ideal_client_key.sk_rlwe().values(),
|
||||
&ideal_rlwe_sk,
|
||||
&mut m_plus_e_times_m1,
|
||||
rlwe_nttop,
|
||||
rlwe_modop,
|
||||
@@ -2838,7 +2744,7 @@ mod tests {
|
||||
let mut m_plus_e_times_m1_more_e = vec![0u64; rlwe_n];
|
||||
decrypt_rlwe(
|
||||
&rlwe_after,
|
||||
ideal_client_key.sk_rlwe().values(),
|
||||
&ideal_rlwe_sk,
|
||||
&mut m_plus_e_times_m1_more_e,
|
||||
rlwe_nttop,
|
||||
rlwe_modop,
|
||||
@@ -2875,8 +2781,7 @@ mod tests {
|
||||
if false {
|
||||
let mut check = Stats { samples: vec![] };
|
||||
|
||||
let mut neg_s_poly =
|
||||
Vec::<u64>::try_convert_from(ideal_client_key.sk_rlwe().values(), rlwe_q);
|
||||
let mut neg_s_poly = Vec::<u64>::try_convert_from(ideal_rlwe_sk.as_slice(), rlwe_q);
|
||||
rlwe_modop.elwise_neg_mut(neg_s_poly.as_mut_slice());
|
||||
|
||||
let g = bool_evaluator.pbs_info.g();
|
||||
@@ -2918,13 +2823,7 @@ mod tests {
|
||||
rlwe_ct[1].copy_from_slice(
|
||||
&auto_key_i[auto_decomposer.decomposition_count() + i],
|
||||
);
|
||||
decrypt_rlwe(
|
||||
&rlwe_ct,
|
||||
ideal_client_key.sk_rlwe().values(),
|
||||
&mut m_out,
|
||||
rlwe_nttop,
|
||||
rlwe_modop,
|
||||
);
|
||||
decrypt_rlwe(&rlwe_ct, &ideal_rlwe_sk, &mut m_out, rlwe_nttop, rlwe_modop);
|
||||
|
||||
// diff
|
||||
rlwe_modop.elwise_sub_mut(m_out.as_mut_slice(), m_ideal.as_slice());
|
||||
@@ -2966,7 +2865,7 @@ mod tests {
|
||||
let mut m_plus_e = vec![0u64; rlwe_n];
|
||||
decrypt_rlwe(
|
||||
&rlwe_ct,
|
||||
ideal_client_key.sk_rlwe().values(),
|
||||
&ideal_rlwe_sk,
|
||||
&mut m_plus_e,
|
||||
rlwe_nttop,
|
||||
rlwe_modop,
|
||||
@@ -3000,13 +2899,7 @@ mod tests {
|
||||
});
|
||||
|
||||
let mut m_out = vec![0u64; rlwe_n];
|
||||
decrypt_rlwe(
|
||||
&rlwe_ct,
|
||||
ideal_client_key.sk_rlwe().values(),
|
||||
&mut m_out,
|
||||
rlwe_nttop,
|
||||
rlwe_modop,
|
||||
);
|
||||
decrypt_rlwe(&rlwe_ct, &ideal_rlwe_sk, &mut m_out, rlwe_nttop, rlwe_modop);
|
||||
|
||||
// diff
|
||||
rlwe_modop.elwise_sub_mut(m_out.as_mut_slice(), m_plus_e_auto.as_slice());
|
||||
@@ -3030,13 +2923,7 @@ mod tests {
|
||||
// Encrypt m \in Q_{ks} using RLWE sk
|
||||
let mut lwe_in_ct = vec![0u64; rlwe_n + 1];
|
||||
let m = RandomElementInModulus::random(&mut rng, &lwe_q.q().unwrap());
|
||||
encrypt_lwe(
|
||||
&mut lwe_in_ct,
|
||||
&m,
|
||||
ideal_client_key.sk_rlwe().values(),
|
||||
lwe_modop,
|
||||
&mut rng,
|
||||
);
|
||||
encrypt_lwe(&mut lwe_in_ct, &m, &ideal_rlwe_sk, lwe_modop, &mut rng);
|
||||
|
||||
// Key switch
|
||||
let mut lwe_out = vec![0u64; lwe_n + 1];
|
||||
@@ -3050,11 +2937,10 @@ mod tests {
|
||||
|
||||
// We only care about noise added by LWE key switch
|
||||
// m+e
|
||||
let m_plus_e =
|
||||
decrypt_lwe(&lwe_in_ct, ideal_client_key.sk_rlwe().values(), lwe_modop);
|
||||
let m_plus_e = decrypt_lwe(&lwe_in_ct, &ideal_rlwe_sk, lwe_modop);
|
||||
|
||||
let m_plus_e_plus_lwe_ksk_noise =
|
||||
decrypt_lwe(&lwe_out, ideal_client_key.sk_lwe().values(), lwe_modop);
|
||||
decrypt_lwe(&lwe_out, &ideal_lwe_sk, lwe_modop);
|
||||
|
||||
let diff = lwe_modop.sub(&m_plus_e_plus_lwe_ksk_noise, &m_plus_e);
|
||||
|
||||
@@ -3274,9 +3160,7 @@ mod tests {
|
||||
|
||||
let parties = 2;
|
||||
|
||||
let cks = (0..parties)
|
||||
.map(|_| evaluator.non_interactive_client_key())
|
||||
.collect_vec();
|
||||
let cks = (0..parties).map(|_| evaluator.client_key()).collect_vec();
|
||||
|
||||
let key_shares = (0..parties)
|
||||
.map(|i| evaluator.non_interactive_multi_party_key_share(&mp_seed, i, parties, &cks[i]))
|
||||
@@ -3295,14 +3179,22 @@ mod tests {
|
||||
|
||||
let mut ideal_rlwe = vec![0; ring_size];
|
||||
cks.iter().for_each(|k| {
|
||||
izip!(ideal_rlwe.iter_mut(), k.sk_rlwe().values().iter()).for_each(|(a, b)| {
|
||||
izip!(
|
||||
ideal_rlwe.iter_mut(),
|
||||
NonInteractiveMultiPartyClientKey::sk_rlwe(k).iter()
|
||||
)
|
||||
.for_each(|(a, b)| {
|
||||
*a = *a + b;
|
||||
});
|
||||
});
|
||||
|
||||
let mut ideal_lwe = vec![0; evaluator.parameters().lwe_n().0];
|
||||
cks.iter().for_each(|k| {
|
||||
izip!(ideal_lwe.iter_mut(), k.sk_lwe().values().iter()).for_each(|(a, b)| {
|
||||
izip!(
|
||||
ideal_lwe.iter_mut(),
|
||||
NonInteractiveMultiPartyClientKey::sk_lwe(k).iter()
|
||||
)
|
||||
.for_each(|(a, b)| {
|
||||
*a = *a + b;
|
||||
});
|
||||
});
|
||||
|
||||
188
src/bool/keys.rs
188
src/bool/keys.rs
@@ -10,112 +10,130 @@ use crate::{
|
||||
Decryptor, Encryptor, Matrix, MatrixEntity, MatrixMut, MultiPartyDecryptor, RowEntity, RowMut,
|
||||
};
|
||||
|
||||
use super::{parameters, BoolEvaluator, BoolParameters, CiphertextModulus};
|
||||
use super::{
|
||||
evaluator::BoolEvaluator,
|
||||
parameters::{BoolParameters, CiphertextModulus},
|
||||
};
|
||||
|
||||
trait SinglePartyClientKey {
|
||||
pub(crate) trait SinglePartyClientKey {
|
||||
type Element;
|
||||
fn sk_rlwe(&self) -> &[Self::Element];
|
||||
fn sk_lwe(&self) -> &[Self::Element];
|
||||
fn sk_rlwe(&self) -> Vec<Self::Element>;
|
||||
fn sk_lwe(&self) -> Vec<Self::Element>;
|
||||
}
|
||||
|
||||
trait InteractiveMultiPartyClientKey {
|
||||
pub(crate) trait InteractiveMultiPartyClientKey {
|
||||
type Element;
|
||||
fn sk_rlwe(&self) -> &[Self::Element];
|
||||
fn sk_lwe(&self) -> &[Self::Element];
|
||||
fn sk_rlwe(&self) -> Vec<Self::Element>;
|
||||
fn sk_lwe(&self) -> Vec<Self::Element>;
|
||||
}
|
||||
|
||||
trait NonInteractiveMultiPartyClientKey {
|
||||
pub(crate) trait NonInteractiveMultiPartyClientKey {
|
||||
type Element;
|
||||
fn sk_rlwe(&self) -> &[Self::Element];
|
||||
fn sk_u_rlwe(&self) -> &[Self::Element];
|
||||
fn sk_lwe(&self) -> &[Self::Element];
|
||||
fn sk_rlwe(&self) -> Vec<Self::Element>;
|
||||
fn sk_u_rlwe(&self) -> Vec<Self::Element>;
|
||||
fn sk_lwe(&self) -> Vec<Self::Element>;
|
||||
}
|
||||
|
||||
/// Client key with RLWE and LWE secrets
|
||||
/// Client key
|
||||
///
|
||||
/// Key is used for all parameter varians - Single party, interactive
|
||||
/// multi-party, and non-interactive multi-party. The only stored the main seed
|
||||
/// and seeds of the Rlwe/Lwe secrets are derived at puncturing the seed desired
|
||||
/// number of times.
|
||||
///
|
||||
/// ### Punctures required:
|
||||
///
|
||||
/// Puncture 1 -> Seed of RLWE secret used as main RLWE secret for
|
||||
/// single-party, interactive/non-interactive multi-party
|
||||
///
|
||||
/// Puncture 2 -> Seed of LWE secret used main LWE secret for single-party,
|
||||
/// interactive/non-interactive multi-party
|
||||
///
|
||||
/// Puncture 3 -> Seed of RLWE secret used as `u` in
|
||||
/// interactive/non-interactive multi-party.
|
||||
#[derive(Clone)]
|
||||
pub struct ClientKey {
|
||||
sk_rlwe: RlweSecret,
|
||||
sk_lwe: LweSecret,
|
||||
}
|
||||
|
||||
/// Client key with RLWE and LWE secrets
|
||||
#[derive(Clone)]
|
||||
pub struct ThrowMeAwayKey {
|
||||
sk_rlwe: RlweSecret,
|
||||
sk_u_rlwe: RlweSecret,
|
||||
sk_lwe: LweSecret,
|
||||
pub struct ClientKey<S, E> {
|
||||
seed: S,
|
||||
parameters: BoolParameters<E>,
|
||||
}
|
||||
|
||||
mod impl_ck {
|
||||
use crate::{
|
||||
random::DefaultSecureRng,
|
||||
utils::{fill_random_ternary_secret_with_hamming_weight, puncture_p_rng},
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
// Client key
|
||||
impl ClientKey {
|
||||
pub(in super::super) fn new(sk_rlwe: RlweSecret, sk_lwe: LweSecret) -> Self {
|
||||
Self { sk_rlwe, sk_lwe }
|
||||
}
|
||||
|
||||
pub(in super::super) fn sk_rlwe(&self) -> &RlweSecret {
|
||||
&self.sk_rlwe
|
||||
}
|
||||
|
||||
pub(in super::super) fn sk_lwe(&self) -> &LweSecret {
|
||||
&self.sk_lwe
|
||||
impl<E> ClientKey<[u8; 32], E> {
|
||||
pub(in super::super) fn new(parameters: BoolParameters<E>) -> ClientKey<[u8; 32], E> {
|
||||
let mut rng = DefaultSecureRng::new();
|
||||
let mut seed = [0u8; 32];
|
||||
rng.fill_bytes(&mut seed);
|
||||
Self { seed, parameters }
|
||||
}
|
||||
}
|
||||
|
||||
// Client key
|
||||
impl ThrowMeAwayKey {
|
||||
pub(in super::super) fn new(
|
||||
sk_rlwe: RlweSecret,
|
||||
sk_u_rlwe: RlweSecret,
|
||||
sk_lwe: LweSecret,
|
||||
) -> Self {
|
||||
Self {
|
||||
sk_rlwe,
|
||||
sk_u_rlwe,
|
||||
sk_lwe,
|
||||
impl<E> SinglePartyClientKey for ClientKey<[u8; 32], E> {
|
||||
type Element = i32;
|
||||
fn sk_lwe(&self) -> Vec<Self::Element> {
|
||||
let mut p_rng = DefaultSecureRng::new_seeded(self.seed);
|
||||
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,
|
||||
);
|
||||
out
|
||||
}
|
||||
fn sk_rlwe(&self) -> Vec<Self::Element> {
|
||||
let mut p_rng = DefaultSecureRng::new_seeded(self.seed);
|
||||
let rlwe_seed = puncture_p_rng::<[u8; 32], DefaultSecureRng>(&mut p_rng, 1);
|
||||
|
||||
let mut rlwe_prng = DefaultSecureRng::new_seeded(rlwe_seed);
|
||||
let mut out = vec![0i32; self.parameters.rlwe_n().0];
|
||||
fill_random_ternary_secret_with_hamming_weight(
|
||||
&mut out,
|
||||
self.parameters.rlwe_n().0 >> 1,
|
||||
&mut rlwe_prng,
|
||||
);
|
||||
out
|
||||
}
|
||||
}
|
||||
|
||||
pub(in super::super) fn sk_rlwe(&self) -> &RlweSecret {
|
||||
&self.sk_rlwe
|
||||
impl<E> InteractiveMultiPartyClientKey for ClientKey<[u8; 32], E> {
|
||||
type Element = i32;
|
||||
fn sk_lwe(&self) -> Vec<Self::Element> {
|
||||
<Self as SinglePartyClientKey>::sk_lwe(&self)
|
||||
}
|
||||
|
||||
pub(in super::super) fn sk_u_rlwe(&self) -> &RlweSecret {
|
||||
&self.sk_u_rlwe
|
||||
}
|
||||
|
||||
pub(in super::super) fn sk_lwe(&self) -> &LweSecret {
|
||||
&self.sk_lwe
|
||||
fn sk_rlwe(&self) -> Vec<Self::Element> {
|
||||
<Self as SinglePartyClientKey>::sk_rlwe(&self)
|
||||
}
|
||||
}
|
||||
|
||||
impl Encryptor<bool, Vec<u64>> for ClientKey {
|
||||
fn encrypt(&self, m: &bool) -> Vec<u64> {
|
||||
BoolEvaluator::with_local(|e| e.sk_encrypt(*m, self))
|
||||
impl<E> NonInteractiveMultiPartyClientKey for ClientKey<[u8; 32], E> {
|
||||
type Element = i32;
|
||||
fn sk_lwe(&self) -> Vec<Self::Element> {
|
||||
<Self as SinglePartyClientKey>::sk_lwe(&self)
|
||||
}
|
||||
fn sk_rlwe(&self) -> Vec<Self::Element> {
|
||||
<Self as SinglePartyClientKey>::sk_rlwe(&self)
|
||||
}
|
||||
fn sk_u_rlwe(&self) -> Vec<Self::Element> {
|
||||
let mut p_rng = DefaultSecureRng::new_seeded(self.seed);
|
||||
let rlwe_seed = puncture_p_rng::<[u8; 32], DefaultSecureRng>(&mut p_rng, 3);
|
||||
|
||||
impl Decryptor<bool, Vec<u64>> for ClientKey {
|
||||
fn decrypt(&self, c: &Vec<u64>) -> bool {
|
||||
BoolEvaluator::with_local(|e| e.sk_decrypt(c, self))
|
||||
}
|
||||
}
|
||||
|
||||
impl MultiPartyDecryptor<bool, Vec<u64>> for ClientKey {
|
||||
type DecryptionShare = u64;
|
||||
|
||||
fn gen_decryption_share(&self, c: &Vec<u64>) -> Self::DecryptionShare {
|
||||
BoolEvaluator::with_local(|e| e.multi_party_decryption_share(c, &self))
|
||||
}
|
||||
|
||||
fn aggregate_decryption_shares(
|
||||
&self,
|
||||
c: &Vec<u64>,
|
||||
shares: &[Self::DecryptionShare],
|
||||
) -> bool {
|
||||
BoolEvaluator::with_local(|e| e.multi_party_decrypt(shares, c))
|
||||
let mut rlwe_prng = DefaultSecureRng::new_seeded(rlwe_seed);
|
||||
let mut out = vec![0i32; self.parameters.rlwe_n().0];
|
||||
fill_random_ternary_secret_with_hamming_weight(
|
||||
&mut out,
|
||||
self.parameters.rlwe_n().0 >> 1,
|
||||
&mut rlwe_prng,
|
||||
);
|
||||
out
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,18 +153,6 @@ pub(super) mod impl_pk {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Rng, ModOp> Encryptor<bool, Vec<u64>> for PublicKey<Vec<Vec<u64>>, Rng, ModOp> {
|
||||
fn encrypt(&self, m: &bool) -> Vec<u64> {
|
||||
BoolEvaluator::with_local(|e| e.pk_encrypt(&self.key, *m))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Rng, ModOp> Encryptor<[bool], Vec<Vec<u64>>> for PublicKey<Vec<Vec<u64>>, Rng, ModOp> {
|
||||
fn encrypt(&self, m: &[bool]) -> Vec<Vec<u64>> {
|
||||
BoolEvaluator::with_local(|e| e.pk_encrypt_batched(&self.key, m))
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
M: MatrixMut + MatrixEntity,
|
||||
Rng: NewWithSeed
|
||||
@@ -456,8 +462,6 @@ pub(super) mod impl_server_key_eval_domain {
|
||||
use itertools::{izip, Itertools};
|
||||
|
||||
use crate::{
|
||||
backend::Modulus,
|
||||
bool::{NonInteractiveMultiPartyCrs, SeededNonInteractiveMultiPartyServerKey},
|
||||
ntt::{Ntt, NttInit},
|
||||
pbs::PbsKey,
|
||||
};
|
||||
@@ -736,7 +740,7 @@ pub(crate) struct NonInteractiveServerKeyEvaluationDomain<M, P, R, N> {
|
||||
pub(super) mod impl_non_interactive_server_key_eval_domain {
|
||||
use itertools::{izip, Itertools};
|
||||
|
||||
use crate::{bool::NonInteractiveMultiPartyCrs, random::RandomFill, Ntt, NttInit};
|
||||
use crate::{bool::evaluator::NonInteractiveMultiPartyCrs, random::RandomFill, Ntt, NttInit};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
pub(crate) mod evaluator;
|
||||
pub(crate) mod keys;
|
||||
mod keys;
|
||||
mod mp_api;
|
||||
mod ni_mp_api;
|
||||
mod noise;
|
||||
pub(crate) mod parameters;
|
||||
|
||||
pub use mp_api::*;
|
||||
pub(crate) use keys::PublicKey;
|
||||
|
||||
pub type FheBool = Vec<u64>;
|
||||
|
||||
use std::{cell::RefCell, sync::OnceLock};
|
||||
|
||||
use evaluator::*;
|
||||
use keys::*;
|
||||
use parameters::*;
|
||||
pub use mp_api::*;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::{cell::RefCell, sync::OnceLock};
|
||||
|
||||
use crate::{
|
||||
backend::{ModularOpsU64, ModulusPowerOf2},
|
||||
ntt::NttBackendU64,
|
||||
@@ -5,7 +7,7 @@ use crate::{
|
||||
utils::{Global, WithLocal},
|
||||
};
|
||||
|
||||
use super::*;
|
||||
use super::{evaluator::*, keys::*, parameters::*};
|
||||
|
||||
thread_local! {
|
||||
static BOOL_EVALUATOR: RefCell<Option<BoolEvaluator<Vec<Vec<u64>>, NttBackendU64, ModularOpsU64<CiphertextModulus<u64>>, ModulusPowerOf2<CiphertextModulus<u64>>, ShoupServerKeyEvaluationDomain<Vec<Vec<u64>>>>>> = RefCell::new(None);
|
||||
@@ -15,6 +17,8 @@ static BOOL_SERVER_KEY: OnceLock<ShoupServerKeyEvaluationDomain<Vec<Vec<u64>>>>
|
||||
|
||||
static MULTI_PARTY_CRS: OnceLock<MultiPartyCrs<[u8; 32]>> = OnceLock::new();
|
||||
|
||||
pub type ClientKey = super::keys::ClientKey<[u8; 32], u64>;
|
||||
|
||||
pub enum ParameterSelector {
|
||||
MultiPartyLessThanOrEqualTo16,
|
||||
}
|
||||
@@ -62,7 +66,7 @@ pub fn gen_mp_keys_phase1(
|
||||
) -> CommonReferenceSeededCollectivePublicKeyShare<Vec<u64>, [u8; 32], BoolParameters<u64>> {
|
||||
let seed = MultiPartyCrs::global().public_key_share_seed::<DefaultSecureRng>();
|
||||
BoolEvaluator::with_local(|e| {
|
||||
let pk_share = e.multi_party_public_key_share(seed, &ck);
|
||||
let pk_share = e.multi_party_public_key_share(seed, ck);
|
||||
pk_share
|
||||
})
|
||||
}
|
||||
@@ -167,3 +171,91 @@ impl Global for RuntimeServerKey {
|
||||
BOOL_SERVER_KEY.get().expect("Server key not set!")
|
||||
}
|
||||
}
|
||||
|
||||
mod impl_enc_dec {
|
||||
use crate::{
|
||||
pbs::{sample_extract, PbsInfo},
|
||||
rgsw::public_key_encrypt_rlwe,
|
||||
Decryptor, Encryptor, Matrix, MatrixEntity, MultiPartyDecryptor, RowEntity,
|
||||
};
|
||||
use num_traits::Zero;
|
||||
|
||||
use super::*;
|
||||
|
||||
type Mat = Vec<Vec<u64>>;
|
||||
|
||||
impl<E> Encryptor<bool, Vec<u64>> for super::super::keys::ClientKey<[u8; 32], E> {
|
||||
fn encrypt(&self, m: &bool) -> Vec<u64> {
|
||||
BoolEvaluator::with_local(|e| e.sk_encrypt(*m, self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> Decryptor<bool, Vec<u64>> for super::super::keys::ClientKey<[u8; 32], E> {
|
||||
fn decrypt(&self, c: &Vec<u64>) -> bool {
|
||||
BoolEvaluator::with_local(|e| e.sk_decrypt(c, self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> MultiPartyDecryptor<bool, <Mat as Matrix>::R>
|
||||
for super::super::keys::ClientKey<[u8; 32], E>
|
||||
{
|
||||
type DecryptionShare = <Mat as Matrix>::MatElement;
|
||||
|
||||
fn gen_decryption_share(&self, c: &<Mat as Matrix>::R) -> Self::DecryptionShare {
|
||||
BoolEvaluator::with_local(|e| e.multi_party_decryption_share(c, self))
|
||||
}
|
||||
|
||||
fn aggregate_decryption_shares(
|
||||
&self,
|
||||
c: &<Mat as Matrix>::R,
|
||||
shares: &[Self::DecryptionShare],
|
||||
) -> bool {
|
||||
BoolEvaluator::with_local(|e| e.multi_party_decrypt(shares, c))
|
||||
}
|
||||
}
|
||||
|
||||
impl<Rng, ModOp> Encryptor<[bool], Mat> for PublicKey<Mat, Rng, ModOp> {
|
||||
fn encrypt(&self, m: &[bool]) -> Mat {
|
||||
BoolEvaluator::with_local(|e| {
|
||||
DefaultSecureRng::with_local_mut(|rng| {
|
||||
let parameters = e.parameters();
|
||||
let mut rlwe_out = <Mat as MatrixEntity>::zeros(2, parameters.rlwe_n().0);
|
||||
assert!(m.len() <= parameters.rlwe_n().0);
|
||||
|
||||
let mut message =
|
||||
vec![<Mat as Matrix>::MatElement::zero(); parameters.rlwe_n().0];
|
||||
m.iter().enumerate().for_each(|(i, v)| {
|
||||
if *v {
|
||||
message[i] = parameters.rlwe_q().true_el()
|
||||
} else {
|
||||
message[i] = parameters.rlwe_q().false_el()
|
||||
}
|
||||
});
|
||||
|
||||
// e.pk_encrypt_batched(self.key(), m)
|
||||
public_key_encrypt_rlwe::<_, _, _, _, i32, _>(
|
||||
&mut rlwe_out,
|
||||
self.key(),
|
||||
&message,
|
||||
e.pbs_info().modop_rlweq(),
|
||||
e.pbs_info().nttop_rlweq(),
|
||||
rng,
|
||||
);
|
||||
rlwe_out
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<Rng, ModOp> Encryptor<bool, <Mat as Matrix>::R> for PublicKey<Mat, Rng, ModOp> {
|
||||
fn encrypt(&self, m: &bool) -> <Mat as Matrix>::R {
|
||||
let m = vec![*m];
|
||||
let rlwe = self.encrypt(m.as_slice());
|
||||
BoolEvaluator::with_local(|e| {
|
||||
let mut lwe = <Mat as Matrix>::R::zeros(e.parameters().rlwe_n().0 + 1);
|
||||
sample_extract(&mut lwe, &rlwe, e.pbs_info().modop_rlweq(), 0);
|
||||
lwe
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
mod impl_enc_dec {
|
||||
use crate::{
|
||||
bool::{
|
||||
evaluator::{BoolEncoding, BoolEvaluator},
|
||||
keys::NonInteractiveMultiPartyClientKey,
|
||||
parameters::CiphertextModulus,
|
||||
},
|
||||
pbs::PbsInfo,
|
||||
random::{DefaultSecureRng, NewWithSeed},
|
||||
rgsw::secret_key_encrypt_rlwe,
|
||||
utils::{TryConvertFrom1, WithLocal},
|
||||
Encryptor, Matrix, RowEntity,
|
||||
};
|
||||
use num_traits::Zero;
|
||||
|
||||
trait SeededCiphertext<M, S> {
|
||||
fn new_with_seed(data: M, seed: S) -> Self;
|
||||
}
|
||||
|
||||
type Mat = Vec<Vec<u64>>;
|
||||
|
||||
impl<K, C> Encryptor<[bool], C> for K
|
||||
where
|
||||
K: NonInteractiveMultiPartyClientKey,
|
||||
C: SeededCiphertext<<Mat as Matrix>::R, <DefaultSecureRng as NewWithSeed>::Seed>,
|
||||
<Mat as Matrix>::R:
|
||||
TryConvertFrom1<[K::Element], CiphertextModulus<<Mat as Matrix>::MatElement>>,
|
||||
{
|
||||
fn encrypt(&self, m: &[bool]) -> C {
|
||||
BoolEvaluator::with_local(|e| {
|
||||
let parameters = e.parameters();
|
||||
assert!(m.len() <= parameters.rlwe_n().0);
|
||||
|
||||
let mut message = vec![<Mat as Matrix>::MatElement::zero(); parameters.rlwe_n().0];
|
||||
m.iter().enumerate().for_each(|(i, v)| {
|
||||
if *v {
|
||||
message[i] = parameters.rlwe_q().true_el()
|
||||
} else {
|
||||
message[i] = parameters.rlwe_q().false_el()
|
||||
}
|
||||
});
|
||||
|
||||
DefaultSecureRng::with_local_mut(|rng| {
|
||||
let mut seed = <DefaultSecureRng as NewWithSeed>::Seed::default();
|
||||
rng.fill_bytes(&mut seed);
|
||||
let mut prng = DefaultSecureRng::new_seeded(seed);
|
||||
|
||||
let mut rlwe_out =
|
||||
<<Mat as Matrix>::R as RowEntity>::zeros(parameters.rlwe_n().0);
|
||||
|
||||
secret_key_encrypt_rlwe(
|
||||
&message,
|
||||
&mut rlwe_out,
|
||||
&self.sk_u_rlwe(),
|
||||
e.pbs_info().modop_rlweq(),
|
||||
e.pbs_info().nttop_rlweq(),
|
||||
&mut prng,
|
||||
rng,
|
||||
);
|
||||
|
||||
C::new_with_seed(rlwe_out, seed)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,19 +2,17 @@ mod test {
|
||||
use itertools::{izip, Itertools};
|
||||
|
||||
use crate::{
|
||||
backend::{ArithmeticOps, ModularOpsU64, Modulus, ModulusPowerOf2},
|
||||
backend::{ModularOpsU64, ModulusPowerOf2},
|
||||
bool::{
|
||||
BoolEncoding, BoolEvaluator, BooleanGates, CiphertextModulus, ClientKey, PublicKey,
|
||||
ServerKeyEvaluationDomain, ShoupServerKeyEvaluationDomain, MP_BOOL_PARAMS,
|
||||
SMALL_MP_BOOL_PARAMS,
|
||||
evaluator::{BoolEncoding, BoolEvaluator, BooleanGates},
|
||||
keys::{
|
||||
InteractiveMultiPartyClientKey, PublicKey, ServerKeyEvaluationDomain,
|
||||
ShoupServerKeyEvaluationDomain,
|
||||
},
|
||||
parameters::{CiphertextModulus, SMALL_MP_BOOL_PARAMS},
|
||||
},
|
||||
lwe::{decrypt_lwe, LweSecret},
|
||||
ntt::NttBackendU64,
|
||||
pbs::PbsInfo,
|
||||
random::DefaultSecureRng,
|
||||
rgsw::RlweSecret,
|
||||
utils::Stats,
|
||||
Ntt, Secret,
|
||||
};
|
||||
|
||||
#[test]
|
||||
@@ -42,30 +40,27 @@ mod test {
|
||||
.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)| {
|
||||
izip!(
|
||||
ideal_rlwe_sk.iter_mut(),
|
||||
InteractiveMultiPartyClientKey::sk_rlwe(k)
|
||||
)
|
||||
.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)| {
|
||||
izip!(
|
||||
ideal_lwe_sk.iter_mut(),
|
||||
InteractiveMultiPartyClientKey::sk_lwe(k)
|
||||
)
|
||||
.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()
|
||||
|
||||
515
src/noise.rs
515
src/noise.rs
@@ -1,292 +1,297 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use itertools::{izip, Itertools};
|
||||
use num_traits::zero;
|
||||
use rand::{thread_rng, Rng};
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use itertools::{izip, Itertools};
|
||||
// use num_traits::zero;
|
||||
// use rand::{thread_rng, Rng};
|
||||
|
||||
use crate::{
|
||||
bool::keys::ClientKey,
|
||||
ntt,
|
||||
random::{
|
||||
DefaultSecureRng, RandomFill, RandomFillGaussianInModulus, RandomFillUniformInModulus,
|
||||
},
|
||||
utils::{
|
||||
fill_random_ternary_secret_with_hamming_weight, generate_prime, Stats, TryConvertFrom1,
|
||||
},
|
||||
ArithmeticOps, Decomposer, DefaultDecomposer, ModInit, ModularOpsU64, Ntt, NttBackendU64,
|
||||
NttInit, VectorOps,
|
||||
};
|
||||
// use crate::{
|
||||
// bool::keys::ClientKey,
|
||||
// ntt,
|
||||
// random::{
|
||||
// DefaultSecureRng, RandomFill, RandomFillGaussianInModulus,
|
||||
// RandomFillUniformInModulus, },
|
||||
// utils::{
|
||||
// fill_random_ternary_secret_with_hamming_weight, generate_prime,
|
||||
// Stats, TryConvertFrom1, },
|
||||
// ArithmeticOps, Decomposer, DefaultDecomposer, ModInit, ModularOpsU64,
|
||||
// Ntt, NttBackendU64, NttInit, VectorOps,
|
||||
// };
|
||||
|
||||
#[test]
|
||||
fn non_interactive_multi_party() {
|
||||
let logq = 56;
|
||||
let ring_size = 1usize << 11;
|
||||
let q = generate_prime(logq, 2 * ring_size as u64, 1 << logq).unwrap();
|
||||
let logb = 1;
|
||||
let d = 56;
|
||||
let decomposer = DefaultDecomposer::new(q, logb, d);
|
||||
let gadget_vec = decomposer.gadget_vector();
|
||||
let mut rng = DefaultSecureRng::new();
|
||||
// #[test]
|
||||
// fn non_interactive_multi_party() {
|
||||
// let logq = 56;
|
||||
// let ring_size = 1usize << 11;
|
||||
// let q = generate_prime(logq, 2 * ring_size as u64, 1 <<
|
||||
// logq).unwrap(); let logb = 1;
|
||||
// let d = 56;
|
||||
// let decomposer = DefaultDecomposer::new(q, logb, d);
|
||||
// let gadget_vec = decomposer.gadget_vector();
|
||||
// let mut rng = DefaultSecureRng::new();
|
||||
|
||||
let modop = ModularOpsU64::new(q);
|
||||
let nttop = NttBackendU64::new(&q, ring_size);
|
||||
// let modop = ModularOpsU64::new(q);
|
||||
// let nttop = NttBackendU64::new(&q, ring_size);
|
||||
|
||||
let no_of_parties = 16;
|
||||
let client_secrets = (0..no_of_parties)
|
||||
.into_iter()
|
||||
.map(|_| {
|
||||
let mut sk = vec![0i64; ring_size];
|
||||
fill_random_ternary_secret_with_hamming_weight(&mut sk, ring_size >> 1, &mut rng);
|
||||
sk
|
||||
})
|
||||
.collect_vec();
|
||||
// let no_of_parties = 16;
|
||||
// let client_secrets = (0..no_of_parties)
|
||||
// .into_iter()
|
||||
// .map(|_| {
|
||||
// let mut sk = vec![0i64; ring_size];
|
||||
// fill_random_ternary_secret_with_hamming_weight(&mut sk,
|
||||
// ring_size >> 1, &mut rng); sk
|
||||
// })
|
||||
// .collect_vec();
|
||||
|
||||
let mut s_ideal = vec![0i64; ring_size];
|
||||
client_secrets.iter().for_each(|s| {
|
||||
izip!(s_ideal.iter_mut(), s.iter()).for_each(|(add_to, v)| {
|
||||
*add_to = *add_to + *v;
|
||||
});
|
||||
});
|
||||
// let mut s_ideal = vec![0i64; ring_size];
|
||||
// client_secrets.iter().for_each(|s| {
|
||||
// izip!(s_ideal.iter_mut(), s.iter()).for_each(|(add_to, v)| {
|
||||
// *add_to = *add_to + *v;
|
||||
// });
|
||||
// });
|
||||
|
||||
let sk_poly_ideal = Vec::<u64>::try_convert_from(s_ideal.as_slice(), &q);
|
||||
let mut sk_poly_ideal_eval = sk_poly_ideal.clone();
|
||||
nttop.forward(&mut sk_poly_ideal_eval);
|
||||
// let sk_poly_ideal = Vec::<u64>::try_convert_from(s_ideal.as_slice(),
|
||||
// &q); let mut sk_poly_ideal_eval = sk_poly_ideal.clone();
|
||||
// nttop.forward(&mut sk_poly_ideal_eval);
|
||||
|
||||
let mut ksk_seed = [0u8; 32];
|
||||
rng.fill_bytes(&mut ksk_seed);
|
||||
// let mut ksk_seed = [0u8; 32];
|
||||
// rng.fill_bytes(&mut ksk_seed);
|
||||
|
||||
// zero encryptions for each party for ksk(u)
|
||||
let client_zero_encs = {
|
||||
client_secrets
|
||||
.iter()
|
||||
.map(|sk| {
|
||||
let sk_poly = Vec::<u64>::try_convert_from(sk.as_slice(), &q);
|
||||
let mut sk_poly_eval = sk_poly.clone();
|
||||
nttop.forward(sk_poly_eval.as_mut_slice());
|
||||
// // zero encryptions for each party for ksk(u)
|
||||
// let client_zero_encs = {
|
||||
// client_secrets
|
||||
// .iter()
|
||||
// .map(|sk| {
|
||||
// let sk_poly = Vec::<u64>::try_convert_from(sk.as_slice(),
|
||||
// &q); let mut sk_poly_eval = sk_poly.clone();
|
||||
// nttop.forward(sk_poly_eval.as_mut_slice());
|
||||
|
||||
let mut zero_encs =
|
||||
vec![vec![0u64; ring_size]; decomposer.decomposition_count()];
|
||||
let mut ksk_prng = DefaultSecureRng::new_seeded(ksk_seed);
|
||||
zero_encs.iter_mut().for_each(|out| {
|
||||
RandomFillUniformInModulus::random_fill(
|
||||
&mut ksk_prng,
|
||||
&q,
|
||||
out.as_mut_slice(),
|
||||
);
|
||||
nttop.forward(out.as_mut_slice());
|
||||
modop.elwise_mul_mut(out.as_mut_slice(), &sk_poly_eval);
|
||||
nttop.backward(out.as_mut_slice());
|
||||
// let mut zero_encs =
|
||||
// vec![vec![0u64; ring_size];
|
||||
// decomposer.decomposition_count()]; let mut ksk_prng =
|
||||
// DefaultSecureRng::new_seeded(ksk_seed);
|
||||
// zero_encs.iter_mut().for_each(|out| {
|
||||
// RandomFillUniformInModulus::random_fill( &mut
|
||||
// ksk_prng, &q,
|
||||
// out.as_mut_slice(),
|
||||
// );
|
||||
// nttop.forward(out.as_mut_slice());
|
||||
// modop.elwise_mul_mut(out.as_mut_slice(),
|
||||
// &sk_poly_eval); nttop.backward(out.as_mut_slice());
|
||||
|
||||
let mut error = vec![0u64; ring_size];
|
||||
RandomFillGaussianInModulus::random_fill(&mut rng, &q, &mut error);
|
||||
// let mut error = vec![0u64; ring_size];
|
||||
// RandomFillGaussianInModulus::random_fill(&mut rng,
|
||||
// &q, &mut error);
|
||||
|
||||
modop.elwise_add_mut(out.as_mut_slice(), &error);
|
||||
});
|
||||
zero_encs
|
||||
})
|
||||
.collect_vec()
|
||||
};
|
||||
// modop.elwise_add_mut(out.as_mut_slice(), &error);
|
||||
// });
|
||||
// zero_encs
|
||||
// })
|
||||
// .collect_vec()
|
||||
// };
|
||||
|
||||
// main values
|
||||
let main_a = {
|
||||
let mut a = vec![0u64; ring_size];
|
||||
RandomFillUniformInModulus::random_fill(&mut rng, &q, &mut a);
|
||||
a
|
||||
};
|
||||
let main_m = {
|
||||
let mut main_m = vec![0u64; ring_size];
|
||||
RandomFillUniformInModulus::random_fill(&mut rng, &q, &mut main_m);
|
||||
main_m
|
||||
};
|
||||
// // main values
|
||||
// let main_a = {
|
||||
// let mut a = vec![0u64; ring_size];
|
||||
// RandomFillUniformInModulus::random_fill(&mut rng, &q, &mut a);
|
||||
// a
|
||||
// };
|
||||
// let main_m = {
|
||||
// let mut main_m = vec![0u64; ring_size];
|
||||
// RandomFillUniformInModulus::random_fill(&mut rng, &q, &mut
|
||||
// main_m); main_m
|
||||
// };
|
||||
|
||||
let mut main_u = vec![0i64; ring_size];
|
||||
fill_random_ternary_secret_with_hamming_weight(&mut main_u, ring_size >> 1, &mut rng);
|
||||
let u_main_poly = Vec::<u64>::try_convert_from(main_u.as_slice(), &q);
|
||||
let mut u_main_poly_eval = u_main_poly.clone();
|
||||
nttop.forward(u_main_poly_eval.as_mut_slice());
|
||||
// let mut main_u = vec![0i64; ring_size];
|
||||
// fill_random_ternary_secret_with_hamming_weight(&mut main_u, ring_size
|
||||
// >> 1, &mut rng); let u_main_poly =
|
||||
// Vec::<u64>::try_convert_from(main_u.as_slice(), &q); let mut
|
||||
// u_main_poly_eval = u_main_poly.clone(); nttop.
|
||||
// forward(u_main_poly_eval.as_mut_slice());
|
||||
|
||||
// party 0
|
||||
let (mut party0_ksk_u, mut rlwe_main_m_parta) = {
|
||||
// party 0's secret
|
||||
let sk = client_secrets[0].clone();
|
||||
let sk_poly = Vec::<u64>::try_convert_from(sk.as_slice(), &q);
|
||||
let mut sk_poly_eval = sk_poly.clone();
|
||||
nttop.forward(sk_poly_eval.as_mut_slice());
|
||||
// // party 0
|
||||
// let (mut party0_ksk_u, mut rlwe_main_m_parta) = {
|
||||
// // party 0's secret
|
||||
// let sk = client_secrets[0].clone();
|
||||
// let sk_poly = Vec::<u64>::try_convert_from(sk.as_slice(), &q);
|
||||
// let mut sk_poly_eval = sk_poly.clone();
|
||||
// nttop.forward(sk_poly_eval.as_mut_slice());
|
||||
|
||||
// `main_a*u + main_m` with ephemeral key u
|
||||
let mut rlwe_main_m = main_a.clone();
|
||||
nttop.forward(&mut rlwe_main_m);
|
||||
modop.elwise_mul_mut(&mut rlwe_main_m, &u_main_poly_eval);
|
||||
nttop.backward(&mut rlwe_main_m);
|
||||
let mut error = vec![0u64; ring_size];
|
||||
RandomFillGaussianInModulus::random_fill(&mut rng, &q, &mut error);
|
||||
modop.elwise_add_mut(&mut rlwe_main_m, &error);
|
||||
modop.elwise_add_mut(&mut rlwe_main_m, &main_m);
|
||||
// // `main_a*u + main_m` with ephemeral key u
|
||||
// let mut rlwe_main_m = main_a.clone();
|
||||
// nttop.forward(&mut rlwe_main_m);
|
||||
// modop.elwise_mul_mut(&mut rlwe_main_m, &u_main_poly_eval);
|
||||
// nttop.backward(&mut rlwe_main_m);
|
||||
// let mut error = vec![0u64; ring_size];
|
||||
// RandomFillGaussianInModulus::random_fill(&mut rng, &q, &mut
|
||||
// error); modop.elwise_add_mut(&mut rlwe_main_m, &error);
|
||||
// modop.elwise_add_mut(&mut rlwe_main_m, &main_m);
|
||||
|
||||
// Generate KSK(u)
|
||||
let mut ksk_prng = DefaultSecureRng::new_seeded(ksk_seed);
|
||||
let mut ksk_u = vec![vec![0u64; ring_size]; 2 * decomposer.decomposition_count()];
|
||||
let (ksk_u_a, ksk_u_b) = ksk_u.split_at_mut(decomposer.decomposition_count());
|
||||
izip!(ksk_u_b.iter_mut(), ksk_u_a.iter_mut(), gadget_vec.iter()).for_each(
|
||||
|(row_b, row_a, beta_i)| {
|
||||
// sample a
|
||||
RandomFillUniformInModulus::random_fill(&mut ksk_prng, &q, row_a.as_mut());
|
||||
// // Generate KSK(u)
|
||||
// let mut ksk_prng = DefaultSecureRng::new_seeded(ksk_seed);
|
||||
// let mut ksk_u = vec![vec![0u64; ring_size]; 2 *
|
||||
// decomposer.decomposition_count()]; let (ksk_u_a, ksk_u_b) =
|
||||
// ksk_u.split_at_mut(decomposer.decomposition_count());
|
||||
// izip!(ksk_u_b.iter_mut(), ksk_u_a.iter_mut(), gadget_vec.iter()).for_each( |(row_b, row_a, beta_i)| {
|
||||
// // sample a
|
||||
// RandomFillUniformInModulus::random_fill(&mut ksk_prng,
|
||||
// &q, row_a.as_mut());
|
||||
|
||||
// s_i * a
|
||||
let mut s_i_a = row_a.clone();
|
||||
nttop.forward(&mut s_i_a);
|
||||
modop.elwise_mul_mut(&mut s_i_a, &sk_poly_eval);
|
||||
nttop.backward(&mut s_i_a);
|
||||
// // s_i * a
|
||||
// let mut s_i_a = row_a.clone();
|
||||
// nttop.forward(&mut s_i_a);
|
||||
// modop.elwise_mul_mut(&mut s_i_a, &sk_poly_eval);
|
||||
// nttop.backward(&mut s_i_a);
|
||||
|
||||
// \beta * u
|
||||
let mut beta_u = u_main_poly.clone();
|
||||
modop.elwise_scalar_mul_mut(beta_u.as_mut_slice(), beta_i);
|
||||
// // \beta * u
|
||||
// let mut beta_u = u_main_poly.clone();
|
||||
// modop.elwise_scalar_mul_mut(beta_u.as_mut_slice(),
|
||||
// beta_i);
|
||||
|
||||
// e
|
||||
RandomFillGaussianInModulus::random_fill(&mut rng, &q, row_b.as_mut_slice());
|
||||
// e + \beta * u
|
||||
modop.elwise_add_mut(row_b.as_mut_slice(), &beta_u);
|
||||
// // e
|
||||
// RandomFillGaussianInModulus::random_fill(&mut rng, &q,
|
||||
// row_b.as_mut_slice()); // e + \beta * u
|
||||
// modop.elwise_add_mut(row_b.as_mut_slice(), &beta_u);
|
||||
|
||||
// b = e + \beta * u + a * s_i
|
||||
modop.elwise_add_mut(row_b.as_mut_slice(), &s_i_a);
|
||||
},
|
||||
);
|
||||
// // b = e + \beta * u + a * s_i
|
||||
// modop.elwise_add_mut(row_b.as_mut_slice(), &s_i_a);
|
||||
// },
|
||||
// );
|
||||
|
||||
// send ksk u from s_0 to s_{ideal}
|
||||
ksk_u_b.iter_mut().enumerate().for_each(|(index, out_b)| {
|
||||
// note: skip zero encryption of party 0
|
||||
client_zero_encs.iter().skip(1).for_each(|encs| {
|
||||
modop.elwise_add_mut(out_b, &encs[index]);
|
||||
});
|
||||
});
|
||||
// // send ksk u from s_0 to s_{ideal}
|
||||
// ksk_u_b.iter_mut().enumerate().for_each(|(index, out_b)| {
|
||||
// // note: skip zero encryption of party 0
|
||||
// client_zero_encs.iter().skip(1).for_each(|encs| {
|
||||
// modop.elwise_add_mut(out_b, &encs[index]);
|
||||
// });
|
||||
// });
|
||||
|
||||
// // put ksk in fourier domain
|
||||
// ksk_u
|
||||
// .iter_mut()
|
||||
// .for_each(|r| nttop.forward(r.as_mut_slice()));
|
||||
(ksk_u, rlwe_main_m)
|
||||
};
|
||||
// // // put ksk in fourier domain
|
||||
// // ksk_u
|
||||
// // .iter_mut()
|
||||
// // .for_each(|r| nttop.forward(r.as_mut_slice()));
|
||||
// (ksk_u, rlwe_main_m)
|
||||
// };
|
||||
|
||||
// Check ksk_u is correct
|
||||
// {
|
||||
// let (ksk_a, ksk_b) =
|
||||
// party0_ksk_u.split_at_mut(decomposer.decomposition_count());
|
||||
// izip!(
|
||||
// ksk_a.iter(),
|
||||
// ksk_b.iter(),
|
||||
// decomposer.gadget_vector().iter()
|
||||
// )
|
||||
// .for_each(|(row_a, row_b, beta_i)| {
|
||||
// // a * s
|
||||
// let mut sa = row_a.clone();
|
||||
// nttop.forward(&mut sa);
|
||||
// modop.elwise_mul_mut(&mut sa, &sk_poly_ideal_eval);
|
||||
// nttop.backward(&mut sa);
|
||||
// // Check ksk_u is correct
|
||||
// // {
|
||||
// // let (ksk_a, ksk_b) =
|
||||
// // party0_ksk_u.split_at_mut(decomposer.decomposition_count());
|
||||
// // izip!(
|
||||
// // ksk_a.iter(),
|
||||
// // ksk_b.iter(),
|
||||
// // decomposer.gadget_vector().iter()
|
||||
// // )
|
||||
// // .for_each(|(row_a, row_b, beta_i)| {
|
||||
// // // a * s
|
||||
// // let mut sa = row_a.clone();
|
||||
// // nttop.forward(&mut sa);
|
||||
// // modop.elwise_mul_mut(&mut sa, &sk_poly_ideal_eval);
|
||||
// // nttop.backward(&mut sa);
|
||||
|
||||
// // b - a*s
|
||||
// let mut out = sa;
|
||||
// modop.elwise_neg_mut(&mut out);
|
||||
// modop.elwise_add_mut(&mut out, row_b);
|
||||
// // // b - a*s
|
||||
// // let mut out = sa;
|
||||
// // modop.elwise_neg_mut(&mut out);
|
||||
// // modop.elwise_add_mut(&mut out, row_b);
|
||||
|
||||
// // beta * u
|
||||
// let mut expected = u_main_poly.clone();
|
||||
// modop.elwise_scalar_mul_mut(&mut expected, beta_i);
|
||||
// assert_eq!(expected, out);
|
||||
// });
|
||||
// }
|
||||
// // // beta * u
|
||||
// // let mut expected = u_main_poly.clone();
|
||||
// // modop.elwise_scalar_mul_mut(&mut expected, beta_i);
|
||||
// // assert_eq!(expected, out);
|
||||
// // });
|
||||
// // }
|
||||
|
||||
// RLWE(0) = main_a * s + e = \sum main_a*s_i + e_i
|
||||
let rlwe_to_switch = {
|
||||
let mut sum = vec![0u64; ring_size];
|
||||
client_secrets.iter().for_each(|sk| {
|
||||
let sk_poly = Vec::<u64>::try_convert_from(sk.as_slice(), &q);
|
||||
let mut sk_poly_eval = sk_poly.clone();
|
||||
nttop.forward(sk_poly_eval.as_mut_slice());
|
||||
// // RLWE(0) = main_a * s + e = \sum main_a*s_i + e_i
|
||||
// let rlwe_to_switch = {
|
||||
// let mut sum = vec![0u64; ring_size];
|
||||
// client_secrets.iter().for_each(|sk| {
|
||||
// let sk_poly = Vec::<u64>::try_convert_from(sk.as_slice(),
|
||||
// &q); let mut sk_poly_eval = sk_poly.clone();
|
||||
// nttop.forward(sk_poly_eval.as_mut_slice());
|
||||
|
||||
// a * s
|
||||
let mut rlwe = main_a.clone();
|
||||
nttop.forward(&mut rlwe);
|
||||
modop.elwise_mul_mut(rlwe.as_mut_slice(), &sk_poly_eval);
|
||||
nttop.backward(&mut rlwe);
|
||||
// a * s + e
|
||||
let mut error = vec![0u64; ring_size];
|
||||
RandomFillGaussianInModulus::random_fill(&mut rng, &q, &mut error);
|
||||
modop.elwise_add_mut(&mut rlwe, &error);
|
||||
// // a * s
|
||||
// let mut rlwe = main_a.clone();
|
||||
// nttop.forward(&mut rlwe);
|
||||
// modop.elwise_mul_mut(rlwe.as_mut_slice(), &sk_poly_eval);
|
||||
// nttop.backward(&mut rlwe);
|
||||
// // a * s + e
|
||||
// let mut error = vec![0u64; ring_size];
|
||||
// RandomFillGaussianInModulus::random_fill(&mut rng, &q, &mut
|
||||
// error); modop.elwise_add_mut(&mut rlwe, &error);
|
||||
|
||||
modop.elwise_add_mut(&mut sum, &rlwe);
|
||||
});
|
||||
sum
|
||||
};
|
||||
// {
|
||||
// let mut tmp = main_a.clone();
|
||||
// nttop.forward(&mut tmp);
|
||||
// modop.elwise_mul_mut(&mut tmp, &sk_poly_ideal_eval);
|
||||
// nttop.backward(&mut tmp);
|
||||
// assert_eq!(&rlwe_to_switch, &tmp);
|
||||
// }
|
||||
// modop.elwise_add_mut(&mut sum, &rlwe);
|
||||
// });
|
||||
// sum
|
||||
// };
|
||||
// // {
|
||||
// // let mut tmp = main_a.clone();
|
||||
// // nttop.forward(&mut tmp);
|
||||
// // modop.elwise_mul_mut(&mut tmp, &sk_poly_ideal_eval);
|
||||
// // nttop.backward(&mut tmp);
|
||||
// // assert_eq!(&rlwe_to_switch, &tmp);
|
||||
// // }
|
||||
|
||||
// Key switch \sum decomp<RLWE(0)> * KSK(i)
|
||||
let mut decomp_rlwe = vec![vec![0u64; ring_size]; decomposer.decomposition_count()];
|
||||
rlwe_to_switch.iter().enumerate().for_each(|(ri, el)| {
|
||||
decomposer
|
||||
.decompose_iter(el)
|
||||
.enumerate()
|
||||
.for_each(|(j, d_el)| {
|
||||
decomp_rlwe[j][ri] = d_el;
|
||||
});
|
||||
});
|
||||
// // Key switch \sum decomp<RLWE(0)> * KSK(i)
|
||||
// let mut decomp_rlwe = vec![vec![0u64; ring_size];
|
||||
// decomposer.decomposition_count()]; rlwe_to_switch.iter().enumerate().
|
||||
// for_each(|(ri, el)| { decomposer
|
||||
// .decompose_iter(el)
|
||||
// .enumerate()
|
||||
// .for_each(|(j, d_el)| {
|
||||
// decomp_rlwe[j][ri] = d_el;
|
||||
// });
|
||||
// });
|
||||
|
||||
// put ksk_u and decomp<RLWE(main_a*s_ideal + e)> in fourier domain
|
||||
decomp_rlwe
|
||||
.iter_mut()
|
||||
.for_each(|r| nttop.forward(r.as_mut_slice()));
|
||||
party0_ksk_u
|
||||
.iter_mut()
|
||||
.for_each(|r| nttop.forward(r.as_mut_slice()));
|
||||
// // put ksk_u and decomp<RLWE(main_a*s_ideal + e)> in fourier domain
|
||||
// decomp_rlwe
|
||||
// .iter_mut()
|
||||
// .for_each(|r| nttop.forward(r.as_mut_slice()));
|
||||
// party0_ksk_u
|
||||
// .iter_mut()
|
||||
// .for_each(|r| nttop.forward(r.as_mut_slice()));
|
||||
|
||||
let (ksk_u_a, ksk_u_b) = party0_ksk_u.split_at(decomposer.decomposition_count());
|
||||
let mut rlwe_main_m_partb_eval = vec![vec![0u64; ring_size]; 2];
|
||||
izip!(decomp_rlwe.iter(), ksk_u_a.iter(), ksk_u_b.iter()).for_each(|(o, a, b)| {
|
||||
// A part
|
||||
// rlwe[0] += o*a
|
||||
izip!(rlwe_main_m_partb_eval[0].iter_mut(), o.iter(), a.iter()).for_each(
|
||||
|(r, o, a)| {
|
||||
*r = modop.add(r, &modop.mul(o, a));
|
||||
},
|
||||
);
|
||||
// let (ksk_u_a, ksk_u_b) =
|
||||
// party0_ksk_u.split_at(decomposer.decomposition_count()); let mut
|
||||
// rlwe_main_m_partb_eval = vec![vec![0u64; ring_size]; 2]; izip!
|
||||
// (decomp_rlwe.iter(), ksk_u_a.iter(), ksk_u_b.iter()).for_each(|(o, a, b)| {
|
||||
// // A part
|
||||
// // rlwe[0] += o*a
|
||||
// izip!(rlwe_main_m_partb_eval[0].iter_mut(), o.iter(),
|
||||
// a.iter()).for_each( |(r, o, a)| {
|
||||
// *r = modop.add(r, &modop.mul(o, a));
|
||||
// },
|
||||
// );
|
||||
|
||||
// B part
|
||||
// rlwe[1] += o*b
|
||||
izip!(rlwe_main_m_partb_eval[1].iter_mut(), o.iter(), b.iter()).for_each(
|
||||
|(r, o, b)| {
|
||||
*r = modop.add(r, &modop.mul(o, b));
|
||||
},
|
||||
);
|
||||
});
|
||||
// // B part
|
||||
// // rlwe[1] += o*b
|
||||
// izip!(rlwe_main_m_partb_eval[1].iter_mut(), o.iter(),
|
||||
// b.iter()).for_each( |(r, o, b)| {
|
||||
// *r = modop.add(r, &modop.mul(o, b));
|
||||
// },
|
||||
// );
|
||||
// });
|
||||
|
||||
// construct RLWE_{s_{ideal}}(-sm)
|
||||
nttop.forward(rlwe_main_m_parta.as_mut_slice());
|
||||
modop.elwise_add_mut(&mut rlwe_main_m_partb_eval[0], &rlwe_main_m_parta);
|
||||
let rlwe_main_m_eval = rlwe_main_m_partb_eval;
|
||||
// // construct RLWE_{s_{ideal}}(-sm)
|
||||
// nttop.forward(rlwe_main_m_parta.as_mut_slice());
|
||||
// modop.elwise_add_mut(&mut rlwe_main_m_partb_eval[0],
|
||||
// &rlwe_main_m_parta); let rlwe_main_m_eval = rlwe_main_m_partb_eval;
|
||||
|
||||
// decrypt RLWE_{s_{ideal}}(m) and check
|
||||
let mut neg_s_m_main_out = rlwe_main_m_eval[0].clone();
|
||||
modop.elwise_mul_mut(&mut neg_s_m_main_out, &sk_poly_ideal_eval);
|
||||
modop.elwise_neg_mut(&mut neg_s_m_main_out);
|
||||
modop.elwise_add_mut(&mut neg_s_m_main_out, &rlwe_main_m_eval[1]);
|
||||
nttop.backward(&mut neg_s_m_main_out);
|
||||
// // decrypt RLWE_{s_{ideal}}(m) and check
|
||||
// let mut neg_s_m_main_out = rlwe_main_m_eval[0].clone();
|
||||
// modop.elwise_mul_mut(&mut neg_s_m_main_out, &sk_poly_ideal_eval);
|
||||
// modop.elwise_neg_mut(&mut neg_s_m_main_out);
|
||||
// modop.elwise_add_mut(&mut neg_s_m_main_out, &rlwe_main_m_eval[1]);
|
||||
// nttop.backward(&mut neg_s_m_main_out);
|
||||
|
||||
let mut neg_s_main_m = main_m.clone();
|
||||
nttop.forward(&mut neg_s_main_m);
|
||||
modop.elwise_mul_mut(&mut neg_s_main_m, &sk_poly_ideal_eval);
|
||||
modop.elwise_neg_mut(&mut neg_s_main_m);
|
||||
nttop.backward(&mut neg_s_main_m);
|
||||
// let mut neg_s_main_m = main_m.clone();
|
||||
// nttop.forward(&mut neg_s_main_m);
|
||||
// modop.elwise_mul_mut(&mut neg_s_main_m, &sk_poly_ideal_eval);
|
||||
// modop.elwise_neg_mut(&mut neg_s_main_m);
|
||||
// nttop.backward(&mut neg_s_main_m);
|
||||
|
||||
let mut diff = neg_s_m_main_out.clone();
|
||||
modop.elwise_sub_mut(&mut diff, &neg_s_main_m);
|
||||
// let mut diff = neg_s_m_main_out.clone();
|
||||
// modop.elwise_sub_mut(&mut diff, &neg_s_main_m);
|
||||
|
||||
let mut stat = Stats::new();
|
||||
stat.add_more(&Vec::<i64>::try_convert_from(&diff, &q));
|
||||
println!("Log2 Std: {}", stat.std_dev().abs().log2());
|
||||
}
|
||||
}
|
||||
// let mut stat = Stats::new();
|
||||
// stat.add_more(&Vec::<i64>::try_convert_from(&diff, &q));
|
||||
// println!("Log2 Std: {}", stat.std_dev().abs().log2());
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use itertools::Itertools;
|
||||
|
||||
use crate::{
|
||||
bool::keys::{ClientKey, PublicKey},
|
||||
bool::{ClientKey, PublicKey},
|
||||
Decryptor, Encryptor, MultiPartyDecryptor,
|
||||
};
|
||||
|
||||
@@ -97,10 +97,7 @@ mod frontend {
|
||||
eight_bit_mul,
|
||||
};
|
||||
use crate::{
|
||||
bool::{
|
||||
evaluator::{self, BoolEvaluator, BooleanGates},
|
||||
keys::{ServerKeyEvaluationDomain, ShoupServerKeyEvaluationDomain},
|
||||
},
|
||||
bool::evaluator::{BoolEvaluator, BooleanGates},
|
||||
utils::{Global, WithLocal},
|
||||
};
|
||||
|
||||
|
||||
11
src/utils.rs
11
src/utils.rs
@@ -190,6 +190,17 @@ pub fn negacyclic_mul<T: PrimInt, F: Fn(&T, &T) -> T>(
|
||||
return r;
|
||||
}
|
||||
|
||||
pub(crate) fn puncture_p_rng<S: Default + Copy, R: RandomFill<S>>(
|
||||
p_rng: &mut R,
|
||||
times: usize,
|
||||
) -> S {
|
||||
let mut out = S::default();
|
||||
for _ in 0..times {
|
||||
RandomFill::<S>::random_fill(p_rng, &mut out);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
pub trait TryConvertFrom1<T: ?Sized, P> {
|
||||
fn try_convert_from(value: &T, parameters: &P) -> Self;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user