poulpy/poulpy-core/src/encryption/gglwe_tsk.rs
poulpy-core/src/encryption/gglwe_tsk.rsRaw
1use poulpy_hal::{
2 api::{
3 SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolBytesOf, SvpPrepare, VecZnxAddInplace, VecZnxAddNormal,
4 VecZnxAddScalarInplace, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform,
5 VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub,
6 VecZnxSubInplace, VecZnxSwitchRing,
7 },
8 layouts::{Backend, DataMut, DataRef, Module, Scratch},
9 source::Source,
10};
11
12use crate::layouts::{
13 GGLWEInfos, GLWEInfos, GLWESecret, GLWESwitchingKey, LWEInfos, Rank, RingDegree, TensorKey, prepared::GLWESecretPrepared,
14};
15
16impl TensorKey<Vec<u8>> {
17 pub fn encrypt_sk_tmp_bytes<B: Backend, A>(module: &Module<B>, infos: &A) -> usize
18 where
19 A: GGLWEInfos,
20 Module<B>: SvpPPolBytesOf + VecZnxNormalizeTmpBytes + VecZnxDftBytesOf + VecZnxNormalizeTmpBytes + VecZnxBigBytesOf,
21 {
22 GLWESecretPrepared::bytes_of(module, infos.rank_out())
23 + module.bytes_of_vec_znx_dft(infos.rank_out().into(), 1)
24 + module.bytes_of_vec_znx_big(1, 1)
25 + module.bytes_of_vec_znx_dft(1, 1)
26 + GLWESecret::bytes_of(RingDegree(module.n() as u32), Rank(1))
27 + GLWESwitchingKey::encrypt_sk_tmp_bytes(module, infos)
28 }
29}
30
31impl<DataSelf: DataMut> TensorKey<DataSelf> {
32 pub fn encrypt_sk<DataSk: DataRef, B: Backend>(
33 &mut self,
34 module: &Module<B>,
35 sk: &GLWESecret<DataSk>,
36 source_xa: &mut Source,
37 source_xe: &mut Source,
38 scratch: &mut Scratch<B>,
39 ) where
40 Module<B>: SvpApplyDftToDft<B>
41 + VecZnxIdftApplyTmpA<B>
42 + VecZnxAddScalarInplace
43 + VecZnxDftBytesOf
44 + VecZnxBigNormalize<B>
45 + VecZnxDftApply<B>
46 + SvpApplyDftToDftInplace<B>
47 + VecZnxIdftApplyConsume<B>
48 + VecZnxNormalizeTmpBytes
49 + VecZnxFillUniform
50 + VecZnxSubInplace
51 + VecZnxAddInplace
52 + VecZnxNormalizeInplace<B>
53 + VecZnxAddNormal
54 + VecZnxNormalize<B>
55 + VecZnxSub
56 + SvpPrepare<B>
57 + VecZnxSwitchRing
58 + SvpPPolBytesOf,
59 Scratch<B>:,
60 {
61 #[cfg(debug_assertions)]
62 {
63 assert_eq!(self.rank_out(), sk.rank());
64 assert_eq!(self.n(), sk.n());
65 }
66
67 let n: RingDegree = sk.n();
68 let rank: Rank = self.rank_out();
69
70 let (mut sk_dft_prep, scratch_1) = scratch.take_glwe_secret_prepared(n, rank);
71 sk_dft_prep.prepare(module, sk, scratch_1);
72
73 let (mut sk_dft, scratch_2) = scratch_1.take_vec_znx_dft(n.into(), rank.into(), 1);
74
75 (0..rank.into()).for_each(|i| {
76 module.vec_znx_dft_apply(1, 0, &mut sk_dft, i, &sk.data.as_vec_znx(), i);
77 });
78
79 let (mut sk_ij_big, scratch_3) = scratch_2.take_vec_znx_big(n.into(), 1, 1);
80 let (mut sk_ij, scratch_4) = scratch_3.take_glwe_secret(n, Rank(1));
81 let (mut sk_ij_dft, scratch_5) = scratch_4.take_vec_znx_dft(n.into(), 1, 1);
82
83 (0..rank.into()).for_each(|i| {
84 (i..rank.into()).for_each(|j| {
85 module.svp_apply_dft_to_dft(&mut sk_ij_dft, 0, &sk_dft_prep.data, j, &sk_dft, i);
86
87 module.vec_znx_idft_apply_tmpa(&mut sk_ij_big, 0, &mut sk_ij_dft, 0);
88 module.vec_znx_big_normalize(
89 self.base2k().into(),
90 &mut sk_ij.data.as_vec_znx_mut(),
91 0,
92 self.base2k().into(),
93 &sk_ij_big,
94 0,
95 scratch_5,
96 );
97
98 self.at_mut(i, j)
99 .encrypt_sk(module, &sk_ij, sk, source_xa, source_xe, scratch_5);
100 });
101 })
102 }
103}