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};
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
25/// default parameters for module-LWE
26impl Default for Parameters {
27    fn default() -> Self {
28        let n = 512;
29        let q = 12289;
30        let k = 8;
31		let omega = omega(q, 2*n);
32        let mut poly_vec = vec![0i64;n+1];
33        poly_vec[0] = 1;
34        poly_vec[n] = 1;
35        let f = Polynomial::new(poly_vec);
36        Parameters { n, q, k, omega, f }
37    }
38}
39
40/// add two vectors of polynomials
41/// # Arguments
42/// * `v0` - vector of polynomials
43/// * `v1` - vector of polynomials
44/// * `modulus` - modulus
45/// * `poly_mod` - polynomial modulus
46/// # Returns
47/// * `result` - vector of polynomials
48pub fn add_vec(v0: &Vec<Polynomial<i64>>, v1: &Vec<Polynomial<i64>>, modulus: i64, poly_mod: &Polynomial<i64>) -> Vec<Polynomial<i64>> {
49	assert!(v0.len() == v1.len());
50	let mut result = vec![];
51	for i in 0..v0.len() {
52		result.push(polyadd(&v0[i], &v1[i], modulus, &poly_mod));
53	}
54	result
55}
56
57/// take the dot product of two vectors of polynomials
58/// # Arguments
59/// * `v0` - vector of polynomials
60/// * `v1` - vector of polynomials
61/// * `modulus` - modulus
62/// * `poly_mod` - polynomial modulus
63/// * `omega` - 2nth root of unity
64/// # Returns
65/// * `result` - polynomial
66pub fn mul_vec_simple(v0: &Vec<Polynomial<i64>>, v1: &Vec<Polynomial<i64>>, modulus: i64, poly_mod: &Polynomial<i64>, omega: i64) -> Polynomial<i64> {
67	assert!(v0.len() == v1.len());
68	let mut result = Polynomial::new(vec![]);
69	for i in 0..v0.len() {
70		result = polyadd(&result, &polymul_fast(&v0[i], &v1[i], modulus, &poly_mod, omega), modulus, &poly_mod);
71	}
72	result
73}
74
75/// multiply a matrix by a vector of polynomials
76/// # Arguments
77/// * `m` - matrix of polynomials
78/// * `v` - vector of polynomials
79/// * `modulus` - modulus
80/// * `poly_mod` - polynomial modulus
81/// * `omega` - 2nth root of unity
82/// # Returns
83/// * `result` - vector of polynomials
84pub 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>> {
85	
86	let mut result = vec![];
87	for i in 0..m.len() {
88		result.push(mul_vec_simple(&m[i], &v, modulus, &poly_mod, omega));
89	}
90	result
91}
92
93/// take the transpose of a matrix of polynomials
94/// # Arguments
95/// * `m` - matrix of polynomials
96/// # Returns
97/// * `result` - matrix of polynomials
98pub fn transpose(m: &Vec<Vec<Polynomial<i64>>>) -> Vec<Vec<Polynomial<i64>>> {
99	let mut result = vec![vec![Polynomial::new(vec![]); m.len()]; m[0].len()];
100	for i in 0..m.len() {
101		for j in 0..m[0].len() {
102			result[j][i] = m[i][j].clone();
103		}
104	}
105	result
106}
107
108/// generates a vector of given rank of degree size-1 polynomials with coefficients in {-1,0,1}
109/// # Arguments
110/// * `size` - degree of the polynomials
111/// * `rank` - rank of the vector
112/// * `seed` - seed for the random number generator
113/// # Returns
114/// * `v` - vector of polynomials
115pub fn gen_small_vector(size : usize, rank: usize, seed: Option<u64>) -> Vec<Polynomial<i64>> {
116	let mut v = vec![];
117	let between = Uniform::new(0,3);
118	let mut rng = match seed {
119        Some(seed) => StdRng::seed_from_u64(seed),
120        None => StdRng::from_entropy(),
121    };
122    let mut coeffs = vec![0i64;size];
123	for _i in 0..rank {
124		for j in 0.. size {
125			coeffs[j] = between.sample(&mut rng)-1;
126		}
127		v.push(Polynomial::new(coeffs.clone()));
128	}
129	v
130}
131
132/// generates a `rank x rank` matrix of degree `size-1` polynomials with uniform coefficients in Z_modulus
133/// # Arguments
134/// * `size` - degree of the polynomials
135/// * `rank` - rank of the matrix
136/// * `modulus` - modulus
137/// * `seed` - seed for the random number generator
138/// # Returns
139/// * `m` - matrix of polynomials
140pub fn gen_uniform_matrix(size : usize, rank: usize, modulus: i64, seed: Option<u64>) -> Vec<Vec<Polynomial<i64>>> {
141	let mut m = vec![vec![Polynomial::new(vec![]); rank]; rank];
142	for i in 0..rank {
143		for j in 0..rank {
144			m[i][j] = gen_uniform_poly(size, modulus, seed);
145		}
146	}
147	m
148}
149
150/// seralize and encode a vector of i64 to a base64 encoded string
151/// # Arguments
152/// * `data` - vector of i64
153/// # Returns
154/// * `encoded` - base64 encoded string
155pub fn compress(data: &Vec<i64>) -> String {
156    let serialized_data = bincode::serialize(data).expect("Failed to serialize data");
157    general_purpose::STANDARD.encode(&serialized_data)
158}
159
160/// decode and deserialize a base64 encoded string to a vector of i64
161/// # Arguments
162/// * `base64_str` - base64 encoded string
163/// # Returns
164/// * `decoded_data` - vector of i64
165pub fn decompress(base64_str: &str) -> Vec<i64> {
166    let decoded_bytes = general_purpose::STANDARD.decode(base64_str).expect("Failed to decode base64 string");
167    bincode::deserialize(&decoded_bytes).expect("Failed to deserialize data")
168}