poulpy/core/src/encryption/compressed/gglwe_ksk.rs
core/src/encryption/compressed/gglwe_ksk.rsRaw
1use backend::hal::{
2 api::{ScratchAvailable, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, VecZnxSwithcDegree},
3 layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch},
4};
5use sampling::source::Source;
6
7use crate::{
8 TakeGLWESecretPrepared,
9 layouts::{
10 GGLWECiphertext, GGLWESwitchingKey, GLWESecret, Infos, compressed::GGLWESwitchingKeyCompressed,
11 prepared::GLWESecretPrepared,
12 },
13};
14
15use crate::trait_families::{GGLWESwitchingKeyEncryptSkFamily, GLWESecretPreparedModuleFamily};
16
17impl GGLWESwitchingKeyCompressed<Vec<u8>> {
18 pub fn encrypt_sk_scratch_space<B: Backend>(
19 module: &Module<B>,
20 n: usize,
21 basek: usize,
22 k: usize,
23 rank_in: usize,
24 rank_out: usize,
25 ) -> usize
26 where
27 Module<B>: GGLWESwitchingKeyEncryptSkFamily<B> + GLWESecretPreparedModuleFamily<B>,
28 {
29 (GGLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k) | ScalarZnx::alloc_bytes(n, 1))
30 + ScalarZnx::alloc_bytes(n, rank_in)
31 + GLWESecretPrepared::bytes_of(module, n, rank_out)
32 }
33}
34
35impl<DataSelf: DataMut> GGLWESwitchingKeyCompressed<DataSelf> {
36 pub fn encrypt_sk<DataSkIn: DataRef, DataSkOut: DataRef, B: Backend>(
37 &mut self,
38 module: &Module<B>,
39 sk_in: &GLWESecret<DataSkIn>,
40 sk_out: &GLWESecret<DataSkOut>,
41 seed_xa: [u8; 32],
42 source_xe: &mut Source,
43 sigma: f64,
44 scratch: &mut Scratch<B>,
45 ) where
46 Module<B>:
47 GGLWESwitchingKeyEncryptSkFamily<B> + VecZnxSwithcDegree + VecZnxAddScalarInplace + GLWESecretPreparedModuleFamily<B>,
48 Scratch<B>:
49 ScratchAvailable + TakeScalarZnx + TakeVecZnxDft<B> + TakeGLWESecretPrepared<B> + ScratchAvailable + TakeVecZnx,
50 {
51 #[cfg(debug_assertions)]
52 {
53 assert!(sk_in.n() <= module.n());
54 assert!(sk_out.n() <= module.n());
55 assert!(
56 scratch.available()
57 >= GGLWESwitchingKey::encrypt_sk_scratch_space(
58 module,
59 sk_out.n(),
60 self.basek(),
61 self.k(),
62 self.rank_in(),
63 self.rank_out()
64 ),
65 "scratch.available()={} < GLWESwitchingKey::encrypt_sk_scratch_space={}",
66 scratch.available(),
67 GGLWESwitchingKey::encrypt_sk_scratch_space(
68 module,
69 sk_out.n(),
70 self.basek(),
71 self.k(),
72 self.rank_in(),
73 self.rank_out()
74 )
75 )
76 }
77
78 let n: usize = sk_in.n().max(sk_out.n());
79
80 let (mut sk_in_tmp, scratch1) = scratch.take_scalar_znx(n, sk_in.rank());
81 (0..sk_in.rank()).for_each(|i| {
82 module.vec_znx_switch_degree(
83 &mut sk_in_tmp.as_vec_znx_mut(),
84 i,
85 &sk_in.data.as_vec_znx(),
86 i,
87 );
88 });
89
90 let (mut sk_out_tmp, scratch2) = scratch1.take_glwe_secret_prepared(n, sk_out.rank());
91 {
92 let (mut tmp, _) = scratch2.take_scalar_znx(n, 1);
93 (0..sk_out.rank()).for_each(|i| {
94 module.vec_znx_switch_degree(&mut tmp.as_vec_znx_mut(), 0, &sk_out.data.as_vec_znx(), i);
95 module.svp_prepare(&mut sk_out_tmp.data, i, &tmp, 0);
96 });
97 }
98
99 self.key.encrypt_sk(
100 module,
101 &sk_in_tmp,
102 &sk_out_tmp,
103 seed_xa,
104 source_xe,
105 sigma,
106 scratch2,
107 );
108 self.sk_in_n = sk_in.n();
109 self.sk_out_n = sk_out.n();
110 }
111}