phantom-zone/src/bool/keys.rs
src/bool/keys.rsRaw
1use std::{collections::HashMap, hash::Hash, marker::PhantomData};
2
3use crate::{
4 backend::{ModInit, VectorOps},
5 lwe::LweSecret,
6 pbs::WithShoupRepr,
7 random::{NewWithSeed, RandomFillUniformInModulus},
8 rgsw::RlweSecret,
9 utils::{ToShoup, WithLocal},
10 Decryptor, Encryptor, Matrix, MatrixEntity, MatrixMut, MultiPartyDecryptor, RowEntity, RowMut,
11};
12
13use super::{parameters, BoolEvaluator, BoolParameters, CiphertextModulus};
14
15/// Client key with RLWE and LWE secrets
16#[derive(Clone)]
17pub struct ClientKey {
18 sk_rlwe: RlweSecret,
19 sk_lwe: LweSecret,
20}
21
22/// Client key with RLWE and LWE secrets
23#[derive(Clone)]
24pub struct NonInteractiveClientKey {
25 sk_rlwe: RlweSecret,
26 sk_u_rlwe: RlweSecret,
27 sk_lwe: LweSecret,
28}
29
30mod impl_ck {
31 use super::*;
32
33 // Client key
34 impl ClientKey {
35 pub(in super::super) fn new(sk_rlwe: RlweSecret, sk_lwe: LweSecret) -> Self {
36 Self { sk_rlwe, sk_lwe }
37 }
38
39 pub(in super::super) fn sk_rlwe(&self) -> &RlweSecret {
40 &self.sk_rlwe
41 }
42
43 pub(in super::super) fn sk_lwe(&self) -> &LweSecret {
44 &self.sk_lwe
45 }
46 }
47
48 // Client key
49 impl NonInteractiveClientKey {
50 pub(in super::super) fn new(
51 sk_rlwe: RlweSecret,
52 sk_u_rlwe: RlweSecret,
53 sk_lwe: LweSecret,
54 ) -> Self {
55 Self {
56 sk_rlwe,
57 sk_u_rlwe,
58 sk_lwe,
59 }
60 }
61
62 pub(in super::super) fn sk_rlwe(&self) -> &RlweSecret {
63 &self.sk_rlwe
64 }
65
66 pub(in super::super) fn sk_u_rlwe(&self) -> &RlweSecret {
67 &self.sk_u_rlwe
68 }
69
70 pub(in super::super) fn sk_lwe(&self) -> &LweSecret {
71 &self.sk_lwe
72 }
73 }
74
75 impl Encryptor<bool, Vec<u64>> for ClientKey {
76 fn encrypt(&self, m: &bool) -> Vec<u64> {
77 BoolEvaluator::with_local(|e| e.sk_encrypt(*m, self))
78 }
79 }
80
81 impl Decryptor<bool, Vec<u64>> for ClientKey {
82 fn decrypt(&self, c: &Vec<u64>) -> bool {
83 BoolEvaluator::with_local(|e| e.sk_decrypt(c, self))
84 }
85 }
86
87 impl MultiPartyDecryptor<bool, Vec<u64>> for ClientKey {
88 type DecryptionShare = u64;
89
90 fn gen_decryption_share(&self, c: &Vec<u64>) -> Self::DecryptionShare {
91 BoolEvaluator::with_local(|e| e.multi_party_decryption_share(c, &self))
92 }
93
94 fn aggregate_decryption_shares(
95 &self,
96 c: &Vec<u64>,
97 shares: &[Self::DecryptionShare],
98 ) -> bool {
99 BoolEvaluator::with_local(|e| e.multi_party_decrypt(shares, c))
100 }
101 }
102}
103
104/// Public key
105pub struct PublicKey<M, Rng, ModOp> {
106 key: M,
107 _phantom: PhantomData<(Rng, ModOp)>,
108}
109
110pub(super) mod impl_pk {
111 use super::*;
112
113 impl<M, R, Mo> PublicKey<M, R, Mo> {
114 pub(in super::super) fn key(&self) -> &M {
115 &self.key
116 }
117 }
118
119 impl<Rng, ModOp> Encryptor<bool, Vec<u64>> for PublicKey<Vec<Vec<u64>>, Rng, ModOp> {
120 fn encrypt(&self, m: &bool) -> Vec<u64> {
121 BoolEvaluator::with_local(|e| e.pk_encrypt(&self.key, *m))
122 }
123 }
124
125 impl<Rng, ModOp> Encryptor<[bool], Vec<Vec<u64>>> for PublicKey<Vec<Vec<u64>>, Rng, ModOp> {
126 fn encrypt(&self, m: &[bool]) -> Vec<Vec<u64>> {
127 BoolEvaluator::with_local(|e| e.pk_encrypt_batched(&self.key, m))
128 }
129 }
130
131 impl<
132 M: MatrixMut + MatrixEntity,
133 Rng: NewWithSeed
134 + RandomFillUniformInModulus<[M::MatElement], CiphertextModulus<M::MatElement>>,
135 ModOp,
136 > From<SeededPublicKey<M::R, Rng::Seed, BoolParameters<M::MatElement>, ModOp>>
137 for PublicKey<M, Rng, ModOp>
138 where
139 <M as Matrix>::R: RowMut,
140 M::MatElement: Copy,
141 {
142 fn from(
143 value: SeededPublicKey<M::R, Rng::Seed, BoolParameters<M::MatElement>, ModOp>,
144 ) -> Self {
145 let mut prng = Rng::new_with_seed(value.seed);
146
147 let mut key = M::zeros(2, value.parameters.rlwe_n().0);
148 // sample A
149 RandomFillUniformInModulus::random_fill(
150 &mut prng,
151 value.parameters.rlwe_q(),
152 key.get_row_mut(0),
153 );
154 // Copy over B
155 key.get_row_mut(1).copy_from_slice(value.part_b.as_ref());
156
157 PublicKey {
158 key,
159 _phantom: PhantomData,
160 }
161 }
162 }
163
164 impl<
165 M: MatrixMut + MatrixEntity,
166 Rng: NewWithSeed
167 + RandomFillUniformInModulus<[M::MatElement], CiphertextModulus<M::MatElement>>,
168 ModOp: VectorOps<Element = M::MatElement> + ModInit<M = CiphertextModulus<M::MatElement>>,
169 >
170 From<
171 &[CommonReferenceSeededCollectivePublicKeyShare<
172 M::R,
173 Rng::Seed,
174 BoolParameters<M::MatElement>,
175 >],
176 > for PublicKey<M, Rng, ModOp>
177 where
178 <M as Matrix>::R: RowMut,
179 Rng::Seed: Copy + PartialEq,
180 M::MatElement: PartialEq + Copy,
181 {
182 fn from(
183 value: &[CommonReferenceSeededCollectivePublicKeyShare<
184 M::R,
185 Rng::Seed,
186 BoolParameters<M::MatElement>,
187 >],
188 ) -> Self {
189 assert!(value.len() > 0);
190
191 let parameters = &value[0].parameters;
192 let mut key = M::zeros(2, parameters.rlwe_n().0);
193
194 // sample A
195 let seed = value[0].cr_seed;
196 let mut main_rng = Rng::new_with_seed(seed);
197 RandomFillUniformInModulus::random_fill(
198 &mut main_rng,
199 parameters.rlwe_q(),
200 key.get_row_mut(0),
201 );
202
203 // Sum all Bs
204 let rlweq_modop = ModOp::new(parameters.rlwe_q().clone());
205 value.iter().for_each(|share_i| {
206 assert!(share_i.cr_seed == seed);
207 assert!(&share_i.parameters == parameters);
208
209 rlweq_modop.elwise_add_mut(key.get_row_mut(1), share_i.share.as_ref());
210 });
211
212 PublicKey {
213 key,
214 _phantom: PhantomData,
215 }
216 }
217 }
218}
219
220/// Seeded public key
221struct SeededPublicKey<Ro, S, P, ModOp> {
222 part_b: Ro,
223 seed: S,
224 parameters: P,
225 _phantom: PhantomData<ModOp>,
226}
227
228mod impl_seeded_pk {
229 use super::*;
230
231 impl<R, S, ModOp>
232 From<&[CommonReferenceSeededCollectivePublicKeyShare<R, S, BoolParameters<R::Element>>]>
233 for SeededPublicKey<R, S, BoolParameters<R::Element>, ModOp>
234 where
235 ModOp: VectorOps<Element = R::Element> + ModInit<M = CiphertextModulus<R::Element>>,
236 S: PartialEq + Clone,
237 R: RowMut + RowEntity + Clone,
238 R::Element: Clone + PartialEq,
239 {
240 fn from(
241 value: &[CommonReferenceSeededCollectivePublicKeyShare<
242 R,
243 S,
244 BoolParameters<R::Element>,
245 >],
246 ) -> Self {
247 assert!(value.len() > 0);
248
249 let parameters = &value[0].parameters;
250 let cr_seed = value[0].cr_seed.clone();
251
252 // Sum all Bs
253 let rlweq_modop = ModOp::new(parameters.rlwe_q().clone());
254 let mut part_b = value[0].share.clone();
255 value.iter().skip(1).for_each(|share_i| {
256 assert!(&share_i.cr_seed == &cr_seed);
257 assert!(&share_i.parameters == parameters);
258
259 rlweq_modop.elwise_add_mut(part_b.as_mut(), share_i.share.as_ref());
260 });
261
262 Self {
263 part_b,
264 seed: cr_seed,
265 parameters: parameters.clone(),
266 _phantom: PhantomData,
267 }
268 }
269 }
270}
271
272/// CRS seeded collective public key share
273pub struct CommonReferenceSeededCollectivePublicKeyShare<Ro, S, P> {
274 share: Ro,
275 cr_seed: S,
276 parameters: P,
277}
278impl<Ro, S, P> CommonReferenceSeededCollectivePublicKeyShare<Ro, S, P> {
279 pub(super) fn new(share: Ro, cr_seed: S, parameters: P) -> Self {
280 CommonReferenceSeededCollectivePublicKeyShare {
281 share,
282 cr_seed,
283 parameters,
284 }
285 }
286}
287
288/// CRS seeded Multi-party server key share
289pub struct CommonReferenceSeededMultiPartyServerKeyShare<M: Matrix, P, S> {
290 rgsw_cts: Vec<M>,
291 /// Auto keys. Key corresponding to g^{k} is at index `k`. Key corresponding
292 /// to -g is at 0
293 auto_keys: HashMap<usize, M>,
294 lwe_ksk: M::R,
295 /// Common reference seed
296 cr_seed: S,
297 parameters: P,
298}
299
300impl<M: Matrix, P, S> CommonReferenceSeededMultiPartyServerKeyShare<M, P, S> {
301 pub(super) fn new(
302 rgsw_cts: Vec<M>,
303 auto_keys: HashMap<usize, M>,
304 lwe_ksk: M::R,
305 cr_seed: S,
306 parameters: P,
307 ) -> Self {
308 CommonReferenceSeededMultiPartyServerKeyShare {
309 rgsw_cts,
310 auto_keys,
311 lwe_ksk,
312 cr_seed,
313 parameters,
314 }
315 }
316
317 pub(super) fn cr_seed(&self) -> &S {
318 &self.cr_seed
319 }
320
321 pub(super) fn parameters(&self) -> &P {
322 &self.parameters
323 }
324
325 pub(super) fn auto_keys(&self) -> &HashMap<usize, M> {
326 &self.auto_keys
327 }
328
329 pub(super) fn rgsw_cts(&self) -> &[M] {
330 &self.rgsw_cts
331 }
332
333 pub(super) fn lwe_ksk(&self) -> &M::R {
334 &self.lwe_ksk
335 }
336}
337
338/// CRS seeded MultiParty server key
339pub struct SeededMultiPartyServerKey<M: Matrix, S, P> {
340 rgsw_cts: Vec<M>,
341 /// Auto keys. Key corresponding to g^{k} is at index `k`. Key corresponding
342 /// to -g is at 0
343 auto_keys: HashMap<usize, M>,
344 lwe_ksk: M::R,
345 cr_seed: S,
346 parameters: P,
347}
348
349impl<M: Matrix, S, P> SeededMultiPartyServerKey<M, S, P> {
350 pub(super) fn new(
351 rgsw_cts: Vec<M>,
352 auto_keys: HashMap<usize, M>,
353 lwe_ksk: M::R,
354 cr_seed: S,
355 parameters: P,
356 ) -> Self {
357 SeededMultiPartyServerKey {
358 rgsw_cts,
359 auto_keys,
360 lwe_ksk,
361 cr_seed,
362 parameters,
363 }
364 }
365
366 pub(super) fn rgsw_cts(&self) -> &[M] {
367 &self.rgsw_cts
368 }
369}
370
371/// Seeded single party server key
372pub struct SeededServerKey<M: Matrix, P, S> {
373 /// Rgsw cts of LWE secret elements
374 pub(crate) rgsw_cts: Vec<M>,
375 /// Auto keys. Key corresponding to g^{k} is at index `k`. Key corresponding
376 /// to -g is at 0
377 pub(crate) auto_keys: HashMap<usize, M>,
378 /// LWE ksk to key switching LWE ciphertext from RLWE secret to LWE secret
379 pub(crate) lwe_ksk: M::R,
380 /// Parameters
381 pub(crate) parameters: P,
382 /// Main seed
383 pub(crate) seed: S,
384}
385impl<M: Matrix, S> SeededServerKey<M, BoolParameters<M::MatElement>, S> {
386 pub(super) fn from_raw(
387 auto_keys: HashMap<usize, M>,
388 rgsw_cts: Vec<M>,
389 lwe_ksk: M::R,
390 parameters: BoolParameters<M::MatElement>,
391 seed: S,
392 ) -> Self {
393 // sanity checks
394 auto_keys.iter().for_each(|v| {
395 assert!(
396 v.1.dimension()
397 == (
398 parameters.auto_decomposition_count().0,
399 parameters.rlwe_n().0
400 )
401 )
402 });
403
404 let (part_a_d, part_b_d) = parameters.rlwe_rgsw_decomposition_count();
405 rgsw_cts.iter().for_each(|v| {
406 assert!(v.dimension() == (part_a_d.0 * 2 + part_b_d.0, parameters.rlwe_n().0))
407 });
408 assert!(
409 lwe_ksk.as_ref().len()
410 == (parameters.lwe_decomposition_count().0 * parameters.rlwe_n().0)
411 );
412
413 SeededServerKey {
414 rgsw_cts,
415 auto_keys,
416 lwe_ksk,
417 parameters,
418 seed,
419 }
420 }
421}
422
423/// Server key in evaluation domain
424pub(crate) struct ServerKeyEvaluationDomain<M, P, R, N> {
425 /// Rgsw cts of LWE secret elements
426 rgsw_cts: Vec<M>,
427 /// Auto keys. Key corresponding to g^{k} is at index `k`. Key corresponding
428 /// to -g is at 0
429 galois_keys: HashMap<usize, M>,
430 /// LWE ksk to key switching LWE ciphertext from RLWE secret to LWE secret
431 lwe_ksk: M,
432 parameters: P,
433 _phanton: PhantomData<(R, N)>,
434}
435
436pub(super) mod impl_server_key_eval_domain {
437 use itertools::{izip, Itertools};
438
439 use crate::{
440 backend::Modulus,
441 ntt::{Ntt, NttInit},
442 pbs::PbsKey,
443 };
444
445 use super::*;
446
447 impl<M, Mod, R, N> ServerKeyEvaluationDomain<M, Mod, R, N> {
448 pub(in super::super) fn rgsw_cts(&self) -> &[M] {
449 &self.rgsw_cts
450 }
451 }
452
453 impl<
454 M: MatrixMut + MatrixEntity,
455 R: RandomFillUniformInModulus<[M::MatElement], CiphertextModulus<M::MatElement>>
456 + NewWithSeed,
457 N: NttInit<CiphertextModulus<M::MatElement>> + Ntt<Element = M::MatElement>,
458 > From<&SeededServerKey<M, BoolParameters<M::MatElement>, R::Seed>>
459 for ServerKeyEvaluationDomain<M, BoolParameters<M::MatElement>, R, N>
460 where
461 <M as Matrix>::R: RowMut,
462 M::MatElement: Copy,
463 R::Seed: Clone,
464 {
465 fn from(value: &SeededServerKey<M, BoolParameters<M::MatElement>, R::Seed>) -> Self {
466 let mut main_prng = R::new_with_seed(value.seed.clone());
467 let parameters = &value.parameters;
468 let g = parameters.g() as isize;
469 let ring_size = value.parameters.rlwe_n().0;
470 let lwe_n = value.parameters.lwe_n().0;
471 let rlwe_q = value.parameters.rlwe_q();
472 let lwq_q = value.parameters.lwe_q();
473
474 let nttop = N::new(rlwe_q, ring_size);
475
476 // galois keys
477 let mut auto_keys = HashMap::new();
478 let auto_decomp_count = parameters.auto_decomposition_count().0;
479 let auto_element_dlogs = parameters.auto_element_dlogs();
480 for i in auto_element_dlogs.into_iter() {
481 let seeded_auto_key = value.auto_keys.get(&i).unwrap();
482 assert!(seeded_auto_key.dimension() == (auto_decomp_count, ring_size));
483
484 let mut data = M::zeros(auto_decomp_count * 2, ring_size);
485
486 // sample RLWE'_A(-s(X^k))
487 data.iter_rows_mut().take(auto_decomp_count).for_each(|ri| {
488 RandomFillUniformInModulus::random_fill(&mut main_prng, &rlwe_q, ri.as_mut())
489 });
490
491 // copy over RLWE'B_(-s(X^k))
492 izip!(
493 data.iter_rows_mut().skip(auto_decomp_count),
494 seeded_auto_key.iter_rows()
495 )
496 .for_each(|(to_ri, from_ri)| to_ri.as_mut().copy_from_slice(from_ri.as_ref()));
497
498 // Send to Evaluation domain
499 data.iter_rows_mut()
500 .for_each(|ri| nttop.forward(ri.as_mut()));
501
502 auto_keys.insert(i, data);
503 }
504
505 // RGSW ciphertexts
506 let (rlrg_a_decomp, rlrg_b_decomp) = parameters.rlwe_rgsw_decomposition_count();
507 let rgsw_cts = value
508 .rgsw_cts
509 .iter()
510 .map(|seeded_rgsw_si| {
511 assert!(
512 seeded_rgsw_si.dimension()
513 == (rlrg_a_decomp.0 * 2 + rlrg_b_decomp.0, ring_size)
514 );
515
516 let mut data = M::zeros(rlrg_a_decomp.0 * 2 + rlrg_b_decomp.0 * 2, ring_size);
517
518 // copy over RLWE'(-sm)
519 izip!(
520 data.iter_rows_mut().take(rlrg_a_decomp.0 * 2),
521 seeded_rgsw_si.iter_rows().take(rlrg_a_decomp.0 * 2)
522 )
523 .for_each(|(to_ri, from_ri)| to_ri.as_mut().copy_from_slice(from_ri.as_ref()));
524
525 // sample RLWE'_A(m)
526 data.iter_rows_mut()
527 .skip(rlrg_a_decomp.0 * 2)
528 .take(rlrg_b_decomp.0)
529 .for_each(|ri| {
530 RandomFillUniformInModulus::random_fill(
531 &mut main_prng,
532 &rlwe_q,
533 ri.as_mut(),
534 )
535 });
536
537 // copy over RLWE'_B(m)
538 izip!(
539 data.iter_rows_mut()
540 .skip(rlrg_a_decomp.0 * 2 + rlrg_b_decomp.0),
541 seeded_rgsw_si.iter_rows().skip(rlrg_a_decomp.0 * 2)
542 )
543 .for_each(|(to_ri, from_ri)| to_ri.as_mut().copy_from_slice(from_ri.as_ref()));
544
545 // send polynomials to evaluation domain
546 data.iter_rows_mut()
547 .for_each(|ri| nttop.forward(ri.as_mut()));
548
549 data
550 })
551 .collect_vec();
552
553 // LWE ksk
554 let lwe_ksk = {
555 let d = parameters.lwe_decomposition_count().0;
556 assert!(value.lwe_ksk.as_ref().len() == d * ring_size);
557
558 let mut data = M::zeros(d * ring_size, lwe_n + 1);
559 izip!(data.iter_rows_mut(), value.lwe_ksk.as_ref().iter()).for_each(
560 |(lwe_i, bi)| {
561 RandomFillUniformInModulus::random_fill(
562 &mut main_prng,
563 &lwq_q,
564 &mut lwe_i.as_mut()[1..],
565 );
566 lwe_i.as_mut()[0] = *bi;
567 },
568 );
569
570 data
571 };
572
573 ServerKeyEvaluationDomain {
574 rgsw_cts,
575 galois_keys: auto_keys,
576 lwe_ksk,
577 parameters: parameters.clone(),
578 _phanton: PhantomData,
579 }
580 }
581 }
582
583 impl<
584 M: MatrixMut + MatrixEntity,
585 Rng: NewWithSeed,
586 N: NttInit<CiphertextModulus<M::MatElement>> + Ntt<Element = M::MatElement>,
587 > From<&SeededMultiPartyServerKey<M, Rng::Seed, BoolParameters<M::MatElement>>>
588 for ServerKeyEvaluationDomain<M, BoolParameters<M::MatElement>, Rng, N>
589 where
590 <M as Matrix>::R: RowMut,
591 Rng::Seed: Copy,
592 Rng: RandomFillUniformInModulus<[M::MatElement], CiphertextModulus<M::MatElement>>,
593 M::MatElement: Copy,
594 {
595 fn from(
596 value: &SeededMultiPartyServerKey<M, Rng::Seed, BoolParameters<M::MatElement>>,
597 ) -> Self {
598 let g = value.parameters.g() as isize;
599 let rlwe_n = value.parameters.rlwe_n().0;
600 let lwe_n = value.parameters.lwe_n().0;
601 let rlwe_q = value.parameters.rlwe_q();
602 let lwe_q = value.parameters.lwe_q();
603
604 let mut main_prng = Rng::new_with_seed(value.cr_seed);
605
606 let rlwe_nttop = N::new(rlwe_q, rlwe_n);
607
608 // auto keys
609 let mut auto_keys = HashMap::new();
610 let auto_d_count = value.parameters.auto_decomposition_count().0;
611 let auto_element_dlogs = value.parameters.auto_element_dlogs();
612 for i in auto_element_dlogs.into_iter() {
613 let mut key = M::zeros(auto_d_count * 2, rlwe_n);
614
615 // sample a
616 key.iter_rows_mut().take(auto_d_count).for_each(|ri| {
617 RandomFillUniformInModulus::random_fill(&mut main_prng, &rlwe_q, ri.as_mut())
618 });
619
620 let key_part_b = value.auto_keys.get(&i).unwrap();
621 assert!(key_part_b.dimension() == (auto_d_count, rlwe_n));
622 izip!(
623 key.iter_rows_mut().skip(auto_d_count),
624 key_part_b.iter_rows()
625 )
626 .for_each(|(to_ri, from_ri)| {
627 to_ri.as_mut().copy_from_slice(from_ri.as_ref());
628 });
629
630 // send to evaluation domain
631 key.iter_rows_mut()
632 .for_each(|ri| rlwe_nttop.forward(ri.as_mut()));
633
634 auto_keys.insert(i, key);
635 }
636
637 // rgsw cts
638 let (rlrg_d_a, rlrg_d_b) = value.parameters.rlwe_rgsw_decomposition_count();
639 let rgsw_ct_out = rlrg_d_a.0 * 2 + rlrg_d_b.0 * 2;
640 let rgsw_cts = value
641 .rgsw_cts
642 .iter()
643 .map(|ct_i_in| {
644 assert!(ct_i_in.dimension() == (rgsw_ct_out, rlwe_n));
645 let mut eval_ct_i_out = M::zeros(rgsw_ct_out, rlwe_n);
646
647 izip!(eval_ct_i_out.iter_rows_mut(), ct_i_in.iter_rows()).for_each(
648 |(to_ri, from_ri)| {
649 to_ri.as_mut().copy_from_slice(from_ri.as_ref());
650 rlwe_nttop.forward(to_ri.as_mut());
651 },
652 );
653
654 eval_ct_i_out
655 })
656 .collect_vec();
657
658 // lwe ksk
659 let d_lwe = value.parameters.lwe_decomposition_count().0;
660 let mut lwe_ksk = M::zeros(rlwe_n * d_lwe, lwe_n + 1);
661 izip!(lwe_ksk.iter_rows_mut(), value.lwe_ksk.as_ref().iter()).for_each(
662 |(lwe_i, bi)| {
663 RandomFillUniformInModulus::random_fill(
664 &mut main_prng,
665 &lwe_q,
666 &mut lwe_i.as_mut()[1..],
667 );
668 lwe_i.as_mut()[0] = *bi;
669 },
670 );
671
672 ServerKeyEvaluationDomain {
673 rgsw_cts,
674 galois_keys: auto_keys,
675 lwe_ksk,
676 parameters: value.parameters.clone(),
677 _phanton: PhantomData,
678 }
679 }
680 }
681
682 impl<M: Matrix, P, R, N> PbsKey for ServerKeyEvaluationDomain<M, P, R, N> {
683 type AutoKey = M;
684 type LweKskKey = M;
685 type RgswCt = M;
686
687 fn galois_key_for_auto(&self, k: usize) -> &Self::AutoKey {
688 self.galois_keys.get(&k).unwrap()
689 }
690 fn rgsw_ct_lwe_si(&self, si: usize) -> &Self::RgswCt {
691 &self.rgsw_cts[si]
692 }
693
694 fn lwe_ksk(&self) -> &Self::LweKskKey {
695 &self.lwe_ksk
696 }
697 }
698}
699
700/// Server key in evaluation domain
701pub(crate) struct ShoupServerKeyEvaluationDomain<M> {
702 /// Rgsw cts of LWE secret elements
703 rgsw_cts: Vec<NormalAndShoup<M>>,
704 /// Auto keys. Key corresponding to g^{k} is at index `k`. Key corresponding
705 /// to -g is at 0
706 galois_keys: HashMap<usize, NormalAndShoup<M>>,
707 /// LWE ksk to key switching LWE ciphertext from RLWE secret to LWE secret
708 lwe_ksk: M,
709}
710
711/// Stores normal and shoup representation of Matrix elements (Normal, Shoup)
712pub(crate) struct NormalAndShoup<M>(M, M);
713
714impl<M: ToShoup> NormalAndShoup<M> {
715 fn new_with_modulus(value: M, modulus: <M as ToShoup>::Modulus) -> Self {
716 let value_shoup = M::to_shoup(&value, modulus);
717 NormalAndShoup(value, value_shoup)
718 }
719}
720
721impl<M> AsRef<M> for NormalAndShoup<M> {
722 fn as_ref(&self) -> &M {
723 &self.0
724 }
725}
726
727impl<M> WithShoupRepr for NormalAndShoup<M> {
728 type M = M;
729 fn shoup_repr(&self) -> &Self::M {
730 &self.1
731 }
732}
733
734mod shoup_server_key_eval_domain {
735 use itertools::{izip, Itertools};
736 use num_traits::{FromPrimitive, PrimInt};
737
738 use crate::{backend::Modulus, pbs::PbsKey};
739
740 use super::*;
741
742 impl<M: MatrixMut + MatrixEntity + ToShoup<Modulus = M::MatElement>, R, N>
743 From<ServerKeyEvaluationDomain<M, BoolParameters<M::MatElement>, R, N>>
744 for ShoupServerKeyEvaluationDomain<M>
745 where
746 <M as Matrix>::R: RowMut,
747 M::MatElement: PrimInt + FromPrimitive,
748 {
749 fn from(value: ServerKeyEvaluationDomain<M, BoolParameters<M::MatElement>, R, N>) -> Self {
750 let q = value.parameters.rlwe_q().q().unwrap();
751 // Rgsw ciphertexts
752 let rgsw_cts = value
753 .rgsw_cts
754 .into_iter()
755 .map(|ct| NormalAndShoup::new_with_modulus(ct, q))
756 .collect_vec();
757
758 let mut auto_keys = HashMap::new();
759 value.galois_keys.into_iter().for_each(|(index, key)| {
760 auto_keys.insert(index, NormalAndShoup::new_with_modulus(key, q));
761 });
762
763 Self {
764 rgsw_cts,
765 galois_keys: auto_keys,
766 lwe_ksk: value.lwe_ksk,
767 }
768 }
769 }
770
771 impl<M: Matrix> PbsKey for ShoupServerKeyEvaluationDomain<M> {
772 type AutoKey = NormalAndShoup<M>;
773 type LweKskKey = M;
774 type RgswCt = NormalAndShoup<M>;
775
776 fn galois_key_for_auto(&self, k: usize) -> &Self::AutoKey {
777 self.galois_keys.get(&k).unwrap()
778 }
779 fn rgsw_ct_lwe_si(&self, si: usize) -> &Self::RgswCt {
780 &self.rgsw_cts[si]
781 }
782
783 fn lwe_ksk(&self) -> &Self::LweKskKey {
784 &self.lwe_ksk
785 }
786 }
787}