From 4efe22e723914635ef74c2b6bb01ab522a357207 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Bossuat Date: Tue, 6 May 2025 14:38:22 +0200 Subject: [PATCH] Start of full rewrite of rlwe crate --- rlwe/Cargo.toml | 4 -- rlwe/src/ciphertext.rs | 4 -- rlwe/src/elem.rs | 85 ++++++++++++++++++++++++++++++++++++++++++ rlwe/src/encryption.rs | 71 +++++++++++++++++++++++++++++++++++ rlwe/src/keys.rs | 64 +++++++++++++++++++++++++++++++ rlwe/src/lib.rs | 4 +- 6 files changed, 223 insertions(+), 9 deletions(-) delete mode 100644 rlwe/src/ciphertext.rs create mode 100644 rlwe/src/elem.rs create mode 100644 rlwe/src/encryption.rs create mode 100644 rlwe/src/keys.rs diff --git a/rlwe/Cargo.toml b/rlwe/Cargo.toml index 0822281..692c4fb 100644 --- a/rlwe/Cargo.toml +++ b/rlwe/Cargo.toml @@ -10,7 +10,3 @@ base2k = {path="../base2k"} sampling = {path="../sampling"} rand_distr = {workspace = true} itertools = {workspace = true} - -[[bench]] -name = "gadget_product" -harness = false \ No newline at end of file diff --git a/rlwe/src/ciphertext.rs b/rlwe/src/ciphertext.rs deleted file mode 100644 index dc83a66..0000000 --- a/rlwe/src/ciphertext.rs +++ /dev/null @@ -1,4 +0,0 @@ - -pub struct Ciphertext{ - x -} \ No newline at end of file diff --git a/rlwe/src/elem.rs b/rlwe/src/elem.rs new file mode 100644 index 0000000..7574bf5 --- /dev/null +++ b/rlwe/src/elem.rs @@ -0,0 +1,85 @@ +use base2k::{Backend, FFT64, MatZnxDft, MatZnxDftAlloc, Module, VecZnx, VecZnxAlloc}; + +pub struct Ciphertext { + data: T, + log_base2k: usize, + log_q: usize, +} + +impl Ciphertext { + pub fn log_base2k(&self) -> usize { + self.log_base2k + } + + pub fn log_q(&self) -> usize { + self.log_q + } + + pub fn data(&self) -> &T { + &self.data + } + + pub fn data_mut(&mut self) -> &mut T { + &mut self.data + } +} + +pub struct Plaintext { + data: T, + log_base2k: usize, + log_q: usize, +} + +impl Plaintext { + pub fn log_base2k(&self) -> usize { + self.log_base2k + } + + pub fn log_q(&self) -> usize { + self.log_q + } + + pub fn data(&self) -> &T { + &self.data + } + + pub fn data_mut(&mut self) -> &mut T { + &mut self.data + } +} + +pub(crate) type CipherVecZnx = Ciphertext>; + +impl Ciphertext>> { + pub fn new(module: &Module, log_base2k: usize, log_q: usize, cols: usize) -> Self { + Self { + data: module.new_vec_znx(cols, derive_size(log_base2k, log_q)), + log_base2k: log_base2k, + log_q: log_q, + } + } +} + +impl Plaintext>> { + pub fn new(module: &Module, log_base2k: usize, log_q: usize) -> Self { + Self { + data: module.new_vec_znx(1, derive_size(log_base2k, log_q)), + log_base2k: log_base2k, + log_q: log_q, + } + } +} + +impl Ciphertext, B>> { + pub fn new(module: &Module, log_base2k: usize, rows: usize, cols_in: usize, cols_out: usize, log_q: usize) -> Self { + Self { + data: module.new_mat_znx_dft(rows, cols_in, cols_out, derive_size(log_base2k, log_q)), + log_base2k: log_base2k, + log_q: log_q, + } + } +} + +pub(crate) fn derive_size(log_base2k: usize, log_q: usize) -> usize { + (log_q + log_base2k - 1) / log_base2k +} diff --git a/rlwe/src/encryption.rs b/rlwe/src/encryption.rs new file mode 100644 index 0000000..ca4b837 --- /dev/null +++ b/rlwe/src/encryption.rs @@ -0,0 +1,71 @@ +use base2k::{ + AddNormal, Backend, FillUniform, Module, VecZnxDftOps, ScalarZnxDftOps, ScalarZnxDftToRef, VecZnxBigOps, Scratch, VecZnx, VecZnxToMut, VecZnxToRef, ZnxInfos, FFT64 +}; + +use sampling::source::Source; + +use crate::{ + elem::{CipherVecZnx, Plaintext}, + keys::SecretKey, +}; + +pub trait EncryptSk { + fn encrypt( + module: &Module, + res: &mut D, + pt: Option<&Plaintext

>, + sk: &SecretKey, + source_xa: &mut Source, + source_xe: &mut Source, + scratch: &mut Scratch, + sigma: f64, + bound: f64, + ) where + P: VecZnxToRef, + S: ScalarZnxDftToRef; +} + +impl EncryptSk> for CipherVecZnx +where + VecZnx: VecZnxToMut + VecZnxToRef, +{ + fn encrypt( + module: &Module, + ct: &mut CipherVecZnx, + pt: Option<&Plaintext

>, + sk: &SecretKey, + source_xa: &mut Source, + source_xe: &mut Source, + scratch: &mut Scratch, + sigma: f64, + bound: f64, + ) where + P: VecZnxToRef, + S: ScalarZnxDftToRef, + { + let log_base2k: usize = ct.log_base2k(); + let log_q: usize = ct.log_q(); + let mut ct_mut: VecZnx<&mut [u8]> = ct.data_mut().to_mut(); + let size: usize = ct_mut.size(); + + ct_mut.fill_uniform(log_base2k, 1, size, source_xa); + + // c1_dft = DFT(a) * DFT(s) + let (mut c1_dft, scratch_1) = scratch.tmp_vec_znx_dft(module, 1, size); + module.svp_apply(&mut c1_dft, 0, &sk.data().to_ref(), 0, &ct_mut, 1); + + // c1_big = IDFT(c1_dft) + let (mut c1_big, scratch_2) = scratch_1.tmp_vec_znx_big(module, 1, size); + module.vec_znx_idft_tmp_a(&mut c1_big, 0, &mut c1_dft, 0); + + // c1_big = m - c1_big + if let Some(pt) = pt { + module.vec_znx_big_sub_small_b_inplace(&mut c1_big, 0, &pt.data().to_ref(), 0); + } + // c1_big += e + c1_big.add_normal(log_base2k, 0, log_q, source_xe, sigma, bound); + + // c0 = norm(c1_big) + module.vec_znx_big_normalize(log_base2k, &mut ct_mut, 0, &c1_big, 0, scratch_2); + } +} diff --git a/rlwe/src/keys.rs b/rlwe/src/keys.rs new file mode 100644 index 0000000..50f1221 --- /dev/null +++ b/rlwe/src/keys.rs @@ -0,0 +1,64 @@ +use base2k::{ + Backend, FFT64, Module, Scalar, ScalarAlloc, ScalarZnxDft, ScalarZnxDftOps, ScalarZnxDftToMut, Scratch, VecZnx, VecZnxDft, + VecZnxDftAlloc, VecZnxDftToMut, +}; +use sampling::source::Source; + +use crate::elem::derive_size; + +pub struct SecretKey { + data: T, +} + +impl SecretKey { + pub fn data(&self) -> &T { + &self.data + } + + pub fn data_mut(&self) -> &mut T { + &mut self.data + } +} + +impl SecretKey>> { + pub fn new(module: &Module) -> Self { + Self { + data: module.new_scalar(1), + } + } + + pub fn fill_ternary_prob(&mut self, prob: f64, source: &mut Source) { + self.data.fill_ternary_prob(0, prob, source); + } + + pub fn fill_ternary_hw(&mut self, hw: usize, source: &mut Source) { + self.data.fill_ternary_hw(0, hw, source); + } + + pub fn svp_prepare(&self, module: &Module, sk_prep: &mut SecretKey>) + where + ScalarZnxDft: ScalarZnxDftToMut, + { + module.svp_prepare(&mut sk_prep.data, 0, &self.data, 0) + } +} + +pub struct PublicKey { + data: VecZnxDft, +} + +impl PublicKey, B> { + pub fn new(module: &Module, log_base2k: usize, log_q: usize) -> Self { + Self { + data: module.new_vec_znx_dft(2, derive_size(log_base2k, log_q)), + } + } +} + +impl> PublicKey { + pub fn generate(&mut self, module: &Module, sk: &SecretKey>) + where + ScalarZnxDft: ScalarZnxDftToMut, + { + } +} diff --git a/rlwe/src/lib.rs b/rlwe/src/lib.rs index 3a7eec6..023acb5 100644 --- a/rlwe/src/lib.rs +++ b/rlwe/src/lib.rs @@ -1 +1,3 @@ -pub mod ciphertext; \ No newline at end of file +pub mod elem; +pub mod encryption; +pub mod keys;