use polynomial_ring::Polynomial;
use ring_lwe::utils::{polysub,nearest_int};
use crate::utils::{Parameters,mul_vec_simple,decompress};
pub fn decrypt(
sk: &Vec<Polynomial<i64>>, u: &Vec<Polynomial<i64>>, v: &Polynomial<i64> , params: &Parameters
) -> Vec<i64> {
let (q, f, omega) = (params.q, ¶ms.f, params.omega); let scaled_pt = polysub(&v, &mul_vec_simple(&sk, &u, q, &f, omega), q, f); let half_q = nearest_int(q,2); let mut decrypted_coeffs = vec![];
let mut s;
for c in scaled_pt.coeffs().iter() {
s = nearest_int(*c,half_q).rem_euclid(2);
decrypted_coeffs.push(s);
}
decrypted_coeffs
}
pub fn decrypt_string(sk_string: &String, ciphertext_base64: &String, params: &Parameters) -> String {
let (n, k) = (params.n, params.k);
let sk_array: Vec<i64> = decompress(sk_string);
let sk: Vec<Polynomial<i64>> = sk_array.chunks(n)
.map(|chunk| Polynomial::new(chunk.to_vec()))
.collect();
let ciphertext_list: Vec<i64> = decompress(ciphertext_base64);
let block_size = (k + 1) * n;
let num_blocks = ciphertext_list.len() / block_size;
let mut message_binary = vec![];
for i in 0..num_blocks {
let u_array = &ciphertext_list[i * block_size..i * block_size + k * n];
let v_array = &ciphertext_list[i * block_size + k * n..(i + 1) * block_size];
let u: Vec<Polynomial<i64>> = u_array.chunks(n)
.map(|chunk| Polynomial::new(chunk.to_vec()))
.collect();
let v = Polynomial::new(v_array.to_vec());
let m_b = decode_block(&sk, &u, &v, params);
message_binary.extend(m_b);
}
let byte_chunks: Vec<String> = message_binary.chunks(8)
.map(|chunk| chunk.iter().map(|bit| bit.to_string()).collect())
.collect();
let message_string: String = byte_chunks.iter()
.map(|byte| char::from_u32(i64::from_str_radix(byte, 2).unwrap() as u32).unwrap())
.collect();
message_string.trim_end_matches('\0').to_string()
}
fn decode_block(sk: &Vec<Polynomial<i64>>, u: &Vec<Polynomial<i64>>, v: &Polynomial<i64>, params: &Parameters) -> Vec<i64> {
let mut m_b = decrypt(sk, u, v, params);
m_b.resize(params.n, 0);
m_b
}