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