Browse Source

add seeded server key

par-agg-key-shares
Janmajaya Mall 11 months ago
parent
commit
b817b09859
3 changed files with 306 additions and 151 deletions
  1. +270
    -111
      src/bool.rs
  2. +6
    -7
      src/lwe.rs
  3. +30
    -33
      src/rgsw.rs

+ 270
- 111
src/bool.rs

@ -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 PbsKey for ServerKey {
} }
} }
#[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> {
// let sk_rlwe = &client_key.sk_rlwe;
// let sk_lwe = &client_key.sk_lwe;
// let d_rgsw_gadget_vec = gadget_vector(
// self.parameters.rlwe_logq,
// self.parameters.logb_rgsw,
// self.parameters.d_rgsw,
// );
// // generate galois key -g, g
// let mut galois_keys = HashMap::new();
// 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);
// }
// // generate rgsw ciphertexts RGSW(si) where si is i^th LWE secret element
// let ring_size = self.parameters.rlwe_n;
// let rlwe_q = self.parameters.rlwe_q;
// let rgsw_cts = sk_lwe
// .values()
// .iter()
// .map(|si| {
// // X^{si}; assume |emebedding_factor * si| < N
// let mut m = M::zeros(1, ring_size);
// let si = (self.embedding_factor as i32) * si;
// // dbg!(si);
// if si < 0 {
// // X^{-i} = X^{2N - i} = -X^{N-i}
// m.set(
// 0,
// ring_size - (si.abs() as usize),
// 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| {
// let mut rgsw_si = M::zeros(self.parameters.d_rgsw * 4,
// ring_size); secret_key_encrypt_rgsw(
// &mut rgsw_si,
// &m,
// &d_rgsw_gadget_vec,
// sk_rlwe,
// &self.rlwe_modop,
// &self.rlwe_nttop,
// rng,
// );
// rgsw_si
// });
// rgsw_si
// })
// .collect_vec();
// // 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 = DefaultSecureRng::with_local_mut(|rng| {
// let mut out = M::zeros(self.parameters.d_lwe * ring_size,
// self.parameters.lwe_n + 1); lwe_ksk_keygen(
// &sk_rlwe.values(),
// &sk_lwe.values(),
// &mut out,
// &d_lwe_gadget,
// &self.lwe_modop,
// rng,
// );
// out
// });
fn server_key(
&self,
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 mut main_prng = DefaultSecureRng::new_seeded(main_seed);
// ServerKey {
// rgsw_cts,
// galois_keys,
// lwe_ksk,
// }
let sk_rlwe = &client_key.sk_rlwe;
let sk_lwe = &client_key.sk_lwe;
todo!()
let d_rgsw_gadget_vec = gadget_vector(
self.parameters.rlwe_logq,
self.parameters.logb_rgsw,
self.parameters.d_rgsw,
);
// generate auto keys -g, g
let mut auto_keys = HashMap::new();
let g = self.parameters.g as isize;
for i in [g, -g] {
let mut gk = M::zeros(self.parameters.d_rgsw, self.parameters.rlwe_n);
galois_key_gen(
&mut gk,
sk_rlwe.values(),
i,
&d_rgsw_gadget_vec,
&self.rlwe_modop,
&self.rlwe_nttop,
&mut main_prng,
rng,
);
auto_keys.insert(i, gk);
}
// generate rgsw ciphertexts RGSW(si) where si is i^th LWE secret element
let ring_size = self.parameters.rlwe_n;
let rlwe_q = self.parameters.rlwe_q;
let rgsw_cts = sk_lwe
.values()
.iter()
.map(|si| {
// X^{si}; assume |emebedding_factor * si| < N
let mut m = M::R::zeros(ring_size);
let si = (self.embedding_factor as i32) * si;
// dbg!(si);
if si < 0 {
// X^{-i} = X^{2N - i} = -X^{N-i}
m.as_mut()[ring_size - (si.abs() as usize)] = rlwe_q - M::MatElement::one();
} else {
// X^{i}
m.as_mut()[si.abs() as usize] = M::MatElement::one();
}
let mut rgsw_si = M::zeros(self.parameters.d_rgsw * 3, ring_size);
secret_key_encrypt_rgsw(
&mut rgsw_si,
&m,
&d_rgsw_gadget_vec,
sk_rlwe.values(),
&self.rlwe_modop,
&self.rlwe_nttop,
&mut main_prng,
rng,
);
rgsw_si
})
.collect_vec();
// 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() {
// DefaultSecureRng::with_local_mut(|r| {
// let rng = DefaultSecureRng::new_seeded([19u8; 32]);
// *r = rng;
// });
fn bool_nand() {
DefaultSecureRng::with_local_mut(|r| {
let rng = DefaultSecureRng::new_seeded([19u8; 32]);
*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,
); );

+ 6
- 7
src/lwe.rs

@ -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>
+ RandomUniformDist<[Ro::Element], Parameters = Ro::Element>
+ NewWithSeed,
R: RandomGaussianDist<Ro::Element, Parameters = Ro::Element>,
PR: RandomUniformDist<[Ro::Element], Parameters = Ro::Element>,
>( >(
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);

+ 30
- 33
src/rgsw.rs

@ -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>
+ RandomUniformDist<[Mmut::MatElement], Parameters = Mmut::MatElement>
+ NewWithSeed,
R: RandomGaussianDist<[Mmut::MatElement], Parameters = Mmut::MatElement>,
PR: RandomUniformDist<[Mmut::MatElement], Parameters = Mmut::MatElement>,
>( >(
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>
+ RandomUniformDist<[Mmut::MatElement], Parameters = Mmut::MatElement>
+ NewWithSeed,
R: RandomGaussianDist<[Mmut::MatElement], Parameters = Mmut::MatElement>,
PR: RandomUniformDist<[Mmut::MatElement], Parameters = Mmut::MatElement>,
>( >(
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>
+ NewWithSeed,
+ RandomUniformDist<[Mmut::MatElement], Parameters = Mmut::MatElement>,
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:
RowMut + RowEntity + TryConvertFrom<[S], Parameters = Mmut::MatElement> + Debug,
Mmut::MatElement: Copy + Debug,
Mmut: Debug,
<Mmut as Matrix>::R: RowMut + RowEntity + TryConvertFrom<[S], Parameters = Mmut::MatElement>,
Mmut::MatElement: Copy,
{ {
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>
+ RandomGaussianDist<[Ro::Element], Parameters = Ro::Element>
+ NewWithSeed,
R: RandomGaussianDist<[Ro::Element], Parameters = Ro::Element>,
PR: RandomUniformDist<[Ro::Element], Parameters = Ro::Element>,
>( >(
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(&mut p_rng, &q, a.as_mut());
RandomUniformDist::random_fill(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 =

Loading…
Cancel
Save