fhe-study/gfhe/src/glev.rs
gfhe/src/glev.rsRaw
1use anyhow::Result;
2use rand::Rng;
3use rand_distr::{Normal, Uniform};
4use std::ops::{Add, Mul};
5
6use arith::{Ring, TR};
7
8use crate::glwe::{PublicKey, SecretKey, GLWE};
9
10const ERR_SIGMA: f64 = 3.2;
11
12// l GLWEs
13#[derive(Clone, Debug)]
14pub struct GLev<R: Ring, const K: usize>(pub(crate) Vec<GLWE<R, K>>);
15
16impl<R: Ring, const K: usize> GLev<R, K> {
17 pub fn encrypt(
18 mut rng: impl Rng,
19 beta: u32,
20 l: u32,
21 pk: &PublicKey<R, K>,
22 m: &R,
23 ) -> Result<Self> {
24 let glev: Vec<GLWE<R, K>> = (0..l)
25 .map(|i| {
26 GLWE::<R, K>::encrypt(&mut rng, pk, &(*m * (R::Q / beta.pow(i as u32) as u64)))
27 })
28 .collect::<Result<Vec<_>>>()?;
29
30 Ok(Self(glev))
31 }
32 pub fn encrypt_s(
33 mut rng: impl Rng,
34 beta: u32,
35 l: u32,
36 sk: &SecretKey<R, K>,
37 m: &R,
38 // delta: u64,
39 ) -> Result<Self> {
40 let glev: Vec<GLWE<R, K>> = (1..l + 1)
41 .map(|i| {
42 GLWE::<R, K>::encrypt_s(&mut rng, sk, &(*m * (R::Q / beta.pow(i as u32) as u64)))
43 })
44 .collect::<Result<Vec<_>>>()?;
45
46 Ok(Self(glev))
47 }
48
49 pub fn decrypt<const T: u64>(&self, sk: &SecretKey<R, K>, beta: u32) -> R {
50 let pt = self.0[1].decrypt(sk);
51 pt.mul_div_round(beta as u64, R::Q)
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use anyhow::Result;
58 use rand::distributions::Uniform;
59
60 use super::*;
61 use arith::Rq;
62
63 #[test]
64 fn test_encrypt_decrypt() -> Result<()> {
65 const Q: u64 = 2u64.pow(16) + 1;
66 const N: usize = 128;
67 const T: u64 = 2; // plaintext modulus
68 const K: usize = 16;
69 type S = GLev<Rq<Q, N>, K>;
70
71 let beta: u32 = 2;
72 let l: u32 = 16;
73
74 // let delta: u64 = Q / T; // floored
75 let mut rng = rand::thread_rng();
76 let msg_dist = Uniform::new(0_u64, T);
77
78 for _ in 0..200 {
79 let (sk, pk) = GLWE::<Rq<Q, N>, K>::new_key(&mut rng)?;
80
81 let m = Rq::<T, N>::rand_u64(&mut rng, msg_dist)?;
82 let m: Rq<Q, N> = m.remodule::<Q>();
83
84 let c = S::encrypt(&mut rng, beta, l, &pk, &m)?;
85 let m_recovered = c.decrypt::<T>(&sk, beta);
86
87 assert_eq!(m.remodule::<T>(), m_recovered.remodule::<T>());
88 }
89
90 Ok(())
91 }
92}