From cd971771baefd9c8e52214ae70b1f81fe1bb66db Mon Sep 17 00:00:00 2001 From: tjaysilver Date: Tue, 18 Feb 2025 22:58:20 -0500 Subject: [PATCH] use polymul_fast Use polymul_fast function from ring_lwe for dot product and matrix multiplication. Also, decrypt function updated to use paramters as input. --- Cargo.toml | 1 + src/decrypt.rs | 14 +++++++------- src/encrypt.rs | 6 +++--- src/keygen.rs | 4 ++-- src/test.rs | 2 +- src/utils.rs | 26 ++++++++++++++++---------- 6 files changed, 30 insertions(+), 23 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8ee2ffd..9abbb13 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,4 +13,5 @@ polynomial-ring = "0.5.0" num-traits = "=0.2.19" rand = "0.8.5" rand_distr = "0.4.3" +ntt = "0.1.9" ring-lwe = "0.1.5" \ No newline at end of file diff --git a/src/decrypt.rs b/src/decrypt.rs index 6608196..9bcd99f 100644 --- a/src/decrypt.rs +++ b/src/decrypt.rs @@ -18,17 +18,17 @@ use crate::utils::{Parameters,mul_vec_simple}; /// let mut m_b = vec![0,1,0,1,0,0,1,1,1,0,1]; /// m_b.resize(params.n, 0); /// let (u, v) = module_lwe::encrypt::encrypt(&pk.0, &pk.1, &m_b, ¶ms, None); -/// let decrypted_coeffs = module_lwe::decrypt::decrypt(&sk, params.q, ¶ms.f, &u, &v); +/// let decrypted_coeffs = module_lwe::decrypt::decrypt(&sk, &u, &v, ¶ms); /// assert_eq!(m_b, decrypted_coeffs); /// ``` pub fn decrypt( sk: &Vec>, //secret key - q: i64, //ciphertext modulus - f: &Polynomial, //polynomial modulus u: &Vec>, //ciphertext vector - v: &Polynomial //ciphertext polynomial + v: &Polynomial , //ciphertext polynomial + params: &Parameters ) -> Vec { - let scaled_pt = polysub(&v, &mul_vec_simple(&sk, &u, q, &f), q, f); //Compute v-sk*u mod q + let (q, f, omega) = (params.q, ¶ms.f, params.omega); //get parameters + let scaled_pt = polysub(&v, &mul_vec_simple(&sk, &u, q, &f, omega), q, f); //Compute v-sk*u mod q let half_q = nearest_int(q,2); // compute nearest integer to q/2 let mut decrypted_coeffs = vec![]; let mut s; @@ -49,7 +49,7 @@ pub fn decrypt( pub fn decrypt_string(sk_string: &String, ciphertext_string: &String, params: &Parameters) -> String { //get parameters - let (n, q, k, f) = (params.n, params.q, params.k, ¶ms.f); + let (n, k) = (params.n, params.k); // Convert the secret key string into a Vec> let sk_array: Vec = sk_string.split(',') @@ -79,7 +79,7 @@ pub fn decrypt_string(sk_string: &String, ciphertext_string: &String, params: &P let v = Polynomial::new(v_array.to_vec()); // Decrypt the ciphertext - let mut m_b = decrypt(&sk, q, &f, &u, &v); + let mut m_b = decrypt(&sk, &u, &v, ¶ms); m_b.resize(n,0); message_binary.extend(m_b); diff --git a/src/encrypt.rs b/src/encrypt.rs index 29e53b2..fea74dd 100644 --- a/src/encrypt.rs +++ b/src/encrypt.rs @@ -27,7 +27,7 @@ pub fn encrypt( ) -> (Vec>, Polynomial) { //get parameters - let (n, q, k, f) = (params.n, params.q, params.k, ¶ms.f); + let (n, q, k, f, omega) = (params.n, params.q, params.k, ¶ms.f, params.omega); //generate random ephermal keys let r = gen_small_vector(n, k, seed); @@ -41,10 +41,10 @@ pub fn encrypt( let m = Polynomial::new(vec![half_q])*Polynomial::new(m_b.to_vec()); // Compute u = a^T * r + e_1 mod q - let u = add_vec(&mul_mat_vec_simple(&transpose(a), &r, q, f), &e1, q, f); + let u = add_vec(&mul_mat_vec_simple(&transpose(a), &r, q, f, omega), &e1, q, f); // Compute v = t * r + e_2 - m mod q - let v = polysub(&polyadd(&mul_vec_simple(t, &r, q, &f), &e2, q, f), &m, q, f); + let v = polysub(&polyadd(&mul_vec_simple(t, &r, q, &f, omega), &e2, q, f), &m, q, f); (u, v) } diff --git a/src/keygen.rs b/src/keygen.rs index 37071a1..5f82df6 100644 --- a/src/keygen.rs +++ b/src/keygen.rs @@ -17,12 +17,12 @@ pub fn keygen( params: &Parameters, seed: Option //random seed ) -> ((Vec>>, Vec>), Vec>) { - let (n,q,k,f) = (params.n, params.q, params.k, ¶ms.f); + let (n,q,k,f,omega) = (params.n, params.q, params.k, ¶ms.f, params.omega); //Generate a public and secret key let a = gen_uniform_matrix(n, k, q, seed); let sk = gen_small_vector(n, k, seed); let e = gen_small_vector(n, k, seed); - let t = add_vec(&mul_mat_vec_simple(&a, &sk, q, &f), &e, q, &f); + let t = add_vec(&mul_mat_vec_simple(&a, &sk, q, &f, omega), &e, q, &f); //Return public key (a, t) and secret key (sk) as a 2-tuple ((a, t), sk) diff --git a/src/test.rs b/src/test.rs index 3ce7c50..7bec9ba 100644 --- a/src/test.rs +++ b/src/test.rs @@ -49,7 +49,7 @@ mod tests { let ciphertext_sum = (add_vec(&u.0,&v.0,q,f), polyadd(&u.1,&v.1,q,f)); // Decrypt ciphertext sum u+v - let mut decrypted_sum = decrypt(&sk, q, f, &ciphertext_sum.0, &ciphertext_sum.1); + let mut decrypted_sum = decrypt(&sk, &ciphertext_sum.0, &ciphertext_sum.1, ¶ms); decrypted_sum.resize(n, 0); assert_eq!(decrypted_sum, plaintext_sum, "test failed: {:?} != {:?}", decrypted_sum, plaintext_sum); diff --git a/src/utils.rs b/src/utils.rs index 405bfff..f282d2e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -2,7 +2,8 @@ use polynomial_ring::Polynomial; use rand_distr::{Uniform, Distribution}; use rand::SeedableRng; use rand::rngs::StdRng; -use ring_lwe::utils::{polyadd, polymul, gen_uniform_poly}; +use ring_lwe::utils::{polyadd, polymul_fast, gen_uniform_poly}; +use ntt::omega; #[derive(Debug)] /// default parameters for module-LWE @@ -11,23 +12,26 @@ pub struct Parameters { pub n: usize, /// Ciphertext modulus pub q: i64, - /// Plaintext modulus - pub k: usize, + /// Module rank + pub k: usize, + /// 2n-th root of unity + pub omega: i64, /// Polynomial modulus - pub f: Polynomial, + pub f: Polynomial, } /// default parameters for module-LWE impl Default for Parameters { fn default() -> Self { let n = 32; - let q = 59049; + let q = 12289; let k = 8; + let omega = omega(q, 2*n); let mut poly_vec = vec![0i64;n+1]; poly_vec[0] = 1; poly_vec[n] = 1; let f = Polynomial::new(poly_vec); - Parameters { n, q, k, f } + Parameters { n, q, k, omega, f } } } @@ -54,13 +58,14 @@ pub fn add_vec(v0: &Vec>, v1: &Vec>, modulus: i6 /// * `v1` - vector of polynomials /// * `modulus` - modulus /// * `poly_mod` - polynomial modulus +/// * `omega` - 2nth root of unity /// # Returns /// * `result` - polynomial -pub fn mul_vec_simple(v0: &Vec>, v1: &Vec>, modulus: i64, poly_mod: &Polynomial) -> Polynomial { +pub fn mul_vec_simple(v0: &Vec>, v1: &Vec>, modulus: i64, poly_mod: &Polynomial, omega: i64) -> Polynomial { assert!(v0.len() == v1.len()); let mut result = Polynomial::new(vec![]); for i in 0..v0.len() { - result = polyadd(&result, &polymul(&v0[i], &v1[i], modulus, &poly_mod), modulus, &poly_mod); + result = polyadd(&result, &polymul_fast(&v0[i], &v1[i], modulus, &poly_mod, omega), modulus, &poly_mod); } result } @@ -71,13 +76,14 @@ pub fn mul_vec_simple(v0: &Vec>, v1: &Vec>, modu /// * `v` - vector of polynomials /// * `modulus` - modulus /// * `poly_mod` - polynomial modulus +/// * `omega` - 2nth root of unity /// # Returns /// * `result` - vector of polynomials -pub fn mul_mat_vec_simple(m: &Vec>>, v: &Vec>, modulus: i64, poly_mod: &Polynomial) -> Vec> { +pub fn mul_mat_vec_simple(m: &Vec>>, v: &Vec>, modulus: i64, poly_mod: &Polynomial, omega: i64) -> Vec> { let mut result = vec![]; for i in 0..m.len() { - result.push(mul_vec_simple(&m[i], &v, modulus, &poly_mod)); + result.push(mul_vec_simple(&m[i], &v, modulus, &poly_mod, omega)); } result }