mirror of
https://github.com/arnaucube/phantom-zone.git
synced 2026-01-09 15:41:30 +01:00
add KeySize trait (in test cfg) and describe fields in keys
This commit is contained in:
@@ -11,8 +11,8 @@ fn fhe_circuit(fhe_a: &FheUint8, fhe_b: &FheUint8, fhe_c: &FheUint8) -> FheUint8
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
set_parameter_set(ParameterSelector::MultiPartyLessThanOrEqualTo16);
|
set_parameter_set(ParameterSelector::InteractiveLTE2Party);
|
||||||
let no_of_parties = 8;
|
let no_of_parties = 2;
|
||||||
let client_keys = (0..no_of_parties)
|
let client_keys = (0..no_of_parties)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|_| gen_client_key())
|
.map(|_| gen_client_key())
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use num_traits::ToPrimitive;
|
use num_traits::ToPrimitive;
|
||||||
|
|
||||||
use crate::Row;
|
use crate::{utils::log2, Row};
|
||||||
|
|
||||||
mod modulus_u64;
|
mod modulus_u64;
|
||||||
mod power_of_2;
|
mod power_of_2;
|
||||||
@@ -13,6 +13,8 @@ pub trait Modulus {
|
|||||||
type Element;
|
type Element;
|
||||||
/// Modulus value if it fits in Element
|
/// Modulus value if it fits in Element
|
||||||
fn q(&self) -> Option<Self::Element>;
|
fn q(&self) -> Option<Self::Element>;
|
||||||
|
/// Log2 of `q`
|
||||||
|
fn log_q(&self) -> usize;
|
||||||
/// Modulus value as f64 if it fits in f64
|
/// Modulus value as f64 if it fits in f64
|
||||||
fn q_as_f64(&self) -> Option<f64>;
|
fn q_as_f64(&self) -> Option<f64>;
|
||||||
/// Is modulus native?
|
/// Is modulus native?
|
||||||
@@ -35,7 +37,7 @@ pub trait Modulus {
|
|||||||
impl Modulus for u64 {
|
impl Modulus for u64 {
|
||||||
type Element = u64;
|
type Element = u64;
|
||||||
fn is_native(&self) -> bool {
|
fn is_native(&self) -> bool {
|
||||||
// q of size u64 can never be a naitve modulus
|
// q that fits in u64 can never be a native modulus
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
fn largest_unsigned_value(&self) -> Self::Element {
|
fn largest_unsigned_value(&self) -> Self::Element {
|
||||||
@@ -56,21 +58,22 @@ impl Modulus for u64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn map_element_from_f64(&self, v: f64) -> Self::Element {
|
fn map_element_from_f64(&self, v: f64) -> Self::Element {
|
||||||
//FIXME (Jay): Before I check whether v is smaller than 0 with `let is_neg =
|
|
||||||
// o.is_sign_negative() && o != 0.0; I'm ocnfused why didn't I simply check <
|
|
||||||
// 0.0?
|
|
||||||
let v = v.round();
|
let v = v.round();
|
||||||
|
let v_u64 = v.abs().to_u64().unwrap();
|
||||||
|
assert!(v_u64 <= self.largest_unsigned_value());
|
||||||
if v < 0.0 {
|
if v < 0.0 {
|
||||||
self - v.abs().to_u64().unwrap()
|
self - v_u64
|
||||||
} else {
|
} else {
|
||||||
v.to_u64().unwrap()
|
v_u64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn map_element_from_i64(&self, v: i64) -> Self::Element {
|
fn map_element_from_i64(&self, v: i64) -> Self::Element {
|
||||||
|
let v_u64 = v.abs().to_u64().unwrap();
|
||||||
|
assert!(v_u64 <= self.largest_unsigned_value());
|
||||||
if v < 0 {
|
if v < 0 {
|
||||||
self - v.abs().to_u64().unwrap()
|
self - v_u64
|
||||||
} else {
|
} else {
|
||||||
v.to_u64().unwrap()
|
v_u64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn q(&self) -> Option<Self::Element> {
|
fn q(&self) -> Option<Self::Element> {
|
||||||
@@ -79,6 +82,9 @@ impl Modulus for u64 {
|
|||||||
fn q_as_f64(&self) -> Option<f64> {
|
fn q_as_f64(&self) -> Option<f64> {
|
||||||
self.to_f64()
|
self.to_f64()
|
||||||
}
|
}
|
||||||
|
fn log_q(&self) -> usize {
|
||||||
|
log2(&self.q().unwrap())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ModInit {
|
pub trait ModInit {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use itertools::{izip, Itertools};
|
use itertools::{izip, Itertools};
|
||||||
use num_traits::{FromPrimitive, One, PrimInt, ToPrimitive, WrappingAdd, WrappingSub, Zero};
|
use num_traits::{FromPrimitive, Num, One, PrimInt, ToPrimitive, WrappingAdd, WrappingSub, Zero};
|
||||||
use rand_distr::uniform::SampleUniform;
|
use rand_distr::uniform::SampleUniform;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -18,21 +18,20 @@ use crate::{
|
|||||||
non_interactive_ksk_gen, non_interactive_ksk_zero_encryptions_for_other_party_i,
|
non_interactive_ksk_gen, non_interactive_ksk_zero_encryptions_for_other_party_i,
|
||||||
public_key_share,
|
public_key_share,
|
||||||
},
|
},
|
||||||
ntt::{self, Ntt, NttBackendU64, NttInit},
|
ntt::{Ntt, NttInit},
|
||||||
pbs::{pbs, sample_extract, PbsInfo, PbsKey, WithShoupRepr},
|
pbs::{pbs, sample_extract, PbsInfo, PbsKey, WithShoupRepr},
|
||||||
random::{
|
random::{
|
||||||
DefaultSecureRng, NewWithSeed, RandomFill, RandomFillGaussianInModulus,
|
DefaultSecureRng, NewWithSeed, RandomFill, RandomFillGaussianInModulus,
|
||||||
RandomFillUniformInModulus, RandomGaussianElementInModulus,
|
RandomFillUniformInModulus, RandomGaussianElementInModulus,
|
||||||
},
|
},
|
||||||
rgsw::{
|
rgsw::{
|
||||||
decrypt_rlwe, generate_auto_map, public_key_encrypt_rgsw, rgsw_by_rgsw_inplace,
|
generate_auto_map, public_key_encrypt_rgsw, rgsw_by_rgsw_inplace, rgsw_x_rgsw_scratch_rows,
|
||||||
rgsw_x_rgsw_scratch_rows, rlwe_auto, rlwe_auto_scratch_rows, rlwe_x_rgsw_scratch_rows,
|
rlwe_auto_scratch_rows, rlwe_x_rgsw_scratch_rows, secret_key_encrypt_rgsw,
|
||||||
secret_key_encrypt_rgsw, seeded_auto_key_gen, RgswCiphertext, RgswCiphertextMutRef,
|
seeded_auto_key_gen, RgswCiphertextMutRef, RgswCiphertextRef, RuntimeScratchMutRef,
|
||||||
RgswCiphertextRef, RuntimeScratchMutRef,
|
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
encode_x_pow_si_with_emebedding_factor, fill_random_ternary_secret_with_hamming_weight,
|
encode_x_pow_si_with_emebedding_factor, fill_random_ternary_secret_with_hamming_weight,
|
||||||
generate_prime, mod_exponent, puncture_p_rng, Global, TryConvertFrom1, WithLocal,
|
mod_exponent, puncture_p_rng, TryConvertFrom1, WithLocal,
|
||||||
},
|
},
|
||||||
Encoder, Matrix, MatrixEntity, MatrixMut, RowEntity, RowMut,
|
Encoder, Matrix, MatrixEntity, MatrixMut, RowEntity, RowMut,
|
||||||
};
|
};
|
||||||
@@ -40,10 +39,10 @@ use crate::{
|
|||||||
use super::{
|
use super::{
|
||||||
keys::{
|
keys::{
|
||||||
ClientKey, CommonReferenceSeededCollectivePublicKeyShare,
|
ClientKey, CommonReferenceSeededCollectivePublicKeyShare,
|
||||||
CommonReferenceSeededMultiPartyServerKeyShare,
|
CommonReferenceSeededInteractiveMultiPartyServerKeyShare,
|
||||||
CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare,
|
CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare,
|
||||||
InteractiveMultiPartyClientKey, NonInteractiveMultiPartyClientKey,
|
InteractiveMultiPartyClientKey, NonInteractiveMultiPartyClientKey,
|
||||||
SeededMultiPartyServerKey, SeededNonInteractiveMultiPartyServerKey,
|
SeededInteractiveMultiPartyServerKey, SeededNonInteractiveMultiPartyServerKey,
|
||||||
SeededSinglePartyServerKey, SinglePartyClientKey,
|
SeededSinglePartyServerKey, SinglePartyClientKey,
|
||||||
},
|
},
|
||||||
parameters::{BoolParameters, CiphertextModulus, DecompositionCount, DoubleDecomposerParams},
|
parameters::{BoolParameters, CiphertextModulus, DecompositionCount, DoubleDecomposerParams},
|
||||||
@@ -268,13 +267,13 @@ pub(super) trait BoolEncoding {
|
|||||||
impl<T> BoolEncoding for CiphertextModulus<T>
|
impl<T> BoolEncoding for CiphertextModulus<T>
|
||||||
where
|
where
|
||||||
CiphertextModulus<T>: Modulus<Element = T>,
|
CiphertextModulus<T>: Modulus<Element = T>,
|
||||||
T: PrimInt,
|
T: PrimInt + NumInfo,
|
||||||
{
|
{
|
||||||
type Element = T;
|
type Element = T;
|
||||||
|
|
||||||
fn qby4(&self) -> Self::Element {
|
fn qby4(&self) -> Self::Element {
|
||||||
if self.is_native() {
|
if self.is_native() {
|
||||||
T::one() << (CiphertextModulus::<T>::_bits() - 2)
|
T::one() << ((T::BITS as usize) - 2)
|
||||||
} else {
|
} else {
|
||||||
self.q().unwrap() >> 2
|
self.q().unwrap() >> 2
|
||||||
}
|
}
|
||||||
@@ -282,7 +281,7 @@ where
|
|||||||
/// Q/8
|
/// Q/8
|
||||||
fn true_el(&self) -> Self::Element {
|
fn true_el(&self) -> Self::Element {
|
||||||
if self.is_native() {
|
if self.is_native() {
|
||||||
T::one() << (CiphertextModulus::<T>::_bits() - 3)
|
T::one() << ((T::BITS as usize) - 3)
|
||||||
} else {
|
} else {
|
||||||
self.q().unwrap() >> 3
|
self.q().unwrap() >> 3
|
||||||
}
|
}
|
||||||
@@ -954,7 +953,7 @@ where
|
|||||||
cr_seed: &MultiPartyCrs<[u8; 32]>,
|
cr_seed: &MultiPartyCrs<[u8; 32]>,
|
||||||
collective_pk: &M,
|
collective_pk: &M,
|
||||||
client_key: &K,
|
client_key: &K,
|
||||||
) -> CommonReferenceSeededMultiPartyServerKeyShare<
|
) -> CommonReferenceSeededInteractiveMultiPartyServerKeyShare<
|
||||||
M,
|
M,
|
||||||
BoolParameters<M::MatElement>,
|
BoolParameters<M::MatElement>,
|
||||||
MultiPartyCrs<[u8; 32]>,
|
MultiPartyCrs<[u8; 32]>,
|
||||||
@@ -1085,7 +1084,7 @@ where
|
|||||||
&sk_lwe,
|
&sk_lwe,
|
||||||
);
|
);
|
||||||
|
|
||||||
CommonReferenceSeededMultiPartyServerKeyShare::new(
|
CommonReferenceSeededInteractiveMultiPartyServerKeyShare::new(
|
||||||
self_leader_rgsws,
|
self_leader_rgsws,
|
||||||
not_self_leader_rgsws,
|
not_self_leader_rgsws,
|
||||||
auto_keys,
|
auto_keys,
|
||||||
@@ -1098,12 +1097,12 @@ where
|
|||||||
|
|
||||||
pub(super) fn aggregate_multi_party_server_key_shares<S>(
|
pub(super) fn aggregate_multi_party_server_key_shares<S>(
|
||||||
&self,
|
&self,
|
||||||
shares: &[CommonReferenceSeededMultiPartyServerKeyShare<
|
shares: &[CommonReferenceSeededInteractiveMultiPartyServerKeyShare<
|
||||||
M,
|
M,
|
||||||
BoolParameters<M::MatElement>,
|
BoolParameters<M::MatElement>,
|
||||||
MultiPartyCrs<S>,
|
MultiPartyCrs<S>,
|
||||||
>],
|
>],
|
||||||
) -> SeededMultiPartyServerKey<M, MultiPartyCrs<S>, BoolParameters<M::MatElement>>
|
) -> SeededInteractiveMultiPartyServerKey<M, MultiPartyCrs<S>, BoolParameters<M::MatElement>>
|
||||||
where
|
where
|
||||||
S: PartialEq + Clone,
|
S: PartialEq + Clone,
|
||||||
M: Clone,
|
M: Clone,
|
||||||
@@ -1255,7 +1254,13 @@ where
|
|||||||
lweq_modop.elwise_add_mut(lwe_ksk.as_mut(), si.lwe_ksk().as_ref())
|
lweq_modop.elwise_add_mut(lwe_ksk.as_mut(), si.lwe_ksk().as_ref())
|
||||||
});
|
});
|
||||||
|
|
||||||
SeededMultiPartyServerKey::new(rgsw_cts, auto_keys, lwe_ksk, cr_seed.clone(), parameters)
|
SeededInteractiveMultiPartyServerKey::new(
|
||||||
|
rgsw_cts,
|
||||||
|
auto_keys,
|
||||||
|
lwe_ksk,
|
||||||
|
cr_seed.clone(),
|
||||||
|
parameters,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn aggregate_non_interactive_multi_party_key_share(
|
pub(super) fn aggregate_non_interactive_multi_party_key_share(
|
||||||
@@ -1264,6 +1269,7 @@ where
|
|||||||
total_users: usize,
|
total_users: usize,
|
||||||
key_shares: &[CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare<
|
key_shares: &[CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare<
|
||||||
M,
|
M,
|
||||||
|
BoolParameters<M::MatElement>,
|
||||||
NonInteractiveMultiPartyCrs<[u8; 32]>,
|
NonInteractiveMultiPartyCrs<[u8; 32]>,
|
||||||
>],
|
>],
|
||||||
) -> SeededNonInteractiveMultiPartyServerKey<
|
) -> SeededNonInteractiveMultiPartyServerKey<
|
||||||
@@ -1280,6 +1286,8 @@ where
|
|||||||
&ParameterVariant::NonInteractiveMultiParty
|
&ParameterVariant::NonInteractiveMultiParty
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// TODO: Check parameters are equivalent!
|
||||||
|
|
||||||
let total_users = key_shares.len();
|
let total_users = key_shares.len();
|
||||||
let key_shares = (0..total_users)
|
let key_shares = (0..total_users)
|
||||||
.map(|user_id| {
|
.map(|user_id| {
|
||||||
@@ -1662,6 +1670,7 @@ where
|
|||||||
client_key: &K,
|
client_key: &K,
|
||||||
) -> CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare<
|
) -> CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare<
|
||||||
M,
|
M,
|
||||||
|
BoolParameters<M::MatElement>,
|
||||||
NonInteractiveMultiPartyCrs<[u8; 32]>,
|
NonInteractiveMultiPartyCrs<[u8; 32]>,
|
||||||
> {
|
> {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -2004,6 +2013,7 @@ where
|
|||||||
total_users,
|
total_users,
|
||||||
self.parameters().lwe_n().0,
|
self.parameters().lwe_n().0,
|
||||||
cr_seed.clone(),
|
cr_seed.clone(),
|
||||||
|
self.parameters().clone(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
286
src/bool/keys.rs
286
src/bool/keys.rs
@@ -1,17 +1,14 @@
|
|||||||
use std::{collections::HashMap, hash::Hash, marker::PhantomData};
|
use std::{collections::HashMap, marker::PhantomData};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{ModInit, VectorOps},
|
backend::{ModInit, VectorOps},
|
||||||
pbs::WithShoupRepr,
|
pbs::WithShoupRepr,
|
||||||
random::{NewWithSeed, RandomFillUniformInModulus},
|
random::{NewWithSeed, RandomFillUniformInModulus},
|
||||||
utils::{ToShoup, WithLocal},
|
utils::ToShoup,
|
||||||
Decryptor, Encryptor, Matrix, MatrixEntity, MatrixMut, MultiPartyDecryptor, RowEntity, RowMut,
|
Matrix, MatrixEntity, MatrixMut, RowEntity, RowMut, SizeInBitsWithLogModulus,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::parameters::{BoolParameters, CiphertextModulus};
|
||||||
evaluator::BoolEvaluator,
|
|
||||||
parameters::{BoolParameters, CiphertextModulus},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub(crate) trait SinglePartyClientKey {
|
pub(crate) trait SinglePartyClientKey {
|
||||||
type Element;
|
type Element;
|
||||||
@@ -48,7 +45,7 @@ pub(crate) trait NonInteractiveMultiPartyClientKey {
|
|||||||
/// interactive/non-interactive multi-party
|
/// interactive/non-interactive multi-party
|
||||||
///
|
///
|
||||||
/// Puncture 3 -> Seed of RLWE secret used as `u` in
|
/// Puncture 3 -> Seed of RLWE secret used as `u` in
|
||||||
/// interactive/non-interactive multi-party.
|
/// non-interactive multi-party.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ClientKey<S, E> {
|
pub struct ClientKey<S, E> {
|
||||||
seed: S,
|
seed: S,
|
||||||
@@ -143,8 +140,6 @@ pub struct PublicKey<M, Rng, ModOp> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) mod impl_pk {
|
pub(super) mod impl_pk {
|
||||||
use crate::evaluator::MultiPartyCrs;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
impl<M, R, Mo> PublicKey<M, R, Mo> {
|
impl<M, R, Mo> PublicKey<M, R, Mo> {
|
||||||
@@ -296,8 +291,11 @@ mod impl_seeded_pk {
|
|||||||
|
|
||||||
/// CRS seeded collective public key share
|
/// CRS seeded collective public key share
|
||||||
pub struct CommonReferenceSeededCollectivePublicKeyShare<Ro, S, P> {
|
pub struct CommonReferenceSeededCollectivePublicKeyShare<Ro, S, P> {
|
||||||
|
/// Public key share polynomial
|
||||||
share: Ro,
|
share: Ro,
|
||||||
|
/// Common reference seed
|
||||||
cr_seed: S,
|
cr_seed: S,
|
||||||
|
/// Parameters
|
||||||
parameters: P,
|
parameters: P,
|
||||||
}
|
}
|
||||||
impl<Ro, S, P> CommonReferenceSeededCollectivePublicKeyShare<Ro, S, P> {
|
impl<Ro, S, P> CommonReferenceSeededCollectivePublicKeyShare<Ro, S, P> {
|
||||||
@@ -310,21 +308,36 @@ impl<Ro, S, P> CommonReferenceSeededCollectivePublicKeyShare<Ro, S, P> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CRS seeded Multi-party server key share
|
/// Common reference seed seeded interactive multi-party server key share
|
||||||
pub struct CommonReferenceSeededMultiPartyServerKeyShare<M: Matrix, P, S> {
|
pub struct CommonReferenceSeededInteractiveMultiPartyServerKeyShare<M: Matrix, P, S> {
|
||||||
|
/// Public key encrypted RGSW(m = X^{s[i]}) ciphertexts for LWE secret
|
||||||
|
/// indices for which `Self` is the leader. Note that when `Self` is
|
||||||
|
/// leader RGSW ciphertext is encrypted using RLWE x RGSW decomposer
|
||||||
self_leader_rgsws: Vec<M>,
|
self_leader_rgsws: Vec<M>,
|
||||||
|
/// Public key encrypted RGSW(m = X^{s[i]}) ciphertext for LWE secret
|
||||||
|
/// indices for which `Self` is `not` the leader. Note that when `Self`
|
||||||
|
/// is not the leader RGSW ciphertext is encrypted using RGSW1
|
||||||
|
/// decomposer for RGSW0 x RGSW1
|
||||||
not_self_leader_rgsws: Vec<M>,
|
not_self_leader_rgsws: Vec<M>,
|
||||||
/// Auto keys. Key corresponding to g^{k} is at index `k`. Key corresponding
|
/// Auto key shares for auto elements [g^{-1}, g, g^2, .., g^{w}] where `w`
|
||||||
/// to -g is at 0
|
/// is the window size parameter. Share corresponding to auto element g^{-1}
|
||||||
|
/// is stored at key `0` and share corresponding to auto element g^{k} is
|
||||||
|
/// stored at key `k`.
|
||||||
auto_keys: HashMap<usize, M>,
|
auto_keys: HashMap<usize, M>,
|
||||||
|
/// LWE key switching key share to key switching ciphertext LWE_{q, s}(m) to
|
||||||
|
/// LWE_{q, z}(m) where q is LWE ciphertext modulus, `s` is the ideal RLWE
|
||||||
|
/// secret with dimension N, and `z` is the ideal LWE secret of dimension n.
|
||||||
lwe_ksk: M::R,
|
lwe_ksk: M::R,
|
||||||
/// Common reference seed
|
/// Common reference seed
|
||||||
cr_seed: S,
|
cr_seed: S,
|
||||||
parameters: P,
|
parameters: P,
|
||||||
|
/// User id assigned by the server.
|
||||||
|
///
|
||||||
|
/// User id must be unique and a number in range [0, total_users)
|
||||||
user_id: usize,
|
user_id: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M: Matrix, P, S> CommonReferenceSeededMultiPartyServerKeyShare<M, P, S> {
|
impl<M: Matrix, P, S> CommonReferenceSeededInteractiveMultiPartyServerKeyShare<M, P, S> {
|
||||||
pub(super) fn new(
|
pub(super) fn new(
|
||||||
self_leader_rgsws: Vec<M>,
|
self_leader_rgsws: Vec<M>,
|
||||||
not_self_leader_rgsws: Vec<M>,
|
not_self_leader_rgsws: Vec<M>,
|
||||||
@@ -334,7 +347,7 @@ impl<M: Matrix, P, S> CommonReferenceSeededMultiPartyServerKeyShare<M, P, S> {
|
|||||||
parameters: P,
|
parameters: P,
|
||||||
user_id: usize,
|
user_id: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
CommonReferenceSeededMultiPartyServerKeyShare {
|
CommonReferenceSeededInteractiveMultiPartyServerKeyShare {
|
||||||
self_leader_rgsws,
|
self_leader_rgsws,
|
||||||
not_self_leader_rgsws,
|
not_self_leader_rgsws,
|
||||||
auto_keys,
|
auto_keys,
|
||||||
@@ -374,18 +387,26 @@ impl<M: Matrix, P, S> CommonReferenceSeededMultiPartyServerKeyShare<M, P, S> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CRS seeded MultiParty server key
|
/// Common reference seeded interactive multi-party server key
|
||||||
pub struct SeededMultiPartyServerKey<M: Matrix, S, P> {
|
pub struct SeededInteractiveMultiPartyServerKey<M: Matrix, S, P> {
|
||||||
|
/// RGSW ciphertexts RGSW(X^{s[i]}) encrypted under ideal RLWE secret key
|
||||||
|
/// where `s` is ideal LWE secret key for each LWE secret dimension.
|
||||||
rgsw_cts: Vec<M>,
|
rgsw_cts: Vec<M>,
|
||||||
/// Auto keys. Key corresponding to g^{k} is at index `k`. Key corresponding
|
/// Seeded auto keys under ideal RLWE secret for RLWE automorphisms with
|
||||||
/// to -g is at 0
|
/// auto elements [g^-1, g, g^2,..., g^{w}]. Auto key corresponidng to
|
||||||
|
/// auto element g^{-1} is stored at key `0` and key corresponding to auto
|
||||||
|
/// element g^{k} is stored at key `k`
|
||||||
auto_keys: HashMap<usize, M>,
|
auto_keys: HashMap<usize, M>,
|
||||||
|
/// Seeded LWE key switching key under ideal LWE secret to switch LWE_{q,
|
||||||
|
/// s}(m) to LWE_{q, z}(m) where s is ideal RLWE secret and z is ideal LWE
|
||||||
|
/// secret.
|
||||||
lwe_ksk: M::R,
|
lwe_ksk: M::R,
|
||||||
|
/// Common reference seed
|
||||||
cr_seed: S,
|
cr_seed: S,
|
||||||
parameters: P,
|
parameters: P,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M: Matrix, S, P> SeededMultiPartyServerKey<M, S, P> {
|
impl<M: Matrix, S, P> SeededInteractiveMultiPartyServerKey<M, S, P> {
|
||||||
pub(super) fn new(
|
pub(super) fn new(
|
||||||
rgsw_cts: Vec<M>,
|
rgsw_cts: Vec<M>,
|
||||||
auto_keys: HashMap<usize, M>,
|
auto_keys: HashMap<usize, M>,
|
||||||
@@ -393,7 +414,7 @@ impl<M: Matrix, S, P> SeededMultiPartyServerKey<M, S, P> {
|
|||||||
cr_seed: S,
|
cr_seed: S,
|
||||||
parameters: P,
|
parameters: P,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
SeededMultiPartyServerKey {
|
SeededInteractiveMultiPartyServerKey {
|
||||||
rgsw_cts,
|
rgsw_cts,
|
||||||
auto_keys,
|
auto_keys,
|
||||||
lwe_ksk,
|
lwe_ksk,
|
||||||
@@ -461,12 +482,12 @@ impl<M: Matrix, S> SeededSinglePartyServerKey<M, BoolParameters<M::MatElement>,
|
|||||||
|
|
||||||
/// Server key in evaluation domain
|
/// Server key in evaluation domain
|
||||||
pub(crate) struct ServerKeyEvaluationDomain<M, P, R, N> {
|
pub(crate) struct ServerKeyEvaluationDomain<M, P, R, N> {
|
||||||
/// Rgsw cts of LWE secret elements
|
/// RGSW ciphertext RGSW(X^{s[i]}) for each LWE index in evaluation domain
|
||||||
rgsw_cts: Vec<M>,
|
rgsw_cts: Vec<M>,
|
||||||
/// Auto keys. Key corresponding to g^{k} is at index `k`. Key corresponding
|
/// Auto keys for all auto elements [g^{-1}, g, g^2,..., g^w] in evaluation
|
||||||
/// to -g is at 0
|
/// domain
|
||||||
galois_keys: HashMap<usize, M>,
|
galois_keys: HashMap<usize, M>,
|
||||||
/// LWE ksk to key switching LWE ciphertext from RLWE secret to LWE secret
|
/// LWE key switching key to key switch LWE_{q, s}(m) to LWE_{q, z}(m)
|
||||||
lwe_ksk: M,
|
lwe_ksk: M,
|
||||||
parameters: P,
|
parameters: P,
|
||||||
_phanton: PhantomData<(R, N)>,
|
_phanton: PhantomData<(R, N)>,
|
||||||
@@ -627,8 +648,13 @@ pub(super) mod impl_server_key_eval_domain {
|
|||||||
Rng: NewWithSeed,
|
Rng: NewWithSeed,
|
||||||
N: NttInit<CiphertextModulus<M::MatElement>> + Ntt<Element = M::MatElement>,
|
N: NttInit<CiphertextModulus<M::MatElement>> + Ntt<Element = M::MatElement>,
|
||||||
>
|
>
|
||||||
From<&SeededMultiPartyServerKey<M, MultiPartyCrs<Rng::Seed>, BoolParameters<M::MatElement>>>
|
From<
|
||||||
for ServerKeyEvaluationDomain<M, BoolParameters<M::MatElement>, Rng, N>
|
&SeededInteractiveMultiPartyServerKey<
|
||||||
|
M,
|
||||||
|
MultiPartyCrs<Rng::Seed>,
|
||||||
|
BoolParameters<M::MatElement>,
|
||||||
|
>,
|
||||||
|
> for ServerKeyEvaluationDomain<M, BoolParameters<M::MatElement>, Rng, N>
|
||||||
where
|
where
|
||||||
<M as Matrix>::R: RowMut,
|
<M as Matrix>::R: RowMut,
|
||||||
Rng::Seed: Copy + Default,
|
Rng::Seed: Copy + Default,
|
||||||
@@ -637,7 +663,7 @@ pub(super) mod impl_server_key_eval_domain {
|
|||||||
M::MatElement: Copy,
|
M::MatElement: Copy,
|
||||||
{
|
{
|
||||||
fn from(
|
fn from(
|
||||||
value: &SeededMultiPartyServerKey<
|
value: &SeededInteractiveMultiPartyServerKey<
|
||||||
M,
|
M,
|
||||||
MultiPartyCrs<Rng::Seed>,
|
MultiPartyCrs<Rng::Seed>,
|
||||||
BoolParameters<M::MatElement>,
|
BoolParameters<M::MatElement>,
|
||||||
@@ -767,15 +793,21 @@ pub(super) mod impl_server_key_eval_domain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Non-interactive multi-party server key in evaluation domain.
|
||||||
|
///
|
||||||
|
/// The key is derived from Seeded non-interactive mmulti-party server key
|
||||||
|
/// `SeededNonInteractiveMultiPartyServerKey`.
|
||||||
pub(crate) struct NonInteractiveServerKeyEvaluationDomain<M, P, R, N> {
|
pub(crate) struct NonInteractiveServerKeyEvaluationDomain<M, P, R, N> {
|
||||||
/// RGSW ciphertexts ideal lwe secret key elements under ideal rlwe secret
|
/// RGSW ciphertexts RGSW(X^{s[i]}) under ideal RLWE secret key in
|
||||||
|
/// evaluation domain
|
||||||
rgsw_cts: Vec<M>,
|
rgsw_cts: Vec<M>,
|
||||||
/// Automorphism keys under ideal rlwe secret
|
/// Auto keys for all auto elements [g^{-1}, g, g^2, g^w] in evaluation
|
||||||
|
/// domain
|
||||||
auto_keys: HashMap<usize, M>,
|
auto_keys: HashMap<usize, M>,
|
||||||
/// LWE key switching key from Q -> Q_{ks}
|
/// LWE key switching key to key switch LWE_{q, s}(m) to LWE_{q, z}(m)
|
||||||
lwe_ksk: M,
|
lwe_ksk: M,
|
||||||
/// Key switching key from user j to ideal secret key s. User j's ksk is at
|
/// Key switching key from user j's secret u_j to ideal RLWE secret key `s`
|
||||||
/// j'th element
|
/// in evaluation domain. User j's key switching key is at j'th index.
|
||||||
ui_to_s_ksks: Vec<M>,
|
ui_to_s_ksks: Vec<M>,
|
||||||
parameters: P,
|
parameters: P,
|
||||||
_phanton: PhantomData<(R, N)>,
|
_phanton: PhantomData<(R, N)>,
|
||||||
@@ -967,14 +999,22 @@ pub(super) mod impl_non_interactive_server_key_eval_domain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Seeded non-interactive multi-party server key.
|
||||||
|
///
|
||||||
|
/// Given common reference seeded non-interactive multi-party key shares of each
|
||||||
|
/// users with unique user-ids, seeded non-interactive can be generated using
|
||||||
|
/// `BoolEvaluator::aggregate_non_interactive_multi_party_key_share`
|
||||||
pub struct SeededNonInteractiveMultiPartyServerKey<M: Matrix, S, P> {
|
pub struct SeededNonInteractiveMultiPartyServerKey<M: Matrix, S, P> {
|
||||||
/// u_i to s key switching keys in random order. Key switchin key for user j
|
/// Key switching key from user j's secret u_j to ideal RLWE secret key `s`.
|
||||||
/// is stored at j^th index
|
/// User j's key switching key is at j'th index.
|
||||||
ui_to_s_ksks: Vec<M>,
|
ui_to_s_ksks: Vec<M>,
|
||||||
/// RGSW ciphertets
|
/// RGSW ciphertexts RGSW(X^{s[i]}) under ideal RLWE secret key
|
||||||
rgsw_cts: Vec<M>,
|
rgsw_cts: Vec<M>,
|
||||||
|
/// Auto keys for all auto elements [g^{-1}, g, g^2, g^w]
|
||||||
auto_keys: HashMap<usize, M>,
|
auto_keys: HashMap<usize, M>,
|
||||||
|
/// LWE key switching key to key switch LWE_{q, s}(m) to LWE_{q, z}(m)
|
||||||
lwe_ksk: M::R,
|
lwe_ksk: M::R,
|
||||||
|
/// Common reference seed
|
||||||
cr_seed: S,
|
cr_seed: S,
|
||||||
parameters: P,
|
parameters: P,
|
||||||
}
|
}
|
||||||
@@ -982,7 +1022,6 @@ pub struct SeededNonInteractiveMultiPartyServerKey<M: Matrix, S, P> {
|
|||||||
impl<M: Matrix, S, P> SeededNonInteractiveMultiPartyServerKey<M, S, P> {
|
impl<M: Matrix, S, P> SeededNonInteractiveMultiPartyServerKey<M, S, P> {
|
||||||
pub(super) fn new(
|
pub(super) fn new(
|
||||||
ui_to_s_ksks: Vec<M>,
|
ui_to_s_ksks: Vec<M>,
|
||||||
|
|
||||||
rgsw_cts: Vec<M>,
|
rgsw_cts: Vec<M>,
|
||||||
auto_keys: HashMap<usize, M>,
|
auto_keys: HashMap<usize, M>,
|
||||||
lwe_ksk: M::R,
|
lwe_ksk: M::R,
|
||||||
@@ -1001,15 +1040,13 @@ impl<M: Matrix, S, P> SeededNonInteractiveMultiPartyServerKey<M, S, P> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This key is equivalent to NonInteractiveServerKeyEvaluationDomain with the
|
||||||
|
/// addition that each polynomial in evaluation domain has a corresponding shoup
|
||||||
|
/// representation suitable for shoup multiplication.
|
||||||
pub(crate) struct ShoupNonInteractiveServerKeyEvaluationDomain<M> {
|
pub(crate) struct ShoupNonInteractiveServerKeyEvaluationDomain<M> {
|
||||||
/// RGSW ciphertexts ideal lwe secret key elements under ideal rlwe secret
|
|
||||||
rgsw_cts: Vec<NormalAndShoup<M>>,
|
rgsw_cts: Vec<NormalAndShoup<M>>,
|
||||||
/// Automorphism keys under ideal rlwe secret
|
|
||||||
auto_keys: HashMap<usize, NormalAndShoup<M>>,
|
auto_keys: HashMap<usize, NormalAndShoup<M>>,
|
||||||
/// LWE key switching key from Q -> Q_{ks}
|
|
||||||
lwe_ksk: M,
|
lwe_ksk: M,
|
||||||
/// Key switching key from user j to ideal secret key s. User j's ksk is at
|
|
||||||
/// j'th element
|
|
||||||
ui_to_s_ksks: Vec<NormalAndShoup<M>>,
|
ui_to_s_ksks: Vec<NormalAndShoup<M>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1018,7 +1055,7 @@ mod impl_shoup_non_interactive_server_key_eval_domain {
|
|||||||
use num_traits::{FromPrimitive, PrimInt, ToPrimitive};
|
use num_traits::{FromPrimitive, PrimInt, ToPrimitive};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{backend::Modulus, pbs::PbsKey};
|
use crate::{backend::Modulus, decomposer::NumInfo, pbs::PbsKey};
|
||||||
|
|
||||||
impl<M> ShoupNonInteractiveServerKeyEvaluationDomain<M> {
|
impl<M> ShoupNonInteractiveServerKeyEvaluationDomain<M> {
|
||||||
pub(in super::super) fn ui_to_s_ksk(&self, user_id: usize) -> &NormalAndShoup<M> {
|
pub(in super::super) fn ui_to_s_ksk(&self, user_id: usize) -> &NormalAndShoup<M> {
|
||||||
@@ -1030,7 +1067,7 @@ mod impl_shoup_non_interactive_server_key_eval_domain {
|
|||||||
From<NonInteractiveServerKeyEvaluationDomain<M, BoolParameters<M::MatElement>, R, N>>
|
From<NonInteractiveServerKeyEvaluationDomain<M, BoolParameters<M::MatElement>, R, N>>
|
||||||
for ShoupNonInteractiveServerKeyEvaluationDomain<M>
|
for ShoupNonInteractiveServerKeyEvaluationDomain<M>
|
||||||
where
|
where
|
||||||
M::MatElement: FromPrimitive + ToPrimitive + PrimInt,
|
M::MatElement: FromPrimitive + ToPrimitive + PrimInt + NumInfo,
|
||||||
{
|
{
|
||||||
fn from(
|
fn from(
|
||||||
value: NonInteractiveServerKeyEvaluationDomain<M, BoolParameters<M::MatElement>, R, N>,
|
value: NonInteractiveServerKeyEvaluationDomain<M, BoolParameters<M::MatElement>, R, N>,
|
||||||
@@ -1114,14 +1151,12 @@ mod impl_shoup_non_interactive_server_key_eval_domain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Server key in evaluation domain with Shoup representations
|
/// This is equivalent to ServerKeyEvaluationDomain with the addition that each
|
||||||
|
/// polynomial in evaluation domain has corresponding shoup representation
|
||||||
|
/// suitable for shoup multiplication.
|
||||||
pub(crate) struct ShoupServerKeyEvaluationDomain<M> {
|
pub(crate) struct ShoupServerKeyEvaluationDomain<M> {
|
||||||
/// Rgsw cts of LWE secret elements
|
|
||||||
rgsw_cts: Vec<NormalAndShoup<M>>,
|
rgsw_cts: Vec<NormalAndShoup<M>>,
|
||||||
/// Auto keys. Key corresponding to g^{k} is at index `k`. Key corresponding
|
|
||||||
/// to -g is at 0
|
|
||||||
galois_keys: HashMap<usize, NormalAndShoup<M>>,
|
galois_keys: HashMap<usize, NormalAndShoup<M>>,
|
||||||
/// LWE ksk to key switching LWE ciphertext from RLWE secret to LWE secret
|
|
||||||
lwe_ksk: M,
|
lwe_ksk: M,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1129,7 +1164,7 @@ mod shoup_server_key_eval_domain {
|
|||||||
use itertools::{izip, Itertools};
|
use itertools::{izip, Itertools};
|
||||||
use num_traits::{FromPrimitive, PrimInt};
|
use num_traits::{FromPrimitive, PrimInt};
|
||||||
|
|
||||||
use crate::{backend::Modulus, pbs::PbsKey};
|
use crate::{backend::Modulus, decomposer::NumInfo, pbs::PbsKey};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@@ -1138,7 +1173,7 @@ mod shoup_server_key_eval_domain {
|
|||||||
for ShoupServerKeyEvaluationDomain<M>
|
for ShoupServerKeyEvaluationDomain<M>
|
||||||
where
|
where
|
||||||
<M as Matrix>::R: RowMut,
|
<M as Matrix>::R: RowMut,
|
||||||
M::MatElement: PrimInt + FromPrimitive,
|
M::MatElement: PrimInt + FromPrimitive + NumInfo,
|
||||||
{
|
{
|
||||||
fn from(value: ServerKeyEvaluationDomain<M, BoolParameters<M::MatElement>, R, N>) -> Self {
|
fn from(value: ServerKeyEvaluationDomain<M, BoolParameters<M::MatElement>, R, N>) -> Self {
|
||||||
let q = value.parameters.rlwe_q().q().unwrap();
|
let q = value.parameters.rlwe_q().q().unwrap();
|
||||||
@@ -1180,27 +1215,56 @@ mod shoup_server_key_eval_domain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare<M: Matrix, S> {
|
pub struct CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare<M: Matrix, P, S> {
|
||||||
/// Non-interactive RGSW ciphertexts for secret indices for which user is
|
/// Non-interactive RGSW ciphertexts for LWE secret indices for which user
|
||||||
/// the leader
|
/// is the leader
|
||||||
self_leader_ni_rgsw_cts: Vec<M>,
|
self_leader_ni_rgsw_cts: Vec<M>,
|
||||||
/// Non-interactive RGSW ciphertexts for secret indices for which user is
|
/// Non-interactive RGSW ciphertexts for LWE secret indices for which user
|
||||||
/// not the leader
|
/// is not the leader
|
||||||
not_self_leader_ni_rgsw_cts: Vec<M>,
|
not_self_leader_ni_rgsw_cts: Vec<M>,
|
||||||
/// Zero encryptions for RGSW ciphertexts for all indicces
|
/// Zero encryptions for RGSW ciphertexts for all indices
|
||||||
ni_rgsw_zero_encs: Vec<M>,
|
ni_rgsw_zero_encs: Vec<M>,
|
||||||
|
|
||||||
/// (ak*si + e + \beta ui, ak*si + e)
|
/// Key switching key from u_j to s where u_j is user j's RLWE secret `u`
|
||||||
|
/// and `s` is ideal RLWE secret. Note that in server key share the key
|
||||||
|
/// switching key is encrypted under user j's RLWE secret `s_j`. It is
|
||||||
|
/// then switched to ideal RLWE secret after adding zero encryptions
|
||||||
|
/// generated using same `a_k`s from other users.
|
||||||
|
///
|
||||||
|
/// That is the key share has the following key switching key:
|
||||||
|
/// (a_k*s_j + e + \beta u_j, a_k*s_j + e)
|
||||||
ui_to_s_ksk: M,
|
ui_to_s_ksk: M,
|
||||||
|
/// Zero encryptions to switch user l's key switching key u_l to s from
|
||||||
|
/// user l's RLWE secret s_l to ideal RLWE secret `s`.
|
||||||
|
///
|
||||||
|
/// If there are P total parties then zero encryption sets are generated for
|
||||||
|
/// each party l \in [0, P) and l != j where j self's user_id.
|
||||||
|
///
|
||||||
|
/// Zero encryption set for user `l` is stored at index l is l < j otherwise
|
||||||
|
/// it is stored at index l - 1, where j is self's user_id
|
||||||
ksk_zero_encs_for_others: Vec<M>,
|
ksk_zero_encs_for_others: Vec<M>,
|
||||||
|
|
||||||
|
/// RLWE auto key shares for auto elements [g^{-1}, g, g^2, g^{w}] where `w`
|
||||||
|
/// is the window size. Auto key share corresponding to auto element g^{-1}
|
||||||
|
/// is stored at key 0 and key share corresponding to auto element g^{k} is
|
||||||
|
/// stored at key `k`
|
||||||
auto_keys_share: HashMap<usize, M>,
|
auto_keys_share: HashMap<usize, M>,
|
||||||
|
/// LWE key switching key share to key switching LWE_{q, s}(m) to LWE_{q,
|
||||||
|
/// z}(m)
|
||||||
lwe_ksk_share: M::R,
|
lwe_ksk_share: M::R,
|
||||||
|
|
||||||
user_index: usize,
|
/// User's id.
|
||||||
|
///
|
||||||
|
/// If there are P total parties, then user id must be inque and in range
|
||||||
|
/// [0, P)
|
||||||
|
user_id: usize,
|
||||||
|
/// Total users participating in multi-party compute
|
||||||
total_users: usize,
|
total_users: usize,
|
||||||
|
/// LWE dimension
|
||||||
lwe_n: usize,
|
lwe_n: usize,
|
||||||
|
/// Common reference seed
|
||||||
cr_seed: S,
|
cr_seed: S,
|
||||||
|
parameters: P,
|
||||||
}
|
}
|
||||||
|
|
||||||
mod impl_common_ref_non_interactive_multi_party_server_share {
|
mod impl_common_ref_non_interactive_multi_party_server_share {
|
||||||
@@ -1208,7 +1272,7 @@ mod impl_common_ref_non_interactive_multi_party_server_share {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
impl<M: Matrix, S> CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare<M, S> {
|
impl<M: Matrix, P, S> CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare<M, P, S> {
|
||||||
pub(in super::super) fn new(
|
pub(in super::super) fn new(
|
||||||
self_leader_ni_rgsw_cts: Vec<M>,
|
self_leader_ni_rgsw_cts: Vec<M>,
|
||||||
not_self_leader_ni_rgsw_cts: Vec<M>,
|
not_self_leader_ni_rgsw_cts: Vec<M>,
|
||||||
@@ -1221,6 +1285,7 @@ mod impl_common_ref_non_interactive_multi_party_server_share {
|
|||||||
total_users: usize,
|
total_users: usize,
|
||||||
lwe_n: usize,
|
lwe_n: usize,
|
||||||
cr_seed: S,
|
cr_seed: S,
|
||||||
|
parameters: P,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
self_leader_ni_rgsw_cts,
|
self_leader_ni_rgsw_cts,
|
||||||
@@ -1230,10 +1295,11 @@ mod impl_common_ref_non_interactive_multi_party_server_share {
|
|||||||
ksk_zero_encs_for_others,
|
ksk_zero_encs_for_others,
|
||||||
auto_keys_share,
|
auto_keys_share,
|
||||||
lwe_ksk_share,
|
lwe_ksk_share,
|
||||||
user_index,
|
user_id: user_index,
|
||||||
total_users,
|
total_users,
|
||||||
lwe_n,
|
lwe_n,
|
||||||
cr_seed,
|
cr_seed,
|
||||||
|
parameters,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1242,7 +1308,7 @@ mod impl_common_ref_non_interactive_multi_party_server_share {
|
|||||||
lwe_index: usize,
|
lwe_index: usize,
|
||||||
) -> &M {
|
) -> &M {
|
||||||
let self_segment = interactive_mult_party_user_id_lwe_segment(
|
let self_segment = interactive_mult_party_user_id_lwe_segment(
|
||||||
self.user_index,
|
self.user_id,
|
||||||
self.total_users,
|
self.total_users,
|
||||||
self.lwe_n,
|
self.lwe_n,
|
||||||
);
|
);
|
||||||
@@ -1255,7 +1321,7 @@ mod impl_common_ref_non_interactive_multi_party_server_share {
|
|||||||
lwe_index: usize,
|
lwe_index: usize,
|
||||||
) -> &M {
|
) -> &M {
|
||||||
let self_segment = interactive_mult_party_user_id_lwe_segment(
|
let self_segment = interactive_mult_party_user_id_lwe_segment(
|
||||||
self.user_index,
|
self.user_id,
|
||||||
self.total_users,
|
self.total_users,
|
||||||
self.lwe_n,
|
self.lwe_n,
|
||||||
);
|
);
|
||||||
@@ -1281,7 +1347,7 @@ mod impl_common_ref_non_interactive_multi_party_server_share {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(in super::super) fn user_index(&self) -> usize {
|
pub(in super::super) fn user_index(&self) -> usize {
|
||||||
self.user_index
|
self.user_id
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(in super::super) fn auto_keys_share(&self) -> &HashMap<usize, M> {
|
pub(in super::super) fn auto_keys_share(&self) -> &HashMap<usize, M> {
|
||||||
@@ -1293,8 +1359,8 @@ mod impl_common_ref_non_interactive_multi_party_server_share {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(in super::super) fn ui_to_s_ksk_zero_encs_for_user_i(&self, user_i: usize) -> &M {
|
pub(in super::super) fn ui_to_s_ksk_zero_encs_for_user_i(&self, user_i: usize) -> &M {
|
||||||
assert!(user_i != self.user_index);
|
assert!(user_i != self.user_id);
|
||||||
if user_i < self.user_index {
|
if user_i < self.user_id {
|
||||||
&self.ksk_zero_encs_for_others[user_i]
|
&self.ksk_zero_encs_for_others[user_i]
|
||||||
} else {
|
} else {
|
||||||
&self.ksk_zero_encs_for_others[user_i - 1]
|
&self.ksk_zero_encs_for_others[user_i - 1]
|
||||||
@@ -1303,7 +1369,11 @@ mod impl_common_ref_non_interactive_multi_party_server_share {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stores normal and shoup representation of Matrix elements (Normal, Shoup)
|
/// Stores both normal and shoup representation of elements in the container
|
||||||
|
/// (for ex, a matrix).
|
||||||
|
///
|
||||||
|
/// To access normal representation borrow self as a `self.as_ref()`. To access
|
||||||
|
/// shoup representation call `self.shoup_repr()`
|
||||||
pub(crate) struct NormalAndShoup<M>(M, M);
|
pub(crate) struct NormalAndShoup<M>(M, M);
|
||||||
|
|
||||||
impl<M: ToShoup> NormalAndShoup<M> {
|
impl<M: ToShoup> NormalAndShoup<M> {
|
||||||
@@ -1326,6 +1396,83 @@ impl<M> WithShoupRepr for NormalAndShoup<M> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) mod key_size {
|
||||||
|
use num_traits::{FromPrimitive, PrimInt};
|
||||||
|
|
||||||
|
use crate::{backend::Modulus, decomposer::NumInfo};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
/// Size of the Key in Bits
|
||||||
|
pub(crate) trait KeySize {
|
||||||
|
/// Returns size of the key in bits
|
||||||
|
fn size(&self) -> usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M: Matrix, El, S> KeySize
|
||||||
|
for CommonReferenceSeededInteractiveMultiPartyServerKeyShare<M, BoolParameters<El>, S>
|
||||||
|
where
|
||||||
|
M: SizeInBitsWithLogModulus,
|
||||||
|
M::R: SizeInBitsWithLogModulus,
|
||||||
|
El: PrimInt + NumInfo + FromPrimitive,
|
||||||
|
{
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
let mut total = 0;
|
||||||
|
|
||||||
|
let log_rlweq = self.parameters().rlwe_q().log_q();
|
||||||
|
self.self_leader_rgsws
|
||||||
|
.iter()
|
||||||
|
.for_each(|v| total += v.size(log_rlweq));
|
||||||
|
self.not_self_leader_rgsws
|
||||||
|
.iter()
|
||||||
|
.for_each(|v| total += v.size(log_rlweq));
|
||||||
|
self.auto_keys
|
||||||
|
.values()
|
||||||
|
.for_each(|v| total += v.size(log_rlweq));
|
||||||
|
|
||||||
|
let log_lweq = self.parameters().lwe_q().log_q();
|
||||||
|
total += self.lwe_ksk.size(log_lweq);
|
||||||
|
total
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<M: Matrix, El, S> KeySize
|
||||||
|
for CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare<M, BoolParameters<El>, S>
|
||||||
|
where
|
||||||
|
M: SizeInBitsWithLogModulus,
|
||||||
|
M::R: SizeInBitsWithLogModulus,
|
||||||
|
El: PrimInt + NumInfo + FromPrimitive,
|
||||||
|
{
|
||||||
|
fn size(&self) -> usize {
|
||||||
|
let mut total = 0;
|
||||||
|
|
||||||
|
let log_rlweq = self.parameters.rlwe_q().log_q();
|
||||||
|
self.self_leader_ni_rgsw_cts
|
||||||
|
.iter()
|
||||||
|
.for_each(|v| total += v.size(log_rlweq));
|
||||||
|
self.not_self_leader_ni_rgsw_cts
|
||||||
|
.iter()
|
||||||
|
.for_each(|v| total += v.size(log_rlweq));
|
||||||
|
self.ni_rgsw_zero_encs
|
||||||
|
.iter()
|
||||||
|
.for_each(|v| total += v.size(log_rlweq));
|
||||||
|
total += self.ui_to_s_ksk.size(log_rlweq);
|
||||||
|
self.ksk_zero_encs_for_others
|
||||||
|
.iter()
|
||||||
|
.for_each(|v| total += v.size(log_rlweq));
|
||||||
|
self.auto_keys_share
|
||||||
|
.values()
|
||||||
|
.for_each(|v| total += v.size(log_rlweq));
|
||||||
|
|
||||||
|
let log_lweq = self.parameters.lwe_q().log_q();
|
||||||
|
total += self.lwe_ksk_share.size(log_lweq);
|
||||||
|
|
||||||
|
total
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) mod tests {
|
pub(super) mod tests {
|
||||||
use itertools::izip;
|
use itertools::izip;
|
||||||
use num_traits::{FromPrimitive, PrimInt, ToPrimitive, Zero};
|
use num_traits::{FromPrimitive, PrimInt, ToPrimitive, Zero};
|
||||||
@@ -1333,6 +1480,7 @@ pub(super) mod tests {
|
|||||||
use crate::{
|
use crate::{
|
||||||
backend::{GetModulus, Modulus},
|
backend::{GetModulus, Modulus},
|
||||||
bool::ClientKey,
|
bool::ClientKey,
|
||||||
|
decomposer::NumInfo,
|
||||||
lwe::decrypt_lwe,
|
lwe::decrypt_lwe,
|
||||||
parameters::CiphertextModulus,
|
parameters::CiphertextModulus,
|
||||||
utils::TryConvertFrom1,
|
utils::TryConvertFrom1,
|
||||||
@@ -1376,7 +1524,7 @@ pub(super) mod tests {
|
|||||||
) -> f64
|
) -> f64
|
||||||
where
|
where
|
||||||
R: TryConvertFrom1<[S], CiphertextModulus<R::Element>>,
|
R: TryConvertFrom1<[S], CiphertextModulus<R::Element>>,
|
||||||
R::Element: Zero + FromPrimitive + PrimInt,
|
R::Element: Zero + FromPrimitive + PrimInt + NumInfo,
|
||||||
{
|
{
|
||||||
let noisy_m = decrypt_lwe(lwe_ct, &sk, modop);
|
let noisy_m = decrypt_lwe(lwe_ct, &sk, modop);
|
||||||
let noise = modop.sub(&m_expected, &noisy_m);
|
let noise = modop.sub(&m_expected, &noisy_m);
|
||||||
|
|||||||
@@ -20,8 +20,7 @@ pub use mp_api::*;
|
|||||||
pub type ClientKey = keys::ClientKey<[u8; 32], u64>;
|
pub type ClientKey = keys::ClientKey<[u8; 32], u64>;
|
||||||
|
|
||||||
pub enum ParameterSelector {
|
pub enum ParameterSelector {
|
||||||
HighCommunicationButFast2Party,
|
InteractiveLTE2Party,
|
||||||
MultiPartyLessThanOrEqualTo16,
|
|
||||||
NonInteractiveLTE2Party,
|
NonInteractiveLTE2Party,
|
||||||
NonInteractiveLTE4Party,
|
NonInteractiveLTE4Party,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,13 +27,10 @@ static MULTI_PARTY_CRS: OnceLock<MultiPartyCrs<[u8; 32]>> = OnceLock::new();
|
|||||||
|
|
||||||
pub fn set_parameter_set(select: ParameterSelector) {
|
pub fn set_parameter_set(select: ParameterSelector) {
|
||||||
match select {
|
match select {
|
||||||
ParameterSelector::MultiPartyLessThanOrEqualTo16 => {
|
ParameterSelector::InteractiveLTE2Party => {
|
||||||
BOOL_EVALUATOR.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(SMALL_MP_BOOL_PARAMS)));
|
BOOL_EVALUATOR.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(I_2P)));
|
||||||
}
|
|
||||||
ParameterSelector::HighCommunicationButFast2Party => {
|
|
||||||
BOOL_EVALUATOR
|
|
||||||
.with_borrow_mut(|v| *v = Some(BoolEvaluator::new(OPTIMISED_SMALL_MP_BOOL_PARAMS)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {
|
_ => {
|
||||||
panic!("Paramerters not supported")
|
panic!("Paramerters not supported")
|
||||||
}
|
}
|
||||||
@@ -65,7 +62,7 @@ pub fn gen_mp_keys_phase2<R, ModOp>(
|
|||||||
user_id: usize,
|
user_id: usize,
|
||||||
total_users: usize,
|
total_users: usize,
|
||||||
pk: &PublicKey<Vec<Vec<u64>>, R, ModOp>,
|
pk: &PublicKey<Vec<Vec<u64>>, R, ModOp>,
|
||||||
) -> CommonReferenceSeededMultiPartyServerKeyShare<
|
) -> CommonReferenceSeededInteractiveMultiPartyServerKeyShare<
|
||||||
Vec<Vec<u64>>,
|
Vec<Vec<u64>>,
|
||||||
BoolParameters<u64>,
|
BoolParameters<u64>,
|
||||||
MultiPartyCrs<[u8; 32]>,
|
MultiPartyCrs<[u8; 32]>,
|
||||||
@@ -93,17 +90,18 @@ pub fn aggregate_public_key_shares(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn aggregate_server_key_shares(
|
pub fn aggregate_server_key_shares(
|
||||||
shares: &[CommonReferenceSeededMultiPartyServerKeyShare<
|
shares: &[CommonReferenceSeededInteractiveMultiPartyServerKeyShare<
|
||||||
Vec<Vec<u64>>,
|
Vec<Vec<u64>>,
|
||||||
BoolParameters<u64>,
|
BoolParameters<u64>,
|
||||||
MultiPartyCrs<[u8; 32]>,
|
MultiPartyCrs<[u8; 32]>,
|
||||||
>],
|
>],
|
||||||
) -> SeededMultiPartyServerKey<Vec<Vec<u64>>, MultiPartyCrs<[u8; 32]>, BoolParameters<u64>> {
|
) -> SeededInteractiveMultiPartyServerKey<Vec<Vec<u64>>, MultiPartyCrs<[u8; 32]>, BoolParameters<u64>>
|
||||||
|
{
|
||||||
BoolEvaluator::with_local(|e| e.aggregate_multi_party_server_key_shares(shares))
|
BoolEvaluator::with_local(|e| e.aggregate_multi_party_server_key_shares(shares))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl
|
impl
|
||||||
SeededMultiPartyServerKey<
|
SeededInteractiveMultiPartyServerKey<
|
||||||
Vec<Vec<u64>>,
|
Vec<Vec<u64>>,
|
||||||
MultiPartyCrs<<DefaultSecureRng as NewWithSeed>::Seed>,
|
MultiPartyCrs<<DefaultSecureRng as NewWithSeed>::Seed>,
|
||||||
BoolParameters<u64>,
|
BoolParameters<u64>,
|
||||||
@@ -256,7 +254,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn multi_party_bool_gates() {
|
fn multi_party_bool_gates() {
|
||||||
set_parameter_set(ParameterSelector::HighCommunicationButFast2Party);
|
set_parameter_set(ParameterSelector::InteractiveLTE2Party);
|
||||||
let mut seed = [0u8; 32];
|
let mut seed = [0u8; 32];
|
||||||
thread_rng().fill_bytes(&mut seed);
|
thread_rng().fill_bytes(&mut seed);
|
||||||
set_mp_seed(seed);
|
set_mp_seed(seed);
|
||||||
@@ -349,7 +347,7 @@ mod tests {
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::ModulusPowerOf2, evaluator::BoolEncoding, pbs::PbsInfo,
|
backend::ModulusPowerOf2, evaluator::BoolEncoding, pbs::PbsInfo,
|
||||||
rgsw::secret_key_encrypt_rlwe, utils::WithLocal, Decryptor, ModularOpsU64,
|
rgsw::seeded_secret_key_encrypt_rlwe, utils::WithLocal, Decryptor, ModularOpsU64,
|
||||||
NttBackendU64, SampleExtractor,
|
NttBackendU64, SampleExtractor,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -441,8 +439,7 @@ mod tests {
|
|||||||
|
|
||||||
// encrypt message
|
// encrypt message
|
||||||
let mut rlwe_out = vec![0u64; parameters.rlwe_n().0];
|
let mut rlwe_out = vec![0u64; parameters.rlwe_n().0];
|
||||||
|
seeded_secret_key_encrypt_rlwe(
|
||||||
secret_key_encrypt_rlwe(
|
|
||||||
&message,
|
&message,
|
||||||
&mut rlwe_out,
|
&mut rlwe_out,
|
||||||
&sk_u,
|
&sk_u,
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ pub fn gen_server_key_share(
|
|||||||
client_key: &ClientKey,
|
client_key: &ClientKey,
|
||||||
) -> CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare<
|
) -> CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare<
|
||||||
Vec<Vec<u64>>,
|
Vec<Vec<u64>>,
|
||||||
|
BoolParameters<u64>,
|
||||||
NonInteractiveMultiPartyCrs<[u8; 32]>,
|
NonInteractiveMultiPartyCrs<[u8; 32]>,
|
||||||
> {
|
> {
|
||||||
BoolEvaluator::with_local(|e| {
|
BoolEvaluator::with_local(|e| {
|
||||||
@@ -90,6 +91,7 @@ pub fn gen_server_key_share(
|
|||||||
pub fn aggregate_server_key_shares(
|
pub fn aggregate_server_key_shares(
|
||||||
shares: &[CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare<
|
shares: &[CommonReferenceSeededNonInteractiveMultiPartyServerKeyShare<
|
||||||
Vec<Vec<u64>>,
|
Vec<Vec<u64>>,
|
||||||
|
BoolParameters<u64>,
|
||||||
NonInteractiveMultiPartyCrs<[u8; 32]>,
|
NonInteractiveMultiPartyCrs<[u8; 32]>,
|
||||||
>],
|
>],
|
||||||
) -> SeededNonInteractiveMultiPartyServerKey<
|
) -> SeededNonInteractiveMultiPartyServerKey<
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
use num_traits::{ConstZero, FromPrimitive, PrimInt};
|
use num_traits::{ConstZero, FromPrimitive, PrimInt};
|
||||||
|
|
||||||
use crate::{backend::Modulus, decomposer::Decomposer};
|
use crate::{
|
||||||
|
backend::Modulus,
|
||||||
|
decomposer::{Decomposer, NumInfo},
|
||||||
|
utils::log2,
|
||||||
|
};
|
||||||
|
|
||||||
pub(crate) trait DoubleDecomposerCount {
|
pub(crate) trait DoubleDecomposerCount {
|
||||||
type Count;
|
type Count;
|
||||||
@@ -84,27 +86,69 @@ pub(crate) enum ParameterVariant {
|
|||||||
}
|
}
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub struct BoolParameters<El> {
|
pub struct BoolParameters<El> {
|
||||||
|
/// RLWE ciphertext modulus Q
|
||||||
rlwe_q: CiphertextModulus<El>,
|
rlwe_q: CiphertextModulus<El>,
|
||||||
|
/// LWE ciphertext modulus q (usually referred to as Q_{ks})
|
||||||
lwe_q: CiphertextModulus<El>,
|
lwe_q: CiphertextModulus<El>,
|
||||||
|
/// Blind rotation modulus. It is the modulus to which we switch before
|
||||||
|
/// blind rotation.
|
||||||
|
///
|
||||||
|
/// Since blind rotation decrypts LWE ciphertext in the exponent of a ring
|
||||||
|
/// polynomial, which is a ring mod 2N, blind rotation modulus is
|
||||||
|
/// always <= 2N.
|
||||||
br_q: usize,
|
br_q: usize,
|
||||||
|
/// Ring dimension `N` for 2N^{th} cyclotomic polynomial ring
|
||||||
rlwe_n: PolynomialSize,
|
rlwe_n: PolynomialSize,
|
||||||
|
/// LWE dimension `n`
|
||||||
lwe_n: LweDimension,
|
lwe_n: LweDimension,
|
||||||
|
/// LWE key switch decompositon params
|
||||||
lwe_decomposer_params: (DecompostionLogBase, DecompositionCount),
|
lwe_decomposer_params: (DecompostionLogBase, DecompositionCount),
|
||||||
/// RLWE x RGSW decomposition count for (part A, part B)
|
/// Decompostion parameters for RLWE x RGSW.
|
||||||
|
///
|
||||||
|
/// We restrict decomposition for RLWE'(-sm) and RLWE'(m) to have same base
|
||||||
|
/// but can have different decomposition count. We refer to this
|
||||||
|
/// DoubleDecomposer / RlweDecomposer
|
||||||
|
///
|
||||||
|
/// Decomposition count `d_a` (i.e. for SignedDecompose(RLWE_A(m)) x
|
||||||
|
/// RLWE'(-sm)) and `d_b` (i.e. for SignedDecompose(RLWE_B(m)) x RLWE'(m))
|
||||||
|
/// are always stored as `(d_a, d_b)`
|
||||||
rlrg_decomposer_params: (
|
rlrg_decomposer_params: (
|
||||||
DecompostionLogBase,
|
DecompostionLogBase,
|
||||||
(DecompositionCount, DecompositionCount),
|
(DecompositionCount, DecompositionCount),
|
||||||
),
|
),
|
||||||
|
/// Decomposition parameters for RLWE automorphism
|
||||||
auto_decomposer_params: (DecompostionLogBase, DecompositionCount),
|
auto_decomposer_params: (DecompostionLogBase, DecompositionCount),
|
||||||
/// RGSW x RGSW decomposition count for (part A, part B)
|
/// Decomposition parameters for RGSW0 x RGSW1
|
||||||
|
///
|
||||||
|
/// `0` and `1` indicate that RGSW0 and RGSW1 may not use same decomposition
|
||||||
|
/// parameters.
|
||||||
|
///
|
||||||
|
/// In RGSW0 x RGSW1, decomposition parameters for RGSW1 are required.
|
||||||
|
/// Hence, the parameters we store are decomposition parameters of RGSW1.
|
||||||
|
///
|
||||||
|
/// Like RLWE x RGSW decomposition parameters (1) we restrict to same base
|
||||||
|
/// but can have different decomposition counts `d_a` and `d_b` and (2)
|
||||||
|
/// decomposition count `d_a` and `d_b` are always stored as `(d_a, d_b)`
|
||||||
|
///
|
||||||
|
/// RGSW0 x RGSW1 are optional because they only necessary to be supplied in
|
||||||
|
/// multi-party setting.
|
||||||
rgrg_decomposer_params: Option<(
|
rgrg_decomposer_params: Option<(
|
||||||
DecompostionLogBase,
|
DecompostionLogBase,
|
||||||
(DecompositionCount, DecompositionCount),
|
(DecompositionCount, DecompositionCount),
|
||||||
)>,
|
)>,
|
||||||
|
/// Decomposition parameters for non-interactive key switching from u_j to
|
||||||
|
/// s, hwere u_j is RLWE secret `u` of party `j` and `s` is the ideal RLWE
|
||||||
|
/// secret key.
|
||||||
|
///
|
||||||
|
/// Decomposition parameters for non-interactive key switching are optional
|
||||||
|
/// and must be supplied only for non-interactive multi-party
|
||||||
non_interactive_ui_to_s_key_switch_decomposer:
|
non_interactive_ui_to_s_key_switch_decomposer:
|
||||||
Option<(DecompostionLogBase, DecompositionCount)>,
|
Option<(DecompostionLogBase, DecompositionCount)>,
|
||||||
|
/// Group generator for Z^*_{2N}
|
||||||
g: usize,
|
g: usize,
|
||||||
|
/// Window size parameter for LMKC++ blind rotation
|
||||||
w: usize,
|
w: usize,
|
||||||
|
/// Parameter variant
|
||||||
variant: ParameterVariant,
|
variant: ParameterVariant,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,10 +391,10 @@ impl<T: ConstZero> CiphertextModulus<T> {
|
|||||||
|
|
||||||
impl<T> CiphertextModulus<T>
|
impl<T> CiphertextModulus<T>
|
||||||
where
|
where
|
||||||
T: PrimInt,
|
T: PrimInt + NumInfo,
|
||||||
{
|
{
|
||||||
pub(crate) fn _bits() -> usize {
|
fn _bits() -> usize {
|
||||||
std::mem::size_of::<T>() as usize * 8
|
T::BITS as usize
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _native(&self) -> bool {
|
fn _native(&self) -> bool {
|
||||||
@@ -376,7 +420,7 @@ where
|
|||||||
|
|
||||||
impl<T> Modulus for CiphertextModulus<T>
|
impl<T> Modulus for CiphertextModulus<T>
|
||||||
where
|
where
|
||||||
T: PrimInt + FromPrimitive,
|
T: PrimInt + FromPrimitive + NumInfo,
|
||||||
{
|
{
|
||||||
type Element = T;
|
type Element = T;
|
||||||
fn is_native(&self) -> bool {
|
fn is_native(&self) -> bool {
|
||||||
@@ -403,6 +447,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn map_element_to_i64(&self, v: &Self::Element) -> i64 {
|
fn map_element_to_i64(&self, v: &Self::Element) -> i64 {
|
||||||
|
assert!(*v <= self.largest_unsigned_value());
|
||||||
if *v > self._half_q() {
|
if *v > self._half_q() {
|
||||||
-((self.largest_unsigned_value() - *v) + T::one())
|
-((self.largest_unsigned_value() - *v) + T::one())
|
||||||
.to_i64()
|
.to_i64()
|
||||||
@@ -414,18 +459,24 @@ where
|
|||||||
|
|
||||||
fn map_element_from_f64(&self, v: f64) -> Self::Element {
|
fn map_element_from_f64(&self, v: f64) -> Self::Element {
|
||||||
let v = v.round();
|
let v = v.round();
|
||||||
|
|
||||||
|
let v_el = T::from_f64(v.abs()).unwrap();
|
||||||
|
assert!(v_el <= self.largest_unsigned_value());
|
||||||
|
|
||||||
if v < 0.0 {
|
if v < 0.0 {
|
||||||
self.largest_unsigned_value() - T::from_f64(v.abs()).unwrap() + T::one()
|
self.largest_unsigned_value() - v_el + T::one()
|
||||||
} else {
|
} else {
|
||||||
T::from_f64(v.abs()).unwrap()
|
v_el
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn map_element_from_i64(&self, v: i64) -> Self::Element {
|
fn map_element_from_i64(&self, v: i64) -> Self::Element {
|
||||||
|
let v_el = T::from_i64(v.abs()).unwrap();
|
||||||
|
assert!(v_el <= self.largest_unsigned_value());
|
||||||
if v < 0 {
|
if v < 0 {
|
||||||
self.largest_unsigned_value() - T::from_i64(v.abs()).unwrap() + T::one()
|
self.largest_unsigned_value() - v_el + T::one()
|
||||||
} else {
|
} else {
|
||||||
T::from_i64(v.abs()).unwrap()
|
v_el
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,6 +491,14 @@ where
|
|||||||
self.0.to_f64()
|
self.0.to_f64()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn log_q(&self) -> usize {
|
||||||
|
if self.is_native() {
|
||||||
|
Self::_bits()
|
||||||
|
} else {
|
||||||
|
log2(&self.q().unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) const MP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {
|
pub(crate) const MP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {
|
||||||
@@ -491,7 +550,7 @@ pub(crate) const I_2P: BoolParameters<u64> = BoolParameters::<u64> {
|
|||||||
lwe_q: CiphertextModulus::new_non_native(1 << 15),
|
lwe_q: CiphertextModulus::new_non_native(1 << 15),
|
||||||
br_q: 1 << 11,
|
br_q: 1 << 11,
|
||||||
rlwe_n: PolynomialSize(1 << 11),
|
rlwe_n: PolynomialSize(1 << 11),
|
||||||
lwe_n: LweDimension(500),
|
lwe_n: LweDimension(480),
|
||||||
lwe_decomposer_params: (DecompostionLogBase(1), DecompositionCount(11)),
|
lwe_decomposer_params: (DecompostionLogBase(1), DecompositionCount(11)),
|
||||||
rlrg_decomposer_params: (
|
rlrg_decomposer_params: (
|
||||||
DecompostionLogBase(16),
|
DecompostionLogBase(16),
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use rand_distr::uniform::SampleUniform;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::{GetModulus, Modulus},
|
backend::{GetModulus, Modulus},
|
||||||
decomposer::RlweDecomposer,
|
decomposer::{Decomposer, NumInfo, RlweDecomposer},
|
||||||
lwe::{decrypt_lwe, lwe_key_switch},
|
lwe::{decrypt_lwe, lwe_key_switch},
|
||||||
parameters::{BoolParameters, CiphertextModulus},
|
parameters::{BoolParameters, CiphertextModulus},
|
||||||
random::{DefaultSecureRng, RandomFillUniformInModulus},
|
random::{DefaultSecureRng, RandomFillUniformInModulus},
|
||||||
@@ -15,8 +15,8 @@ use crate::{
|
|||||||
RuntimeScratchMutRef,
|
RuntimeScratchMutRef,
|
||||||
},
|
},
|
||||||
utils::{encode_x_pow_si_with_emebedding_factor, tests::Stats, TryConvertFrom1},
|
utils::{encode_x_pow_si_with_emebedding_factor, tests::Stats, TryConvertFrom1},
|
||||||
ArithmeticOps, ClientKey, Decomposer, MatrixEntity, MatrixMut, ModInit, Ntt, NttInit,
|
ArithmeticOps, ClientKey, MatrixEntity, MatrixMut, ModInit, Ntt, NttInit, RowEntity, RowMut,
|
||||||
RowEntity, RowMut, VectorOps,
|
VectorOps,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::keys::tests::{ideal_sk_lwe, ideal_sk_rlwe};
|
use super::keys::tests::{ideal_sk_lwe, ideal_sk_rlwe};
|
||||||
@@ -84,7 +84,7 @@ fn collect_server_key_stats<
|
|||||||
) -> ServerKeyStats<i64>
|
) -> ServerKeyStats<i64>
|
||||||
where
|
where
|
||||||
M::R: RowMut + RowEntity + TryConvertFrom1<[i32], CiphertextModulus<M::MatElement>> + Clone,
|
M::R: RowMut + RowEntity + TryConvertFrom1<[i32], CiphertextModulus<M::MatElement>> + Clone,
|
||||||
M::MatElement: Copy + PrimInt + FromPrimitive + SampleUniform + Zero + Debug,
|
M::MatElement: Copy + PrimInt + FromPrimitive + SampleUniform + Zero + Debug + NumInfo,
|
||||||
{
|
{
|
||||||
let ideal_sk_rlwe = ideal_sk_rlwe(client_keys);
|
let ideal_sk_rlwe = ideal_sk_rlwe(client_keys);
|
||||||
let ideal_sk_lwe = ideal_sk_lwe(client_keys);
|
let ideal_sk_lwe = ideal_sk_lwe(client_keys);
|
||||||
@@ -370,27 +370,30 @@ mod tests {
|
|||||||
fn qwerty() {
|
fn qwerty() {
|
||||||
use crate::{
|
use crate::{
|
||||||
aggregate_public_key_shares, aggregate_server_key_shares,
|
aggregate_public_key_shares, aggregate_server_key_shares,
|
||||||
bool::keys::ServerKeyEvaluationDomain,
|
bool::keys::{key_size::KeySize, ServerKeyEvaluationDomain},
|
||||||
evaluator::MultiPartyCrs,
|
evaluator::MultiPartyCrs,
|
||||||
gen_client_key, gen_mp_keys_phase1, gen_mp_keys_phase2,
|
gen_client_key, gen_mp_keys_phase1, gen_mp_keys_phase2,
|
||||||
parameters::{BoolParameters, CiphertextModulus},
|
parameters::CiphertextModulus,
|
||||||
random::DefaultSecureRng,
|
random::DefaultSecureRng,
|
||||||
set_mp_seed, set_parameter_set,
|
set_mp_seed, set_parameter_set,
|
||||||
utils::WithLocal,
|
utils::WithLocal,
|
||||||
BoolEvaluator, DefaultDecomposer, ModularOpsU64, Ntt, NttBackendU64,
|
BoolEvaluator, DefaultDecomposer, ModularOpsU64, Ntt, NttBackendU64,
|
||||||
};
|
};
|
||||||
|
|
||||||
set_parameter_set(crate::ParameterSelector::HighCommunicationButFast2Party);
|
set_parameter_set(crate::ParameterSelector::InteractiveLTE2Party);
|
||||||
set_mp_seed(MultiPartyCrs::random().seed);
|
set_mp_seed(MultiPartyCrs::random().seed);
|
||||||
let parties = 2;
|
let parties = 2;
|
||||||
let cks = (0..parties).map(|_| gen_client_key()).collect_vec();
|
let cks = (0..parties).map(|_| gen_client_key()).collect_vec();
|
||||||
let pk_shares = cks.iter().map(|k| gen_mp_keys_phase1(k)).collect_vec();
|
let pk_shares = cks.iter().map(|k| gen_mp_keys_phase1(k)).collect_vec();
|
||||||
|
|
||||||
let pk = aggregate_public_key_shares(&pk_shares);
|
let pk = aggregate_public_key_shares(&pk_shares);
|
||||||
let server_key_shares = cks
|
let server_key_shares = cks
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(index, k)| gen_mp_keys_phase2(k, index, parties, &pk))
|
.map(|(index, k)| gen_mp_keys_phase2(k, index, parties, &pk))
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
|
|
||||||
|
println!("Size: {}", server_key_shares[0].size());
|
||||||
let seeded_server_key = aggregate_server_key_shares(&server_key_shares);
|
let seeded_server_key = aggregate_server_key_shares(&server_key_shares);
|
||||||
let server_key_eval =
|
let server_key_eval =
|
||||||
ServerKeyEvaluationDomain::<_, _, DefaultSecureRng, NttBackendU64>::from(
|
ServerKeyEvaluationDomain::<_, _, DefaultSecureRng, NttBackendU64>::from(
|
||||||
@@ -428,11 +431,16 @@ mod tests {
|
|||||||
#[cfg(feature = "non_interactive_mp")]
|
#[cfg(feature = "non_interactive_mp")]
|
||||||
fn querty2() {
|
fn querty2() {
|
||||||
use crate::{
|
use crate::{
|
||||||
aggregate_server_key_shares, bool::keys::NonInteractiveServerKeyEvaluationDomain,
|
aggregate_server_key_shares,
|
||||||
evaluator::NonInteractiveMultiPartyCrs, gen_client_key, gen_server_key_share,
|
bool::keys::{key_size::KeySize, NonInteractiveServerKeyEvaluationDomain},
|
||||||
parameters::CiphertextModulus, random::DefaultSecureRng, set_common_reference_seed,
|
decomposer::DefaultDecomposer,
|
||||||
set_parameter_set, utils::WithLocal, BoolEvaluator, DefaultDecomposer, ModularOpsU64,
|
evaluator::NonInteractiveMultiPartyCrs,
|
||||||
NttBackendU64,
|
gen_client_key, gen_server_key_share,
|
||||||
|
parameters::CiphertextModulus,
|
||||||
|
random::DefaultSecureRng,
|
||||||
|
set_common_reference_seed, set_parameter_set,
|
||||||
|
utils::WithLocal,
|
||||||
|
BoolEvaluator, ModularOpsU64, NttBackendU64,
|
||||||
};
|
};
|
||||||
|
|
||||||
set_parameter_set(crate::ParameterSelector::NonInteractiveLTE2Party);
|
set_parameter_set(crate::ParameterSelector::NonInteractiveLTE2Party);
|
||||||
@@ -444,6 +452,7 @@ mod tests {
|
|||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(user_id, k)| gen_server_key_share(user_id, parties, k))
|
.map(|(user_id, k)| gen_server_key_share(user_id, parties, k))
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
|
println!("Size: {}", server_key_shares[0].size());
|
||||||
let server_key = aggregate_server_key_shares(&server_key_shares);
|
let server_key = aggregate_server_key_shares(&server_key_shares);
|
||||||
|
|
||||||
let server_key_eval =
|
let server_key_eval =
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ use crate::{
|
|||||||
parameters::{
|
parameters::{
|
||||||
DecompositionCount, DecompostionLogBase, DoubleDecomposerParams, SingleDecomposerParams,
|
DecompositionCount, DecompostionLogBase, DoubleDecomposerParams, SingleDecomposerParams,
|
||||||
},
|
},
|
||||||
|
utils::log2,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn gadget_vector<T: PrimInt>(logq: usize, logb: usize, d: usize) -> Vec<T> {
|
fn gadget_vector<T: PrimInt>(logq: usize, logb: usize, d: usize) -> Vec<T> {
|
||||||
@@ -156,12 +157,7 @@ impl<
|
|||||||
|
|
||||||
fn new(q: T, logb: usize, d: usize) -> DefaultDecomposer<T> {
|
fn new(q: T, logb: usize, d: usize) -> DefaultDecomposer<T> {
|
||||||
// if q is power of 2, then `BITS - leading_zeros` outputs logq + 1.
|
// if q is power of 2, then `BITS - leading_zeros` outputs logq + 1.
|
||||||
let logq = if q & (q - T::one()) == T::zero() {
|
let logq = log2(&q);
|
||||||
(T::BITS - q.leading_zeros() - 1) as usize
|
|
||||||
} else {
|
|
||||||
(T::BITS - q.leading_zeros()) as usize
|
|
||||||
};
|
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
logq >= (logb * d),
|
logq >= (logb * d),
|
||||||
"Decomposer wants logq >= logb*d but got logq={logq}, logb={logb}, d={d}"
|
"Decomposer wants logq >= logb*d but got logq={logq}, logb={logb}, d={d}"
|
||||||
|
|||||||
22
src/lib.rs
22
src/lib.rs
@@ -24,10 +24,11 @@ pub use backend::{
|
|||||||
// gen_mp_keys_phase1, gen_mp_keys_phase2, set_mp_seed, set_parameter_set,
|
// gen_mp_keys_phase1, gen_mp_keys_phase2, set_mp_seed, set_parameter_set,
|
||||||
// ParameterSelector, };
|
// ParameterSelector, };
|
||||||
pub use bool::*;
|
pub use bool::*;
|
||||||
pub use decomposer::{Decomposer, DecomposerIter, DefaultDecomposer};
|
|
||||||
pub use ntt::{Ntt, NttBackendU64, NttInit};
|
pub use ntt::{Ntt, NttBackendU64, NttInit};
|
||||||
pub use shortint::FheUint8;
|
pub use shortint::FheUint8;
|
||||||
|
|
||||||
|
pub use decomposer::{Decomposer, DecomposerIter, DefaultDecomposer};
|
||||||
|
|
||||||
pub trait Matrix: AsRef<[Self::R]> {
|
pub trait Matrix: AsRef<[Self::R]> {
|
||||||
type MatElement;
|
type MatElement;
|
||||||
type R: Row<Element = Self::MatElement>;
|
type R: Row<Element = Self::MatElement>;
|
||||||
@@ -193,3 +194,22 @@ pub trait SampleExtractor<R> {
|
|||||||
trait Encoder<F, T> {
|
trait Encoder<F, T> {
|
||||||
fn encode(&self, v: F) -> T;
|
fn encode(&self, v: F) -> T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait SizeInBitsWithLogModulus {
|
||||||
|
/// Returns size of `Self` containing several elements mod Q where
|
||||||
|
/// 2^{log_modulus-1} < Q <= `2^log_modulus`
|
||||||
|
fn size(&self, log_modulus: usize) -> usize;
|
||||||
|
}
|
||||||
|
impl SizeInBitsWithLogModulus for Vec<Vec<u64>> {
|
||||||
|
fn size(&self, log_modulus: usize) -> usize {
|
||||||
|
let mut total = 0;
|
||||||
|
self.iter().for_each(|r| total += log_modulus * r.len());
|
||||||
|
total
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SizeInBitsWithLogModulus for Vec<u64> {
|
||||||
|
fn size(&self, log_modulus: usize) -> usize {
|
||||||
|
self.len() * log_modulus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
10
src/utils.rs
10
src/utils.rs
@@ -5,6 +5,7 @@ use num_traits::{One, PrimInt, Signed};
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::Modulus,
|
backend::Modulus,
|
||||||
|
decomposer::NumInfo,
|
||||||
random::{RandomElementInModulus, RandomFill},
|
random::{RandomElementInModulus, RandomFill},
|
||||||
Matrix, RowEntity, RowMut,
|
Matrix, RowEntity, RowMut,
|
||||||
};
|
};
|
||||||
@@ -226,6 +227,15 @@ pub(crate) fn puncture_p_rng<S: Default + Copy, R: RandomFill<S>>(
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn log2<T: PrimInt + NumInfo>(v: &T) -> usize {
|
||||||
|
if (*v & (*v - T::one())) == T::zero() {
|
||||||
|
// value is power of 2
|
||||||
|
(T::BITS - v.leading_zeros() - 1) as usize
|
||||||
|
} else {
|
||||||
|
(T::BITS - v.leading_zeros()) as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait TryConvertFrom1<T: ?Sized, P> {
|
pub trait TryConvertFrom1<T: ?Sized, P> {
|
||||||
fn try_convert_from(value: &T, parameters: &P) -> Self;
|
fn try_convert_from(value: &T, parameters: &P) -> Self;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user