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_core::{
9 GLWESub, SIGMA,
10 layouts::{
11 Base2K, Degree, GLWE, GLWELayout, GLWEPlaintext, GLWEPlaintextLayout, GLWESecret, LWEInfos, Rank, TorusPrecision,
12 prepared::GLWESecretPrepared,
13 },
14};
15use poulpy_cpu_ref::FFT64Ref;
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: Degree = Degree(1 << log_n);
27
28 // Base-2-k (implicit digit decomposition)
29 let base2k: Base2K = Base2K(14);
30
31 // Ciphertext Torus precision (equivalent to ciphertext modulus)
32 let k_ct: TorusPrecision = TorusPrecision(27);
33
34 // Plaintext Torus precision (equivament to plaintext modulus)
35 let k_pt: TorusPrecision = TorusPrecision(base2k.into());
36
37 // GLWE rank
38 let rank: Rank = Rank(1);
39
40 // Instantiate Module (DFT Tables)
41 let module: Module<FFT64Ref> = Module::<FFT64Ref>::new(n.0 as u64);
42
43 let glwe_ct_infos: GLWELayout = GLWELayout {
44 n,
45 base2k,
46 k: k_ct,
47 rank,
48 };
49
50 let glwe_pt_infos: GLWEPlaintextLayout = GLWEPlaintextLayout { n, base2k, k: k_pt };
51
52 // Allocates ciphertext & plaintexts
53 let mut ct: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_ct_infos);
54 let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_pt_infos);
55 let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_pt_infos);
56
57 // CPRNG
58 let mut source_xs: Source = Source::new([0u8; 32]);
59 let mut source_xe: Source = Source::new([1u8; 32]);
60 let mut source_xa: Source = Source::new([2u8; 32]);
61
62 // Scratch space
63 let mut scratch: ScratchOwned<FFT64Ref> = ScratchOwned::alloc(
64 GLWE::encrypt_sk_tmp_bytes(&module, &glwe_ct_infos) | GLWE::decrypt_tmp_bytes(&module, &glwe_ct_infos),
65 );
66
67 // Generate secret-key
68 let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_ct_infos);
69 sk.fill_ternary_prob(0.5, &mut source_xs);
70
71 // Backend-prepared secret
72 let mut sk_prepared: GLWESecretPrepared<Vec<u8>, FFT64Ref> = GLWESecretPrepared::alloc(&module, rank);
73 sk_prepared.prepare(&module, &sk);
74
75 // Uniform plaintext
76 module.vec_znx_fill_uniform(base2k.into(), &mut pt_want.data, 0, &mut source_xa);
77
78 // Encryption
79 ct.encrypt_sk(
80 &module,
81 &pt_want,
82 &sk_prepared,
83 &mut source_xa,
84 &mut source_xe,
85 scratch.borrow(),
86 );
87
88 // Decryption
89 ct.decrypt(&module, &mut pt_have, &sk_prepared, scratch.borrow());
90
91 // Diff between pt - Dec(Enc(pt))
92 module.glwe_sub_inplace(&mut pt_want, &pt_have);
93
94 // Ideal vs. actual noise
95 let noise_have: f64 = pt_want.data.stats(base2k.into(), 0).std() * (ct.k().as_u32() as f64).exp2();
96 let noise_want: f64 = SIGMA;
97
98 // Check
99 assert!(noise_have <= noise_want + 0.2);
100}
101```
102
103## Layouts
104
105This 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:
106
107* **Standard** → Front-end, serializable layouts. These are backend-agnostic and act as inputs/outputs of computations (e.g., `GGLWEAutomorphismKey`).
108* **Compressed** → Compact serializable variants of the standard layouts. They are not usable for computation but significantly reduce storage size (e.g., `GGLWEAutomorphismKeyCompressed`).
109* **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`).
110
111All **standard** and **compressed** layouts implement the `WriterTo` and `ReaderFrom` traits, enabling straightforward serialization/deserialization with any type implementing `Write` or `Read`:
112
113```rust
114pub trait WriterTo {
115 fn write_to<W: Write>(&self, writer: &mut W) -> Result<()>;
116}
117
118pub trait ReaderFrom {
119 fn read_from<R: Read>(&mut self, reader: &mut R) -> Result<()>;
120}
121```
122
123### Example Workflow
124
125```mermaid
126flowchart TD
127 A[GGLWEAutomorphismKeyCompressed]-->|decompress|B[GGLWEAutomorphismKey]-->|prepare|C[GGLWEAutomorphismKeyPrepared]
128```
129
130Equivalent Rust:
131
132```rust
133let mut atk_compressed: GGLWEAutomorphismKeyCompressed<Vec<u8>> =
134 GGLWEAutomorphismKeyCompressed::alloc(...);
135let mut atk: GGLWEAutomorphismKey<Vec<u8>> =
136 GGLWEAutomorphismKey::alloc(...);
137atk.decompress(module, &atk_compressed);
138let mut atk_prep: GGLWEAutomorphismKeyPrepared<Vec<u8>, B> = GLWESecretPrepared<Vec<u8>, B> = atk.prepare_alloc(...);
139```
140
141---
142
143## Encryption & Decryption
144
145* **Encryption** → Supported for all **standard** and **compressed** layouts.
146* **Decryption** → Only directly available for `LWECiphertext` and `GLWECiphertext`.
147 However, it remains naturally usable on `GGLWE` and `GGSW` objects, since these are vectors/matrices of `GLWECiphertext`.
148
149```rust
150let mut atk: GGLWEAutomorphismKey<Vec<u8>> =
151 GGLWEAutomorphismKey::alloc(...);
152atk.encrypt_sk(...);
153atk.at(row, 0).decrypt(...);
154```
155## Keyswitching, Automorphism & External Product
156
157Keyswitching, automorphisms and external products are supported for all ciphertext types where they are well-defined.
158This includes subtypes such as `GGLWEAutomorphismKey`.
159
160For example:
161
162```rust
163atk.external_product(...);
164ggsw.automorphism(...);
165```
166
167---
168
169## Additional Features
170
171* Ciphertexts: `LWE` and `GLWE`
172* `GLWE` ring packing
173* `GLWE` trace
174* Noise analysis for `GLWE`, `GGLWE`, `GGSW`
175* Basic operations over `GLWE` ciphertexts and plaintexts
176
177---
178
179## Tests
180
181A fully generic test suite is available in [`src/tests/test_suite`](./src/tests/test_suite).