poulpy/poulpy-core/src/encryption/glwe_switching_key.rs
poulpy-core/src/encryption/glwe_switching_key.rsRaw
1use poulpy_hal::{
2 api::{ModuleN, ScratchAvailable, ScratchTakeBasic, SvpPrepare, VecZnxSwitchRing},
3 layouts::{Backend, DataMut, Module, ScalarZnx, Scratch},
4 source::Source,
5};
6
7use crate::{
8 ScratchTakeCore,
9 encryption::gglwe::GGLWEEncryptSk,
10 layouts::{
11 GGLWEInfos, GGLWEToMut, GLWEInfos, GLWESecret, GLWESecretToRef, GLWESwitchingKey, GLWESwitchingKeyDegreesMut, LWEInfos,
12 prepared::GLWESecretPreparedFactory,
13 },
14};
15
16impl GLWESwitchingKey<Vec<u8>> {
17 pub fn encrypt_sk_tmp_bytes<M, A, BE: Backend>(module: &M, infos: &A) -> usize
18 where
19 A: GGLWEInfos,
20 M: GLWESwitchingKeyEncryptSk<BE>,
21 {
22 module.glwe_switching_key_encrypt_sk_tmp_bytes(infos)
23 }
24
25 pub fn encrypt_pk_tmp_bytes<M, A, BE: Backend>(module: &M, infos: &A) -> usize
26 where
27 A: GGLWEInfos,
28 M: GLWESwitchingKeyEncryptPk<BE>,
29 {
30 module.glwe_switching_key_encrypt_pk_tmp_bytes(infos)
31 }
32}
33
34impl<DataSelf: DataMut> GLWESwitchingKey<DataSelf> {
35 pub fn encrypt_sk<M, S1, S2, BE: Backend>(
36 &mut self,
37 module: &M,
38 sk_in: &S1,
39 sk_out: &S2,
40 source_xa: &mut Source,
41 source_xe: &mut Source,
42 scratch: &mut Scratch<BE>,
43 ) where
44 S1: GLWESecretToRef,
45 S2: GLWESecretToRef,
46 M: GLWESwitchingKeyEncryptSk<BE>,
47 Scratch<BE>: ScratchTakeCore<BE>,
48 {
49 module.glwe_switching_key_encrypt_sk(self, sk_in, sk_out, source_xa, source_xe, scratch);
50 }
51}
52
53pub trait GLWESwitchingKeyEncryptSk<BE: Backend> {
54 fn glwe_switching_key_encrypt_sk_tmp_bytes<A>(&self, infos: &A) -> usize
55 where
56 A: GGLWEInfos;
57
58 fn glwe_switching_key_encrypt_sk<R, S1, S2>(
59 &self,
60 res: &mut R,
61 sk_in: &S1,
62 sk_out: &S2,
63 source_xa: &mut Source,
64 source_xe: &mut Source,
65 scratch: &mut Scratch<BE>,
66 ) where
67 R: GGLWEToMut + GLWESwitchingKeyDegreesMut + GGLWEInfos,
68 S1: GLWESecretToRef,
69 S2: GLWESecretToRef;
70}
71
72impl<BE: Backend> GLWESwitchingKeyEncryptSk<BE> for Module<BE>
73where
74 Self: ModuleN + GGLWEEncryptSk<BE> + GLWESecretPreparedFactory<BE> + VecZnxSwitchRing + SvpPrepare<BE>,
75 Scratch<BE>: ScratchTakeCore<BE>,
76{
77 fn glwe_switching_key_encrypt_sk_tmp_bytes<A>(&self, infos: &A) -> usize
78 where
79 A: GGLWEInfos,
80 {
81 self.gglwe_encrypt_sk_tmp_bytes(infos).max(ScalarZnx::bytes_of(self.n(), 1))
82 + ScalarZnx::bytes_of(self.n(), infos.rank_in().into())
83 + self.bytes_of_glwe_secret_prepared_from_infos(infos)
84 }
85
86 fn glwe_switching_key_encrypt_sk<R, S1, S2>(
87 &self,
88 res: &mut R,
89 sk_in: &S1,
90 sk_out: &S2,
91 source_xa: &mut Source,
92 source_xe: &mut Source,
93 scratch: &mut Scratch<BE>,
94 ) where
95 R: GGLWEToMut + GLWESwitchingKeyDegreesMut + GGLWEInfos,
96 S1: GLWESecretToRef,
97 S2: GLWESecretToRef,
98 {
99 let sk_in: &GLWESecret<&[u8]> = &sk_in.to_ref();
100 let sk_out: &GLWESecret<&[u8]> = &sk_out.to_ref();
101
102 assert!(sk_in.n().0 <= self.n() as u32);
103 assert!(sk_out.n().0 <= self.n() as u32);
104 assert!(
105 scratch.available() >= self.glwe_switching_key_encrypt_sk_tmp_bytes(res),
106 "scratch.available()={} < GLWESwitchingKey::encrypt_sk_tmp_bytes={}",
107 scratch.available(),
108 self.glwe_switching_key_encrypt_sk_tmp_bytes(res)
109 );
110
111 let (mut sk_in_tmp, scratch_1) = scratch.take_scalar_znx(self.n(), sk_in.rank().into());
112 for i in 0..sk_in.rank().into() {
113 self.vec_znx_switch_ring(&mut sk_in_tmp.as_vec_znx_mut(), i, &sk_in.data.as_vec_znx(), i);
114 }
115
116 let (mut sk_out_tmp, scratch_2) = scratch_1.take_glwe_secret_prepared(self, sk_out.rank());
117 {
118 let (mut tmp, _) = scratch_2.take_scalar_znx(self.n(), 1);
119 for i in 0..sk_out.rank().into() {
120 self.vec_znx_switch_ring(&mut tmp.as_vec_znx_mut(), 0, &sk_out.data.as_vec_znx(), i);
121 self.svp_prepare(&mut sk_out_tmp.data, i, &tmp, 0);
122 }
123 }
124
125 sk_out_tmp.dist = sk_out.dist;
126
127 self.gglwe_encrypt_sk(res, &sk_in_tmp, &sk_out_tmp, source_xa, source_xe, scratch_2);
128
129 *res.input_degree() = sk_in.n();
130 *res.output_degree() = sk_out.n();
131 }
132}
133
134pub trait GLWESwitchingKeyEncryptPk<BE: Backend> {
135 fn glwe_switching_key_encrypt_pk_tmp_bytes<A>(&self, infos: &A) -> usize
136 where
137 A: GGLWEInfos;
138}
139
140impl<BE: Backend> GLWESwitchingKeyEncryptPk<BE> for Module<BE> {
141 fn glwe_switching_key_encrypt_pk_tmp_bytes<A>(&self, _infos: &A) -> usize
142 where
143 A: GGLWEInfos,
144 {
145 unimplemented!()
146 }
147}