rust_sike/kem/
mod.rs

1//! Key encapsulation mechanism
2//!
3//! # Examples
4//! ```rust
5//! use rust_sike::{self, KEM};
6//! let params = rust_sike::sike_p434_params(None, None);
7//!
8//! let kem = KEM::setup(params);
9//!
10//! // Alice runs keygen, publishes pk3. Values s and sk3 are secret
11//! let (s, sk3, pk3) = kem.keygen();
12//!
13//! // Bob uses pk3 to derive a key k and encapsulation c
14//! let (c, k) = kem.encaps(&pk3);
15//!
16//! // Bob sends c to Alice
17//! // Alice uses s, c, sk3 and pk3 to recover k
18//! let k_recovered = kem.decaps(&s, &sk3, &pk3, c);
19//!
20//! assert_eq!(k, k_recovered);
21//! ```
22
23use crate::{
24    ff::FiniteField,
25    isogeny::{PublicKey, PublicParameters, SecretKey},
26    pke::{Ciphertext, Message, PKE},
27    utils::{conversion, shake},
28};
29
30use std::fmt::Debug;
31
32/// Key-encapsulation mechanism (ref Algorithm 2, Section 1.3.10)
33pub struct KEM<K> {
34    params: PublicParameters<K>,
35    pke: PKE<K>,
36    n: usize,
37}
38
39impl<K: FiniteField + Clone + Debug> KEM<K> {
40    /// Initialise the KEM
41    #[inline]
42    pub fn setup(params: PublicParameters<K>) -> Self {
43        Self {
44            pke: PKE::setup(params.clone()),
45            n: params.secparam,
46            params,
47        }
48    }
49
50    /// Generate a secret and a keypair
51    #[inline]
52    pub fn keygen(&self) -> Result<(Vec<u8>, SecretKey, PublicKey<K>), String> {
53        let sk3 = SecretKey::get_random_secret_key(self.params.keyspace3 as usize)?;
54        let pk3 = self.pke.isogenies.isogen3(&sk3)?;
55        let s = Self::random_string(self.n);
56
57        Ok((s, sk3, pk3))
58    }
59
60    /// Encapsulate the shared secret using the PKE encryption
61    #[inline]
62    pub fn encaps(&self, pk: &PublicKey<K>) -> Result<(Ciphertext, Vec<u8>), String> {
63        let message = Message::from_bytes(Self::random_string(self.n / 8));
64        let r = self.hash_function_g(&message.clone(), &pk);
65        let det_sk = SecretKey::from_bytes(&r);
66
67        let c0: PublicKey<K> = self.pke.isogenies.isogen2(&det_sk)?;
68
69        let j_inv = self.pke.isogenies.isoex2(&det_sk, &pk)?;
70        let h = self.pke.hash_function_f(j_inv);
71
72        if h.len() != message.bytes.len() {
73            return Err(String::from("Incorrect Hash"));
74        }
75
76        let c1_bytes = PKE::<K>::xor(&message.bytes, &h);
77
78        let (part1, part2, part3) = c0.into_bytes();
79        let cipher = Ciphertext {
80            bytes00: part1,
81            bytes01: part2,
82            bytes02: part3,
83            bytes1: c1_bytes,
84        };
85
86        let k = self.hash_function_h(&message, &cipher);
87        Ok((cipher, k))
88    }
89
90    /// Decapsulate the shared secret using the PKE decryption
91    #[inline]
92    pub fn decaps(
93        &self,
94        s: &[u8],
95        sk: &SecretKey,
96        pk: &PublicKey<K>,
97        c: Ciphertext,
98    ) -> Result<Vec<u8>, String> {
99        let m = self.pke.dec(&sk, c.clone())?;
100        let s = Message::from_bytes(s.to_vec());
101        let r = self.hash_function_g(&m.clone(), &pk);
102
103        let c0 = PublicKey::from_bytes(&c.bytes00, &c.bytes01, &c.bytes02)?;
104        let rsk = SecretKey::from_bytes(&r);
105
106        let c0p = self.pke.isogenies.isogen2(&rsk)?;
107
108        if c0p == c0 {
109            Ok(self.hash_function_h(&m, &c))
110        } else {
111            Ok(self.hash_function_h(&s, &c))
112        }
113    }
114
115    fn random_string(size: usize) -> Vec<u8> {
116        let mut result = vec![0; size];
117        getrandom::getrandom(&mut result).unwrap();
118        result
119    }
120
121    fn hash_function_g(&self, m: &Message, pk: &PublicKey<K>) -> Vec<u8> {
122        let (part1, part2, part3) = pk.clone().into_bytes();
123        let msg_bytes = m.clone().into_bytes();
124        let input = conversion::concatenate(&[&msg_bytes, &part1, &part2, &part3]);
125
126        let n: usize = self.params.secparam;
127
128        shake::shake256(&input, n / 8)
129    }
130
131    fn hash_function_h(&self, m: &Message, c: &Ciphertext) -> Vec<u8> {
132        let input = conversion::concatenate(&[
133            &m.clone().into_bytes(),
134            &c.bytes00,
135            &c.bytes01,
136            &c.bytes02,
137            &c.bytes1,
138        ]);
139
140        let n = self.params.secparam;
141
142        shake::shake256(&input, n / 8)
143    }
144}
145
146#[cfg(test)]
147mod tests {
148    use super::*;
149    use crate::{
150        isogeny::{sike_p434_params, sike_p503_params, sike_p610_params, sike_p751_params},
151        utils::strategy::*,
152    };
153
154    #[test]
155    fn test_kem_p434() {
156        let params = sike_p434_params(None, None).unwrap();
157
158        let kem = KEM::setup(params);
159
160        // Alice runs keygen, publishes pk3. Values s and sk3 are secret
161        let (s, sk3, pk3) = kem.keygen().unwrap();
162
163        // Bob uses pk3 to derive a key k and encapsulation c
164        let (c, k) = kem.encaps(&pk3).unwrap();
165
166        // Bob sends c to Alice
167        // Alice uses s, c, sk3 and pk3 to recover k
168        let k_recovered = kem.decaps(&s, &sk3, &pk3, c).unwrap();
169
170        assert_eq!(k, k_recovered);
171    }
172
173    #[test]
174    fn test_kem_p503() {
175        let params = sike_p503_params(None, None).unwrap();
176
177        let kem = KEM::setup(params);
178
179        // Alice runs keygen, publishes pk3. Values s and sk3 are secret
180        let (s, sk3, pk3) = kem.keygen().unwrap();
181
182        // Bob uses pk3 to derive a key k and encapsulation c
183        let (c, k) = kem.encaps(&pk3).unwrap();
184
185        // Bob sends c to Alice
186        // Alice uses s, c, sk3 and pk3 to recover k
187        let k_recovered = kem.decaps(&s, &sk3, &pk3, c).unwrap();
188
189        assert_eq!(k, k_recovered);
190    }
191
192    #[test]
193    fn test_kem_p610() {
194        let params = sike_p610_params(None, None).unwrap();
195
196        let kem = KEM::setup(params);
197
198        // Alice runs keygen, publishes pk3. Values s and sk3 are secret
199        let (s, sk3, pk3) = kem.keygen().unwrap();
200
201        // Bob uses pk3 to derive a key k and encapsulation c
202        let (c, k) = kem.encaps(&pk3).unwrap();
203
204        // Bob sends c to Alice
205        // Alice uses s, c, sk3 and pk3 to recover k
206        let k_recovered = kem.decaps(&s, &sk3, &pk3, c).unwrap();
207
208        assert_eq!(k, k_recovered);
209    }
210
211    #[test]
212    fn test_kem_p751() {
213        let params = sike_p751_params(None, None).unwrap();
214
215        let kem = KEM::setup(params);
216
217        // Alice runs keygen, publishes pk3. Values s and sk3 are secret
218        let (s, sk3, pk3) = kem.keygen().unwrap();
219
220        // Bob uses pk3 to derive a key k and encapsulation c
221        let (c, k) = kem.encaps(&pk3).unwrap();
222
223        // Bob sends c to Alice
224        // Alice uses s, c, sk3 and pk3 to recover k
225        let k_recovered = kem.decaps(&s, &sk3, &pk3, c).unwrap();
226
227        assert_eq!(k, k_recovered);
228    }
229
230    #[test]
231    fn test_kem_optim_p434() {
232        let params = sike_p434_params(
233            Some(P434_TWO_TORSION_STRATEGY.to_vec()),
234            Some(P434_THREE_TORSION_STRATEGY.to_vec()),
235        )
236        .unwrap();
237
238        let kem = KEM::setup(params);
239
240        // Alice runs keygen, publishes pk3. Values s and sk3 are secret
241        let (s, sk3, pk3) = kem.keygen().unwrap();
242
243        // Bob uses pk3 to derive a key k and encapsulation c
244        let (c, k) = kem.encaps(&pk3).unwrap();
245
246        // Bob sends c to Alice
247        // Alice uses s, c, sk3 and pk3 to recover k
248        let k_recovered = kem.decaps(&s, &sk3, &pk3, c).unwrap();
249
250        assert_eq!(k, k_recovered);
251    }
252
253    #[test]
254    fn test_kem_optim_p503() {
255        let params = sike_p503_params(
256            Some(P503_TWO_TORSION_STRATEGY.to_vec()),
257            Some(P503_THREE_TORSION_STRATEGY.to_vec()),
258        )
259        .unwrap();
260
261        let kem = KEM::setup(params);
262
263        // Alice runs keygen, publishes pk3. Values s and sk3 are secret
264        let (s, sk3, pk3) = kem.keygen().unwrap();
265
266        // Bob uses pk3 to derive a key k and encapsulation c
267        let (c, k) = kem.encaps(&pk3).unwrap();
268
269        // Bob sends c to Alice
270        // Alice uses s, c, sk3 and pk3 to recover k
271        let k_recovered = kem.decaps(&s, &sk3, &pk3, c).unwrap();
272
273        assert_eq!(k, k_recovered);
274    }
275
276    #[test]
277    fn test_kem_optim_p610() {
278        let params = sike_p610_params(
279            Some(P610_TWO_TORSION_STRATEGY.to_vec()),
280            Some(P610_THREE_TORSION_STRATEGY.to_vec()),
281        )
282        .unwrap();
283
284        let kem = KEM::setup(params);
285
286        // Alice runs keygen, publishes pk3. Values s and sk3 are secret
287        let (s, sk3, pk3) = kem.keygen().unwrap();
288
289        // Bob uses pk3 to derive a key k and encapsulation c
290        let (c, k) = kem.encaps(&pk3).unwrap();
291
292        // Bob sends c to Alice
293        // Alice uses s, c, sk3 and pk3 to recover k
294        let k_recovered = kem.decaps(&s, &sk3, &pk3, c).unwrap();
295
296        assert_eq!(k, k_recovered);
297    }
298
299    #[test]
300    fn test_kem_optim_p751() {
301        let params = sike_p751_params(
302            Some(P751_TWO_TORSION_STRATEGY.to_vec()),
303            Some(P751_THREE_TORSION_STRATEGY.to_vec()),
304        )
305        .unwrap();
306
307        let kem = KEM::setup(params);
308
309        // Alice runs keygen, publishes pk3. Values s and sk3 are secret
310        let (s, sk3, pk3) = kem.keygen().unwrap();
311
312        // Bob uses pk3 to derive a key k and encapsulation c
313        let (c, k) = kem.encaps(&pk3).unwrap();
314
315        // Bob sends c to Alice
316        // Alice uses s, c, sk3 and pk3 to recover k
317        let k_recovered = kem.decaps(&s, &sk3, &pk3, c).unwrap();
318
319        assert_eq!(k, k_recovered);
320    }
321}