From 1e2ea824fd50d21fe2c52532e422821508415317 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Wed, 16 Jul 2025 18:57:32 +0200 Subject: [PATCH] implement GLev encryption & decryption --- gfhe/src/glev.rs | 91 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 gfhe/src/glev.rs diff --git a/gfhe/src/glev.rs b/gfhe/src/glev.rs new file mode 100644 index 0000000..8337c1b --- /dev/null +++ b/gfhe/src/glev.rs @@ -0,0 +1,91 @@ +use anyhow::Result; +use rand::Rng; +use rand_distr::{Normal, Uniform}; +use std::ops::{Add, Mul}; + +use arith::{Ring, Rq, TR}; + +use crate::glwe::{PublicKey, SecretKey, GLWE}; + +const ERR_SIGMA: f64 = 3.2; + +// l GLWEs +#[derive(Clone, Debug)] +pub struct GLev(pub(crate) Vec>); + +impl GLev { + pub fn encrypt( + mut rng: impl Rng, + beta: u32, + l: u32, + pk: &PublicKey, + m: &Rq, + // delta: u64, + ) -> Result { + let glev: Vec> = (0..l) + .map(|i| { + GLWE::::encrypt(&mut rng, pk, &(*m * (Q / beta.pow(i as u32) as u64)), 1) + }) + .collect::>>()?; + + Ok(Self(glev)) + } + pub fn encrypt_s( + mut rng: impl Rng, + beta: u32, + l: u32, + sk: &SecretKey, + m: &Rq, + // delta: u64, + ) -> Result { + let glev: Vec> = (0..l) + .map(|i| { + GLWE::::encrypt_s(&mut rng, sk, &(*m * (Q / beta.pow(i as u32) as u64)), 1) + }) + .collect::>>()?; + + Ok(Self(glev)) + } + + pub fn decrypt(&self, sk: &SecretKey, delta: u64) -> Rq { + self.0[1].decrypt::(sk, delta) + } +} + +#[cfg(test)] +mod tests { + use anyhow::Result; + use rand::distributions::Uniform; + + use super::*; + + #[test] + fn test_encrypt_decrypt() -> Result<()> { + const Q: u64 = 2u64.pow(16) + 1; + const N: usize = 128; + const T: u64 = 2; // plaintext modulus + const K: usize = 16; + type S = GLev; + + let beta: u32 = 2; + let l: u32 = 16; + + let delta: u64 = Q / T; // floored + let mut rng = rand::thread_rng(); + + for _ in 0..200 { + let (sk, pk) = GLWE::::new_key(&mut rng)?; + + let msg_dist = Uniform::new(0_u64, T); + let m = Rq::::rand_u64(&mut rng, msg_dist)?; + let m: Rq = m.remodule::(); + + let c = S::encrypt(&mut rng, beta, l, &pk, &m)?; + let m_recovered = c.decrypt::(&sk, delta); + + assert_eq!(m.remodule::(), m_recovered.remodule::()); + } + + Ok(()) + } +}