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