Skip to content

Commit 1144629

Browse files
feat(kyberlib): ✨ new macros, fixes and document updates
1 parent 122cf72 commit 1144629

File tree

8 files changed

+334
-66
lines changed

8 files changed

+334
-66
lines changed

README.md

Lines changed: 20 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,6 @@ KyberLib is a robust Rust library designed for CRYSTALS-Kyber Post-Quantum Crypt
6666

6767
See [Documentation][08] for full API details.
6868

69-
![Divider][01]
70-
7169
## Getting Started 🚀
7270

7371
It takes just a few minutes to get up and running with `kyberlib`.
@@ -90,8 +88,6 @@ using the following command:
9088
cargo install kyberlib
9189
```
9290

93-
![Divider][01]
94-
9591
## Usage 📖
9692

9793
To use the `kyberlib` library in your project, add the following to your
@@ -181,6 +177,25 @@ alice.client_confirm(server_response, &alice_keys.secret)?;
181177
assert_eq!(alice.shared_secret, bob.shared_secret);
182178
```
183179

180+
## Macros
181+
182+
The KyberLib crate provides several macros to simplify common cryptographic operations:
183+
184+
- `kyberlib_assert!`: Asserts that a given expression is true. Panics if the assertion fails.
185+
- `kyberlib_min!`: Returns the minimum of the given values.
186+
- `kyberlib_max!`: Returns the maximum of the given values.
187+
- `kyberlib_generate_key_pair!`: Generates a public and private key pair for CCA-secure Kyber key encapsulation mechanism.
188+
- `kyberlib_encrypt_message!`: Generates cipher text and a shared secret for a given public key.
189+
- `kyberlib_decrypt_message!`: Generates a shared secret for a given cipher text and private key.
190+
- `kyberlib_uake_client_init!`: Initiates a Unilaterally Authenticated Key Exchange.
191+
- `kyberlib_uake_server_receive!`: Handles the output of a `kyberlib_uake_client_init()` request.
192+
- `kyberlib_uake_client_confirm!`: Decapsulates and authenticates the shared secret from the output of `kyberlib_uake_server_receive()`.
193+
- `kyberlib_ake_client_init!`: Initiates a Mutually Authenticated Key Exchange.
194+
- `kyberlib_ake_server_receive!`: Handles and authenticates the output of a `kyberlib_ake_client_init()` request.
195+
- `kyberlib_ake_client_confirm!`: Decapsulates and authenticates the shared secret from the output of `kyberlib_ake_server_receive()`.
196+
197+
See the [macros module documentation](https://docs.rs/kyberlib/latest/kyberlib/macros/index.html) for more details and usage examples.
198+
184199
## Errors
185200

186201
The KyberLibError enum has two variants:
@@ -189,8 +204,6 @@ The KyberLibError enum has two variants:
189204
- **Decapsulation** - The ciphertext was unable to be authenticated. The shared secret was not decapsulated.
190205
- **RandomBytesGeneration** - Error trying to fill random bytes (i.e external (hardware) RNG modules can fail).
191206

192-
![Divider][01]
193-
194207
## Examples
195208

196209
To get started with `kyberlib`, you can use the examples provided in the
@@ -229,47 +242,9 @@ Run the following command in your terminal from the project root directory.
229242
cargo run --example uake
230243
```
231244

232-
![Divider][01]
233-
234245
### Platform support
235246

236-
`kyberlib` is supported and tested on the following platforms:
237-
238-
### Tier 1 platforms 🏆
239-
240-
| | Operating System | Target | Description |
241-
| --- | --- | --- | --- |
242-
|| Linux | aarch64-unknown-linux-gnu | 64-bit Linux systems on ARM architecture |
243-
|| Windows | i686-pc-windows-gnu | 32-bit Windows systems using the GNU toolchain |
244-
|| Windows | i686-pc-windows-msvc | 32-bit Windows systems using the Microsoft Visual C toolchain |
245-
|| Linux | i686-unknown-linux-gnu | 32-bit Linux systems (kernel 3.2+, glibc 2.17+) |
246-
|| macOS | x86_64-apple-darwin | 64-bit macOS systems (10.7 Lion or later) |
247-
|| Windows | x86_64-pc-windows-gnu | 64-bit Windows systems using the GNU toolchain |
248-
|| Windows | x86_64-pc-windows-msvc | 64-bit Windows systems using the Microsoft Visual C toolchain |
249-
|| Linux | x86_64-unknown-linux-gnu | 64-bit Linux systems (kernel 2.6.32+, glibc 2.11+) |
250-
251-
### Tier 2 platforms 🥈
252-
253-
| | Operating System | Target | Description |
254-
| --- | --- | --- | --- |
255-
|| Linux | aarch64-apple-darwin | 64-bit macOS on Apple Silicon |
256-
|| Windows | aarch64-pc-windows-msvc | 64-bit Windows on ARM architecture using the Microsoft Visual C toolchain |
257-
|| Linux | aarch64-unknown-linux-musl | 64-bit Linux on ARM architecture with musl libc |
258-
|| Linux | arm-unknown-linux-gnueabi | ARMv6 Linux systems (kernel 3.2, glibc 2.17) |
259-
|| Linux | arm-unknown-linux-gnueabihf | ARMv7 Linux systems, hardfloat (kernel 3.2, glibc 2.17) |
260-
|| Linux | armv7-unknown-linux-gnueabihf | ARMv7 Linux systems, hardfloat (kernel 3.2, glibc 2.17) |
261-
|| Linux | powerpc-unknown-linux-gnu | PowerPC Linux systems (kernel 3.2, glibc 2.17) |
262-
|| Linux | powerpc64-unknown-linux-gnu | PowerPC64 Linux systems (kernel 3.2, glibc 2.17) |
263-
|| Linux | powerpc64le-unknown-linux-gnu | PowerPC64le Linux systems (kernel 3.2, glibc 2.17) |
264-
|| Linux | riscv64gc-unknown-linux-gnu | RISC-V Linux systems (kernel 3.2, glibc 2.17) |
265-
|| Linux | s390x-unknown-linux-gnu | s390x Linux systems (kernel 3.2, glibc 2.17) |
266-
|| Linux | x86_64-unknown-freebsd | 64-bit FreeBSD systems on x86-64 architecture |
267-
|| Linux | x86_64-unknown-linux-musl | 64-bit Linux systems (kernel 2.6.32+, musl libc) |
268-
269-
The [GitHub Actions][10] shows the platforms in which the `kyberlib`
270-
library tests are run.
271-
272-
![Divider][01]
247+
`kyberlib` is supported and tested on MacOS, Linux, and Windows. The [GitHub Actions][10] shows the platforms in which the `kyberlib` library tests are run.
273248

274249
### Documentation
275250

@@ -281,15 +256,11 @@ library tests are run.
281256
For transparency into our release cycle and in striving to maintain
282257
backward compatibility, `kyberlib` follows [semantic versioning][06].
283258

284-
![Divider][01]
285-
286259
## License 📝
287260

288261
The project is licensed under the terms of Apache License, Version 2.0 and the
289262
MIT license.
290263

291-
![Divider][01]
292-
293264
## Contribution 🤝
294265

295266
We welcome all people who want to contribute. Please see the
@@ -303,8 +274,6 @@ submitted for inclusion in the work by you, as defined in the
303274
Apache-2.0 license, shall be dual licensed as above, without any
304275
additional terms or conditions.
305276

306-
![Divider][01]
307-
308277
## Acknowledgements 💙
309278

310279
A big thank you to all the awesome contributors of [kyberlib][05] for their

src/api.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,52 @@ where
3939
Ok(Keypair { public, secret })
4040
}
4141

42+
/// Verify that given secret and public key matches and put them in
43+
/// the KeyPair structure after zeroize them if asked.
44+
/// ### Example
45+
/// ```
46+
/// # use kyberlib::*;
47+
/// # fn main() -> Result<(), KyberLibError> {
48+
/// let mut rng = rand::thread_rng();
49+
/// let keys = keypair(&mut rng)?;
50+
/// let mut public = keys.public;
51+
/// let mut secret = keys.secret;
52+
/// let _ = keypairfrom(&mut public, &mut secret, &mut rng)?;
53+
/// # Ok(())}
54+
/// ```
55+
pub fn keypairfrom<R>(
56+
public: &mut [u8; KYBER_PUBLIC_KEY_BYTES],
57+
secret: &mut [u8; KYBER_SECRET_KEY_BYTES],
58+
rng: &mut R,
59+
) -> Result<Keypair, KyberLibError>
60+
where
61+
R: RngCore + CryptoRng,
62+
{
63+
//Try to encapsulate and decapsule to verify secret key matches public key
64+
let (ciphertext, shared_secret) = encapsulate(public, rng)?;
65+
let expected_shared_secret = decapsulate(&ciphertext, secret)?;
66+
//If it does match, return a KeyPair
67+
if expected_shared_secret == shared_secret {
68+
let public2 = *public;
69+
let secret2 = *secret;
70+
let key = Keypair {
71+
public: public2,
72+
secret: secret2,
73+
};
74+
#[cfg(feature = "zeroize")]
75+
{
76+
public.zeroize();
77+
secret.zeroize();
78+
public2.zeroize();
79+
secret2.zeroize();
80+
}
81+
Ok(key)
82+
} else {
83+
//Else return an error
84+
Err(KyberLibError::InvalidKey)
85+
}
86+
}
87+
4288
/// Encapsulates a public key and returns the ciphertext to send and the shared secret.
4389
///
4490
/// This function encapsulates a public key and returns the ciphertext and the shared secret.

src/error.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ pub enum KyberLibError {
88
/// two parties using different security levels while trying to negotiate a key exchange.
99
InvalidInput,
1010

11+
/// Error when generating keys
12+
InvalidKey,
13+
1114
/// The ciphertext was unable to be authenticated. The shared secret was not decapsulated.
1215
Decapsulation,
1316

@@ -26,6 +29,9 @@ impl core::fmt::Display for KyberLibError {
2629
KyberLibError::RandomBytesGeneration => {
2730
write!(f, "Random bytes generation function failed")
2831
}
32+
KyberLibError::InvalidKey => {
33+
write!(f, "The secret and public key given does not match.")
34+
}
2935
}
3036
}
3137
}

src/kex.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,13 @@ pub struct Uake {
6666
/// The resulting shared secret from a key exchange
6767
pub shared_secret: SharedSecret,
6868
/// Sent when initiating a key exchange
69-
send_a: UakeSendInit,
69+
pub send_a: UakeSendInit,
7070
/// Response to a key exchange initiation
71-
send_b: UakeSendResponse,
72-
// Ephemeral keys
73-
temp_key: TempKey,
74-
eska: Eska,
71+
pub send_b: UakeSendResponse,
72+
/// Ephemeral keys for the key exchange
73+
pub temp_key: TempKey,
74+
/// Ephemeral secret key
75+
pub eska: Eska,
7576
}
7677

7778
impl Default for Uake {
@@ -208,12 +209,13 @@ pub struct Ake {
208209
/// The resulting shared secret from a key exchange
209210
pub shared_secret: SharedSecret,
210211
/// Sent when initiating a key exchange
211-
send_a: AkeSendInit,
212+
pub send_a: AkeSendInit,
212213
/// Response to a key exchange initiation
213-
send_b: AkeSendResponse,
214-
// Ephemeral keys
215-
temp_key: TempKey,
216-
eska: Eska,
214+
pub send_b: AkeSendResponse,
215+
/// Ephemeral keys for the key exchange
216+
pub temp_key: TempKey,
217+
/// Ephemeral secret key
218+
pub eska: Eska,
217219
}
218220

219221
impl Default for Ake {

src/lib.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,25 @@
118118
//! # Ok(()) }
119119
//! ```
120120
//!
121+
//! ## Macros
122+
//!
123+
//! The KyberLib crate provides several macros to simplify common cryptographic operations:
124+
//!
125+
//! - `kyberlib_assert!`: Asserts that a given expression is true. Panics if the assertion fails.
126+
//! - `kyberlib_min!`: Returns the minimum of the given values.
127+
//! - `kyberlib_max!`: Returns the maximum of the given values.
128+
//! - `kyberlib_generate_key_pair!`: Generates a public and private key pair for CCA-secure Kyber key encapsulation mechanism.
129+
//! - `kyberlib_encrypt_message!`: Generates cipher text and a shared secret for a given public key.
130+
//! - `kyberlib_decrypt_message!`: Generates a shared secret for a given cipher text and private key.
131+
//! - `kyberlib_uake_client_init!`: Initiates a Unilaterally Authenticated Key Exchange.
132+
//! - `kyberlib_uake_server_receive!`: Handles the output of a `kyberlib_uake_client_init()` request.
133+
//! - `kyberlib_uake_client_confirm!`: Decapsulates and authenticates the shared secret from the output of `kyberlib_uake_server_receive()`.
134+
//! - `kyberlib_ake_client_init!`: Initiates a Mutually Authenticated Key Exchange.
135+
//! - `kyberlib_ake_server_receive!`: Handles and authenticates the output of a `kyberlib_ake_client_init()` request.
136+
//! - `kyberlib_ake_client_confirm!`: Decapsulates and authenticates the shared secret from the output of `kyberlib_ake_server_receive()`.
137+
//!
138+
//! See the [macros module documentation](https://docs.rs/kyberlib/latest/kyberlib/macros/index.html) for more details and usage examples.
139+
//!
121140
//! ## Errors
122141
//!
123142
//! The [KyberLibError](enum.KyberLibError.html) enum handles errors with two variants:

src/macros.rs

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,121 @@ macro_rules! kyberlib_encrypt_message {
111111
///
112112
/// On failure, `ss` will contain a pseudo-random value.
113113
#[macro_export]
114+
#[doc = "Macro to decrypt a message using the Kyber key encapsulation mechanism."]
114115
macro_rules! kyberlib_decrypt_message {
115116
($ss:expr, $ct:expr, $sk:expr) => {
116117
kyberlib::kem::decrypt_message($ss, $ct, $sk)
117118
};
118119
}
119120

121+
/// Initiates a Unilaterally Authenticated Key Exchange.
122+
///
123+
/// # Arguments
124+
///
125+
/// * `pubkey` - Input public key (an already allocated array of CRYPTO_PUBLICKEYBYTES bytes).
126+
/// * `rng` - Random number generator implementing RngCore + CryptoRng.
127+
///
128+
/// # Returns
129+
///
130+
/// The bytes to send when initiating a unilateral key exchange (UakeSendInit).
131+
#[macro_export]
132+
#[doc = "Macro to initiate a Unilaterally Authenticated Key Exchange."]
133+
macro_rules! kyberlib_uake_client_init {
134+
($pubkey:expr, $rng:expr) => {
135+
kyberlib::kex::Uake::new().client_init($pubkey, $rng)
136+
};
137+
}
138+
139+
/// Handles the output of a `kyberlib_uake_client_init()` request.
140+
///
141+
/// # Arguments
142+
///
143+
/// * `send_a` - The bytes received from the `kyberlib_uake_client_init()` request.
144+
/// * `secretkey` - The secret key (an already allocated array of CRYPTO_SECRETKEYBYTES bytes).
145+
/// * `rng` - Random number generator implementing RngCore + CryptoRng.
146+
///
147+
/// # Returns
148+
///
149+
/// The bytes to send when responding to a unilateral key exchange (UakeSendResponse).
150+
#[macro_export]
151+
#[doc = "Macro to handle the output of a Unilaterally Authenticated Key Exchange."]
152+
macro_rules! kyberlib_uake_server_receive {
153+
($send_a:expr, $secretkey:expr, $rng:expr) => {
154+
kyberlib::kex::Uake::new().server_receive($send_a, $secretkey, $rng)
155+
};
156+
}
157+
158+
/// Decapsulates and authenticates the shared secret from the output of
159+
/// `kyberlib_uake_server_receive()`.
160+
///
161+
/// # Arguments
162+
///
163+
/// * `send_b` - The bytes received from the `kyberlib_uake_server_receive()` request.
164+
///
165+
/// # Returns
166+
///
167+
/// Nothing (the shared secret is stored in the `Uake` struct).
168+
#[macro_export]
169+
#[doc = "Macro to decapsulate and authenticate the shared secret from a Unilaterally Authenticated Key Exchange."]
170+
macro_rules! kyberlib_uake_client_confirm {
171+
($send_b:expr) => {
172+
kyberlib::kex::Uake::new().client_confirm($send_b)
173+
};
174+
}
120175

176+
/// Initiates a Mutually Authenticated Key Exchange.
177+
///
178+
/// # Arguments
179+
///
180+
/// * `pubkey` - Input public key (an already allocated array of CRYPTO_PUBLICKEYBYTES bytes).
181+
/// * `rng` - Random number generator implementing RngCore + CryptoRng.
182+
///
183+
/// # Returns
184+
///
185+
/// The bytes to send when initiating a mutual key exchange (AkeSendInit).
186+
#[macro_export]
187+
#[doc = "Macro to initiate a Mutually Authenticated Key Exchange."]
188+
macro_rules! kyberlib_ake_client_init {
189+
($pubkey:expr, $rng:expr) => {
190+
kyberlib::kex::Ake::new().client_init($pubkey, $rng)
191+
};
192+
}
193+
194+
/// Handles and authenticates the output of a `kyberlib_ake_client_init()` request.
195+
///
196+
/// # Arguments
197+
///
198+
/// * `ake_send_a` - The bytes received from the `kyberlib_ake_client_init()` request.
199+
/// * `pubkey` - The public key (an already allocated array of CRYPTO_PUBLICKEYBYTES bytes).
200+
/// * `secretkey` - The secret key (an already allocated array of CRYPTO_SECRETKEYBYTES bytes).
201+
/// * `rng` - Random number generator implementing RngCore + CryptoRng.
202+
///
203+
/// # Returns
204+
///
205+
/// The bytes to send when responding to a mutual key exchange (AkeSendResponse).
206+
#[macro_export]
207+
#[doc = "Macro to handle the output of a Mutually Authenticated Key Exchange."]
208+
macro_rules! kyberlib_ake_server_receive {
209+
($ake_send_a:expr, $pubkey:expr, $secretkey:expr, $rng:expr) => {
210+
kyberlib::kex::Ake::new().server_receive($ake_send_a, $pubkey, $secretkey, $rng)
211+
};
212+
}
213+
214+
/// Decapsulates and authenticates the shared secret from the output of
215+
/// `kyberlib_ake_server_receive()`.
216+
///
217+
/// # Arguments
218+
///
219+
/// * `send_b` - The bytes received from the `kyberlib_ake_server_receive()` request.
220+
/// * `secretkey` - The secret key (an already allocated array of CRYPTO_SECRETKEYBYTES bytes).
221+
///
222+
/// # Returns
223+
///
224+
/// Nothing (the shared secret is stored in the `Ake` struct).
225+
#[macro_export]
226+
#[doc = "Macro to decapsulate and authenticate the shared secret from a Mutually Authenticated Key Exchange."]
227+
macro_rules! kyberlib_ake_client_confirm {
228+
($send_b:expr, $secretkey:expr) => {
229+
kyberlib::kex::Ake::new().client_confirm($send_b, $secretkey)
230+
};
231+
}

0 commit comments

Comments
 (0)