poulpy/poulpy-core/src/encryption/gglwe_ksk.rs
poulpy-core/src/encryption/gglwe_ksk.rsRaw
1use poulpy_hal::{
2 api::{
3 ScratchAvailable, SvpApplyDftToDftInplace, SvpPPolAllocBytes, SvpPrepare, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft,
4 VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftApply,
5 VecZnxFillUniform, VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub,
6 VecZnxSubInplace, VecZnxSwitchRing,
7 },
8 layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch},
9 source::Source,
10};
11
12use crate::{
13 TakeGLWESecretPrepared,
14 layouts::{
15 Degree, GGLWECiphertext, GGLWEInfos, GGLWESwitchingKey, GLWEInfos, GLWESecret, LWEInfos, prepared::GLWESecretPrepared,
16 },
17};
18
19impl GGLWESwitchingKey<Vec<u8>> {
20 pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize
21 where
22 A: GGLWEInfos,
23 Module<B>: SvpPPolAllocBytes + VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes,
24 {
25 (GGLWECiphertext::encrypt_sk_scratch_space(module, infos) | ScalarZnx::alloc_bytes(module.n(), 1))
26 + ScalarZnx::alloc_bytes(module.n(), infos.rank_in().into())
27 + GLWESecretPrepared::alloc_bytes(module, &infos.glwe_layout())
28 }
29
30 pub fn encrypt_pk_scratch_space<B: Backend, A>(module: &Module<B>, _infos: &A) -> usize
31 where
32 A: GGLWEInfos,
33 {
34 GGLWECiphertext::encrypt_pk_scratch_space(module, _infos)
35 }
36}
37
38impl<DataSelf: DataMut> GGLWESwitchingKey<DataSelf> {
39 #[allow(clippy::too_many_arguments)]
40 pub fn encrypt_sk<DataSkIn: DataRef, DataSkOut: DataRef, B: Backend>(
41 &mut self,
42 module: &Module<B>,
43 sk_in: &GLWESecret<DataSkIn>,
44 sk_out: &GLWESecret<DataSkOut>,
45 source_xa: &mut Source,
46 source_xe: &mut Source,
47 scratch: &mut Scratch<B>,
48 ) where
49 Module<B>: VecZnxAddScalarInplace
50 + VecZnxDftAllocBytes
51 + VecZnxBigNormalize<B>
52 + VecZnxDftApply<B>
53 + SvpApplyDftToDftInplace<B>
54 + VecZnxIdftApplyConsume<B>
55 + VecZnxNormalizeTmpBytes
56 + VecZnxFillUniform
57 + VecZnxSubInplace
58 + VecZnxAddInplace
59 + VecZnxNormalizeInplace<B>
60 + VecZnxAddNormal
61 + VecZnxNormalize<B>
62 + VecZnxSub
63 + SvpPrepare<B>
64 + VecZnxSwitchRing
65 + SvpPPolAllocBytes,
66 Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx + TakeScalarZnx + TakeGLWESecretPrepared<B>,
67 {
68 #[cfg(debug_assertions)]
69 {
70 assert!(sk_in.n().0 <= module.n() as u32);
71 assert!(sk_out.n().0 <= module.n() as u32);
72 assert!(
73 scratch.available() >= GGLWESwitchingKey::encrypt_sk_scratch_space(module, self),
74 "scratch.available()={} < GLWESwitchingKey::encrypt_sk_scratch_space={}",
75 scratch.available(),
76 GGLWESwitchingKey::encrypt_sk_scratch_space(module, self)
77 )
78 }
79
80 let n: usize = sk_in.n().max(sk_out.n()).into();
81
82 let (mut sk_in_tmp, scratch_1) = scratch.take_scalar_znx(n, sk_in.rank().into());
83 (0..sk_in.rank().into()).for_each(|i| {
84 module.vec_znx_switch_ring(
85 &mut sk_in_tmp.as_vec_znx_mut(),
86 i,
87 &sk_in.data.as_vec_znx(),
88 i,
89 );
90 });
91
92 let (mut sk_out_tmp, scratch_2) = scratch_1.take_glwe_secret_prepared(Degree(n as u32), sk_out.rank());
93 {
94 let (mut tmp, _) = scratch_2.take_scalar_znx(n, 1);
95 (0..sk_out.rank().into()).for_each(|i| {
96 module.vec_znx_switch_ring(&mut tmp.as_vec_znx_mut(), 0, &sk_out.data.as_vec_znx(), i);
97 module.svp_prepare(&mut sk_out_tmp.data, i, &tmp, 0);
98 });
99 }
100
101 self.key.encrypt_sk(
102 module,
103 &sk_in_tmp,
104 &sk_out_tmp,
105 source_xa,
106 source_xe,
107 scratch_2,
108 );
109 self.sk_in_n = sk_in.n().into();
110 self.sk_out_n = sk_out.n().into();
111 }
112}