poulpy_core/encryption/
lwe_switching_key.rs

1use poulpy_hal::{
2    api::{ModuleN, VecZnxAutomorphismInplace},
3    layouts::{Backend, DataMut, Module, Scratch, ZnxView, ZnxViewMut},
4    source::Source,
5};
6
7use crate::{
8    ScratchTakeCore,
9    encryption::glwe_switching_key::GLWESwitchingKeyEncryptSk,
10    layouts::{
11        GGLWEInfos, GGLWEToMut, GLWESecret, GLWESwitchingKey, GLWESwitchingKeyDegreesMut, LWEInfos, LWESecret, LWESecretToRef,
12        LWESwitchingKey, Rank,
13        prepared::{GLWESecretPrepared, GLWESecretPreparedFactory},
14    },
15};
16
17impl LWESwitchingKey<Vec<u8>> {
18    pub fn encrypt_sk_tmp_bytes<M, A, BE: Backend>(module: &M, infos: &A) -> usize
19    where
20        A: GGLWEInfos,
21        M: LWESwitchingKeyEncrypt<BE>,
22    {
23        module.lwe_switching_key_encrypt_sk_tmp_bytes(infos)
24    }
25}
26
27impl<D: DataMut> LWESwitchingKey<D> {
28    pub fn encrypt_sk<S1, S2, M, BE: Backend>(
29        &mut self,
30        module: &M,
31        sk_lwe_in: &S1,
32        sk_lwe_out: &S2,
33        source_xa: &mut Source,
34        source_xe: &mut Source,
35        scratch: &mut Scratch<BE>,
36    ) where
37        S1: LWESecretToRef,
38        S2: LWESecretToRef,
39        M: LWESwitchingKeyEncrypt<BE>,
40    {
41        module.lwe_switching_key_encrypt_sk(self, sk_lwe_in, sk_lwe_out, source_xa, source_xe, scratch);
42    }
43}
44
45pub trait LWESwitchingKeyEncrypt<BE: Backend> {
46    fn lwe_switching_key_encrypt_sk_tmp_bytes<A>(&self, infos: &A) -> usize
47    where
48        A: GGLWEInfos;
49
50    fn lwe_switching_key_encrypt_sk<R, S1, S2>(
51        &self,
52        res: &mut R,
53        sk_lwe_in: &S1,
54        sk_lwe_out: &S2,
55        source_xa: &mut Source,
56        source_xe: &mut Source,
57        scratch: &mut Scratch<BE>,
58    ) where
59        R: GGLWEToMut + GLWESwitchingKeyDegreesMut + GGLWEInfos,
60        S1: LWESecretToRef,
61        S2: LWESecretToRef;
62}
63
64impl<BE: Backend> LWESwitchingKeyEncrypt<BE> for Module<BE>
65where
66    Self: ModuleN + GLWESwitchingKeyEncryptSk<BE> + GLWESecretPreparedFactory<BE> + VecZnxAutomorphismInplace<BE>,
67    Scratch<BE>: ScratchTakeCore<BE>,
68{
69    fn lwe_switching_key_encrypt_sk_tmp_bytes<A>(&self, infos: &A) -> usize
70    where
71        A: GGLWEInfos,
72    {
73        assert_eq!(
74            infos.dsize().0,
75            1,
76            "dsize > 1 is not supported for LWESwitchingKey"
77        );
78        assert_eq!(
79            infos.rank_in().0,
80            1,
81            "rank_in > 1 is not supported for LWESwitchingKey"
82        );
83        assert_eq!(
84            infos.rank_out().0,
85            1,
86            "rank_out > 1 is not supported for LWESwitchingKey"
87        );
88        GLWESecret::bytes_of(self.n().into(), Rank(1))
89            + GLWESecretPrepared::bytes_of(self, Rank(1))
90            + GLWESwitchingKey::encrypt_sk_tmp_bytes(self, infos)
91    }
92
93    #[allow(clippy::too_many_arguments)]
94    fn lwe_switching_key_encrypt_sk<R, S1, S2>(
95        &self,
96        res: &mut R,
97        sk_lwe_in: &S1,
98        sk_lwe_out: &S2,
99        source_xa: &mut Source,
100        source_xe: &mut Source,
101        scratch: &mut Scratch<BE>,
102    ) where
103        R: GGLWEToMut + GLWESwitchingKeyDegreesMut + GGLWEInfos,
104        S1: LWESecretToRef,
105        S2: LWESecretToRef,
106    {
107        let sk_lwe_in: &LWESecret<&[u8]> = &sk_lwe_in.to_ref();
108        let sk_lwe_out: &LWESecret<&[u8]> = &sk_lwe_out.to_ref();
109
110        assert!(sk_lwe_in.n().0 <= res.n().0);
111        assert!(sk_lwe_out.n().0 <= res.n().0);
112        assert!(res.n() <= self.n() as u32);
113
114        let (mut sk_glwe_in, scratch_1) = scratch.take_glwe_secret(self.n().into(), Rank(1));
115        let (mut sk_glwe_out, scratch_2) = scratch_1.take_glwe_secret(self.n().into(), Rank(1));
116
117        sk_glwe_in.dist = sk_lwe_in.dist;
118        sk_glwe_out.dist = sk_lwe_out.dist;
119
120        sk_glwe_out.data.at_mut(0, 0)[..sk_lwe_out.n().into()].copy_from_slice(sk_lwe_out.data.at(0, 0));
121        sk_glwe_out.data.at_mut(0, 0)[sk_lwe_out.n().into()..].fill(0);
122        self.vec_znx_automorphism_inplace(-1, &mut sk_glwe_out.data.as_vec_znx_mut(), 0, scratch_2);
123
124        sk_glwe_in.data.at_mut(0, 0)[..sk_lwe_in.n().into()].copy_from_slice(sk_lwe_in.data.at(0, 0));
125        sk_glwe_in.data.at_mut(0, 0)[sk_lwe_in.n().into()..].fill(0);
126        self.vec_znx_automorphism_inplace(-1, &mut sk_glwe_in.data.as_vec_znx_mut(), 0, scratch_2);
127
128        self.glwe_switching_key_encrypt_sk(
129            res,
130            &sk_glwe_in,
131            &sk_glwe_out,
132            source_xa,
133            source_xe,
134            scratch_2,
135        );
136    }
137}