Skip to content

Commit b9a1c9b

Browse files
authored
Merge pull request #56 from Nichokas/new-mlkem-lib
New mlkem lib
2 parents e168be6 + 83a3015 commit b9a1c9b

File tree

10 files changed

+341
-544
lines changed

10 files changed

+341
-544
lines changed

Cargo.lock

Lines changed: 177 additions & 421 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,11 @@ chacha20poly1305 = { version = "0.10.1", features = ["std"] }
2323
hkdf = "0.12.4"
2424
serde = { version = "1.0.219", features = ["derive"] }
2525
sha2 = "0.10.9"
26-
kyberlib = "0.0.6"
2726
zerocopy = "0.8.25"
2827
bincode = { version = "2.0.1", features = ["serde"] }
2928
serde_bytes = "0.11.17"
30-
rand_chacha = "0.3.1"
31-
rand = "0.8.5"
29+
rand_chacha = "0.9.0"
30+
libcrux-ml-kem = "0.0.2"
3231

3332

3433
[dev-dependencies]

benches/chacha_bench.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
// benches/chacha_bench.rs
1+
use chacha20poly1305::aead::rand_core::OsRng as ChaChaOsRng;
22
use chacha20poly1305::aead::Aead;
33
use chacha20poly1305::{aead::AeadCore, ChaCha20Poly1305, KeyInit};
44
use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion};
5-
use rand::RngCore;
5+
use rand_chacha::rand_core::{RngCore, SeedableRng};
6+
use rand_chacha::ChaCha20Rng;
67

78
fn key_derivation_benchmark(c: &mut Criterion) {
89
c.bench_function("chacha_key_derivation", |b| {
910
b.iter_batched(
1011
|| {
1112
let mut key = [0u8; 32];
12-
rand::thread_rng().fill_bytes(&mut key);
13+
let mut rng = ChaCha20Rng::from_os_rng();
14+
rng.fill_bytes(&mut key);
1315
key
1416
},
1517
|key| {
@@ -28,13 +30,15 @@ fn encryption_benchmark(c: &mut Criterion) {
2830
group.bench_with_input(format!("encrypt_{}B", size), size, |b, &size| {
2931
b.iter_batched(
3032
|| {
31-
let key = ChaCha20Poly1305::generate_key(&mut rand::thread_rng());
33+
let mut rng = ChaChaOsRng;
34+
let key = ChaCha20Poly1305::generate_key(&mut rng);
3235
let msg = vec![0u8; size];
3336
(key, msg)
3437
},
3538
|(key, msg)| {
3639
let cipher = ChaCha20Poly1305::new(&key);
37-
let nonce = ChaCha20Poly1305::generate_nonce(&mut rand::thread_rng());
40+
let mut rng = ChaChaOsRng;
41+
let nonce = ChaCha20Poly1305::generate_nonce(&mut rng);
3842
cipher.encrypt(&nonce, &*msg).unwrap()
3943
},
4044
BatchSize::SmallInput,
@@ -50,9 +54,11 @@ fn decryption_benchmark(c: &mut Criterion) {
5054
group.bench_with_input(format!("decrypt_{}B", size), size, |b, &size| {
5155
b.iter_batched(
5256
|| {
53-
let key = ChaCha20Poly1305::generate_key(&mut rand::thread_rng());
57+
let mut rng = ChaChaOsRng;
58+
let key = ChaCha20Poly1305::generate_key(&mut rng);
5459
let cipher = ChaCha20Poly1305::new(&key);
55-
let nonce = ChaCha20Poly1305::generate_nonce(&mut rand::thread_rng());
60+
let mut rng = ChaChaOsRng;
61+
let nonce = ChaCha20Poly1305::generate_nonce(&mut rng);
5662
let msg = vec![0u8; size];
5763
let ct = cipher.encrypt(&nonce, &*msg).unwrap();
5864
(key, nonce, ct)
@@ -76,4 +82,4 @@ criterion_group! {
7682
decryption_benchmark
7783
}
7884

79-
criterion_main!(benches);
85+
criterion_main!(benches);

benches/kyber_bench.rs

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,47 @@
11
// benches/kyber_bench.rs
22
use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion};
33
use kychacha_crypto::{decrypt, encrypt, generate_keypair};
4+
use libcrux_ml_kem::mlkem768::{self};
5+
use rand_chacha::rand_core::{RngCore, SeedableRng};
6+
use rand_chacha::ChaCha20Rng;
47

58
fn keygen_benchmark(c: &mut Criterion) {
6-
c.bench_function("kyber_keypair_generation", |b| {
9+
c.bench_function("mlkem_keypair_generation", |b| {
710
b.iter(|| {
8-
black_box(generate_keypair().unwrap());
11+
black_box(generate_keypair());
912
});
1013
});
1114
}
1215

1316
fn encapsulation_benchmark(c: &mut Criterion) {
14-
let server_kp = generate_keypair().unwrap();
17+
let server_kp = generate_keypair();
1518

16-
c.bench_function("kyber_encapsulation", |b| {
19+
c.bench_function("mlkem_encapsulation", |b| {
1720
b.iter(|| {
18-
let (ct, _ss) =
19-
kyberlib::encapsulate(&server_kp.public, &mut rand::thread_rng()).unwrap();
20-
black_box(ct);
21+
let mut rng = ChaCha20Rng::from_os_rng();
22+
let mut randomness = [0u8; 32];
23+
rng.fill_bytes(&mut randomness);
24+
let (_ct, _ss) = black_box(mlkem768::encapsulate(&server_kp.public_key(), randomness));
2125
});
2226
});
2327
}
2428

2529
fn decapsulation_benchmark(c: &mut Criterion) {
26-
let server_kp = generate_keypair().unwrap();
27-
let (ct, _) = kyberlib::encapsulate(&server_kp.public, &mut rand::thread_rng()).unwrap();
30+
let server_kp = generate_keypair();
31+
let mut rng = ChaCha20Rng::from_os_rng();
32+
let mut randomness = [0u8; 32];
33+
rng.fill_bytes(&mut randomness);
34+
let (ct, _) = mlkem768::encapsulate(&server_kp.public_key(), randomness);
2835

29-
c.bench_function("kyber_decapsulation", |b| {
36+
c.bench_function("mlkem_decapsulation", |b| {
3037
b.iter(|| {
31-
let ss = kyberlib::decapsulate(&ct, &server_kp.secret).unwrap();
32-
black_box(ss);
38+
black_box(mlkem768::decapsulate(&server_kp.private_key(), &ct));
3339
});
3440
});
3541
}
3642

3743
fn full_encryption_benchmark(c: &mut Criterion) {
38-
let server_kp = generate_keypair().unwrap();
44+
let server_kp = generate_keypair();
3945
let messages = vec![
4046
("short", b"test".to_vec()),
4147
("medium", vec![0u8; 1024]),
@@ -46,24 +52,24 @@ fn full_encryption_benchmark(c: &mut Criterion) {
4652
c.bench_function(&format!("full_encryption_{}", name), |b| {
4753
b.iter_batched(
4854
|| message.clone(),
49-
|msg| black_box(encrypt(&server_kp.public, &msg).unwrap()),
55+
|msg| black_box(encrypt(&server_kp.public_key(), &msg)),
5056
BatchSize::SmallInput,
5157
)
5258
});
5359
}
5460
}
5561

5662
fn full_decryption_benchmark(c: &mut Criterion) {
57-
let server_kp = generate_keypair().unwrap();
63+
let server_kp = generate_keypair();
5864
let messages = vec![
59-
("short", encrypt(&server_kp.public, b"test").unwrap()),
65+
("short", encrypt(&server_kp.public_key(), b"test").unwrap()),
6066
(
6167
"medium",
62-
encrypt(&server_kp.public, &vec![0u8; 1024]).unwrap(),
68+
encrypt(&server_kp.public_key(), &vec![0u8; 1024]).unwrap(),
6369
),
6470
(
6571
"long",
66-
encrypt(&server_kp.public, &vec![0u8; 4096]).unwrap(),
72+
encrypt(&server_kp.public_key(), &vec![0u8; 4096]).unwrap(),
6773
),
6874
];
6975

@@ -87,4 +93,4 @@ criterion_group! {
8793
full_decryption_benchmark
8894
}
8995

90-
criterion_main!(benches);
96+
criterion_main!(benches);

src/encryption.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ use chacha20poly1305::{
1414
///
1515
/// // do not use this on your code, instead use encrypt fn
1616
/// let key = [0u8; 32];
17-
/// let (nonce, cifrado) = encrypt_with_key(&key, b"mensaje").unwrap();
17+
/// let (nonce, encrypted) = encrypt_with_key(&key, b"message").unwrap();
1818
/// ```
1919
///
20-
/// # Errores
20+
/// # Errors
2121
/// - key ≠ 32 bytes
2222
/// - Error while encrypting
2323
pub fn encrypt_with_key(key: &[u8; 32], plaintext: &[u8]) -> Result<(Vec<u8>, Vec<u8>)> {
@@ -42,12 +42,12 @@ pub fn encrypt_with_key(key: &[u8; 32], plaintext: &[u8]) -> Result<(Vec<u8>, Ve
4242
///
4343
/// let key = [0u8; 32];
4444
/// // do not use this on your code, instead use encrypt fn
45-
/// let (nonce, encrypted) = encrypt_with_key(&key, b"mensaje").unwrap();
45+
/// let (nonce, encrypted) = encrypt_with_key(&key, b"message").unwrap();
4646
/// // do not use this on your code, instead use decrypt fn
4747
/// let decrypted_text = decrypt_with_key(&key, &nonce, &encrypted).unwrap();
4848
/// ```
4949
///
50-
/// # Errores
50+
/// # Errors
5151
/// - Key ≠ 32 bytes or nonce ≠ 12 bytes
5252
/// - Failed auth or corruption on the data
5353
pub fn decrypt_with_key(key: &[u8; 32], nonce: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>> {

src/key_exchange.rs

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,42 @@
11
//! Kyber-1024 key exchange implementation (NIST PQC Round 3)
22
3-
use anyhow::{anyhow, Error};
43
use hkdf::Hkdf;
5-
use kyberlib::{keypair, SharedSecret};
6-
use rand::SeedableRng;
74
use rand_chacha::ChaCha20Rng;
85
use sha2::Sha256;
96
use zerocopy::IntoBytes;
10-
use kyberlib::{RngCore, CryptoRng};
11-
12-
/// Kyber-768 key sizes
13-
pub const KYBER_PUBLIC_KEY_BYTES: usize = 1184;
14-
/// Kyber-768 key sizes
15-
pub const KYBER_SECRET_KEY_BYTES: usize = 2400;
7+
use libcrux_ml_kem::*;
8+
use libcrux_ml_kem::mlkem768::MlKem768KeyPair;
9+
use rand_chacha::rand_core::{RngCore, SeedableRng};
1610

1711
/// Derives 256-bit ChaCha20 key from Kyber shared secret
1812
///
1913
/// Uses HKDF-SHA256 with protocol-specific context
2014
///
2115
/// # Security
2216
/// Context string prevents key reuse in different protocol components
23-
pub fn derive_chacha_key(shared_secret: &SharedSecret) -> [u8; 32] {
17+
pub fn derive_chacha_key(shared_secret: &MlKemSharedSecret) -> [u8; 32] {
2418
let hk = Hkdf::<Sha256>::new(None, shared_secret.as_bytes());
2519
let mut okm = [0u8; 32];
2620
hk.expand(b"chacha-encryption-v1", &mut okm)
2721
.expect("HKDF failed");
2822
okm
2923
}
3024

31-
/// Generates CPA-secure Kyber-1024 keypair
25+
/// Generates ML-KEM keypair
3226
///
3327
/// # Example
3428
/// ```
3529
/// # use std::error::Error;
3630
/// # fn main() -> Result<(), Box<dyn Error>> {
3731
/// use kychacha_crypto::generate_keypair;
3832
///
39-
/// let keypair = generate_keypair()?;
33+
/// let keypair = generate_keypair();
4034
/// Ok(())
4135
/// # }
4236
/// ```
43-
pub fn generate_keypair() -> std::result::Result<kyberlib::Keypair, Error> {
44-
let mut rng = ChaCha20Rng::from_entropy();
45-
keypair(&mut rng).map_err(|e| anyhow!("Key generation failed: {}", e))
37+
pub fn generate_keypair() -> MlKem768KeyPair {
38+
let mut rng = ChaCha20Rng::from_os_rng();
39+
let mut randomness = [0u8; 64];
40+
rng.fill_bytes(&mut randomness);
41+
mlkem768::generate_key_pair(randomness)
4642
}

0 commit comments

Comments
 (0)