module_lwe/encrypt.rs
1use polynomial_ring::Polynomial;
2use ring_lwe::utils::{polyadd,polysub};
3use crate::utils::{Parameters, add_vec, mul_mat_vec_simple, transpose, mul_vec_simple, gen_small_vector, compress, decompress, encode_message};
4
5/// Encrypt a message using the ring-LWE cryptosystem
6/// # Arguments
7/// * `a` - public key matrix
8/// * `t` - public key vector
9/// * `m_b` - binary message
10/// * `params` - Parameters for the ring-LWE cryptosystem
11/// * `seed` - random seed
12/// # Returns
13/// * `(u, v)` - ciphertext
14/// # Example
15/// ```
16/// let params = module_lwe::utils::Parameters::default();
17/// let (pk,sk) = module_lwe::keygen::keygen(¶ms, None);
18/// let m_b = vec![0,1,0,1,1,0,1,0];
19/// let (u, v) = module_lwe::encrypt::encrypt(&pk.0, &pk.1, &m_b, ¶ms, None);
20/// ```
21pub fn encrypt(
22 a: &Vec<Vec<Polynomial<i64>>>,
23 t: &Vec<Polynomial<i64>>,
24 m_b: &Vec<i64>,
25 params: &Parameters,
26 seed: Option<u64>
27) -> (Vec<Polynomial<i64>>, Polynomial<i64>) {
28
29 //get parameters
30 let (n, q, k, f, omega) = (params.n, params.q, params.k, ¶ms.f, params.omega);
31
32 //generate random ephermal keys
33 let r = gen_small_vector(n, k, seed);
34 let e1 = gen_small_vector(n, k, seed);
35 let e2 = gen_small_vector(n, 1, seed)[0].clone(); // Single polynomial
36
37 // encode the message from binary to polynomial
38 let m = encode_message(&m_b, q);
39
40 // Compute u = a^T * r + e_1 mod q
41 let u = add_vec(&mul_mat_vec_simple(&transpose(a), &r, q, f, omega), &e1, q, f);
42
43 // Compute v = t * r + e_2 - m mod q
44 let v = polysub(&polyadd(&mul_vec_simple(t, &r, q, &f, omega), &e2, q, f), &m, q, f);
45
46 (u, v)
47}
48
49/// function to encrypt a message given a public_key string
50/// # Arguments
51/// * `pk_string` - public key string in base64 encoding
52/// * `message_string` - message string in base64 encoding
53/// * `params` - Parameters for the ring-LWE cryptosystem
54/// * `seed` - random seed
55/// # Returns
56/// * `ciphertext_str` - ciphertext string in base64 encoding
57/// # Example
58/// ```
59/// let params = module_lwe::utils::Parameters::default();
60/// let keypair = module_lwe::keygen::keygen_string(¶ms,None);
61/// let pk_string = keypair.get("public").unwrap();
62/// let sk_string = keypair.get("secret").unwrap();
63/// let message_string = "Hello, world!".to_string();
64/// let ciphertext_string = module_lwe::encrypt::encrypt_string(&pk_string, &message_string, ¶ms, None);
65/// ```
66pub fn encrypt_string(pk_string: &String, message_string: &String, params: &Parameters, seed: Option<u64>) -> String {
67 // Get parameters
68 let (n, k) = (params.n, params.k);
69
70 // Decode and deserialize the base64-encoded public key string
71 let pk_list: Vec<i64> = decompress(pk_string);
72
73 // Parse the public key
74 let a: Vec<Vec<Polynomial<i64>>> = pk_list[..k * k * n]
75 .chunks(k * n)
76 .map(|chunk| {
77 chunk.chunks(n).map(|coeffs| Polynomial::new(coeffs.to_vec())).collect()
78 })
79 .collect();
80
81 let t: Vec<Polynomial<i64>> = pk_list[k * k * n..]
82 .chunks(n)
83 .map(|coeffs| Polynomial::new(coeffs.to_vec()))
84 .collect();
85
86 // Parse message
87 let message_binary: Vec<i64> = message_string
88 .bytes()
89 .flat_map(|byte| (0..8).rev().map(move |i| ((byte >> i) & 1) as i64))
90 .collect();
91
92 // Break message into blocks
93 let message_blocks: Vec<Vec<i64>> = message_binary
94 .chunks(n) // Divide the binary message into chunks of size `n`
95 .map(|chunk| chunk.to_vec()) // Convert each chunk into a vector
96 .collect();
97
98 // Encrypt each block
99 let mut ciphertext_list = vec![];
100 for block in message_blocks {
101 let (u, v) = encrypt(&a, &t, &block, params, seed);
102 let u_flattened: Vec<i64> = u.iter()
103 .flat_map(|poly| {
104 let mut coeffs = poly.coeffs().to_vec();
105 coeffs.resize(n, 0); // Resize to include leading zeros up to size `n`
106 coeffs
107 })
108 .collect();
109 let mut v_flattened: Vec<i64> = v.coeffs().to_vec();
110 v_flattened.resize(n, 0);
111 ciphertext_list.extend(u_flattened);
112 ciphertext_list.extend(v_flattened);
113 }
114
115 // Serialize and Base64 encode the ciphertext coefficient list
116 compress(&ciphertext_list)
117}