arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/glwe/tests/generic_encryption.rs
core/src/glwe/tests/generic_encryption.rsRaw
  1use backend::hal::{
  2    api::{
  3        ScalarZnxAlloc, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxAlloc, VecZnxCopy, VecZnxDftAlloc, VecZnxFillUniform,
  4        VecZnxStd, VecZnxSubABInplace,
  5    },
  6    layouts::{Backend, Module, ScratchOwned},
  7    oep::{
  8        ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
  9        TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl,
 10    },
 11};
 12use sampling::source::Source;
 13
 14use crate::{
 15    GLWECiphertext, GLWECiphertextCompressed, GLWEDecryptFamily, GLWEEncryptPkFamily, GLWEEncryptSkFamily, GLWEOps,
 16    GLWEPlaintext, GLWEPublicKey, GLWEPublicKeyExec, GLWESecret, GLWESecretExec, GLWESecretFamily, Infos,
 17};
 18
 19pub(crate) trait EncryptionTestModuleFamily<B: Backend> =
 20    GLWEDecryptFamily<B> + GLWESecretFamily<B> + VecZnxAlloc + ScalarZnxAlloc + VecZnxStd;
 21
 22pub(crate) trait EncryptionTestScratchFamily<B: Backend> = TakeVecZnxDftImpl<B>
 23    + TakeVecZnxBigImpl<B>
 24    + TakeSvpPPolImpl<B>
 25    + ScratchOwnedAllocImpl<B>
 26    + ScratchOwnedBorrowImpl<B>
 27    + ScratchAvailableImpl<B>
 28    + TakeScalarZnxImpl<B>
 29    + TakeVecZnxImpl<B>;
 30
 31pub(crate) fn test_encrypt_sk<B: Backend>(module: &Module<B>, basek: usize, k_ct: usize, k_pt: usize, sigma: f64, rank: usize)
 32where
 33    Module<B>: EncryptionTestModuleFamily<B> + GLWEEncryptSkFamily<B>,
 34    B: EncryptionTestScratchFamily<B>,
 35{
 36    let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(module, basek, k_ct, rank);
 37    let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(module, basek, k_pt);
 38    let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(module, basek, k_pt);
 39
 40    let mut source_xs: Source = Source::new([0u8; 32]);
 41    let mut source_xe: Source = Source::new([0u8; 32]);
 42    let mut source_xa: Source = Source::new([0u8; 32]);
 43
 44    let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
 45        GLWECiphertext::encrypt_sk_scratch_space(module, basek, ct.k())
 46            | GLWECiphertext::decrypt_scratch_space(module, basek, ct.k()),
 47    );
 48
 49    let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank);
 50    sk.fill_ternary_prob(0.5, &mut source_xs);
 51    let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk);
 52
 53    module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_pt, &mut source_xa);
 54
 55    ct.encrypt_sk(
 56        module,
 57        &pt_want,
 58        &sk_exec,
 59        &mut source_xa,
 60        &mut source_xe,
 61        sigma,
 62        scratch.borrow(),
 63    );
 64
 65    ct.decrypt(module, &mut pt_have, &sk_exec, scratch.borrow());
 66
 67    pt_want.sub_inplace_ab(module, &pt_have);
 68
 69    let noise_have: f64 = module.vec_znx_std(basek, &pt_want.data, 0) * (ct.k() as f64).exp2();
 70    let noise_want: f64 = sigma;
 71
 72    assert!(noise_have <= noise_want + 0.2);
 73}
 74
 75pub(crate) fn test_encrypt_sk_compressed<B: Backend>(
 76    module: &Module<B>,
 77    basek: usize,
 78    k_ct: usize,
 79    k_pt: usize,
 80    sigma: f64,
 81    rank: usize,
 82) where
 83    Module<B>: EncryptionTestModuleFamily<B> + GLWEEncryptSkFamily<B> + VecZnxCopy,
 84    B: EncryptionTestScratchFamily<B>,
 85{
 86    let mut ct_compressed: GLWECiphertextCompressed<Vec<u8>> = GLWECiphertextCompressed::alloc(module, basek, k_ct, rank);
 87
 88    let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(module, basek, k_pt);
 89    let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(module, basek, k_pt);
 90
 91    let mut source_xs: Source = Source::new([0u8; 32]);
 92    let mut source_xe: Source = Source::new([0u8; 32]);
 93    let mut source_xa: Source = Source::new([0u8; 32]);
 94
 95    let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
 96        GLWECiphertextCompressed::encrypt_sk_scratch_space(module, basek, k_ct)
 97            | GLWECiphertext::decrypt_scratch_space(module, basek, k_ct),
 98    );
 99
100    let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank);
101    sk.fill_ternary_prob(0.5, &mut source_xs);
102    let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk);
103
104    module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_pt, &mut source_xa);
105
106    let seed_xa: [u8; 32] = [1u8; 32];
107
108    ct_compressed.encrypt_sk(
109        module,
110        &pt_want,
111        &sk_exec,
112        seed_xa,
113        &mut source_xe,
114        sigma,
115        scratch.borrow(),
116    );
117
118    let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(module, basek, k_ct, rank);
119    ct.decompress(module, &ct_compressed);
120
121    ct.decrypt(module, &mut pt_have, &sk_exec, scratch.borrow());
122
123    pt_want.sub_inplace_ab(module, &pt_have);
124
125    let noise_have: f64 = module.vec_znx_std(basek, &pt_want.data, 0) * (ct.k() as f64).exp2();
126    let noise_want: f64 = sigma;
127
128    assert!(noise_have <= noise_want + 0.2);
129}
130
131pub(crate) fn test_encrypt_zero_sk<B: Backend>(module: &Module<B>, basek: usize, k_ct: usize, sigma: f64, rank: usize)
132where
133    Module<B>: EncryptionTestModuleFamily<B> + GLWEEncryptSkFamily<B>,
134    B: EncryptionTestScratchFamily<B>,
135{
136    let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(module, basek, k_ct);
137
138    let mut source_xs: Source = Source::new([0u8; 32]);
139    let mut source_xe: Source = Source::new([1u8; 32]);
140    let mut source_xa: Source = Source::new([0u8; 32]);
141
142    let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank);
143    sk.fill_ternary_prob(0.5, &mut source_xs);
144    let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk);
145
146    let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(module, basek, k_ct, rank);
147
148    let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
149        GLWECiphertext::decrypt_scratch_space(module, basek, k_ct)
150            | GLWECiphertext::encrypt_sk_scratch_space(module, basek, k_ct),
151    );
152
153    ct.encrypt_zero_sk(
154        module,
155        &sk_exec,
156        &mut source_xa,
157        &mut source_xe,
158        sigma,
159        scratch.borrow(),
160    );
161    ct.decrypt(module, &mut pt, &sk_exec, scratch.borrow());
162
163    assert!((sigma - module.vec_znx_std(basek, &pt.data, 0) * (k_ct as f64).exp2()) <= 0.2);
164}
165
166pub(crate) fn test_encrypt_pk<B: Backend>(module: &Module<B>, basek: usize, k_ct: usize, k_pk: usize, sigma: f64, rank: usize)
167where
168    Module<B>: EncryptionTestModuleFamily<B>
169        + GLWEEncryptPkFamily<B>
170        + GLWEEncryptSkFamily<B>
171        + VecZnxDftAlloc<B>
172        + VecZnxFillUniform
173        + VecZnxSubABInplace,
174    B: EncryptionTestScratchFamily<B>,
175{
176    let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(module, basek, k_ct, rank);
177    let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(module, basek, k_ct);
178    let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(module, basek, k_ct);
179
180    let mut source_xs: Source = Source::new([0u8; 32]);
181    let mut source_xe: Source = Source::new([0u8; 32]);
182    let mut source_xa: Source = Source::new([0u8; 32]);
183    let mut source_xu: Source = Source::new([0u8; 32]);
184
185    let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(module, rank);
186    sk.fill_ternary_prob(0.5, &mut source_xs);
187    let sk_exec: GLWESecretExec<Vec<u8>, B> = GLWESecretExec::from(module, &sk);
188
189    let mut pk: GLWEPublicKey<Vec<u8>> = GLWEPublicKey::alloc(module, basek, k_pk, rank);
190    pk.generate_from_sk(module, &sk_exec, &mut source_xa, &mut source_xe, sigma);
191
192    let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
193        GLWECiphertext::encrypt_sk_scratch_space(module, basek, ct.k())
194            | GLWECiphertext::decrypt_scratch_space(module, basek, ct.k())
195            | GLWECiphertext::encrypt_pk_scratch_space(module, basek, pk.k()),
196    );
197
198    module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_ct, &mut source_xa);
199
200    let pk_exec: GLWEPublicKeyExec<Vec<u8>, B> = GLWEPublicKeyExec::from(module, &pk, scratch.borrow());
201
202    ct.encrypt_pk(
203        module,
204        &pt_want,
205        &pk_exec,
206        &mut source_xu,
207        &mut source_xe,
208        sigma,
209        scratch.borrow(),
210    );
211
212    ct.decrypt(module, &mut pt_have, &sk_exec, scratch.borrow());
213
214    pt_want.sub_inplace_ab(module, &pt_have);
215
216    let noise_have: f64 = module.vec_znx_std(basek, &pt_want.data, 0).log2();
217    let noise_want: f64 = ((((rank as f64) + 1.0) * module.n() as f64 * 0.5 * sigma * sigma).sqrt()).log2() - (k_ct as f64);
218
219    assert!(
220        noise_have <= noise_want + 0.2,
221        "{} {}",
222        noise_have,
223        noise_want
224    );
225}