arnaucube
arnaucube/phantom-zonePublic Self-hosted repository
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}