fix parameters
@@ -12,6 +12,7 @@ };
use itertools::{izip, partition, Itertools}; use num_traits::{FromPrimitive, Num, One, Pow, PrimInt, ToPrimitive, WrappingSub, Zero}; +use rand::Rng; use rand_distr::uniform::SampleUniform; use crate::{@@ -20,7 +21,7 @@ ArithmeticOps, GetModulus, ModInit, ModularOpsU64, Modulus, ShoupMatrixFMA, VectorOps,
}, decomposer::{Decomposer, DefaultDecomposer, NumInfo, RlweDecomposer}, lwe::{decrypt_lwe, encrypt_lwe, lwe_key_switch, lwe_ksk_keygen, measure_noise_lwe, LweSecret}, - multi_party::public_key_share, + multi_party::{non_interactive_ksk_gen, public_key_share}, ntt::{self, Ntt, NttBackendU64, NttInit}, pbs::{pbs, sample_extract, PbsInfo, PbsKey, WithShoupRepr}, random::{@@ -44,7 +45,7 @@ use super::{
keys::ClientKey, parameters::{BoolParameters, CiphertextModulus}, CommonReferenceSeededCollectivePublicKeyShare, CommonReferenceSeededMultiPartyServerKeyShare, - SeededMultiPartyServerKey, SeededServerKey, ServerKeyEvaluationDomain, + NonInteractiveClientKey, SeededMultiPartyServerKey, SeededServerKey, ServerKeyEvaluationDomain, ShoupServerKeyEvaluationDomain, };@@ -711,6 +712,23 @@ cr_seed,
self.pbs_info.parameters.clone(), ) }) + } + + pub(super) fn non_interactive_multi_party_key_share( + self_ui_to_ksk_seed: [u8; 32], + others_ui_to_ksk_seed: &[[u8; 32]], + client_key: &NonInteractiveClientKey, + ) { + // // ui_to_s_ksk + // non_interactive_ksk_gen( + // client_key.sk_rlwe().values(), + // client_key.sk_u_rlwe().values(), + // gadget_vec, + // p_rng, + // rng, + // nttop, + // modop, + // ) } pub(super) fn multi_party_public_key_share(
@@ -19,6 +19,14 @@ sk_rlwe: RlweSecret,
sk_lwe: LweSecret, } +/// Client key with RLWE and LWE secrets +#[derive(Clone)] +pub struct NonInteractiveClientKey { + sk_rlwe: RlweSecret, + sk_u_rlwe: RlweSecret, + sk_lwe: LweSecret, +} + mod impl_ck { use super::*;@@ -36,6 +44,44 @@ }
pub(in super::super) fn sk_rlwe(&self) -> &RlweSecret { &self.sk_rlwe + } + + pub(in super::super) fn sk_lwe(&self) -> &LweSecret { + &self.sk_lwe + } + } + + // Client key + impl NonInteractiveClientKey { + pub(in super::super) fn random() -> Self { + let sk_rlwe = RlweSecret::random(0, 0); + let sk_u_rlwe = RlweSecret::random(0, 0); + let sk_lwe = LweSecret::random(0, 0); + Self { + sk_rlwe, + sk_u_rlwe, + sk_lwe, + } + } + + 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, + } + } + + pub(in super::super) fn sk_rlwe(&self) -> &RlweSecret { + &self.sk_rlwe + } + + pub(in super::super) fn sk_u_rlwe(&self) -> &RlweSecret { + &self.sk_u_rlwe } pub(in super::super) fn sk_lwe(&self) -> &LweSecret {
@@ -2,6 +2,91 @@ use num_traits::{ConstZero, FromPrimitive, PrimInt};
use crate::{backend::Modulus, decomposer::Decomposer}; +trait DoubleDecomposerParams { + type Base; + type Count; + + fn new(base: Self::Base, count_a: Self::Count, count_b: Self::Count) -> Self; + fn decomposition_base(&self) -> Self::Base; + fn decomposition_count_a(&self) -> Self::Count; + fn decomposition_count_b(&self) -> Self::Count; +} + +trait SingleDecomposerParams { + type Base; + type Count; + + fn new(base: Self::Base, count: Self::Count) -> Self; + fn decomposition_base(&self) -> Self::Base; + fn decomposition_count(&self) -> Self::Count; +} + +impl DoubleDecomposerParams + for ( + DecompostionLogBase, + (DecompositionCount, DecompositionCount), + ) +{ + type Base = DecompostionLogBase; + type Count = DecompositionCount; + + fn new( + base: DecompostionLogBase, + count_a: DecompositionCount, + count_b: DecompositionCount, + ) -> Self { + (base, (count_a, count_b)) + } + + fn decomposition_base(&self) -> Self::Base { + self.0 + } + + fn decomposition_count_a(&self) -> Self::Count { + self.1 .0 + } + + fn decomposition_count_b(&self) -> Self::Count { + self.1 .1 + } +} + +impl SingleDecomposerParams for (DecompostionLogBase, DecompositionCount) { + type Base = DecompostionLogBase; + type Count = DecompositionCount; + + fn new(base: DecompostionLogBase, count: DecompositionCount) -> Self { + (base, count) + } + + fn decomposition_base(&self) -> Self::Base { + self.0 + } + + fn decomposition_count(&self) -> Self::Count { + self.1 + } +} + +// impl DecomposerParams for (DecompostionLogBase, (DecompositionCount)) { +// type Base = DecompostionLogBase; +// type Count = DecompositionCount; + +// fn decomposition_base(&self) -> Self::Base { +// self.0 +// } + +// fn decomposition_count(&self) -> Self::Count { +// self.1 +// } +// } + +#[derive(Clone, PartialEq, Debug)] +pub(crate) enum ParameterVariant { + SingleParty, + MultiParty, + NonInteractiveMultiParty, +} #[derive(Clone, PartialEq)] pub struct BoolParameters<El> { rlwe_q: CiphertextModulus<El>,@@ -9,18 +94,21 @@ lwe_q: CiphertextModulus<El>,
br_q: usize, rlwe_n: PolynomialSize, lwe_n: LweDimension, - lwe_decomposer_base: DecompostionLogBase, - lwe_decomposer_count: DecompositionCount, - rlrg_decomposer_base: DecompostionLogBase, + lwe_decomposer_params: (DecompostionLogBase, DecompositionCount), /// RLWE x RGSW decomposition count for (part A, part B) - rlrg_decomposer_count: (DecompositionCount, DecompositionCount), - rgrg_decomposer_base: DecompostionLogBase, + rlrg_decomposer_params: ( + DecompostionLogBase, + (DecompositionCount, DecompositionCount), + ), /// RGSW x RGSW decomposition count for (part A, part B) - rgrg_decomposer_count: (DecompositionCount, DecompositionCount), - auto_decomposer_base: DecompostionLogBase, - auto_decomposer_count: DecompositionCount, + rgrg_decomposer_params: Option<( + DecompostionLogBase, + (DecompositionCount, DecompositionCount), + )>, + auto_decomposer_params: (DecompostionLogBase, DecompositionCount), g: usize, w: usize, + variant: ParameterVariant, } impl<El> BoolParameters<El> {@@ -53,53 +141,57 @@ self.w
} pub(crate) fn rlwe_rgsw_decomposition_base(&self) -> DecompostionLogBase { - self.rlrg_decomposer_base + self.rlrg_decomposer_params.0 } pub(crate) fn rlwe_rgsw_decomposition_count(&self) -> (DecompositionCount, DecompositionCount) { - self.rlrg_decomposer_count - } - - pub(crate) fn rgsw_rgsw_decomposition_base(&self) -> DecompostionLogBase { - self.rgrg_decomposer_base + self.rlrg_decomposer_params.1 } pub(crate) fn rgsw_rgsw_decomposition_count(&self) -> (DecompositionCount, DecompositionCount) { - self.rgrg_decomposer_count + let params = self.rgrg_decomposer_params.expect(&format!( + "Parameter variant {:?} does not support RGSW x RGSW", + self.variant + )); + params.1 } pub(crate) fn auto_decomposition_base(&self) -> DecompostionLogBase { - self.auto_decomposer_base + self.auto_decomposer_params.decomposition_base() } pub(crate) fn auto_decomposition_count(&self) -> DecompositionCount { - self.auto_decomposer_count + self.auto_decomposer_params.decomposition_count() } pub(crate) fn lwe_decomposition_base(&self) -> DecompostionLogBase { - self.lwe_decomposer_base + self.lwe_decomposer_params.decomposition_base() } pub(crate) fn lwe_decomposition_count(&self) -> DecompositionCount { - self.lwe_decomposer_count + self.lwe_decomposer_params.decomposition_count() } pub(crate) fn rgsw_rgsw_decomposer<D: Decomposer<Element = El>>(&self) -> (D, D) where El: Copy, { + let params = self.rgrg_decomposer_params.expect(&format!( + "Parameter variant {:?} does not support RGSW x RGSW", + self.variant + )); ( // A D::new( self.rlwe_q.0, - self.rgrg_decomposer_base.0, - self.rgrg_decomposer_count.0 .0, + params.decomposition_base().0, + params.decomposition_count_a().0, ), // B D::new( self.rlwe_q.0, - self.rgrg_decomposer_base.0, - self.rgrg_decomposer_count.1 .0, + params.decomposition_base().0, + params.decomposition_count_b().0, ), ) }@@ -110,8 +202,8 @@ El: Copy,
{ D::new( self.rlwe_q.0, - self.auto_decomposer_base.0, - self.auto_decomposer_count.0, + self.auto_decomposer_params.decomposition_base().0, + self.auto_decomposer_params.decomposition_count().0, ) }@@ -121,8 +213,8 @@ El: Copy,
{ D::new( self.lwe_q.0, - self.lwe_decomposer_base.0, - self.lwe_decomposer_count.0, + self.lwe_decomposer_params.decomposition_base().0, + self.lwe_decomposer_params.decomposition_count().0, ) }@@ -134,14 +226,14 @@ (
// A D::new( self.rlwe_q.0, - self.rlrg_decomposer_base.0, - self.rlrg_decomposer_count.0 .0, + self.rlrg_decomposer_params.decomposition_base().0, + self.rlrg_decomposer_params.decomposition_count_a().0, ), // B D::new( self.rlwe_q.0, - self.rlrg_decomposer_base.0, - self.rlrg_decomposer_count.1 .0, + self.rlrg_decomposer_params.decomposition_base().0, + self.rlrg_decomposer_params.decomposition_count_b().0, ), ) }@@ -298,16 +390,16 @@ lwe_q: CiphertextModulus::new_non_native(1 << 16),
br_q: 1 << 10, rlwe_n: PolynomialSize(1 << 10), lwe_n: LweDimension(500), - lwe_decomposer_base: DecompostionLogBase(4), - lwe_decomposer_count: DecompositionCount(4), - rlrg_decomposer_base: DecompostionLogBase(7), - rlrg_decomposer_count: (DecompositionCount(4), DecompositionCount(4)), - rgrg_decomposer_base: DecompostionLogBase(7), - rgrg_decomposer_count: (DecompositionCount(4), DecompositionCount(4)), - auto_decomposer_base: DecompostionLogBase(7), - auto_decomposer_count: DecompositionCount(4), + lwe_decomposer_params: (DecompostionLogBase(4), DecompositionCount(4)), + rlrg_decomposer_params: ( + DecompostionLogBase(7), + (DecompositionCount(4), DecompositionCount(4)), + ), + rgrg_decomposer_params: None, + auto_decomposer_params: (DecompostionLogBase(7), DecompositionCount(4)), g: 5, w: 5, + variant: ParameterVariant::SingleParty, }; pub(crate) const MP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {@@ -316,16 +408,19 @@ lwe_q: CiphertextModulus::new_non_native(1 << 20),
br_q: 1 << 11, rlwe_n: PolynomialSize(1 << 11), lwe_n: LweDimension(500), - lwe_decomposer_base: DecompostionLogBase(4), - lwe_decomposer_count: DecompositionCount(5), - rlrg_decomposer_base: DecompostionLogBase(12), - rlrg_decomposer_count: (DecompositionCount(5), DecompositionCount(5)), - rgrg_decomposer_base: DecompostionLogBase(12), - rgrg_decomposer_count: (DecompositionCount(5), DecompositionCount(5)), - auto_decomposer_base: DecompostionLogBase(12), - auto_decomposer_count: DecompositionCount(5), + lwe_decomposer_params: (DecompostionLogBase(4), DecompositionCount(5)), + rlrg_decomposer_params: ( + DecompostionLogBase(12), + (DecompositionCount(5), DecompositionCount(5)), + ), + rgrg_decomposer_params: Some(( + DecompostionLogBase(12), + (DecompositionCount(5), DecompositionCount(5)), + )), + auto_decomposer_params: (DecompostionLogBase(12), DecompositionCount(5)), g: 5, w: 10, + variant: ParameterVariant::MultiParty, }; pub(crate) const SMALL_MP_BOOL_PARAMS: BoolParameters<u64> = BoolParameters::<u64> {@@ -334,16 +429,19 @@ lwe_q: CiphertextModulus::new_non_native(1 << 20),
br_q: 1 << 11, rlwe_n: PolynomialSize(1 << 11), lwe_n: LweDimension(600), - lwe_decomposer_base: DecompostionLogBase(4), - lwe_decomposer_count: DecompositionCount(5), - rlrg_decomposer_base: DecompostionLogBase(11), - rlrg_decomposer_count: (DecompositionCount(2), DecompositionCount(1)), - rgrg_decomposer_base: DecompostionLogBase(11), - rgrg_decomposer_count: (DecompositionCount(5), DecompositionCount(4)), - auto_decomposer_base: DecompostionLogBase(11), - auto_decomposer_count: DecompositionCount(2), + lwe_decomposer_params: (DecompostionLogBase(4), DecompositionCount(5)), + rlrg_decomposer_params: ( + DecompostionLogBase(11), + (DecompositionCount(2), DecompositionCount(1)), + ), + rgrg_decomposer_params: Some(( + DecompostionLogBase(11), + (DecompositionCount(5), DecompositionCount(4)), + )), + auto_decomposer_params: (DecompostionLogBase(11), DecompositionCount(2)), g: 5, w: 10, + variant: ParameterVariant::MultiParty, }; #[cfg(test)]
@@ -57,7 +57,7 @@ NttOp: Ntt<Element = M::MatElement>,
ModOp: VectorOps<Element = M::MatElement> + GetModulus<Element = M::MatElement>, >( s: &[S], - ephemeral_u: &[S], + u: &[S], m: &[M::MatElement], gadget_vec: &[M::MatElement], p_rng: &mut PRng,@@ -69,14 +69,14 @@ where
<M as Matrix>::R: RowMut + TryConvertFrom1<[S], ModOp::M> + RowEntity, M::MatElement: Copy, { - assert_eq!(s.len(), ephemeral_u.len()); + assert_eq!(s.len(), u.len()); assert_eq!(s.len(), m.len()); let q = modop.modulus(); let d = gadget_vec.len(); let ring_size = s.len(); let mut s_poly_eval = M::R::try_convert_from(s, q); - let mut u_poly_eval = M::R::try_convert_from(ephemeral_u, q); + let mut u_poly_eval = M::R::try_convert_from(u, q); nttop.forward(s_poly_eval.as_mut()); nttop.forward(u_poly_eval.as_mut());@@ -125,7 +125,7 @@
(enc_beta_m, zero_encryptions) } -fn non_interactive_ksk_gen< +pub(crate) fn non_interactive_ksk_gen< M: MatrixMut + MatrixEntity, S, PRng: RandomFillUniformInModulus<[M::MatElement], ModOp::M>,@@ -134,7 +134,7 @@ NttOp: Ntt<Element = M::MatElement>,
ModOp: VectorOps<Element = M::MatElement> + GetModulus<Element = M::MatElement>, >( s: &[S], - ephemeral_u: &[S], + u: &[S], gadget_vec: &[M::MatElement], p_rng: &mut PRng, rng: &mut Rng,@@ -144,7 +144,7 @@ ) where
<M as Matrix>::R: RowMut + TryConvertFrom1<[S], ModOp::M> + RowEntity, M::MatElement: Copy, { - assert_eq!(s.len(), ephemeral_u.len()); + assert_eq!(s.len(), u.len()); let q = modop.modulus(); let d = gadget_vec.len();@@ -152,24 +152,16 @@ let ring_size = s.len();
let mut s_poly_eval = M::R::try_convert_from(s, q); nttop.forward(s_poly_eval.as_mut()); - let u_poly = M::R::try_convert_from(ephemeral_u, q); + let u_poly = M::R::try_convert_from(u, q); // a_i * s + \beta u + e - // a_i * s + e let mut ksk = M::zeros(d, ring_size); - let mut zero_encs = M::zeros(d, ring_size); let mut scratch_space = M::R::zeros(ring_size); - izip!( - ksk.iter_rows_mut(), - zero_encs.iter_rows_mut(), - gadget_vec.iter() - ) - .for_each(|(e_ksk, e_zero, beta)| { + izip!(ksk.iter_rows_mut(), gadget_vec.iter()).for_each(|(e_ksk, beta)| { // sample a_i RandomFillUniformInModulus::random_fill(p_rng, q, e_ksk.as_mut()); - e_zero.as_mut().copy_from_slice(e_ksk.as_ref()); // a_i * s + e + beta u nttop.forward(e_ksk.as_mut());@@ -183,13 +175,51 @@ // \beta * u
modop.elwise_scalar_mul(scratch_space.as_mut(), u_poly.as_ref(), beta); // a_i * s + e + \beta * u modop.elwise_add_mut(e_ksk.as_mut(), scratch_space.as_ref()); + }); +} + +pub(crate) fn non_interactive_ksk_zero_encryptions_for_other_party_i< + M: MatrixMut + MatrixEntity, + S, + PRng: RandomFillUniformInModulus<[M::MatElement], ModOp::M>, + Rng: RandomFillGaussianInModulus<[M::MatElement], ModOp::M>, + NttOp: Ntt<Element = M::MatElement>, + ModOp: VectorOps<Element = M::MatElement> + GetModulus<Element = M::MatElement>, +>( + s: &[S], + gadget_vec: &[M::MatElement], + p_rng: &mut PRng, + rng: &mut Rng, + nttop: &NttOp, + modop: &ModOp, +) -> M +where + <M as Matrix>::R: RowMut + TryConvertFrom1<[S], ModOp::M> + RowEntity, + M::MatElement: Copy, +{ + let q = modop.modulus(); + let d = gadget_vec.len(); + let ring_size = s.len(); + + let mut s_poly_eval = M::R::try_convert_from(s, q); + nttop.forward(s_poly_eval.as_mut()); + + // a_i * s + e + let mut zero_encs = M::zeros(d, ring_size); + + let mut scratch_space = M::R::zeros(ring_size); + + izip!(zero_encs.iter_rows_mut()).for_each(|(e_zero)| { + // sample a_i + RandomFillUniformInModulus::random_fill(p_rng, q, e_zero.as_mut()); // a_i * s + e nttop.forward(e_zero.as_mut()); modop.elwise_mul_mut(e_zero.as_mut(), s_poly_eval.as_ref()); nttop.backward(e_zero.as_mut()); - // sample error e + // sample error e RandomFillGaussianInModulus::random_fill(rng, q, scratch_space.as_mut()); - + modop.elwise_add_mut(e_zero.as_mut(), scratch_space.as_ref()); }); + zero_encs }