arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-core/src/tests/test_suite/encryption/glwe_tsk.rs
poulpy-core/src/tests/test_suite/encryption/glwe_tsk.rsRaw
  1use poulpy_hal::{
  2    api::{
  3        ScratchAvailable, ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDft, VecZnxBigAlloc, VecZnxBigNormalize, VecZnxCopy, VecZnxDftAlloc, VecZnxDftApply, VecZnxFillUniform, VecZnxIdftApplyTmpA, VecZnxSubScalarInplace, VecZnxSwitchRing
  4    }, layouts::{Backend, Module, Scratch, ScratchOwned, VecZnxDft}, oep::{VecZnxNormalizeImpl, VecZnxNormalizeInplaceImpl}, source::Source
  5};
  6
  7use crate::{
  8    decryption::GLWEDecrypt, encryption::SIGMA, layouts::{
  9        prepared::GLWESecretPrepared, Dsize, GLWEPlaintext, GLWESecret, GLWESecretPrepare, GLWESecretPreparedAlloc, TensorKey, TensorKeyAlloc, TensorKeyCompressed, TensorKeyLayout
 10    }, GGLWETensorKeyCompressedEncryptSk, ScratchTakeCore, TensorKeyEncryptSk
 11};
 12
 13pub fn test_gglwe_tensor_key_encrypt_sk<BE: Backend>(module: &Module<BE>)
 14where
 15    Module<BE>: TensorKeyEncryptSk<BE>
 16        + TensorKeyAlloc
 17        + GLWESecretPrepare<BE>
 18        + GLWESecretPreparedAlloc<BE>
 19        + GLWEDecrypt<BE>
 20        + VecZnxDftAlloc<BE>
 21        + VecZnxBigAlloc<BE>
 22        + VecZnxDftApply<BE>
 23        + SvpApplyDftToDft<BE>
 24        + VecZnxIdftApplyTmpA<BE>
 25        + VecZnxBigNormalize<BE>
 26        + VecZnxSubScalarInplace,
 27    ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
 28    Scratch<BE>: ScratchAvailable + ScratchTakeCore<BE>,
 29{
 30    let base2k: usize = 8;
 31    let k: usize = 54;
 32
 33    for rank in 1_usize..3 {
 34        let n: usize = module.n();
 35        let dnum: usize = k / base2k;
 36
 37        let tensor_key_infos = TensorKeyLayout {
 38            n: n.into(),
 39            base2k: base2k.into(),
 40            k: k.into(),
 41            dnum: dnum.into(),
 42            dsize: Dsize(1),
 43            rank: rank.into(),
 44        };
 45
 46        let mut tensor_key: TensorKey<Vec<u8>> = TensorKey::alloc_from_infos(module, &tensor_key_infos);
 47
 48        let mut source_xs: Source = Source::new([0u8; 32]);
 49        let mut source_xe: Source = Source::new([0u8; 32]);
 50        let mut source_xa: Source = Source::new([0u8; 32]);
 51
 52        let mut scratch: ScratchOwned<BE> = ScratchOwned::alloc(TensorKey::encrypt_sk_tmp_bytes(
 53            module,
 54            &tensor_key_infos,
 55        ));
 56
 57        let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(module, &tensor_key_infos);
 58        sk.fill_ternary_prob(0.5, &mut source_xs);
 59        let mut sk_prepared: GLWESecretPrepared<Vec<u8>, BE> = GLWESecretPrepared::alloc(module, rank.into());
 60        sk_prepared.prepare(module, &sk);
 61
 62        tensor_key.encrypt_sk(
 63            module,
 64            &sk,
 65            &mut source_xa,
 66            &mut source_xe,
 67            scratch.borrow(),
 68        );
 69
 70        let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(module, &tensor_key_infos);
 71
 72        let mut sk_ij_dft = module.vec_znx_dft_alloc(1, 1);
 73        let mut sk_ij_big = module.vec_znx_big_alloc(1, 1);
 74        let mut sk_ij: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, 1_u32.into());
 75        let mut sk_dft: VecZnxDft<Vec<u8>, BE> = module.vec_znx_dft_alloc(rank, 1);
 76
 77        for i in 0..rank {
 78            module.vec_znx_dft_apply(1, 0, &mut sk_dft, i, &sk.data.as_vec_znx(), i);
 79        }
 80
 81        for i in 0..rank {
 82            for j in 0..rank {
 83                module.svp_apply_dft_to_dft(&mut sk_ij_dft, 0, &sk_prepared.data, j, &sk_dft, i);
 84                module.vec_znx_idft_apply_tmpa(&mut sk_ij_big, 0, &mut sk_ij_dft, 0);
 85                module.vec_znx_big_normalize(
 86                    base2k,
 87                    &mut sk_ij.data.as_vec_znx_mut(),
 88                    0,
 89                    base2k,
 90                    &sk_ij_big,
 91                    0,
 92                    scratch.borrow(),
 93                );
 94                for row_i in 0..dnum {
 95                    let ct = tensor_key
 96                    .at(i, j)
 97                    .at(row_i, 0);
 98
 99                    ct.decrypt(module, &mut pt, &sk_prepared, scratch.borrow());
100
101                    module.vec_znx_sub_scalar_inplace(&mut pt.data, 0, row_i, &sk_ij.data, 0);
102
103                    let std_pt: f64 = pt.data.std(base2k, 0) * (k as f64).exp2();
104                    assert!((SIGMA - std_pt).abs() <= 0.5, "{SIGMA} {std_pt}");
105                }
106            }
107        }
108    }
109}
110
111pub fn test_gglwe_tensor_key_compressed_encrypt_sk<BE: Backend>(module: &Module<BE>)
112where
113    Module<BE>: TensorKeyEncryptSk<BE>
114    + TensorKeyAlloc
115    + GLWESecretPrepare<BE>
116    + GLWESecretPreparedAlloc<BE>
117    + GGLWETensorKeyCompressedEncryptSk<BE>
118    + GLWEDecrypt<BE>
119    + VecZnxDftAlloc<BE>
120    + VecZnxBigAlloc<BE>
121    + VecZnxDftApply<BE>
122    + SvpApplyDftToDft<BE>
123    + VecZnxIdftApplyTmpA<BE>
124    + VecZnxSubScalarInplace
125    + VecZnxFillUniform
126    + VecZnxCopy
127    + VecZnxSwitchRing,
128    // + VecZnxNormalizeInplaceImpl<BE>
129    // + VecZnxNormalizeImpl<BE>,
130    ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
131    Scratch<BE>: ScratchAvailable + ScratchTakeCore<BE>,
132{
133    let base2k = 8;
134    let k = 54;
135    for rank in 1_usize..3 {
136        let n: usize = module.n();
137        let dnum: usize = k / base2k;
138
139        let tensor_key_infos: TensorKeyLayout = TensorKeyLayout {
140            n: n.into(),
141            base2k: base2k.into(),
142            k: k.into(),
143            dnum: dnum.into(),
144            dsize: Dsize(1),
145            rank: rank.into(),
146        };
147
148        let mut tensor_key_compressed: TensorKeyCompressed<Vec<u8>> = TensorKeyCompressed::alloc_from_infos(module, &tensor_key_infos);
149
150        let mut source_xs: Source = Source::new([0u8; 32]);
151        let mut source_xe: Source = Source::new([0u8; 32]);
152
153        let mut scratch: ScratchOwned<BE> = ScratchOwned::alloc(TensorKeyCompressed::encrypt_sk_tmp_bytes(
154            module,
155            &tensor_key_infos,
156        ));
157
158        let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(module, &tensor_key_infos);
159        sk.fill_ternary_prob(0.5, &mut source_xs);
160        let mut sk_prepared: GLWESecretPrepared<Vec<u8>, BE> = GLWESecretPrepared::alloc(module, rank.into());
161        sk_prepared.prepare(module, &sk);
162
163        let seed_xa: [u8; 32] = [1u8; 32];
164
165        tensor_key_compressed.encrypt_sk(module, &sk, seed_xa, &mut source_xe, scratch.borrow());
166
167        let mut tensor_key: TensorKey<Vec<u8>> = TensorKey::alloc_from_infos(module, &tensor_key_infos);
168        tensor_key.decompress(module, &tensor_key_compressed);
169
170        let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(module, &tensor_key_infos);
171
172        let mut sk_ij_dft = module.vec_znx_dft_alloc(1, 1);
173        let mut sk_ij_big = module.vec_znx_big_alloc(1, 1);
174        let mut sk_ij: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, 1_u32.into());
175        let mut sk_dft: VecZnxDft<Vec<u8>, BE> = module.vec_znx_dft_alloc(rank, 1);
176
177        for i in 0..rank {
178            module.vec_znx_dft_apply(1, 0, &mut sk_dft, i, &sk.data.as_vec_znx(), i);
179        }
180
181        for i in 0..rank {
182            for j in 0..rank {
183                module.svp_apply_dft_to_dft(&mut sk_ij_dft, 0, &sk_prepared.data, j, &sk_dft, i);
184                module.vec_znx_idft_apply_tmpa(&mut sk_ij_big, 0, &mut sk_ij_dft, 0);
185                module.vec_znx_big_normalize(
186                    base2k,
187                    &mut sk_ij.data.as_vec_znx_mut(),
188                    0,
189                    base2k,
190                    &sk_ij_big,
191                    0,
192                    scratch.borrow(),
193                );
194                for row_i in 0..dnum {
195                    tensor_key
196                        .at(i, j)
197                        .at(row_i, 0)
198                        .decrypt(module, &mut pt, &sk_prepared, scratch.borrow());
199
200                    module.vec_znx_sub_scalar_inplace(&mut pt.data, 0, row_i, &sk_ij.data, 0);
201
202                    let std_pt: f64 = pt.data.std(base2k, 0) * (k as f64).exp2();
203                    assert!((SIGMA - std_pt).abs() <= 0.5, "{SIGMA} {std_pt}");
204                }
205            }
206        }
207    }
208}