poulpy/core/src/encryption/compressed/gglwe_ksk.rs
core/src/encryption/compressed/gglwe_ksk.rsRaw
1use backend::hal::{
2 api::{
3 ScratchAvailable, SvpApplyInplace, SvpPPolAllocBytes, SvpPrepare, TakeScalarZnx, TakeVecZnx, TakeVecZnxDft,
4 VecZnxAddInplace, VecZnxAddNormal, VecZnxAddScalarInplace, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxDftFromVecZnx,
5 VecZnxDftToVecZnxBigConsume, VecZnxFillUniform, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes,
6 VecZnxSub, VecZnxSubABInplace, VecZnxSwithcDegree,
7 },
8 layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch},
9};
10use sampling::source::Source;
11
12use crate::{
13 TakeGLWESecretPrepared,
14 layouts::{GGLWECiphertext, GLWESecret, compressed::GGLWESwitchingKeyCompressed, prepared::GLWESecretPrepared},
15};
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>: VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes + VecZnxNormalizeTmpBytes + SvpPPolAllocBytes,
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>: SvpPrepare<B>
47 + SvpPPolAllocBytes
48 + VecZnxSwithcDegree
49 + VecZnxDftAllocBytes
50 + VecZnxBigNormalize<B>
51 + VecZnxDftFromVecZnx<B>
52 + SvpApplyInplace<B>
53 + VecZnxDftToVecZnxBigConsume<B>
54 + VecZnxNormalizeTmpBytes
55 + VecZnxFillUniform
56 + VecZnxSubABInplace
57 + VecZnxAddInplace
58 + VecZnxNormalizeInplace<B>
59 + VecZnxAddNormal
60 + VecZnxNormalize<B>
61 + VecZnxSub
62 + VecZnxAddScalarInplace,
63 Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx + TakeScalarZnx + TakeGLWESecretPrepared<B>,
64 {
65 #[cfg(debug_assertions)]
66 {
67 use crate::layouts::{GGLWESwitchingKey, Infos};
68
69 assert!(sk_in.n() <= module.n());
70 assert!(sk_out.n() <= module.n());
71 assert!(
72 scratch.available()
73 >= GGLWESwitchingKey::encrypt_sk_scratch_space(
74 module,
75 sk_out.n(),
76 self.basek(),
77 self.k(),
78 self.rank_in(),
79 self.rank_out()
80 ),
81 "scratch.available()={} < GLWESwitchingKey::encrypt_sk_scratch_space={}",
82 scratch.available(),
83 GGLWESwitchingKey::encrypt_sk_scratch_space(
84 module,
85 sk_out.n(),
86 self.basek(),
87 self.k(),
88 self.rank_in(),
89 self.rank_out()
90 )
91 )
92 }
93
94 let n: usize = sk_in.n().max(sk_out.n());
95
96 let (mut sk_in_tmp, scratch1) = scratch.take_scalar_znx(n, sk_in.rank());
97 (0..sk_in.rank()).for_each(|i| {
98 module.vec_znx_switch_degree(
99 &mut sk_in_tmp.as_vec_znx_mut(),
100 i,
101 &sk_in.data.as_vec_znx(),
102 i,
103 );
104 });
105
106 let (mut sk_out_tmp, scratch2) = scratch1.take_glwe_secret_prepared(n, sk_out.rank());
107 {
108 let (mut tmp, _) = scratch2.take_scalar_znx(n, 1);
109 (0..sk_out.rank()).for_each(|i| {
110 module.vec_znx_switch_degree(&mut tmp.as_vec_znx_mut(), 0, &sk_out.data.as_vec_znx(), i);
111 module.svp_prepare(&mut sk_out_tmp.data, i, &tmp, 0);
112 });
113 }
114
115 self.key.encrypt_sk(
116 module,
117 &sk_in_tmp,
118 &sk_out_tmp,
119 seed_xa,
120 source_xe,
121 sigma,
122 scratch2,
123 );
124 self.sk_in_n = sk_in.n();
125 self.sk_out_n = sk_out.n();
126 }
127}