ring_lwe/decrypt.rs
1use crate::utils::{Parameters, polymul_fast, polyadd, nearest_int, decompress};
2use polynomial_ring::Polynomial;
3
4/// Decrypt a ciphertext using the secret key
5/// # Arguments:
6/// * `sk` - secret key
7/// * `ct` - array of ciphertext polynomials
8/// * `params` - ring-LWE parameters
9/// # Returns:
10/// decrypted polynomial
11/// # Example:
12/// ```
13/// let params = ring_lwe::utils::Parameters::default();
14/// let (pk, sk) = ring_lwe::keygen::keygen(¶ms, None);
15/// let m = polynomial_ring::Polynomial::new(vec![1, 0, 1]);
16/// let ct = ring_lwe::encrypt::encrypt(&pk, &m, ¶ms, None);
17/// let decrypted_m = ring_lwe::decrypt::decrypt(&sk, &ct, ¶ms);
18/// ```
19pub fn decrypt(
20 sk: &Polynomial<i64>, // Secret key
21 ct: &[Polynomial<i64>; 2], // Array of ciphertext polynomials
22 params: &Parameters
23) -> Polynomial<i64> {
24 let (_n,q,t,f,omega) = (params.n, params.q, params.t, ¶ms.f, params.omega);
25 let scaled_pt = polyadd(&polymul_fast(&ct[1], sk, q, f, omega),&ct[0], q, f);
26 let mut decrypted_coeffs = vec![];
27 let mut s;
28 for c in scaled_pt.coeffs().iter() {
29 s = nearest_int(c*t,q);
30 decrypted_coeffs.push(s.rem_euclid(t));
31 }
32 Polynomial::new(decrypted_coeffs)
33}
34
35/// Decrypt a ciphertext string using the secret key
36/// # Arguments:
37/// * `sk_string` - secret key as a base64 encoded string
38/// * `ciphertext_string` - ciphertext to decrypt as a base64 encoded string
39/// * `params` - ring-LWE parameters
40/// # Returns:
41/// decrypted plaintext message
42/// # Example:
43/// ```
44/// let params = ring_lwe::utils::Parameters::default();
45/// let keys = ring_lwe::keygen::keygen_string(¶ms, None);
46/// let sk_string = keys.get("secret").unwrap();
47/// let pk_string = keys.get("public").unwrap();
48/// let message = String::from("hello");
49/// let ciphertext_string = ring_lwe::encrypt::encrypt_string(pk_string, &message, ¶ms, None);
50/// let decrypted_message = ring_lwe::decrypt::decrypt_string(sk_string, &ciphertext_string, ¶ms);
51/// ```
52pub fn decrypt_string(sk_base64: &String, ciphertext_base64: &String, params: &Parameters) -> String {
53 // Decode the base64 secret key string and deserialize into a vector of i64 coefficients
54 let sk = Polynomial::new(decompress(sk_base64));
55
56 // Decode the Base64 ciphertext string and deserialize into vector of i64 coefficients
57 let ciphertext_array: Vec<i64> = decompress(ciphertext_base64);
58
59 let num_blocks = ciphertext_array.len() / (2 * params.n);
60 let mut decrypted_bits: Vec<i64> = Vec::new();
61
62 for i in 0..num_blocks {
63 let c0 = Polynomial::new(ciphertext_array[2 * i * params.n..(2 * i + 1) * params.n].to_vec());
64 let c1 = Polynomial::new(ciphertext_array[(2 * i + 1) * params.n..(2 * i + 2) * params.n].to_vec());
65 let ct = [c0, c1];
66
67 // Decrypt the ciphertext
68 decrypted_bits.extend(decrypt(&sk, &ct, ¶ms).coeffs());
69 }
70
71 // Convert decrypted bits into a string
72 let decrypted_message: String = decrypted_bits
73 .chunks(8)
74 .map(|byte| {
75 let bit_str: String = byte.iter().map(|&b| (b as u8 + b'0') as char).collect();
76 u8::from_str_radix(&bit_str, 2).unwrap_or(0) as char
77 })
78 .collect();
79
80 decrypted_message.trim_end_matches('\0').to_string()
81}