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