From 1471aa3c39fabf2006477227a05664e89abf6b8c Mon Sep 17 00:00:00 2001 From: Franziskus Kiefer Date: Thu, 25 Apr 2024 13:28:37 +0200 Subject: [PATCH 1/3] wip --- Cargo.toml | 1 + benchmarks/benches/aead.rs | 4 +- benchmarks/benches/drbg.rs | 4 +- benchmarks/benches/kyber768.rs | 8 +- examples/kyber768_encapsulate.rs | 2 +- examples/kyber768_generate_keypair.rs | 2 +- examples/mlkem.rs | 136 ++++++++++++++++++++++++++ src/drbg.rs | 8 +- tests/aesgcm.rs | 2 +- tests/chachapoly.rs | 2 +- tests/p256.rs | 2 +- tests/x25519.rs | 2 +- tests/xkyber_kem.rs | 4 +- tests/xwing_kem.rs | 6 +- 14 files changed, 160 insertions(+), 23 deletions(-) create mode 100644 examples/mlkem.rs diff --git a/Cargo.toml b/Cargo.toml index 9ed716a00..a540c55e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,6 +64,7 @@ quickcheck_macros = "1" serde_json = { version = "1.0" } serde = { version = "1.0", features = ["derive"] } hex = { version = "0.4.3", features = ["serde"] } +clap = { version = "4.5", features = ["derive"] } [target.'cfg(target_arch = "wasm32")'.dev-dependencies] wasm-bindgen-test = "0.3" diff --git a/benchmarks/benches/aead.rs b/benchmarks/benches/aead.rs index 94994baf3..3205ef401 100644 --- a/benchmarks/benches/aead.rs +++ b/benchmarks/benches/aead.rs @@ -11,7 +11,7 @@ use util::*; fn comparisons_encrypt(c: &mut Criterion) { const PAYLOAD_SIZES: [usize; 1] = [1024 * 1024 * 10]; - let mut drbg = drbg::Drbg::new(digest::Algorithm::Sha256).unwrap(); + let mut drbg = drbg::Drag::new(digest::Algorithm::Sha256).unwrap(); let mut group = c.benchmark_group("ChaCha20Poly1305 Encrypt"); for payload_size in PAYLOAD_SIZES.iter() { @@ -118,7 +118,7 @@ fn comparisons_encrypt(c: &mut Criterion) { fn comparisons_decrypt(c: &mut Criterion) { const PAYLOAD_SIZES: [usize; 1] = [1024 * 1024 * 10]; - let mut drbg = drbg::Drbg::new(digest::Algorithm::Sha256).unwrap(); + let mut drbg = drbg::Drag::new(digest::Algorithm::Sha256).unwrap(); let mut group = c.benchmark_group("ChaCha20Poly1305 Decrypt"); for payload_size in PAYLOAD_SIZES.iter() { diff --git a/benchmarks/benches/drbg.rs b/benchmarks/benches/drbg.rs index 5bf9e2b15..daab390a9 100644 --- a/benchmarks/benches/drbg.rs +++ b/benchmarks/benches/drbg.rs @@ -7,7 +7,7 @@ fn init(c: &mut Criterion) { group.bench_function("libcrux Sha256", |b| { b.iter(|| { - let _drbg = Drbg::new(Algorithm::Sha256).unwrap(); + let _drbg = Drag::new(Algorithm::Sha256).unwrap(); }) }); @@ -42,7 +42,7 @@ fn generate(c: &mut Criterion) { group.bench_function("libcrux Sha256", |b| { b.iter_batched( || { - let drbg = Drbg::new(Algorithm::Sha256).unwrap(); + let drbg = Drag::new(Algorithm::Sha256).unwrap(); drbg }, |mut drbg| { diff --git a/benchmarks/benches/kyber768.rs b/benchmarks/benches/kyber768.rs index acd0bc437..0d4fb0d9f 100644 --- a/benchmarks/benches/kyber768.rs +++ b/benchmarks/benches/kyber768.rs @@ -3,13 +3,13 @@ use std::time::Duration; use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; use libcrux::digest; -use libcrux::drbg::Drbg; +use libcrux::drbg::Drag; use libcrux::kem::Algorithm; use rand_core::OsRng; use rand_core::RngCore; pub fn comparisons_key_generation(c: &mut Criterion) { - let mut drbg = Drbg::new(digest::Algorithm::Sha256).unwrap(); + let mut drbg = Drag::new(digest::Algorithm::Sha256).unwrap(); let mut rng = OsRng; let mut group = c.benchmark_group("Kyber768 Key Generation"); group.measurement_time(Duration::from_secs(10)); @@ -86,7 +86,7 @@ pub fn comparisons_encapsulation(c: &mut Criterion) { group.bench_function("libcrux portable", |b| { b.iter_batched( || { - let mut drbg = Drbg::new(digest::Algorithm::Sha256).unwrap(); + let mut drbg = Drag::new(digest::Algorithm::Sha256).unwrap(); let (_secret_key, public_key) = libcrux::kem::key_gen(Algorithm::MlKem768, &mut drbg).unwrap(); @@ -138,7 +138,7 @@ pub fn comparisons_decapsulation(c: &mut Criterion) { group.bench_function("libcrux portable", |b| { b.iter_batched( || { - let mut drbg = Drbg::new(digest::Algorithm::Sha256).unwrap(); + let mut drbg = Drag::new(digest::Algorithm::Sha256).unwrap(); let (secret_key, public_key) = libcrux::kem::key_gen(Algorithm::MlKem768, &mut drbg).unwrap(); let (_shared_secret, ciphertext) = public_key.encapsulate(&mut drbg).unwrap(); diff --git a/examples/kyber768_encapsulate.rs b/examples/kyber768_encapsulate.rs index e57f33cbe..cb55ac77b 100644 --- a/examples/kyber768_encapsulate.rs +++ b/examples/kyber768_encapsulate.rs @@ -7,7 +7,7 @@ use rand_core::OsRng; fn main() { #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; diff --git a/examples/kyber768_generate_keypair.rs b/examples/kyber768_generate_keypair.rs index d2f0e4a29..ec3da4944 100644 --- a/examples/kyber768_generate_keypair.rs +++ b/examples/kyber768_generate_keypair.rs @@ -7,7 +7,7 @@ use rand_core::OsRng; fn main() { #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; diff --git a/examples/mlkem.rs b/examples/mlkem.rs new file mode 100644 index 000000000..774358b0c --- /dev/null +++ b/examples/mlkem.rs @@ -0,0 +1,136 @@ +use std::{ + fs::File, + io::{Read, Write}, +}; + +use libcrux::{ + drbg::{self, Drag}, + kem, +}; + +use clap::{Parser, Subcommand}; + +#[derive(Clone, Copy, Debug)] +#[repr(u16)] +enum Variant { + MlKem512 = 512, + MlKem768 = 768, + MlKem1024 = 1024, +} + +#[derive(Subcommand)] +enum GenerateCli { + GenerateKey { + /// Optionally, a file name to store the keys into. + /// + /// The keys will be store into `$out.pub` and `$out` when this is used. + #[arg(short, long)] + out: Option, + }, + Encaps { + /// Public key input file to encrypt to. + #[arg(short, long)] + key: String, + + /// Optionally, a file name to store the encapsulation output. + /// + /// This defaults to `mlkem.ct``. + #[arg(short, long)] + out: Option, + }, + Decaps { + /// Private key input file to decapsulate with. + #[arg(short, long)] + key: String, + + /// Optionally, a file name to store the encapsulation output. + /// + /// This defaults to `mlkem.ct``. + #[arg(short, long)] + out: Option, + }, +} + +#[derive(Parser)] +struct Cli { + /// Generate a key pair and write it out. + /// + /// When no output files are given, `mlkem.pub` and `mlkem` are used. + #[command(subcommand)] + cmd: GenerateCli, + + /// The key length, 512, 768, or 1024 + /// + /// Defaults to 768 + #[arg(short, long)] + length: Option, +} + +fn main() { + pretty_env_logger::init(); + + let cli = Cli::parse(); + + let alg = if let Some(l) = cli.length { + match l { + 512 => kem::Algorithm::MlKem512, + 768 => kem::Algorithm::MlKem768, + 1024 => kem::Algorithm::MlKem1024, + _ => { + eprintln!("Invalid algorithm variant {l}"); + return; + } + } + } else { + kem::Algorithm::MlKem768 + }; + + let mut rng = Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); + + match cli.cmd { + GenerateCli::GenerateKey { out: file } => { + // Generate a key pair and write it out. + let (sk_name, pk_name) = match file { + Some(n) => (n.clone(), format!("{n}.pub")), + None => ("mlkem".to_owned(), "mlkem.pub".to_owned()), + }; + + let (secret_key, public_key) = kem::key_gen(alg, &mut rng).unwrap(); + + File::create(sk_name) + .expect("Can not create file {sk_name}") + .write_all(&secret_key.encode()) + .expect("Error writing private key"); + File::create(pk_name) + .expect("Can not create file {pk_name}") + .write_all(&public_key.encode()) + .expect("Error writing public key"); + } + + GenerateCli::Encaps { key, out } => { + let mut pk = Vec::new(); + File::open(key) + .expect("Error opening key file {key}") + .read_to_end(&mut pk) + .expect("Error reading key file {key}."); + let pk = kem::PublicKey::decode(alg, &pk).expect("Error decoding public key"); + + let (shared_secret, ciphertext) = + pk.encapsulate(&mut rng).expect("Error encapsulating"); + + let out = match out { + Some(n) => n, + None => "mlkem.ct".to_owned(), + }; + + let mut out_file = File::create(out).expect("Can not create file {pk_name}"); + out_file + .write_all(&shared_secret.encode()) + .expect("Error writing public key"); + out_file + .write_all(&ciphertext.encode()) + .expect("Error writing public key"); + } + GenerateCli::Decaps { key, out } => todo!(), + } +} diff --git a/src/drbg.rs b/src/drbg.rs index dd7f70536..e342e030e 100644 --- a/src/drbg.rs +++ b/src/drbg.rs @@ -24,12 +24,12 @@ impl std::fmt::Display for Error { impl std::error::Error for Error {} -pub struct Drbg { +pub struct Drag { state: drbg::Drbg, ctr: u32, // automatic reseed after 512 invocations. It has to happen at least every 1024 times. } -impl Drbg { +impl Drag { /// Create a new DRBG state with the given hash function. /// /// The DRBG state is initialized with 128 bit entropy from the OS. @@ -169,7 +169,7 @@ impl Drbg { } /// Implementation of the [`RngCore`] trait for the [`Drbg`]. -impl RngCore for Drbg { +impl RngCore for Drag { fn next_u32(&mut self) -> u32 { let mut bytes: [u8; 4] = [0; 4]; self.generate(&mut bytes).unwrap(); @@ -193,4 +193,4 @@ impl RngCore for Drbg { } } -impl CryptoRng for Drbg {} +impl CryptoRng for Drag {} diff --git a/tests/aesgcm.rs b/tests/aesgcm.rs index 0954e9a1e..889e98118 100644 --- a/tests/aesgcm.rs +++ b/tests/aesgcm.rs @@ -75,7 +75,7 @@ fn aesgcm_self_test_rand() { let aad = b"associated data" as &[u8]; #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; diff --git a/tests/chachapoly.rs b/tests/chachapoly.rs index c1769cb71..c2ffd5793 100644 --- a/tests/chachapoly.rs +++ b/tests/chachapoly.rs @@ -49,7 +49,7 @@ fn chachapoly_self_test_rand() { let aad = b"associated data" as &[u8]; #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; diff --git a/tests/p256.rs b/tests/p256.rs index 28ac6e734..a11cadab4 100644 --- a/tests/p256.rs +++ b/tests/p256.rs @@ -8,7 +8,7 @@ use rand_core::OsRng; #[test] fn derive_rand() { #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; diff --git a/tests/x25519.rs b/tests/x25519.rs index 6963eb3ba..b8dc9c30a 100644 --- a/tests/x25519.rs +++ b/tests/x25519.rs @@ -16,7 +16,7 @@ fn derive() { let _ = pretty_env_logger::try_init(); #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; diff --git a/tests/xkyber_kem.rs b/tests/xkyber_kem.rs index 1fec45f1c..634ea6817 100644 --- a/tests/xkyber_kem.rs +++ b/tests/xkyber_kem.rs @@ -23,7 +23,7 @@ fn xkyber_selftest() { let _ = pretty_env_logger::try_init(); #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; @@ -41,7 +41,7 @@ fn xkyber_hpke_selftest() { let _ = pretty_env_logger::try_init(); #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; diff --git a/tests/xwing_kem.rs b/tests/xwing_kem.rs index e78cbeb0f..bbb61965f 100644 --- a/tests/xwing_kem.rs +++ b/tests/xwing_kem.rs @@ -28,7 +28,7 @@ fn xwing_selftest() { let _ = pretty_env_logger::try_init(); #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; @@ -46,7 +46,7 @@ fn xwing_hpke_selftest() { let _ = pretty_env_logger::try_init(); #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; @@ -93,7 +93,7 @@ fn xwing_test_vectors() { let _ = pretty_env_logger::try_init(); #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; From 7973d73693f3fa95b5322e061e0e3fd3a59fc467 Mon Sep 17 00:00:00 2001 From: Franziskus Kiefer Date: Fri, 26 Apr 2024 14:30:15 +0200 Subject: [PATCH 2/3] working --- benchmarks/benches/aead.rs | 4 +- benchmarks/benches/drbg.rs | 4 +- benchmarks/benches/kyber768.rs | 8 +-- examples/kyber768_encapsulate.rs | 2 +- examples/kyber768_generate_keypair.rs | 2 +- examples/mlkem.rs | 99 ++++++++++++++++++--------- src/drbg.rs | 8 +-- tests/aesgcm.rs | 2 +- tests/chachapoly.rs | 2 +- tests/p256.rs | 2 +- tests/x25519.rs | 2 +- tests/xkyber_kem.rs | 4 +- tests/xwing_kem.rs | 6 +- 13 files changed, 88 insertions(+), 57 deletions(-) diff --git a/benchmarks/benches/aead.rs b/benchmarks/benches/aead.rs index 3205ef401..94994baf3 100644 --- a/benchmarks/benches/aead.rs +++ b/benchmarks/benches/aead.rs @@ -11,7 +11,7 @@ use util::*; fn comparisons_encrypt(c: &mut Criterion) { const PAYLOAD_SIZES: [usize; 1] = [1024 * 1024 * 10]; - let mut drbg = drbg::Drag::new(digest::Algorithm::Sha256).unwrap(); + let mut drbg = drbg::Drbg::new(digest::Algorithm::Sha256).unwrap(); let mut group = c.benchmark_group("ChaCha20Poly1305 Encrypt"); for payload_size in PAYLOAD_SIZES.iter() { @@ -118,7 +118,7 @@ fn comparisons_encrypt(c: &mut Criterion) { fn comparisons_decrypt(c: &mut Criterion) { const PAYLOAD_SIZES: [usize; 1] = [1024 * 1024 * 10]; - let mut drbg = drbg::Drag::new(digest::Algorithm::Sha256).unwrap(); + let mut drbg = drbg::Drbg::new(digest::Algorithm::Sha256).unwrap(); let mut group = c.benchmark_group("ChaCha20Poly1305 Decrypt"); for payload_size in PAYLOAD_SIZES.iter() { diff --git a/benchmarks/benches/drbg.rs b/benchmarks/benches/drbg.rs index daab390a9..5bf9e2b15 100644 --- a/benchmarks/benches/drbg.rs +++ b/benchmarks/benches/drbg.rs @@ -7,7 +7,7 @@ fn init(c: &mut Criterion) { group.bench_function("libcrux Sha256", |b| { b.iter(|| { - let _drbg = Drag::new(Algorithm::Sha256).unwrap(); + let _drbg = Drbg::new(Algorithm::Sha256).unwrap(); }) }); @@ -42,7 +42,7 @@ fn generate(c: &mut Criterion) { group.bench_function("libcrux Sha256", |b| { b.iter_batched( || { - let drbg = Drag::new(Algorithm::Sha256).unwrap(); + let drbg = Drbg::new(Algorithm::Sha256).unwrap(); drbg }, |mut drbg| { diff --git a/benchmarks/benches/kyber768.rs b/benchmarks/benches/kyber768.rs index 0d4fb0d9f..acd0bc437 100644 --- a/benchmarks/benches/kyber768.rs +++ b/benchmarks/benches/kyber768.rs @@ -3,13 +3,13 @@ use std::time::Duration; use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; use libcrux::digest; -use libcrux::drbg::Drag; +use libcrux::drbg::Drbg; use libcrux::kem::Algorithm; use rand_core::OsRng; use rand_core::RngCore; pub fn comparisons_key_generation(c: &mut Criterion) { - let mut drbg = Drag::new(digest::Algorithm::Sha256).unwrap(); + let mut drbg = Drbg::new(digest::Algorithm::Sha256).unwrap(); let mut rng = OsRng; let mut group = c.benchmark_group("Kyber768 Key Generation"); group.measurement_time(Duration::from_secs(10)); @@ -86,7 +86,7 @@ pub fn comparisons_encapsulation(c: &mut Criterion) { group.bench_function("libcrux portable", |b| { b.iter_batched( || { - let mut drbg = Drag::new(digest::Algorithm::Sha256).unwrap(); + let mut drbg = Drbg::new(digest::Algorithm::Sha256).unwrap(); let (_secret_key, public_key) = libcrux::kem::key_gen(Algorithm::MlKem768, &mut drbg).unwrap(); @@ -138,7 +138,7 @@ pub fn comparisons_decapsulation(c: &mut Criterion) { group.bench_function("libcrux portable", |b| { b.iter_batched( || { - let mut drbg = Drag::new(digest::Algorithm::Sha256).unwrap(); + let mut drbg = Drbg::new(digest::Algorithm::Sha256).unwrap(); let (secret_key, public_key) = libcrux::kem::key_gen(Algorithm::MlKem768, &mut drbg).unwrap(); let (_shared_secret, ciphertext) = public_key.encapsulate(&mut drbg).unwrap(); diff --git a/examples/kyber768_encapsulate.rs b/examples/kyber768_encapsulate.rs index cb55ac77b..e57f33cbe 100644 --- a/examples/kyber768_encapsulate.rs +++ b/examples/kyber768_encapsulate.rs @@ -7,7 +7,7 @@ use rand_core::OsRng; fn main() { #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; diff --git a/examples/kyber768_generate_keypair.rs b/examples/kyber768_generate_keypair.rs index ec3da4944..d2f0e4a29 100644 --- a/examples/kyber768_generate_keypair.rs +++ b/examples/kyber768_generate_keypair.rs @@ -7,7 +7,7 @@ use rand_core::OsRng; fn main() { #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; diff --git a/examples/mlkem.rs b/examples/mlkem.rs index 774358b0c..86c4ff81a 100644 --- a/examples/mlkem.rs +++ b/examples/mlkem.rs @@ -3,21 +3,10 @@ use std::{ io::{Read, Write}, }; -use libcrux::{ - drbg::{self, Drag}, - kem, -}; +use libcrux::{drbg::Drbg, kem}; use clap::{Parser, Subcommand}; -#[derive(Clone, Copy, Debug)] -#[repr(u16)] -enum Variant { - MlKem512 = 512, - MlKem768 = 768, - MlKem1024 = 1024, -} - #[derive(Subcommand)] enum GenerateCli { GenerateKey { @@ -34,20 +23,30 @@ enum GenerateCli { /// Optionally, a file name to store the encapsulation output. /// - /// This defaults to `mlkem.ct``. + /// This defaults to `mlkem.ct`. #[arg(short, long)] - out: Option, + ct: Option, + + /// Optionally, a file name to store the shared secret output. + /// + /// This defaults to `mlkem.ss`. + #[arg(short, long)] + ss: Option, }, Decaps { /// Private key input file to decapsulate with. #[arg(short, long)] key: String, - /// Optionally, a file name to store the encapsulation output. + /// Encapsulated secret. + #[arg(short, long)] + ct: String, + + /// Optionally, a file name to store the shared secret. /// - /// This defaults to `mlkem.ct``. + /// This defaults to `mlkem.ss``. #[arg(short, long)] - out: Option, + ss: Option, }, } @@ -63,7 +62,7 @@ struct Cli { /// /// Defaults to 768 #[arg(short, long)] - length: Option, + algorithm: Option, } fn main() { @@ -71,7 +70,7 @@ fn main() { let cli = Cli::parse(); - let alg = if let Some(l) = cli.length { + let alg = if let Some(l) = cli.algorithm { match l { 512 => kem::Algorithm::MlKem512, 768 => kem::Algorithm::MlKem768, @@ -85,7 +84,7 @@ fn main() { kem::Algorithm::MlKem768 }; - let mut rng = Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); match cli.cmd { GenerateCli::GenerateKey { out: file } => { @@ -97,40 +96,72 @@ fn main() { let (secret_key, public_key) = kem::key_gen(alg, &mut rng).unwrap(); - File::create(sk_name) - .expect("Can not create file {sk_name}") + File::create(sk_name.clone()) + .expect(&format!("Can not create file {sk_name}")) .write_all(&secret_key.encode()) .expect("Error writing private key"); - File::create(pk_name) - .expect("Can not create file {pk_name}") + File::create(pk_name.clone()) + .expect(&format!("Can not create file {pk_name}")) .write_all(&public_key.encode()) .expect("Error writing public key"); } - GenerateCli::Encaps { key, out } => { - let mut pk = Vec::new(); - File::open(key) - .expect("Error opening key file {key}") - .read_to_end(&mut pk) - .expect("Error reading key file {key}."); + GenerateCli::Encaps { key, ct: out, ss } => { + let pk = bytes_from_file(key); let pk = kem::PublicKey::decode(alg, &pk).expect("Error decoding public key"); let (shared_secret, ciphertext) = pk.encapsulate(&mut rng).expect("Error encapsulating"); - let out = match out { + let ct_out = match out { Some(n) => n, None => "mlkem.ct".to_owned(), }; + let ss_out = match ss { + Some(n) => n, + None => "mlkem.ss".to_owned(), + }; + + let mut out_file = + File::create(ct_out.clone()).expect(&format!("Can not create file {ct_out}")); + out_file + .write_all(&ciphertext.encode()) + .expect("Error writing public key"); - let mut out_file = File::create(out).expect("Can not create file {pk_name}"); + let mut out_file = + File::create(ss_out.clone()).expect(&format!("Can not create file {ss_out}")); out_file .write_all(&shared_secret.encode()) .expect("Error writing public key"); + } + GenerateCli::Decaps { key, ss: out, ct } => { + let sk = bytes_from_file(key); + let sk = kem::PrivateKey::decode(alg, &sk).expect("Error decoding private key"); + + let ct = bytes_from_file(ct); + + let ct = kem::Ct::decode(alg, &ct).expect("Error decoding ct."); + let shared_secret = ct.decapsulate(&sk).expect("Error decapsulating."); + + let out = match out { + Some(n) => n, + None => "mlkem.ss".to_owned(), + }; + + let mut out_file = + File::create(out.clone()).expect(&format!("Can not create file {out}")); out_file - .write_all(&ciphertext.encode()) + .write_all(&shared_secret.encode()) .expect("Error writing public key"); } - GenerateCli::Decaps { key, out } => todo!(), } } + +fn bytes_from_file(file: String) -> Vec { + let mut bytes = Vec::new(); + File::open(file.clone()) + .expect(&format!("Error opening file {file}")) + .read_to_end(&mut bytes) + .expect(&format!("Error reading file {file}.")); + bytes +} diff --git a/src/drbg.rs b/src/drbg.rs index e342e030e..dd7f70536 100644 --- a/src/drbg.rs +++ b/src/drbg.rs @@ -24,12 +24,12 @@ impl std::fmt::Display for Error { impl std::error::Error for Error {} -pub struct Drag { +pub struct Drbg { state: drbg::Drbg, ctr: u32, // automatic reseed after 512 invocations. It has to happen at least every 1024 times. } -impl Drag { +impl Drbg { /// Create a new DRBG state with the given hash function. /// /// The DRBG state is initialized with 128 bit entropy from the OS. @@ -169,7 +169,7 @@ impl Drag { } /// Implementation of the [`RngCore`] trait for the [`Drbg`]. -impl RngCore for Drag { +impl RngCore for Drbg { fn next_u32(&mut self) -> u32 { let mut bytes: [u8; 4] = [0; 4]; self.generate(&mut bytes).unwrap(); @@ -193,4 +193,4 @@ impl RngCore for Drag { } } -impl CryptoRng for Drag {} +impl CryptoRng for Drbg {} diff --git a/tests/aesgcm.rs b/tests/aesgcm.rs index 889e98118..0954e9a1e 100644 --- a/tests/aesgcm.rs +++ b/tests/aesgcm.rs @@ -75,7 +75,7 @@ fn aesgcm_self_test_rand() { let aad = b"associated data" as &[u8]; #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; diff --git a/tests/chachapoly.rs b/tests/chachapoly.rs index c2ffd5793..c1769cb71 100644 --- a/tests/chachapoly.rs +++ b/tests/chachapoly.rs @@ -49,7 +49,7 @@ fn chachapoly_self_test_rand() { let aad = b"associated data" as &[u8]; #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; diff --git a/tests/p256.rs b/tests/p256.rs index a11cadab4..28ac6e734 100644 --- a/tests/p256.rs +++ b/tests/p256.rs @@ -8,7 +8,7 @@ use rand_core::OsRng; #[test] fn derive_rand() { #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; diff --git a/tests/x25519.rs b/tests/x25519.rs index b8dc9c30a..6963eb3ba 100644 --- a/tests/x25519.rs +++ b/tests/x25519.rs @@ -16,7 +16,7 @@ fn derive() { let _ = pretty_env_logger::try_init(); #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; diff --git a/tests/xkyber_kem.rs b/tests/xkyber_kem.rs index 634ea6817..1fec45f1c 100644 --- a/tests/xkyber_kem.rs +++ b/tests/xkyber_kem.rs @@ -23,7 +23,7 @@ fn xkyber_selftest() { let _ = pretty_env_logger::try_init(); #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; @@ -41,7 +41,7 @@ fn xkyber_hpke_selftest() { let _ = pretty_env_logger::try_init(); #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; diff --git a/tests/xwing_kem.rs b/tests/xwing_kem.rs index bbb61965f..e78cbeb0f 100644 --- a/tests/xwing_kem.rs +++ b/tests/xwing_kem.rs @@ -28,7 +28,7 @@ fn xwing_selftest() { let _ = pretty_env_logger::try_init(); #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; @@ -46,7 +46,7 @@ fn xwing_hpke_selftest() { let _ = pretty_env_logger::try_init(); #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; @@ -93,7 +93,7 @@ fn xwing_test_vectors() { let _ = pretty_env_logger::try_init(); #[cfg(not(target_arch = "wasm32"))] - let mut rng = drbg::Drag::new(libcrux::digest::Algorithm::Sha256).unwrap(); + let mut rng = drbg::Drbg::new(libcrux::digest::Algorithm::Sha256).unwrap(); #[cfg(target_arch = "wasm32")] let mut rng = OsRng; From e49cd8729fbce1a22b7313d54e32cb7affdee3ad Mon Sep 17 00:00:00 2001 From: Franziskus Kiefer Date: Tue, 30 Apr 2024 13:37:43 +0200 Subject: [PATCH 3/3] addressing comments --- examples/mlkem.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/examples/mlkem.rs b/examples/mlkem.rs index 86c4ff81a..d2825e0e8 100644 --- a/examples/mlkem.rs +++ b/examples/mlkem.rs @@ -12,7 +12,7 @@ enum GenerateCli { GenerateKey { /// Optionally, a file name to store the keys into. /// - /// The keys will be store into `$out.pub` and `$out` when this is used. + /// The keys will be store into `$out.pub` and `$out.priv` when this is used. #[arg(short, long)] out: Option, }, @@ -29,7 +29,7 @@ enum GenerateCli { /// Optionally, a file name to store the shared secret output. /// - /// This defaults to `mlkem.ss`. + /// This defaults to `mlkem-encapsulated.ss`. #[arg(short, long)] ss: Option, }, @@ -44,7 +44,7 @@ enum GenerateCli { /// Optionally, a file name to store the shared secret. /// - /// This defaults to `mlkem.ss``. + /// This defaults to `mlkem-decapsulated.ss``. #[arg(short, long)] ss: Option, }, @@ -90,16 +90,18 @@ fn main() { GenerateCli::GenerateKey { out: file } => { // Generate a key pair and write it out. let (sk_name, pk_name) = match file { - Some(n) => (n.clone(), format!("{n}.pub")), - None => ("mlkem".to_owned(), "mlkem.pub".to_owned()), + Some(n) => (format!("{n}.priv"), format!("{n}.pub")), + None => ("mlkem.priv".to_owned(), "mlkem.pub".to_owned()), }; let (secret_key, public_key) = kem::key_gen(alg, &mut rng).unwrap(); + println!("Writing private key to {sk_name}"); File::create(sk_name.clone()) .expect(&format!("Can not create file {sk_name}")) .write_all(&secret_key.encode()) .expect("Error writing private key"); + println!("Writing public key to {pk_name}"); File::create(pk_name.clone()) .expect(&format!("Can not create file {pk_name}")) .write_all(&public_key.encode()) @@ -119,15 +121,17 @@ fn main() { }; let ss_out = match ss { Some(n) => n, - None => "mlkem.ss".to_owned(), + None => "mlkem-encapsulated.ss".to_owned(), }; + println!("Writing ciphertext to {ct_out}"); let mut out_file = File::create(ct_out.clone()).expect(&format!("Can not create file {ct_out}")); out_file .write_all(&ciphertext.encode()) .expect("Error writing public key"); + println!("Writing shared secret to {ss_out}"); let mut out_file = File::create(ss_out.clone()).expect(&format!("Can not create file {ss_out}")); out_file @@ -145,9 +149,10 @@ fn main() { let out = match out { Some(n) => n, - None => "mlkem.ss".to_owned(), + None => "mlkem-decapsulated.ss".to_owned(), }; + println!("Writing shared secret to {out}"); let mut out_file = File::create(out.clone()).expect(&format!("Can not create file {out}")); out_file @@ -158,6 +163,7 @@ fn main() { } fn bytes_from_file(file: String) -> Vec { + println!("Reading file {file}"); let mut bytes = Vec::new(); File::open(file.clone()) .expect(&format!("Error opening file {file}"))