module_lwe/
utils.rs

1use polynomial_ring::Polynomial;
2use rand_distr::{Uniform, Distribution};
3use rand::SeedableRng;
4use rand::rngs::StdRng;
5use ring_lwe::utils::{polyadd, polymul_fast, gen_uniform_poly,nearest_int};
6use ntt::omega;
7use base64::{engine::general_purpose, Engine as _};
8use bincode;
9
10#[derive(Debug)]
11/// Default parameters for module-LWE
12pub struct Parameters {
13    /// Degree of the polynomials
14    pub n: usize,
15    /// Ciphertext modulus
16    pub q: i64,
17    /// Module rank	
18    pub k: usize,
19    /// 2n-th root of unity	
20    pub omega: i64,
21    /// Polynomial modulus
22    pub f: Polynomial<i64>,
23}
24
25impl Default for Parameters {
26    fn default() -> Self {
27        let n = 512;
28        let q = 12289;
29        let k = 8;
30        let omega = omega(q, 2 * n);
31        let mut poly_vec = vec![0i64; n + 1];
32        poly_vec[0] = 1;
33        poly_vec[n] = 1;
34        let f = Polynomial::new(poly_vec);
35        Parameters { n, q, k, omega, f }
36    }
37}
38
39pub fn add_vec(v0: &Vec<Polynomial<i64>>, v1: &Vec<Polynomial<i64>>, modulus: i64, poly_mod: &Polynomial<i64>) -> Vec<Polynomial<i64>> {
40    assert_eq!(v0.len(), v1.len());
41    v0.iter()
42        .zip(v1.iter())
43        .map(|(a, b)| polyadd(a, b, modulus, poly_mod))
44        .collect()
45}
46
47pub fn mul_vec_simple(v0: &Vec<Polynomial<i64>>, v1: &Vec<Polynomial<i64>>, modulus: i64, poly_mod: &Polynomial<i64>, omega: i64) -> Polynomial<i64> {
48    assert_eq!(v0.len(), v1.len());
49    v0.iter()
50        .zip(v1.iter())
51        .map(|(a, b)| polymul_fast(a, b, modulus, poly_mod, omega))
52        .fold(Polynomial::new(vec![]), |acc, p| polyadd(&acc, &p, modulus, poly_mod))
53}
54
55pub fn mul_mat_vec_simple(m: &Vec<Vec<Polynomial<i64>>>, v: &Vec<Polynomial<i64>>, modulus: i64, poly_mod: &Polynomial<i64>, omega: i64) -> Vec<Polynomial<i64>> {
56    m.iter()
57        .map(|row| mul_vec_simple(row, v, modulus, poly_mod, omega))
58        .collect()
59}
60
61pub fn transpose(m: &Vec<Vec<Polynomial<i64>>>) -> Vec<Vec<Polynomial<i64>>> {
62    let rows = m.len();
63    let cols = m[0].len();
64    let mut result = vec![vec![Polynomial::new(vec![]); rows]; cols];
65    for i in 0..rows {
66        for j in 0..cols {
67            result[j][i] = m[i][j].clone();
68        }
69    }
70    result
71}
72
73pub fn gen_small_vector(size: usize, rank: usize, seed: Option<u64>) -> Vec<Polynomial<i64>> {
74    let between = Uniform::new(0, 3);
75    let mut rng = match seed {
76        Some(s) => StdRng::seed_from_u64(s),
77        None => StdRng::from_entropy(),
78    };
79
80    (0..rank)
81        .map(|_| {
82            let coeffs: Vec<i64> = (0..size).map(|_| between.sample(&mut rng) - 1).collect();
83            Polynomial::new(coeffs)
84        })
85        .collect()
86}
87
88pub fn gen_uniform_matrix(size: usize, rank: usize, modulus: i64, seed: Option<u64>) -> Vec<Vec<Polynomial<i64>>> {
89    (0..rank)
90        .map(|_| {
91            (0..rank)
92                .map(|_| gen_uniform_poly(size, modulus, seed))
93                .collect::<Vec<_>>()
94        })
95        .collect::<Vec<_>>()
96}
97
98pub fn compress(data: &Vec<i64>) -> String {
99    let serialized = bincode::serialize(data).expect("Failed to serialize data");
100    general_purpose::STANDARD.encode(&serialized)
101}
102
103pub fn decompress(base64_str: &str) -> Vec<i64> {
104    let decoded = general_purpose::STANDARD.decode(base64_str).expect("Failed to decode base64 string");
105    bincode::deserialize(&decoded).expect("Failed to deserialize data")
106}
107
108pub fn encode_message(m_b: &Vec<i64>, q: i64) -> Polynomial<i64> {
109
110    // Round q/2 to the nearest integer
111    let half_q = nearest_int(q,2);
112
113    // Convert binary message to polynomial
114    Polynomial::new(vec![half_q])*Polynomial::new(m_b.to_vec())
115    
116}