poulpy/core/src/tests/generics/encryption/glwe_tsk.rs
core/src/tests/generics/encryption/glwe_tsk.rsRaw
1use backend::hal::{
2 api::{
3 ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAddScalarInplace, VecZnxBigAlloc, VecZnxCopy, VecZnxDftAlloc,
4 VecZnxSubScalarInplace, VecZnxSwithcDegree, VmpPMatAlloc, VmpPMatPrepare,
5 },
6 layouts::{Backend, Module, ScratchOwned, VecZnxDft},
7 oep::{
8 ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
9 TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl, VecZnxBigAllocBytesImpl, VecZnxDftAllocBytesImpl,
10 },
11};
12use sampling::source::Source;
13
14use crate::{
15 layouts::{
16 GGLWETensorKey, GLWEPlaintext, GLWESecret, Infos,
17 compressed::GGLWETensorKeyCompressed,
18 prepared::{GLWESecretPrepared, PrepareAlloc},
19 },
20 trait_families::{Decompress, GLWEDecryptFamily},
21};
22
23use crate::trait_families::{GGLWEEncryptSkFamily, GGLWETensorKeyEncryptSkFamily, GLWESecretPreparedModuleFamily};
24
25pub fn test_glwe_tensor_key_encrypt_sk<B: Backend>(module: &Module<B>, basek: usize, k: usize, sigma: f64, rank: usize)
26where
27 Module<B>: GGLWEEncryptSkFamily<B>
28 + GLWESecretPreparedModuleFamily<B>
29 + GLWEDecryptFamily<B>
30 + VecZnxSwithcDegree
31 + VecZnxAddScalarInplace
32 + VecZnxSubScalarInplace
33 + VmpPMatAlloc<B>
34 + VmpPMatPrepare<B>
35 + GGLWETensorKeyEncryptSkFamily<B>
36 + GLWEDecryptFamily<B>
37 + VecZnxDftAlloc<B>
38 + VecZnxBigAlloc<B>,
39 B: TakeVecZnxDftImpl<B>
40 + TakeVecZnxBigImpl<B>
41 + TakeSvpPPolImpl<B>
42 + ScratchOwnedAllocImpl<B>
43 + ScratchOwnedBorrowImpl<B>
44 + ScratchAvailableImpl<B>
45 + TakeScalarZnxImpl<B>
46 + TakeVecZnxImpl<B>
47 + VecZnxDftAllocBytesImpl<B>
48 + VecZnxBigAllocBytesImpl<B>
49 + TakeSvpPPolImpl<B>,
50{
51 let n: usize = module.n();
52 let rows: usize = k / basek;
53
54 let mut tensor_key: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(n, basek, k, rows, 1, rank);
55
56 let mut source_xs: Source = Source::new([0u8; 32]);
57 let mut source_xe: Source = Source::new([0u8; 32]);
58 let mut source_xa: Source = Source::new([0u8; 32]);
59
60 let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGLWETensorKey::encrypt_sk_scratch_space(
61 module,
62 n,
63 basek,
64 tensor_key.k(),
65 rank,
66 ));
67
68 let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
69 sk.fill_ternary_prob(0.5, &mut source_xs);
70 let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
71
72 tensor_key.encrypt_sk(
73 module,
74 &sk,
75 &mut source_xa,
76 &mut source_xe,
77 sigma,
78 scratch.borrow(),
79 );
80
81 let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k);
82
83 let mut sk_ij_dft = module.vec_znx_dft_alloc(n, 1, 1);
84 let mut sk_ij_big = module.vec_znx_big_alloc(n, 1, 1);
85 let mut sk_ij: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, 1);
86 let mut sk_dft: VecZnxDft<Vec<u8>, B> = module.vec_znx_dft_alloc(n, rank, 1);
87
88 (0..rank).for_each(|i| {
89 module.vec_znx_dft_from_vec_znx(1, 0, &mut sk_dft, i, &sk.data.as_vec_znx(), i);
90 });
91
92 (0..rank).for_each(|i| {
93 (0..rank).for_each(|j| {
94 module.svp_apply(&mut sk_ij_dft, 0, &sk_prepared.data, j, &sk_dft, i);
95 module.vec_znx_dft_to_vec_znx_big_tmp_a(&mut sk_ij_big, 0, &mut sk_ij_dft, 0);
96 module.vec_znx_big_normalize(
97 basek,
98 &mut sk_ij.data.as_vec_znx_mut(),
99 0,
100 &sk_ij_big,
101 0,
102 scratch.borrow(),
103 );
104 (0..tensor_key.rank_in()).for_each(|col_i| {
105 (0..tensor_key.rows()).for_each(|row_i| {
106 tensor_key
107 .at(i, j)
108 .at(row_i, col_i)
109 .decrypt(module, &mut pt, &sk_prepared, scratch.borrow());
110
111 module.vec_znx_sub_scalar_inplace(&mut pt.data, 0, row_i, &sk_ij.data, col_i);
112
113 let std_pt: f64 = pt.data.std(basek, 0) * (k as f64).exp2();
114 assert!((sigma - std_pt).abs() <= 0.5, "{} {}", sigma, std_pt);
115 });
116 });
117 })
118 })
119}
120
121pub fn test_glwe_tensor_key_compressed_encrypt_sk<B: Backend>(module: &Module<B>, basek: usize, k: usize, sigma: f64, rank: usize)
122where
123 Module<B>: GGLWEEncryptSkFamily<B>
124 + GLWESecretPreparedModuleFamily<B>
125 + GLWEDecryptFamily<B>
126 + VecZnxSwithcDegree
127 + VecZnxAddScalarInplace
128 + VecZnxSubScalarInplace
129 + VmpPMatAlloc<B>
130 + VmpPMatPrepare<B>
131 + GGLWETensorKeyEncryptSkFamily<B>
132 + GLWEDecryptFamily<B>
133 + VecZnxDftAlloc<B>
134 + VecZnxBigAlloc<B>
135 + VecZnxCopy,
136 B: TakeVecZnxDftImpl<B>
137 + TakeVecZnxBigImpl<B>
138 + TakeSvpPPolImpl<B>
139 + ScratchOwnedAllocImpl<B>
140 + ScratchOwnedBorrowImpl<B>
141 + ScratchAvailableImpl<B>
142 + TakeScalarZnxImpl<B>
143 + TakeVecZnxImpl<B>
144 + VecZnxDftAllocBytesImpl<B>
145 + VecZnxBigAllocBytesImpl<B>
146 + TakeSvpPPolImpl<B>,
147{
148 let n: usize = module.n();
149 let rows: usize = k / basek;
150
151 let mut tensor_key_compressed: GGLWETensorKeyCompressed<Vec<u8>> =
152 GGLWETensorKeyCompressed::alloc(n, basek, k, rows, 1, rank);
153
154 let mut source_xs: Source = Source::new([0u8; 32]);
155 let mut source_xe: Source = Source::new([0u8; 32]);
156
157 let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(GGLWETensorKeyCompressed::encrypt_sk_scratch_space(
158 module,
159 n,
160 basek,
161 tensor_key_compressed.k(),
162 rank,
163 ));
164
165 let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
166 sk.fill_ternary_prob(0.5, &mut source_xs);
167 let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
168
169 let seed_xa: [u8; 32] = [1u8; 32];
170
171 tensor_key_compressed.encrypt_sk(
172 module,
173 &sk,
174 seed_xa,
175 &mut source_xe,
176 sigma,
177 scratch.borrow(),
178 );
179
180 let mut tensor_key: GGLWETensorKey<Vec<u8>> = GGLWETensorKey::alloc(n, basek, k, rows, 1, rank);
181 tensor_key.decompress(module, &tensor_key_compressed);
182
183 let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k);
184
185 let mut sk_ij_dft = module.vec_znx_dft_alloc(n, 1, 1);
186 let mut sk_ij_big = module.vec_znx_big_alloc(n, 1, 1);
187 let mut sk_ij: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, 1);
188 let mut sk_dft: VecZnxDft<Vec<u8>, B> = module.vec_znx_dft_alloc(n, rank, 1);
189
190 (0..rank).for_each(|i| {
191 module.vec_znx_dft_from_vec_znx(1, 0, &mut sk_dft, i, &sk.data.as_vec_znx(), i);
192 });
193
194 (0..rank).for_each(|i| {
195 (0..rank).for_each(|j| {
196 module.svp_apply(&mut sk_ij_dft, 0, &sk_prepared.data, j, &sk_dft, i);
197 module.vec_znx_dft_to_vec_znx_big_tmp_a(&mut sk_ij_big, 0, &mut sk_ij_dft, 0);
198 module.vec_znx_big_normalize(
199 basek,
200 &mut sk_ij.data.as_vec_znx_mut(),
201 0,
202 &sk_ij_big,
203 0,
204 scratch.borrow(),
205 );
206 (0..tensor_key.rank_in()).for_each(|col_i| {
207 (0..tensor_key.rows()).for_each(|row_i| {
208 tensor_key
209 .at(i, j)
210 .at(row_i, col_i)
211 .decrypt(module, &mut pt, &sk_prepared, scratch.borrow());
212
213 module.vec_znx_sub_scalar_inplace(&mut pt.data, 0, row_i, &sk_ij.data, col_i);
214
215 let std_pt: f64 = pt.data.std(basek, 0) * (k as f64).exp2();
216 assert!((sigma - std_pt).abs() <= 0.5, "{} {}", sigma, std_pt);
217 });
218 });
219 })
220 })
221}