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