rust_sike/pke/
mod.rs

1//! Public-key cryptosystem:
2//!
3//! A `Message` is encrypted using the public key, and decrypted using the corresponding private key.
4//!
5//! # Examples
6//! ```rust
7//! use rust_sike::{self, pke::{PKE, Message}};
8//! let params = rust_sike::sike_p434_params(
9//!     Some(rust_sike::P434_TWO_TORSION_STRATEGY.to_vec()),
10//!     Some(rust_sike::P434_THREE_TORSION_STRATEGY.to_vec()),
11//! );
12//!
13//! let pke = PKE::setup(params.clone());
14//!
15//! // Alice generates a keypair, she publishes her pk
16//! let (sk, pk) = pke.gen();
17//!
18//! // Bob writes a message
19//! let msg = Message::from_bytes(vec![0; params.secparam / 8]);
20//! // Bob encrypts the message using Alice's pk
21//! let ciphertext = pke.enc(&pk, msg.clone());
22//!
23//! // Bob sends the ciphertext to Alice
24//! // Alice decrypts the message using her sk
25//! let msg_recovered = pke.dec(&sk, ciphertext);
26//!
27//! // Alice should correctly recover Bob's plaintext message
28//! assert_eq!(msg_recovered.to_bytes(), msg.to_bytes());
29//! ```
30
31use crate::{
32    ff::FiniteField,
33    isogeny::{CurveIsogenies, PublicParameters},
34    utils::shake,
35};
36
37pub use crate::isogeny::{PublicKey, SecretKey};
38
39use std::fmt::Debug;
40
41/// `Message`
42#[derive(Clone)]
43pub struct Message {
44    /// Contents of the message
45    pub bytes: Vec<u8>,
46}
47
48impl Message {
49    /// Build a `Message` from a sequence of bytes
50    pub fn from_bytes(bytes: Vec<u8>) -> Self {
51        Self { bytes }
52    }
53
54    /// Obtain bytes from a `Message`
55    pub fn into_bytes(self) -> Vec<u8> {
56        self.bytes
57    }
58}
59
60/// `Ciphertext`
61///
62/// We decompose the ciphertext in subarrays for convenience
63#[derive(Clone)]
64pub struct Ciphertext {
65    /// Ciphertext, part 0, subpart 0
66    pub bytes00: Vec<u8>,
67
68    /// Ciphertext, part 0, subpart 1
69    pub bytes01: Vec<u8>,
70
71    /// Ciphertext, part 0, subpart 2
72    pub bytes02: Vec<u8>,
73
74    /// Ciphertext, part 1
75    pub bytes1: Vec<u8>,
76}
77
78/// Public-key cryptosystem (ref Algorithm 1, Section 1.3.9)
79pub struct PKE<K> {
80    /// Instance of the SIKE problem for this PKE
81    pub isogenies: CurveIsogenies<K>,
82    params: PublicParameters<K>,
83}
84
85impl<K: FiniteField + Clone + Debug> PKE<K> {
86    /// Initialise cryptosystem with parameters `params`
87    #[inline]
88    pub fn setup(params: PublicParameters<K>) -> Self {
89        Self {
90            isogenies: CurveIsogenies::init(params.clone()),
91            params,
92        }
93    }
94
95    /// Generate a keypair
96    #[inline]
97    pub fn gen(&self) -> Result<(SecretKey, PublicKey<K>), String> {
98        // 1.
99        let sk3 = SecretKey::get_random_secret_key(self.params.keyspace3 as usize)?;
100
101        // 2.
102        let pk3 = self.isogenies.isogen3(&sk3)?;
103
104        // 3.
105        Ok((sk3, pk3))
106    }
107
108    /// Encrypt a message
109    #[inline]
110    pub fn enc(&self, pk: &PublicKey<K>, m: Message) -> Result<Ciphertext, String> {
111        // 4.
112        let sk2 = SecretKey::get_random_secret_key(self.params.keyspace2 as usize)?;
113
114        // 5.
115        let c0: PublicKey<K> = self.isogenies.isogen2(&sk2)?;
116
117        // 6.
118        let j = self.isogenies.isoex2(&sk2, &pk)?;
119
120        // 7.
121        let h = self.hash_function_f(j);
122
123        // 8.
124        if h.len() != m.bytes.len() {
125            return Err(String::from("Incorrect Hash"));
126        }
127
128        let c1_bytes = Self::xor(&m.bytes, &h);
129
130        // 9.
131        let (part1, part2, part3) = c0.into_bytes();
132        Ok(Ciphertext {
133            bytes00: part1,
134            bytes01: part2,
135            bytes02: part3,
136            bytes1: c1_bytes,
137        })
138    }
139
140    /// Decrypts a message
141    #[inline]
142    pub fn dec(&self, sk: &SecretKey, c: Ciphertext) -> Result<Message, String> {
143        // 10.
144        let c0 = &PublicKey::from_bytes(&c.bytes00, &c.bytes01, &c.bytes02)?;
145
146        let j: K = self.isogenies.isoex3(sk, c0)?;
147
148        // 11.
149        let h = self.hash_function_f(j);
150
151        // 12.
152        if h.len() != c.bytes1.len() {
153            return Err(String::from("Incorrect Hash"));
154        }
155
156        let m = Self::xor(&h, &c.bytes1);
157
158        // 13.
159        Ok(Message { bytes: m })
160    }
161
162    /// Computes the F function
163    pub fn hash_function_f(&self, j: K) -> Vec<u8> {
164        shake::shake256(&j.into_bytes(), self.params.secparam / 8)
165    }
166
167    /// Computes the bitwise XOR between two sequences
168    pub fn xor(input1: &[u8], input2: &[u8]) -> Vec<u8> {
169        input1
170            .iter()
171            .zip(input2.iter())
172            .map(|(x, y)| x ^ y)
173            .collect()
174    }
175}
176
177#[cfg(test)]
178mod tests {
179    use super::*;
180    use crate::{
181        isogeny::{sike_p434_params, sike_p503_params, sike_p610_params, sike_p751_params},
182        utils::strategy::*,
183    };
184
185    #[test]
186    fn test_pke_optim_p434() {
187        let params = sike_p434_params(
188            Some(P434_TWO_TORSION_STRATEGY.to_vec()),
189            Some(P434_THREE_TORSION_STRATEGY.to_vec()),
190        )
191        .unwrap();
192
193        let pke = PKE::setup(params.clone());
194
195        // Alice generates a keypair, she published her pk
196        println!("[Debug] Key generation");
197        let (sk, pk) = pke.gen().unwrap();
198
199        // Bob writes a message
200        let msg = Message::from_bytes(vec![0; params.secparam / 8]);
201        // Bob encrypts the message using Alice's pk
202        println!("[Debug] Encryption");
203        let ciphertext = pke.enc(&pk, msg.clone()).unwrap();
204
205        // Bob sends the ciphertext to Alice
206        // Alice decrypts the message using her sk
207        println!("[Debug] Decryption");
208        let msg_recovered = pke.dec(&sk, ciphertext).unwrap();
209
210        // Alice should correctly recover Bob's plaintext message
211        assert_eq!(msg_recovered.into_bytes(), msg.into_bytes());
212    }
213
214    #[test]
215    fn test_pke_optim_p503() {
216        let params = sike_p503_params(
217            Some(P503_TWO_TORSION_STRATEGY.to_vec()),
218            Some(P503_THREE_TORSION_STRATEGY.to_vec()),
219        )
220        .unwrap();
221
222        let pke = PKE::setup(params.clone());
223
224        // Alice generates a keypair, she published her pk
225        println!("[Debug] Key generation");
226        let (sk, pk) = pke.gen().unwrap();
227
228        // Bob writes a message
229        let msg = Message::from_bytes(vec![0; params.secparam / 8]);
230        // Bob encrypts the message using Alice's pk
231        println!("[Debug] Encryption");
232        let ciphertext = pke.enc(&pk, msg.clone()).unwrap();
233
234        // Bob sends the ciphertext to Alice
235        // Alice decrypts the message using her sk
236        println!("[Debug] Decryption");
237        let msg_recovered = pke.dec(&sk, ciphertext).unwrap();
238
239        // Alice should correctly recover Bob's plaintext message
240        assert_eq!(msg_recovered.into_bytes(), msg.into_bytes());
241    }
242
243    #[test]
244    fn test_pke_optim_p610() {
245        let params = sike_p610_params(
246            Some(P610_TWO_TORSION_STRATEGY.to_vec()),
247            Some(P610_THREE_TORSION_STRATEGY.to_vec()),
248        )
249        .unwrap();
250
251        let pke = PKE::setup(params.clone());
252
253        // Alice generates a keypair, she published her pk
254        println!("[Debug] Key generation");
255        let (sk, pk) = pke.gen().unwrap();
256
257        // Bob writes a message
258        let msg = Message::from_bytes(vec![0; params.secparam / 8]);
259        // Bob encrypts the message using Alice's pk
260        println!("[Debug] Encryption");
261        let ciphertext = pke.enc(&pk, msg.clone()).unwrap();
262
263        // Bob sends the ciphertext to Alice
264        // Alice decrypts the message using her sk
265        println!("[Debug] Decryption");
266        let msg_recovered = pke.dec(&sk, ciphertext).unwrap();
267
268        // Alice should correctly recover Bob's plaintext message
269        assert_eq!(msg_recovered.into_bytes(), msg.into_bytes());
270    }
271
272    #[test]
273    fn test_pke_optim_p751() {
274        let params = sike_p751_params(
275            Some(P751_TWO_TORSION_STRATEGY.to_vec()),
276            Some(P751_THREE_TORSION_STRATEGY.to_vec()),
277        )
278        .unwrap();
279
280        let pke = PKE::setup(params.clone());
281
282        // Alice generates a keypair, she published her pk
283        println!("[Debug] Key generation");
284        let (sk, pk) = pke.gen().unwrap();
285
286        // Bob writes a message
287        let msg = Message::from_bytes(vec![0; params.secparam / 8]);
288        // Bob encrypts the message using Alice's pk
289        println!("[Debug] Encryption");
290        let ciphertext = pke.enc(&pk, msg.clone()).unwrap();
291
292        // Bob sends the ciphertext to Alice
293        // Alice decrypts the message using her sk
294        println!("[Debug] Decryption");
295        let msg_recovered = pke.dec(&sk, ciphertext).unwrap();
296
297        // Alice should correctly recover Bob's plaintext message
298        assert_eq!(msg_recovered.into_bytes(), msg.into_bytes());
299    }
300
301    #[test]
302    fn test_pke_p434() {
303        let params = sike_p434_params(None, None).unwrap();
304
305        let pke = PKE::setup(params.clone());
306
307        // Alice generates a keypair, she published her pk
308        println!("[Debug] Key generation");
309        let (sk, pk) = pke.gen().unwrap();
310
311        // Bob writes a message
312        let msg = Message::from_bytes(vec![0; params.secparam / 8]);
313        // Bob encrypts the message using Alice's pk
314        println!("[Debug] Encryption");
315        let ciphertext = pke.enc(&pk, msg.clone()).unwrap();
316
317        // Bob sends the ciphertext to Alice
318        // Alice decrypts the message using her sk
319        println!("[Debug] Decryption");
320        let msg_recovered = pke.dec(&sk, ciphertext).unwrap();
321
322        // Alice should correctly recover Bob's plaintext message
323        assert_eq!(msg_recovered.into_bytes(), msg.into_bytes());
324    }
325
326    #[test]
327    fn test_pke_p503() {
328        let params = sike_p503_params(None, None).unwrap();
329
330        let pke = PKE::setup(params.clone());
331
332        // Alice generates a keypair, she published her pk
333        println!("[Debug] Key generation");
334        let (sk, pk) = pke.gen().unwrap();
335
336        // Bob writes a message
337        let msg = Message::from_bytes(vec![0; params.secparam / 8]);
338        // Bob encrypts the message using Alice's pk
339        println!("[Debug] Encryption");
340        let ciphertext = pke.enc(&pk, msg.clone()).unwrap();
341
342        // Bob sends the ciphertext to Alice
343        // Alice decrypts the message using her sk
344        println!("[Debug] Decryption");
345        let msg_recovered = pke.dec(&sk, ciphertext).unwrap();
346
347        // Alice should correctly recover Bob's plaintext message
348        assert_eq!(msg_recovered.into_bytes(), msg.into_bytes());
349    }
350
351    #[test]
352    fn test_pke_p610() {
353        let params = sike_p610_params(None, None).unwrap();
354
355        let pke = PKE::setup(params.clone());
356
357        // Alice generates a keypair, she published her pk
358        println!("[Debug] Key generation");
359        let (sk, pk) = pke.gen().unwrap();
360
361        // Bob writes a message
362        let msg = Message::from_bytes(vec![0; params.secparam / 8]);
363        // Bob encrypts the message using Alice's pk
364        println!("[Debug] Encryption");
365        let ciphertext = pke.enc(&pk, msg.clone()).unwrap();
366
367        // Bob sends the ciphertext to Alice
368        // Alice decrypts the message using her sk
369        println!("[Debug] Decryption");
370        let msg_recovered = pke.dec(&sk, ciphertext).unwrap();
371
372        // Alice should correctly recover Bob's plaintext message
373        assert_eq!(msg_recovered.into_bytes(), msg.into_bytes());
374    }
375
376    #[test]
377    fn test_pke_p751() {
378        let params = sike_p751_params(None, None).unwrap();
379
380        let pke = PKE::setup(params.clone());
381
382        // Alice generates a keypair, she published her pk
383        println!("[Debug] Key generation");
384        let (sk, pk) = pke.gen().unwrap();
385
386        // Bob writes a message
387        let msg = Message::from_bytes(vec![0; params.secparam / 8]);
388        // Bob encrypts the message using Alice's pk
389        println!("[Debug] Encryption");
390        let ciphertext = pke.enc(&pk, msg.clone()).unwrap();
391
392        // Bob sends the ciphertext to Alice
393        // Alice decrypts the message using her sk
394        println!("[Debug] Decryption");
395        let msg_recovered = pke.dec(&sk, ciphertext).unwrap();
396
397        // Alice should correctly recover Bob's plaintext message
398        assert_eq!(msg_recovered.into_bytes(), msg.into_bytes());
399    }
400}