arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-core/README.md
poulpy-core/README.mdRaw
  1# 🐙 Poulpy-Core
  2
  3**Poulpy-Core** is a Rust crate built on **`poulpy-hal`**, providing scheme- and backend-agnostic RLWE-based homomorphic encryption building blocks.
  4
  5## Getting Started
  6
  7```rust
  8use poulpy_backend::cpu_spqlios::FFT64;
  9use poulpy_core::{
 10    GLWEOperations, SIGMA,
 11    layouts::{
 12        GLWECiphertext, GLWEPlaintext, GLWESecret, Infos,
 13        prepared::{GLWESecretPrepared, PrepareAlloc},
 14    },
 15};
 16use poulpy_hal::{
 17    api::{ModuleNew, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxFillUniform},
 18    layouts::{Module, ScratchOwned},
 19    source::Source,
 20};
 21
 22fn main() {
 23    // Ring degree
 24    let log_n: usize = 10;
 25
 26    let n: usize = 1<<log_n;
 27
 28    // Base-2-k (implicit digit decomposition)
 29    let base2k: usize = 14;
 30
 31    // Ciphertext Torus precision (equivalent to ciphertext modulus)
 32    let k_ct: usize = 27;
 33
 34    // Plaintext Torus precision (equivament to plaintext modulus)
 35    let k_pt: usize = base2k;
 36
 37    // GLWE rank
 38    let rank: usize = 1;
 39
 40    // Instantiate Module (DFT Tables)
 41    let module: Module<FFT64> = Module::<FFT64>::new(n as u64);
 42
 43    // Allocates ciphertext & plaintexts
 44    let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, base2k, k_ct, rank);
 45    let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, base2k, k_pt);
 46    let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, base2k, k_pt);
 47
 48    // CPRNG
 49    let mut source_xs: Source = Source::new([0u8; 32]);
 50    let mut source_xe: Source = Source::new([1u8; 32]);
 51    let mut source_xa: Source = Source::new([2u8; 32]);
 52
 53    // Scratch space
 54    let mut scratch: ScratchOwned<FFT64> = ScratchOwned::alloc(
 55        GLWECiphertext::encrypt_sk_scratch_space(&module, n, base2k, ct.k())
 56            | GLWECiphertext::decrypt_scratch_space(&module, n, base2k, ct.k()),
 57    );
 58
 59    // Generate secret-key
 60    let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
 61    sk.fill_ternary_prob(0.5, &mut source_xs);
 62
 63    // Backend-prepared secret
 64    let sk_prepared: GLWESecretPrepared<Vec<u8>, FFT64> = sk.prepare_alloc(&module, scratch.borrow());
 65
 66    // Uniform plaintext
 67    module.vec_znx_fill_uniform(base2k, &mut pt_want.data, 0, k_pt, &mut source_xa);
 68
 69    // Encryption
 70    ct.encrypt_sk(
 71        &module,
 72        &pt_want,
 73        &sk_prepared,
 74        &mut source_xa,
 75        &mut source_xe,
 76        scratch.borrow(),
 77    );
 78
 79    // Decryption
 80    ct.decrypt(&module, &mut pt_have, &sk_prepared, scratch.borrow());
 81
 82    // Diff between pt - Dec(Enc(pt))
 83    pt_want.sub_inplace_ab(&module, &pt_have);
 84
 85    // Ideal vs. actual noise
 86    let noise_have: f64 = pt_want.data.std(base2k, 0) * (ct.k() as f64).exp2();
 87    let noise_want: f64 = SIGMA;
 88
 89    // Check
 90    assert!(noise_have <= noise_want + 0.2);
 91}
 92```
 93
 94## Layouts
 95
 96This crate defines three categories of layouts for `LWE`, `GLWE`, `GGLWE`, and `GGSW` objects (and their derivatives), all instantiated using **`poulpy-hal`** layouts. Each serves a distinct purpose:
 97
 98* **Standard** → Front-end, serializable layouts. These are backend-agnostic and act as inputs/outputs of computations (e.g., `GGLWEAutomorphismKey`).
 99* **Compressed** → Compact serializable variants of the standard layouts. They are not usable for computation but significantly reduce storage size (e.g., `GGLWEAutomorphismKeyCompressed`).
100* **Prepared** → Backend-optimized, opaque layouts used only for computation (write-only). These store preprocessed data for efficient execution on a specific backend (e.g., `GGLWEAutomorphismKeyPrepared`).
101
102All **standard** and **compressed** layouts implement the `WriterTo` and `ReaderFrom` traits, enabling straightforward serialization/deserialization with any type implementing `Write` or `Read`:
103
104```rust
105pub trait WriterTo {
106    fn write_to<W: Write>(&self, writer: &mut W) -> Result<()>;
107}
108
109pub trait ReaderFrom {
110    fn read_from<R: Read>(&mut self, reader: &mut R) -> Result<()>;
111}
112```
113
114### Example Workflow
115
116```mermaid
117flowchart TD
118    A[GGLWEAutomorphismKeyCompressed]-->|decompress|B[GGLWEAutomorphismKey]-->|prepare|C[GGLWEAutomorphismKeyPrepared]
119```
120
121Equivalent Rust:
122
123```rust
124let mut atk_compressed: GGLWEAutomorphismKeyCompressed<Vec<u8>> = 
125    GGLWEAutomorphismKeyCompressed::alloc(...);
126let mut atk: GGLWEAutomorphismKey<Vec<u8>> = 
127    GGLWEAutomorphismKey::alloc(...);
128atk.decompress(module, &atk_compressed);
129let mut atk_prep: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = GLWESecretPrepared<Vec<u8>, B> = atk.prepare_alloc(...);
130```
131
132---
133
134## Encryption & Decryption
135
136* **Encryption** → Supported for all **standard** and **compressed** layouts.
137* **Decryption** → Only directly available for `LWECiphertext` and `GLWECiphertext`.
138  However, it remains naturally usable on `GGLWE` and `GGSW` objects, since these are vectors/matrices of `GLWECiphertext`.
139
140```rust
141let mut atk: GGLWEAutomorphismKey<Vec<u8>> =
142        GGLWEAutomorphismKey::alloc(...);
143atk.encrypt_sk(...);
144atk.at(row, 0).decrypt(...);
145```
146## Keyswitching, Automorphism & External Product
147
148Keyswitching, automorphisms, and external products are supported for all ciphertext types where they are well-defined.
149This includes subtypes such as `GGLWEAutomorphismKey`.
150
151For example:
152
153```rust
154atk.external_product(...);
155ggsw.automorphism(...);
156```
157
158---
159
160## Additional Features
161
162* Ciphertexts: `LWE` and `GLWE`
163* `GLWE` ring packing
164* `GLWE` trace
165* Noise analysis for `GLWE`, `GGLWE`, `GGSW`
166* Basic operations over `GLWE` ciphertexts and plaintexts
167
168---
169
170## Tests
171
172A fully generic test suite is available in [`src/tests/generics`](./src/tests/generics).