arnaucube
arnaucube/fhe-studyPublic Self-hosted repository
fhe-study/tfhe/src/tgsw.rs
tfhe/src/tgsw.rsRaw
 1use anyhow::Result;
 2use itertools::zip_eq;
 3use rand::Rng;
 4use std::array;
 5use std::ops::{Add, Mul};
 6
 7use arith::{Ring, Rq, Tn, T64, TR};
 8
 9use crate::tlev::TLev;
10use crate::tlwe::{PublicKey, SecretKey, TLWE};
11use gfhe::glwe::GLWE;
12
13/// vector of length K+1 = [K], [1]
14#[derive(Clone, Debug)]
15pub struct TGSW<const K: usize>(pub(crate) Vec<TLev<K>>, TLev<K>);
16
17impl<const K: usize> TGSW<K> {
18    pub fn encrypt_s(
19        mut rng: impl Rng,
20        beta: u32,
21        l: u32,
22        sk: &SecretKey<K>,
23        m: &T64,
24    ) -> Result<Self> {
25        let a: Vec<TLev<K>> = (0..K)
26            .map(|i| TLev::encrypt_s(&mut rng, beta, l, sk, &(-sk.0 .0[i] * *m)))
27            .collect::<Result<Vec<_>>>()?;
28        let b: TLev<K> = TLev::encrypt_s(&mut rng, beta, l, sk, m)?;
29        Ok(Self(a, b))
30    }
31
32    pub fn decrypt(&self, sk: &SecretKey<K>, beta: u32) -> T64 {
33        self.1.decrypt(sk, beta)
34    }
35    pub fn from_tlwe(_tlwe: TLWE<K>) -> Self {
36        todo!()
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use anyhow::Result;
43    use rand::distributions::Uniform;
44
45    use super::*;
46
47    #[test]
48    fn test_encrypt_decrypt() -> Result<()> {
49        const T: u64 = 2; // plaintext modulus
50        const K: usize = 16;
51        type S = TGSW<K>;
52
53        let beta: u32 = 2;
54        let l: u32 = 16;
55
56        let mut rng = rand::thread_rng();
57        let msg_dist = Uniform::new(0_u64, T);
58
59        for _ in 0..50 {
60            let (sk, _) = TLWE::<K>::new_key(&mut rng)?;
61
62            let m: Rq<T, 1> = Rq::rand_u64(&mut rng, msg_dist)?;
63            let p: T64 = TLev::<K>::encode::<T>(&m); // plaintext
64
65            let c = S::encrypt_s(&mut rng, beta, l, &sk, &p)?;
66            let p_recovered = c.decrypt(&sk, beta);
67            let m_recovered = TLev::<K>::decode::<T>(&p_recovered);
68
69            assert_eq!(m, m_recovered);
70        }
71
72        Ok(())
73    }
74}