add seeded server key

This commit is contained in:
Janmajaya Mall
2024-05-01 19:59:30 +05:30
parent 99f8e71583
commit b817b09859
3 changed files with 300 additions and 145 deletions

View File

@@ -15,7 +15,7 @@ use crate::{
decomposer::{gadget_vector, Decomposer, DefaultDecomposer, NumInfo}, decomposer::{gadget_vector, Decomposer, DefaultDecomposer, NumInfo},
lwe::{decrypt_lwe, encrypt_lwe, lwe_key_switch, lwe_ksk_keygen, measure_noise_lwe, LweSecret}, lwe::{decrypt_lwe, encrypt_lwe, lwe_key_switch, lwe_ksk_keygen, measure_noise_lwe, LweSecret},
ntt::{Ntt, NttBackendU64, NttInit}, ntt::{Ntt, NttBackendU64, NttInit},
random::{DefaultSecureRng, RandomGaussianDist, RandomUniformDist}, random::{DefaultSecureRng, NewWithSeed, RandomGaussianDist, RandomUniformDist},
rgsw::{ rgsw::{
decrypt_rlwe, galois_auto, galois_key_gen, generate_auto_map, rlwe_by_rgsw, decrypt_rlwe, galois_auto, galois_key_gen, generate_auto_map, rlwe_by_rgsw,
secret_key_encrypt_rgsw, IsTrivial, RlweCiphertext, RlweSecret, secret_key_encrypt_rgsw, IsTrivial, RlweCiphertext, RlweSecret,
@@ -97,19 +97,172 @@ impl ClientKey {
// ClientKey::with_local_mut(|k| *k = key.clone()) // ClientKey::with_local_mut(|k| *k = key.clone())
// } // }
struct ServerKey<M> { struct SeededServerKey<M: Matrix, P, S> {
/// Rgsw cts of LWE secret elements
rgsw_cts: Vec<M>,
/// Auto keys
auto_keys: HashMap<isize, M>,
/// LWE ksk to key switching LWE ciphertext from RLWE secret to LWE secret
lwe_ksk: M::R,
/// Parameters
parameters: P,
/// Main seed
seed: S,
}
impl<M: Matrix, S> SeededServerKey<M, BoolParameters<M::MatElement>, S> {
pub(crate) fn from_raw(
auto_keys: HashMap<isize, M>,
rgsw_cts: Vec<M>,
lwe_ksk: M::R,
parameters: BoolParameters<M::MatElement>,
seed: S,
) -> Self {
// sanity checks
auto_keys
.iter()
.for_each(|v| assert!(v.1.dimension() == (parameters.d_rgsw, parameters.rlwe_n)));
rgsw_cts
.iter()
.for_each(|v| assert!(v.dimension() == (parameters.d_rgsw * 3, parameters.rlwe_n)));
assert!(lwe_ksk.as_ref().len() == (parameters.d_lwe * parameters.rlwe_n));
SeededServerKey {
rgsw_cts,
auto_keys,
lwe_ksk,
parameters,
seed,
}
}
}
struct ServerKeyEvaluationDomain<M, R, N> {
/// Rgsw cts of LWE secret elements /// Rgsw cts of LWE secret elements
rgsw_cts: Vec<M>, rgsw_cts: Vec<M>,
/// Galois keys /// Galois keys
galois_keys: HashMap<isize, M>, galois_keys: HashMap<isize, M>,
/// LWE ksk to key switching LWE ciphertext from RLWE secret to LWE secret /// LWE ksk to key switching LWE ciphertext from RLWE secret to LWE secret
lwe_ksk: M, lwe_ksk: M,
_phanton: PhantomData<(R, N)>,
}
impl<
M: MatrixMut + MatrixEntity,
R: RandomUniformDist<[M::MatElement], Parameters = M::MatElement> + NewWithSeed,
N: NttInit<Element = M::MatElement> + Ntt<Element = M::MatElement>,
> From<&SeededServerKey<M, BoolParameters<M::MatElement>, R::Seed>>
for ServerKeyEvaluationDomain<M, R, N>
where
<M as Matrix>::R: RowMut,
M::MatElement: Copy,
R::Seed: Clone,
{
fn from(value: &SeededServerKey<M, BoolParameters<M::MatElement>, R::Seed>) -> Self {
let mut main_prng = R::new_with_seed(value.seed.clone());
let g = value.parameters.g as isize;
let ring_size = value.parameters.rlwe_n;
let lwe_n = value.parameters.lwe_n;
let d_rgsw = value.parameters.d_rgsw;
let d_lwe = value.parameters.d_lwe;
let rlwe_q = value.parameters.rlwe_q;
let lwq_q = value.parameters.lwe_q;
let nttop = N::new(rlwe_q, ring_size);
// galois keys
let mut auto_keys = HashMap::new();
for i in [g, -g] {
let seeded_auto_key = value.auto_keys.get(&i).unwrap();
assert!(seeded_auto_key.dimension() == (d_rgsw, ring_size));
let mut data = M::zeros(d_rgsw * 2, ring_size);
// sample RLWE'_A(-s(X^k))
data.iter_rows_mut().take(d_rgsw).for_each(|ri| {
RandomUniformDist::random_fill(&mut main_prng, &rlwe_q, ri.as_mut())
});
// copy over RLWE'B_(-s(X^k))
izip!(
data.iter_rows_mut().skip(d_rgsw),
seeded_auto_key.iter_rows()
)
.for_each(|(to_ri, from_ri)| to_ri.as_mut().copy_from_slice(from_ri.as_ref()));
// Send to Evaluation domain
data.iter_rows_mut()
.for_each(|ri| nttop.forward(ri.as_mut()));
auto_keys.insert(i, data);
}
// RGSW ciphertexts
let rgsw_cts = value
.rgsw_cts
.iter()
.map(|seeded_rgsw_si| {
assert!(seeded_rgsw_si.dimension() == (3 * d_rgsw, ring_size));
let mut data = M::zeros(d_rgsw * 4, ring_size);
// copy over RLWE'(-sm)
izip!(
data.iter_rows_mut().take(d_rgsw * 2),
seeded_rgsw_si.iter_rows().take(d_rgsw * 2)
)
.for_each(|(to_ri, from_ri)| to_ri.as_mut().copy_from_slice(from_ri.as_ref()));
// sample RLWE'_A(m)
data.iter_rows_mut()
.skip(2 * d_rgsw)
.take(d_rgsw)
.for_each(|ri| {
RandomUniformDist::random_fill(&mut main_prng, &rlwe_q, ri.as_mut())
});
// copy over RLWE'_B(m)
izip!(
data.iter_rows_mut().skip(d_rgsw * 3),
seeded_rgsw_si.iter_rows().skip(d_rgsw * 2)
)
.for_each(|(to_ri, from_ri)| to_ri.as_mut().copy_from_slice(from_ri.as_ref()));
// send polynomials to evaluation domain
data.iter_rows_mut()
.for_each(|ri| nttop.forward(ri.as_mut()));
data
})
.collect_vec();
// LWE ksk
let lwe_ksk = {
assert!(value.lwe_ksk.as_ref().len() == d_lwe * ring_size);
let mut data = M::zeros(d_lwe * ring_size, lwe_n + 1);
izip!(data.iter_rows_mut(), value.lwe_ksk.as_ref().iter()).for_each(|(lwe_i, bi)| {
RandomUniformDist::random_fill(&mut main_prng, &lwq_q, &mut lwe_i.as_mut()[1..]);
lwe_i.as_mut()[0] = *bi;
});
data
};
ServerKeyEvaluationDomain {
rgsw_cts,
galois_keys: auto_keys,
lwe_ksk,
_phanton: PhantomData,
}
}
} }
//FIXME(Jay): Figure out a way for BoolEvaluator to have access to ServerKey //FIXME(Jay): Figure out a way for BoolEvaluator to have access to ServerKey
// via a pointer and implement PbsKey for BoolEvaluator instead of ServerKey // via a pointer and implement PbsKey for BoolEvaluator instead of ServerKey
// directly // directly
impl<M: Matrix> PbsKey for ServerKey<M> { impl<M: Matrix, R, N> PbsKey for ServerKeyEvaluationDomain<M, R, N> {
type M = M; type M = M;
fn galois_key_for_auto(&self, k: isize) -> &Self::M { fn galois_key_for_auto(&self, k: isize) -> &Self::M {
self.galois_keys.get(&k).unwrap() self.galois_keys.get(&k).unwrap()
@@ -123,6 +276,7 @@ impl<M: Matrix> PbsKey for ServerKey<M> {
} }
} }
#[derive(Clone)]
struct BoolParameters<El> { struct BoolParameters<El> {
rlwe_q: El, rlwe_q: El,
rlwe_logq: usize, rlwe_logq: usize,
@@ -170,7 +324,8 @@ where
<M as Matrix>::R: RowMut, <M as Matrix>::R: RowMut,
DefaultSecureRng: RandomGaussianDist<[M::MatElement], Parameters = M::MatElement> DefaultSecureRng: RandomGaussianDist<[M::MatElement], Parameters = M::MatElement>
+ RandomGaussianDist<M::MatElement, Parameters = M::MatElement> + RandomGaussianDist<M::MatElement, Parameters = M::MatElement>
+ RandomUniformDist<[M::MatElement], Parameters = M::MatElement>, + RandomUniformDist<[M::MatElement], Parameters = M::MatElement>
+ NewWithSeed,
{ {
fn new(parameters: BoolParameters<M::MatElement>) -> Self { fn new(parameters: BoolParameters<M::MatElement>) -> Self {
//TODO(Jay): Run sanity checks for modulus values in parameters //TODO(Jay): Run sanity checks for modulus values in parameters
@@ -285,104 +440,104 @@ where
ClientKey { sk_rlwe, sk_lwe } ClientKey { sk_rlwe, sk_lwe }
} }
fn server_key(&self, client_key: &ClientKey) -> ServerKey<M> { fn server_key(
// let sk_rlwe = &client_key.sk_rlwe; &self,
// let sk_lwe = &client_key.sk_lwe; client_key: &ClientKey,
) -> SeededServerKey<M, BoolParameters<M::MatElement>, [u8; 32]> {
DefaultSecureRng::with_local_mut(|rng| {
let mut main_seed = [0u8; 32];
rng.fill_bytes(&mut main_seed);
// let d_rgsw_gadget_vec = gadget_vector( let mut main_prng = DefaultSecureRng::new_seeded(main_seed);
// self.parameters.rlwe_logq,
// self.parameters.logb_rgsw,
// self.parameters.d_rgsw,
// );
// // generate galois key -g, g let sk_rlwe = &client_key.sk_rlwe;
// let mut galois_keys = HashMap::new(); let sk_lwe = &client_key.sk_lwe;
// let g = self.parameters.g as isize;
// for i in [g, -g] {
// let gk = DefaultSecureRng::with_local_mut(|rng| {
// let mut ksk_out = M::zeros(self.parameters.d_rgsw * 2,
// self.parameters.rlwe_n); galois_key_gen(
// &mut ksk_out,
// sk_rlwe,
// i,
// &d_rgsw_gadget_vec,
// &self.rlwe_modop,
// &self.rlwe_nttop,
// rng,
// );
// ksk_out
// });
// galois_keys.insert(i, gk); let d_rgsw_gadget_vec = gadget_vector(
// } self.parameters.rlwe_logq,
self.parameters.logb_rgsw,
self.parameters.d_rgsw,
);
// // generate rgsw ciphertexts RGSW(si) where si is i^th LWE secret element // generate auto keys -g, g
// let ring_size = self.parameters.rlwe_n; let mut auto_keys = HashMap::new();
// let rlwe_q = self.parameters.rlwe_q; let g = self.parameters.g as isize;
// let rgsw_cts = sk_lwe for i in [g, -g] {
// .values() let mut gk = M::zeros(self.parameters.d_rgsw, self.parameters.rlwe_n);
// .iter() galois_key_gen(
// .map(|si| { &mut gk,
// // X^{si}; assume |emebedding_factor * si| < N sk_rlwe.values(),
// let mut m = M::zeros(1, ring_size); i,
// let si = (self.embedding_factor as i32) * si; &d_rgsw_gadget_vec,
// // dbg!(si); &self.rlwe_modop,
// if si < 0 { &self.rlwe_nttop,
// // X^{-i} = X^{2N - i} = -X^{N-i} &mut main_prng,
// m.set( rng,
// 0, );
// ring_size - (si.abs() as usize), auto_keys.insert(i, gk);
// rlwe_q - M::MatElement::one(), }
// );
// } else {
// // X^{i}
// m.set(0, (si.abs() as usize), M::MatElement::one());
// }
// self.rlwe_nttop.forward(m.get_row_mut(0));
// let rgsw_si = DefaultSecureRng::with_local_mut(|rng| { // generate rgsw ciphertexts RGSW(si) where si is i^th LWE secret element
// let mut rgsw_si = M::zeros(self.parameters.d_rgsw * 4, let ring_size = self.parameters.rlwe_n;
// ring_size); secret_key_encrypt_rgsw( let rlwe_q = self.parameters.rlwe_q;
// &mut rgsw_si, let rgsw_cts = sk_lwe
// &m, .values()
// &d_rgsw_gadget_vec, .iter()
// sk_rlwe, .map(|si| {
// &self.rlwe_modop, // X^{si}; assume |emebedding_factor * si| < N
// &self.rlwe_nttop, let mut m = M::R::zeros(ring_size);
// rng, let si = (self.embedding_factor as i32) * si;
// ); // dbg!(si);
// rgsw_si if si < 0 {
// }); // X^{-i} = X^{2N - i} = -X^{N-i}
// rgsw_si m.as_mut()[ring_size - (si.abs() as usize)] = rlwe_q - M::MatElement::one();
// }) } else {
// .collect_vec(); // X^{i}
m.as_mut()[si.abs() as usize] = M::MatElement::one();
}
// // LWE KSK from RLWE secret s -> LWE secret z let mut rgsw_si = M::zeros(self.parameters.d_rgsw * 3, ring_size);
// let d_lwe_gadget = gadget_vector( secret_key_encrypt_rgsw(
// self.parameters.lwe_logq, &mut rgsw_si,
// self.parameters.logb_lwe, &m,
// self.parameters.d_lwe, &d_rgsw_gadget_vec,
// ); sk_rlwe.values(),
// let mut lwe_ksk = DefaultSecureRng::with_local_mut(|rng| { &self.rlwe_modop,
// let mut out = M::zeros(self.parameters.d_lwe * ring_size, &self.rlwe_nttop,
// self.parameters.lwe_n + 1); lwe_ksk_keygen( &mut main_prng,
// &sk_rlwe.values(), rng,
// &sk_lwe.values(), );
// &mut out,
// &d_lwe_gadget,
// &self.lwe_modop,
// rng,
// );
// out
// });
// ServerKey { rgsw_si
// rgsw_cts, })
// galois_keys, .collect_vec();
// lwe_ksk,
// }
todo!() // LWE KSK from RLWE secret s -> LWE secret z
let d_lwe_gadget = gadget_vector(
self.parameters.lwe_logq,
self.parameters.logb_lwe,
self.parameters.d_lwe,
);
let mut lwe_ksk = M::R::zeros(self.parameters.d_lwe * ring_size);
lwe_ksk_keygen(
&sk_rlwe.values(),
&sk_lwe.values(),
&mut lwe_ksk,
&d_lwe_gadget,
&self.lwe_modop,
&mut main_prng,
rng,
);
SeededServerKey::from_raw(
auto_keys,
rgsw_cts,
lwe_ksk,
self.parameters.clone(),
main_seed,
)
})
} }
/// TODO(Jay): Fetch client key from thread local /// TODO(Jay): Fetch client key from thread local
@@ -434,7 +589,7 @@ where
&self, &self,
c0: &M::R, c0: &M::R,
c1: &M::R, c1: &M::R,
server_key: &ServerKey<M>, server_key: &ServerKeyEvaluationDomain<M, DefaultSecureRng, NttOp>,
scratch_lwen_plus1: &mut M::R, scratch_lwen_plus1: &mut M::R,
scratch_matrix_dplus2_ring: &mut M, scratch_matrix_dplus2_ring: &mut M,
) -> M::R { ) -> M::R {
@@ -984,7 +1139,7 @@ mod tests {
lwe_n: 493, lwe_n: 493,
d_rgsw: 3, d_rgsw: 3,
logb_rgsw: 8, logb_rgsw: 8,
d_lwe: 2, d_lwe: 3,
logb_lwe: 4, logb_lwe: 4,
g: 5, g: 5,
w: 1, w: 1,
@@ -996,7 +1151,7 @@ mod tests {
// } // }
#[test] #[test]
fn encrypt_decrypt_works() { fn bool_encrypt_decrypt_works() {
// let prime = generate_prime(32, 2 * 1024, 1 << 32); // let prime = generate_prime(32, 2 * 1024, 1 << 32);
// dbg!(prime); // dbg!(prime);
let bool_evaluator = let bool_evaluator =
@@ -1014,18 +1169,22 @@ mod tests {
} }
#[test] #[test]
fn trial12() { fn bool_nand() {
// DefaultSecureRng::with_local_mut(|r| { DefaultSecureRng::with_local_mut(|r| {
// let rng = DefaultSecureRng::new_seeded([19u8; 32]); let rng = DefaultSecureRng::new_seeded([19u8; 32]);
// *r = rng; *r = rng;
// }); });
let bool_evaluator = let bool_evaluator =
BoolEvaluator::<Vec<Vec<u64>>, u64, NttBackendU64, ModularOpsU64>::new(SP_BOOL_PARAMS); BoolEvaluator::<Vec<Vec<u64>>, u64, NttBackendU64, ModularOpsU64>::new(SP_BOOL_PARAMS);
// println!("{:?}", bool_evaluator.nand_test_vec); // println!("{:?}", bool_evaluator.nand_test_vec);
let client_key = bool_evaluator.client_key(); let client_key = bool_evaluator.client_key();
let server_key = bool_evaluator.server_key(&client_key); let seeded_server_key = bool_evaluator.server_key(&client_key);
let server_key_eval_domain =
ServerKeyEvaluationDomain::<_, DefaultSecureRng, NttBackendU64>::from(
&seeded_server_key,
);
let mut scratch_lwen_plus1 = vec![0u64; bool_evaluator.parameters.lwe_n + 1]; let mut scratch_lwen_plus1 = vec![0u64; bool_evaluator.parameters.lwe_n + 1];
let mut scratch_matrix_dplus2_ring = vec![ let mut scratch_matrix_dplus2_ring = vec![
@@ -1037,11 +1196,11 @@ mod tests {
let mut m1 = true; let mut m1 = true;
let mut ct0 = bool_evaluator.encrypt(m0, &client_key); let mut ct0 = bool_evaluator.encrypt(m0, &client_key);
let mut ct1 = bool_evaluator.encrypt(m1, &client_key); let mut ct1 = bool_evaluator.encrypt(m1, &client_key);
for _ in 0..100 { for _ in 0..1000 {
let ct_back = bool_evaluator.nand( let ct_back = bool_evaluator.nand(
&ct0, &ct0,
&ct1, &ct1,
&server_key, &server_key_eval_domain,
&mut scratch_lwen_plus1, &mut scratch_lwen_plus1,
&mut scratch_matrix_dplus2_ring, &mut scratch_matrix_dplus2_ring,
); );

View File

@@ -131,16 +131,15 @@ pub fn lwe_ksk_keygen<
Ro: Row + RowMut + RowEntity, Ro: Row + RowMut + RowEntity,
S, S,
Op: VectorOps<Element = Ro::Element> + ArithmeticOps<Element = Ro::Element>, Op: VectorOps<Element = Ro::Element> + ArithmeticOps<Element = Ro::Element>,
R: RandomGaussianDist<Ro::Element, Parameters = Ro::Element> R: RandomGaussianDist<Ro::Element, Parameters = Ro::Element>,
+ RandomUniformDist<[Ro::Element], Parameters = Ro::Element> PR: RandomUniformDist<[Ro::Element], Parameters = Ro::Element>,
+ NewWithSeed,
>( >(
from_lwe_sk: &[S], from_lwe_sk: &[S],
to_lwe_sk: &[S], to_lwe_sk: &[S],
ksk_out: &mut Ro, ksk_out: &mut Ro,
gadget: &[Ro::Element], gadget: &[Ro::Element],
seed: R::Seed,
operator: &Op, operator: &Op,
p_rng: &mut PR,
rng: &mut R, rng: &mut R,
) where ) where
Ro: TryConvertFrom<[S], Parameters = Ro::Element>, Ro: TryConvertFrom<[S], Parameters = Ro::Element>,
@@ -156,13 +155,12 @@ pub fn lwe_ksk_keygen<
let sk_out_m = Ro::try_convert_from(to_lwe_sk, &modulus); let sk_out_m = Ro::try_convert_from(to_lwe_sk, &modulus);
let mut scratch = Ro::zeros(to_lwe_sk.len()); let mut scratch = Ro::zeros(to_lwe_sk.len());
let mut p_rng = R::new_with_seed(seed);
izip!(neg_sk_in_m.as_ref(), ksk_out.as_mut().chunks_mut(d)).for_each( izip!(neg_sk_in_m.as_ref(), ksk_out.as_mut().chunks_mut(d)).for_each(
|(neg_sk_in_si, d_lwes_partb)| { |(neg_sk_in_si, d_lwes_partb)| {
izip!(gadget.iter(), d_lwes_partb.into_iter()).for_each(|(f, lwe_b)| { izip!(gadget.iter(), d_lwes_partb.into_iter()).for_each(|(f, lwe_b)| {
// sample `a` // sample `a`
RandomUniformDist::random_fill(&mut p_rng, &modulus, scratch.as_mut()); RandomUniformDist::random_fill(p_rng, &modulus, scratch.as_mut());
// a * z // a * z
let mut az = Ro::Element::zero(); let mut az = Ro::Element::zero();
@@ -345,14 +343,15 @@ mod tests {
rng.fill_bytes(&mut ksk_seed); rng.fill_bytes(&mut ksk_seed);
let mut seeded_ksk = let mut seeded_ksk =
SeededLweKeySwitchingKey::empty(lwe_in_n, lwe_out_n, d_ks, ksk_seed, q); SeededLweKeySwitchingKey::empty(lwe_in_n, lwe_out_n, d_ks, ksk_seed, q);
let mut p_rng = DefaultSecureRng::new_seeded(ksk_seed);
let gadget = gadget_vector(logq, logb, d_ks); let gadget = gadget_vector(logq, logb, d_ks);
lwe_ksk_keygen( lwe_ksk_keygen(
&lwe_sk_in.values(), &lwe_sk_in.values(),
&lwe_sk_out.values(), &lwe_sk_out.values(),
&mut seeded_ksk.data, &mut seeded_ksk.data,
&gadget, &gadget,
seeded_ksk.seed,
&modq_op, &modq_op,
&mut p_rng,
&mut rng, &mut rng,
); );
// println!("{:?}", ksk); // println!("{:?}", ksk);

View File

@@ -383,9 +383,8 @@ pub(crate) fn rlwe_ksk_gen<
Mmut: MatrixMut + MatrixEntity, Mmut: MatrixMut + MatrixEntity,
ModOp: ArithmeticOps<Element = Mmut::MatElement> + VectorOps<Element = Mmut::MatElement>, ModOp: ArithmeticOps<Element = Mmut::MatElement> + VectorOps<Element = Mmut::MatElement>,
NttOp: Ntt<Element = Mmut::MatElement>, NttOp: Ntt<Element = Mmut::MatElement>,
R: RandomGaussianDist<[Mmut::MatElement], Parameters = Mmut::MatElement> R: RandomGaussianDist<[Mmut::MatElement], Parameters = Mmut::MatElement>,
+ RandomUniformDist<[Mmut::MatElement], Parameters = Mmut::MatElement> PR: RandomUniformDist<[Mmut::MatElement], Parameters = Mmut::MatElement>,
+ NewWithSeed,
>( >(
ksk_out: &mut Mmut, ksk_out: &mut Mmut,
neg_from_s: Mmut::R, neg_from_s: Mmut::R,
@@ -393,7 +392,7 @@ pub(crate) fn rlwe_ksk_gen<
gadget_vector: &[Mmut::MatElement], gadget_vector: &[Mmut::MatElement],
mod_op: &ModOp, mod_op: &ModOp,
ntt_op: &NttOp, ntt_op: &NttOp,
seed: R::Seed, p_rng: &mut PR,
rng: &mut R, rng: &mut R,
) where ) where
<Mmut as Matrix>::R: RowMut, <Mmut as Matrix>::R: RowMut,
@@ -409,9 +408,8 @@ pub(crate) fn rlwe_ksk_gen<
// RLWE'_{to_s}(-from_s) // RLWE'_{to_s}(-from_s)
let mut part_a = { let mut part_a = {
let mut a = Mmut::zeros(d, ring_size); let mut a = Mmut::zeros(d, ring_size);
let mut p_rng = R::new_with_seed(seed);
a.iter_rows_mut() a.iter_rows_mut()
.for_each(|ai| RandomUniformDist::random_fill(&mut p_rng, &q, ai.as_mut())); .for_each(|ai| RandomUniformDist::random_fill(p_rng, &q, ai.as_mut()));
a a
}; };
izip!( izip!(
@@ -443,9 +441,8 @@ pub(crate) fn galois_key_gen<
ModOp: ArithmeticOps<Element = Mmut::MatElement> + VectorOps<Element = Mmut::MatElement>, ModOp: ArithmeticOps<Element = Mmut::MatElement> + VectorOps<Element = Mmut::MatElement>,
NttOp: Ntt<Element = Mmut::MatElement>, NttOp: Ntt<Element = Mmut::MatElement>,
S, S,
R: RandomGaussianDist<[Mmut::MatElement], Parameters = Mmut::MatElement> R: RandomGaussianDist<[Mmut::MatElement], Parameters = Mmut::MatElement>,
+ RandomUniformDist<[Mmut::MatElement], Parameters = Mmut::MatElement> PR: RandomUniformDist<[Mmut::MatElement], Parameters = Mmut::MatElement>,
+ NewWithSeed,
>( >(
ksk_out: &mut Mmut, ksk_out: &mut Mmut,
s: &[S], s: &[S],
@@ -453,7 +450,7 @@ pub(crate) fn galois_key_gen<
gadget_vector: &[Mmut::MatElement], gadget_vector: &[Mmut::MatElement],
mod_op: &ModOp, mod_op: &ModOp,
ntt_op: &NttOp, ntt_op: &NttOp,
seed: R::Seed, p_rng: &mut PR,
rng: &mut R, rng: &mut R,
) where ) where
<Mmut as Matrix>::R: RowMut, <Mmut as Matrix>::R: RowMut,
@@ -488,7 +485,7 @@ pub(crate) fn galois_key_gen<
gadget_vector, gadget_vector,
mod_op, mod_op,
ntt_op, ntt_op,
seed, p_rng,
rng, rng,
); );
} }
@@ -731,8 +728,8 @@ pub(crate) fn secret_key_encrypt_rgsw<
Mmut: MatrixMut + MatrixEntity, Mmut: MatrixMut + MatrixEntity,
S, S,
R: RandomGaussianDist<[Mmut::MatElement], Parameters = Mmut::MatElement> R: RandomGaussianDist<[Mmut::MatElement], Parameters = Mmut::MatElement>
+ RandomUniformDist<[Mmut::MatElement], Parameters = Mmut::MatElement> + RandomUniformDist<[Mmut::MatElement], Parameters = Mmut::MatElement>,
+ NewWithSeed, PR: RandomUniformDist<[Mmut::MatElement], Parameters = Mmut::MatElement>,
ModOp: VectorOps<Element = Mmut::MatElement>, ModOp: VectorOps<Element = Mmut::MatElement>,
NttOp: Ntt<Element = Mmut::MatElement>, NttOp: Ntt<Element = Mmut::MatElement>,
>( >(
@@ -742,13 +739,11 @@ pub(crate) fn secret_key_encrypt_rgsw<
s: &[S], s: &[S],
mod_op: &ModOp, mod_op: &ModOp,
ntt_op: &NttOp, ntt_op: &NttOp,
seed: R::Seed, p_rng: &mut PR,
rng: &mut R, rng: &mut R,
) where ) where
<Mmut as Matrix>::R: <Mmut as Matrix>::R: RowMut + RowEntity + TryConvertFrom<[S], Parameters = Mmut::MatElement>,
RowMut + RowEntity + TryConvertFrom<[S], Parameters = Mmut::MatElement> + Debug, Mmut::MatElement: Copy,
Mmut::MatElement: Copy + Debug,
Mmut: Debug,
{ {
let d = gadget_vector.len(); let d = gadget_vector.len();
let q = mod_op.modulus(); let q = mod_op.modulus();
@@ -793,10 +788,9 @@ pub(crate) fn secret_key_encrypt_rgsw<
// RLWE(m) // RLWE(m)
let mut a_rlwe_dash_m = { let mut a_rlwe_dash_m = {
// polynomials of part A of RLWE'(m) are sampled from seed // polynomials of part A of RLWE'(m) are sampled from seed
let mut p_rng = R::new_with_seed(seed);
let mut a = Mmut::zeros(d, ring_size); let mut a = Mmut::zeros(d, ring_size);
a.iter_rows_mut() a.iter_rows_mut()
.for_each(|ai| RandomUniformDist::random_fill(&mut p_rng, &q, ai.as_mut())); .for_each(|ai| RandomUniformDist::random_fill(p_rng, &q, ai.as_mut()));
a a
}; };
@@ -832,16 +826,15 @@ pub(crate) fn secret_key_encrypt_rlwe<
ModOp: VectorOps<Element = Ro::Element>, ModOp: VectorOps<Element = Ro::Element>,
NttOp: Ntt<Element = Ro::Element>, NttOp: Ntt<Element = Ro::Element>,
S, S,
R: RandomUniformDist<[Ro::Element], Parameters = Ro::Element> R: RandomGaussianDist<[Ro::Element], Parameters = Ro::Element>,
+ RandomGaussianDist<[Ro::Element], Parameters = Ro::Element> PR: RandomUniformDist<[Ro::Element], Parameters = Ro::Element>,
+ NewWithSeed,
>( >(
m: &Ro, m: &Ro,
b_rlwe_out: &mut Ro, b_rlwe_out: &mut Ro,
s: &[S], s: &[S],
mod_op: &ModOp, mod_op: &ModOp,
ntt_op: &NttOp, ntt_op: &NttOp,
seed: R::Seed, p_rng: &mut PR,
rng: &mut R, rng: &mut R,
) where ) where
Ro: TryConvertFrom<[S], Parameters = Ro::Element> + Debug, Ro: TryConvertFrom<[S], Parameters = Ro::Element> + Debug,
@@ -855,8 +848,7 @@ pub(crate) fn secret_key_encrypt_rlwe<
// sample a // sample a
let mut a = { let mut a = {
let mut a = Ro::zeros(ring_size); let mut a = Ro::zeros(ring_size);
let mut p_rng = R::new_with_seed(seed); RandomUniformDist::random_fill(p_rng, &q, a.as_mut());
RandomUniformDist::random_fill(&mut p_rng, &q, a.as_mut());
a a
}; };
@@ -982,7 +974,7 @@ mod tests {
backend::{ModInit, ModularOpsU64}, backend::{ModInit, ModularOpsU64},
decomposer::{gadget_vector, DefaultDecomposer}, decomposer::{gadget_vector, DefaultDecomposer},
ntt::{self, Ntt, NttBackendU64, NttInit}, ntt::{self, Ntt, NttBackendU64, NttInit},
random::{DefaultSecureRng, RandomUniformDist}, random::{DefaultSecureRng, NewWithSeed, RandomUniformDist},
rgsw::{ rgsw::{
measure_noise, AutoKeyEvaluationDomain, RgswCiphertextEvaluationDomain, RlweCiphertext, measure_noise, AutoKeyEvaluationDomain, RgswCiphertextEvaluationDomain, RlweCiphertext,
SeededAutoKey, SeededRgswCiphertext, SeededRlweCiphertext, SeededAutoKey, SeededRgswCiphertext, SeededRlweCiphertext,
@@ -1020,6 +1012,7 @@ mod tests {
rng.fill_bytes(&mut rlwe_seed); rng.fill_bytes(&mut rlwe_seed);
let mut seeded_rlwe_in_ct = let mut seeded_rlwe_in_ct =
SeededRlweCiphertext::<_, [u8; 32]>::empty(ring_size as usize, rlwe_seed, q); SeededRlweCiphertext::<_, [u8; 32]>::empty(ring_size as usize, rlwe_seed, q);
let mut p_rng = DefaultSecureRng::new_with_seed(rlwe_seed);
let encoded_m = m0 let encoded_m = m0
.iter() .iter()
.map(|v| (((*v as f64) * q as f64) / (p as f64)).round() as u64) .map(|v| (((*v as f64) * q as f64) / (p as f64)).round() as u64)
@@ -1030,7 +1023,7 @@ mod tests {
s.values(), s.values(),
&mod_op, &mod_op,
&ntt_op, &ntt_op,
seeded_rlwe_in_ct.seed, &mut p_rng,
&mut rng, &mut rng,
); );
let rlwe_in_ct = let rlwe_in_ct =
@@ -1046,7 +1039,7 @@ mod tests {
); );
let m_back = encoded_m_back let m_back = encoded_m_back
.iter() .iter()
.map(|v| ((*v as f64 * p as f64) / q as f64).round() as u64) .map(|v| (((*v as f64 * p as f64) / q as f64).round() as u64) % p)
.collect_vec(); .collect_vec();
assert_eq!(m0, m_back); assert_eq!(m0, m_back);
} }
@@ -1082,6 +1075,7 @@ mod tests {
rgsw_seed, rgsw_seed,
q, q,
); );
let mut p_rng = DefaultSecureRng::new_seeded(rgsw_seed);
let gadget_vector = gadget_vector(logq, logb, d_rgsw); let gadget_vector = gadget_vector(logq, logb, d_rgsw);
secret_key_encrypt_rgsw( secret_key_encrypt_rgsw(
&mut seeded_rgsw_ct.data, &mut seeded_rgsw_ct.data,
@@ -1090,7 +1084,7 @@ mod tests {
s.values(), s.values(),
&mod_op, &mod_op,
&ntt_op, &ntt_op,
seeded_rgsw_ct.seed, &mut p_rng,
&mut rng, &mut rng,
); );
let rgsw_ct = RgswCiphertextEvaluationDomain::<_, DefaultSecureRng, NttBackendU64>::from( let rgsw_ct = RgswCiphertextEvaluationDomain::<_, DefaultSecureRng, NttBackendU64>::from(
@@ -1102,6 +1096,7 @@ mod tests {
rng.fill_bytes(&mut rlwe_seed); rng.fill_bytes(&mut rlwe_seed);
let mut seeded_rlwe_in_ct = let mut seeded_rlwe_in_ct =
SeededRlweCiphertext::<_, [u8; 32]>::empty(ring_size as usize, rlwe_seed, q); SeededRlweCiphertext::<_, [u8; 32]>::empty(ring_size as usize, rlwe_seed, q);
let mut p_rng = DefaultSecureRng::new_seeded(rlwe_seed);
let encoded_m = m0 let encoded_m = m0
.iter() .iter()
.map(|v| (((*v as f64) * q as f64) / (p as f64)).round() as u64) .map(|v| (((*v as f64) * q as f64) / (p as f64)).round() as u64)
@@ -1112,7 +1107,7 @@ mod tests {
s.values(), s.values(),
&mod_op, &mod_op,
&ntt_op, &ntt_op,
seeded_rlwe_in_ct.seed, &mut p_rng,
&mut rng, &mut rng,
); );
let mut rlwe_in_ct = let mut rlwe_in_ct =
@@ -1181,13 +1176,14 @@ mod tests {
let mut seed_rlwe = [0u8; 32]; let mut seed_rlwe = [0u8; 32];
rng.fill_bytes(&mut seed_rlwe); rng.fill_bytes(&mut seed_rlwe);
let mut seeded_rlwe_m = SeededRlweCiphertext::empty(ring_size as usize, seed_rlwe, q); let mut seeded_rlwe_m = SeededRlweCiphertext::empty(ring_size as usize, seed_rlwe, q);
let mut p_rng = DefaultSecureRng::new_seeded(seed_rlwe);
secret_key_encrypt_rlwe( secret_key_encrypt_rlwe(
&encoded_m, &encoded_m,
&mut seeded_rlwe_m.data, &mut seeded_rlwe_m.data,
s.values(), s.values(),
&mod_op, &mod_op,
&ntt_op, &ntt_op,
seeded_rlwe_m.seed, &mut p_rng,
&mut rng, &mut rng,
); );
let mut rlwe_m = RlweCiphertext::<Vec<Vec<u64>>, DefaultSecureRng>::from(&seeded_rlwe_m); let mut rlwe_m = RlweCiphertext::<Vec<Vec<u64>>, DefaultSecureRng>::from(&seeded_rlwe_m);
@@ -1198,6 +1194,7 @@ mod tests {
let mut seed_auto = [0u8; 32]; let mut seed_auto = [0u8; 32];
rng.fill_bytes(&mut seed_auto); rng.fill_bytes(&mut seed_auto);
let mut seeded_auto_key = SeededAutoKey::empty(ring_size as usize, d_rgsw, seed_auto, q); let mut seeded_auto_key = SeededAutoKey::empty(ring_size as usize, d_rgsw, seed_auto, q);
let mut p_rng = DefaultSecureRng::new_seeded(seed_auto);
let gadget_vector = gadget_vector(logq, logb, d_rgsw); let gadget_vector = gadget_vector(logq, logb, d_rgsw);
galois_key_gen( galois_key_gen(
&mut seeded_auto_key.data, &mut seeded_auto_key.data,
@@ -1206,7 +1203,7 @@ mod tests {
&gadget_vector, &gadget_vector,
&mod_op, &mod_op,
&ntt_op, &ntt_op,
seeded_auto_key.seed, &mut p_rng,
&mut rng, &mut rng,
); );
let auto_key = let auto_key =