bc_components/encapsulation/encapsulation_scheme.rs
1use anyhow::{bail, Result};
2use bc_rand::RandomNumberGenerator;
3
4use crate::MLKEM;
5use crate::{EncapsulationPrivateKey, EncapsulationPublicKey, X25519PrivateKey};
6
7/// Supported key encapsulation mechanisms.
8///
9/// Key Encapsulation Mechanisms (KEMs) are cryptographic algorithms designed to securely
10/// establish a shared secret between parties in public-key cryptography. They are often
11/// used to encapsulate (wrap) symmetric keys for secure key exchange.
12///
13/// This enum represents the various KEM schemes supported in this crate:
14/// - X25519: A Diffie-Hellman key exchange mechanism using the Curve25519 elliptic curve
15/// - ML-KEM (Module Lattice-based Key Encapsulation Mechanism): Post-quantum secure KEM
16/// at different security levels (512, 768, 1024)
17#[derive(Debug, Copy, Clone, PartialEq, Default)]
18pub enum EncapsulationScheme {
19 /// X25519 key agreement (default)
20 #[default]
21 X25519,
22 /// ML-KEM512 post-quantum key encapsulation (NIST level 1)
23 MLKEM512,
24 /// ML-KEM768 post-quantum key encapsulation (NIST level 3)
25 MLKEM768,
26 /// ML-KEM1024 post-quantum key encapsulation (NIST level 5)
27 MLKEM1024,
28}
29
30impl EncapsulationScheme {
31 /// Generates a new random key pair for the specified encapsulation scheme.
32 ///
33 /// # Returns
34 ///
35 /// A tuple containing the private key and public key for the selected encapsulation scheme.
36 ///
37 /// # Example
38 ///
39 /// ```
40 /// use bc_components::EncapsulationScheme;
41 ///
42 /// // Generate a key pair using X25519 (default)
43 /// let (private_key, public_key) = EncapsulationScheme::default().keypair();
44 ///
45 /// // Generate a key pair using ML-KEM768
46 /// let (private_key, public_key) = EncapsulationScheme::MLKEM768.keypair();
47 /// ```
48 pub fn keypair(self) -> (EncapsulationPrivateKey, EncapsulationPublicKey) {
49 match self {
50 EncapsulationScheme::X25519 => {
51 let (private_key, public_key) = X25519PrivateKey::keypair();
52 (
53 EncapsulationPrivateKey::X25519(private_key),
54 EncapsulationPublicKey::X25519(public_key),
55 )
56 }
57 EncapsulationScheme::MLKEM512 => {
58 let (private_key, public_key) = MLKEM::MLKEM512.keypair();
59 (
60 EncapsulationPrivateKey::MLKEM(private_key),
61 EncapsulationPublicKey::MLKEM(public_key),
62 )
63 }
64 EncapsulationScheme::MLKEM768 => {
65 let (private_key, public_key) = MLKEM::MLKEM768.keypair();
66 (
67 EncapsulationPrivateKey::MLKEM(private_key),
68 EncapsulationPublicKey::MLKEM(public_key),
69 )
70 }
71 EncapsulationScheme::MLKEM1024 => {
72 let (private_key, public_key) = MLKEM::MLKEM1024.keypair();
73 (
74 EncapsulationPrivateKey::MLKEM(private_key),
75 EncapsulationPublicKey::MLKEM(public_key),
76 )
77 }
78 }
79 }
80
81 /// Generates a deterministic key pair using the provided random number generator.
82 ///
83 /// # Parameters
84 ///
85 /// * `rng` - A mutable reference to a random number generator
86 ///
87 /// # Returns
88 ///
89 /// A Result containing a tuple with the private key and public key if successful,
90 /// or an error if deterministic key generation is not supported for the selected scheme.
91 ///
92 /// # Errors
93 ///
94 /// Returns an error if deterministic key generation is not supported for the
95 /// selected encapsulation scheme (currently only X25519 supports this).
96 ///
97 /// # Example
98 ///
99 /// ```
100 /// use bc_rand::SecureRandomNumberGenerator;
101 /// use bc_components::EncapsulationScheme;
102 ///
103 /// let mut rng = SecureRandomNumberGenerator;
104 /// let result = EncapsulationScheme::X25519.keypair_using(&mut rng);
105 /// assert!(result.is_ok());
106 ///
107 /// // ML-KEM schemes don't support deterministic key generation
108 /// let result = EncapsulationScheme::MLKEM512.keypair_using(&mut rng);
109 /// assert!(result.is_err());
110 /// ```
111 pub fn keypair_using(
112 self,
113 rng: &mut impl RandomNumberGenerator,
114 ) -> Result<(EncapsulationPrivateKey, EncapsulationPublicKey)> {
115 match self {
116 EncapsulationScheme::X25519 => {
117 let (private_key, public_key) = X25519PrivateKey::keypair_using(rng);
118 Ok((
119 EncapsulationPrivateKey::X25519(private_key),
120 EncapsulationPublicKey::X25519(public_key),
121 ))
122 }
123 _ => bail!(
124 "Deterministic keypair generation not supported for this encapsulation scheme"
125 ),
126 }
127 }
128}