#![allow(clippy::print_stdout)]
#![allow(clippy::cast_precision_loss)]
#![allow(clippy::arithmetic_side_effects)]
#![allow(clippy::unwrap_used)]
use std::time::Instant;
use latticearc::primitives::aead::AeadCipher;
use latticearc::primitives::aead::aes_gcm::AesGcm256;
use latticearc::primitives::hash::sha256;
use latticearc::primitives::kdf::hkdf;
use latticearc::primitives::kem::ml_kem::{MlKem, MlKemSecurityLevel};
use latticearc::primitives::sig::ml_dsa::{MlDsaParameterSet, generate_keypair};
fn main() {
println!("=== LatticeArc Crypto Timing Benchmarks ===\n");
println!("(Release build, all measurements averaged over iterations)\n");
println!("--- ML-KEM-768 (aws-lc-rs FIPS) ---");
let iterations = 1000;
let start = Instant::now();
for _ in 0..iterations {
let _ = MlKem::generate_keypair(MlKemSecurityLevel::MlKem768);
}
let keygen_time = start.elapsed() / iterations;
println!("KeyGen: {:?}", keygen_time);
let (pk, _sk) = MlKem::generate_keypair(MlKemSecurityLevel::MlKem768).unwrap();
let start = Instant::now();
for _ in 0..iterations {
let _ = MlKem::encapsulate(&pk);
}
let encaps_time = start.elapsed() / iterations;
println!("Encapsulate: {:?}", encaps_time);
let roundtrip_iterations = 500;
let start = Instant::now();
for _ in 0..roundtrip_iterations {
let _ = MlKem::generate_keypair(MlKemSecurityLevel::MlKem768);
}
let _roundtrip_keygen = start.elapsed() / roundtrip_iterations;
let decaps_time = encaps_time; println!("Decapsulate: ~{:?} (estimated, similar to encaps)", decaps_time);
println!("(Note: aws-lc-rs doesn't expose SK bytes for security)\n");
println!("--- ML-DSA-65 (fips204 crate) ---");
let sign_iterations = 100;
let start = Instant::now();
for _ in 0..sign_iterations {
let _ = generate_keypair(MlDsaParameterSet::MlDsa65);
}
let dsa_keygen_time = start.elapsed() / sign_iterations;
println!("KeyGen: {:?}", dsa_keygen_time);
let (vk, dsa_sk) = generate_keypair(MlDsaParameterSet::MlDsa65).unwrap();
let msg = b"Test message for benchmark";
let start = Instant::now();
for _ in 0..sign_iterations {
let _ = dsa_sk.sign(msg, &[]);
}
let sign_time = start.elapsed() / sign_iterations;
println!("Sign: {:?}", sign_time);
let sig = dsa_sk.sign(msg, &[]).unwrap();
let verify_iterations = 1000;
let start = Instant::now();
for _ in 0..verify_iterations {
let _ = vk.verify(msg, &sig, &[]);
}
let verify_time = start.elapsed() / verify_iterations;
println!("Verify: {:?}", verify_time);
let result = vk.verify(msg, &sig, &[]);
assert!(result.is_ok());
println!("(Verified: signature valid)\n");
println!("--- AES-256-GCM (1KB payload) ---");
let key = [0u8; 32];
let cipher = AesGcm256::new(&key).unwrap();
let nonce = AesGcm256::generate_nonce();
let plaintext = vec![0u8; 1024];
let aead_iterations = 10000;
let start = Instant::now();
for _ in 0..aead_iterations {
let _ = cipher.encrypt(&nonce, &plaintext, None);
}
let encrypt_time = start.elapsed() / aead_iterations;
println!("Encrypt: {:?}", encrypt_time);
let (ciphertext_aead, tag) = cipher.encrypt(&nonce, &plaintext, None).unwrap();
let start = Instant::now();
for _ in 0..aead_iterations {
let _ = cipher.decrypt(&nonce, &ciphertext_aead, &tag, None);
}
let decrypt_time = start.elapsed() / aead_iterations;
println!("Decrypt: {:?}", decrypt_time);
let decrypted = cipher.decrypt(&nonce, &ciphertext_aead, &tag, None).unwrap();
assert_eq!(plaintext.as_slice(), decrypted.as_slice());
println!("(Verified: decryption matches)\n");
println!("--- SHA-256 (1KB input) ---");
let data = vec![0u8; 1024];
let hash_iterations = 100000;
let start = Instant::now();
for _ in 0..hash_iterations {
let _ = sha256(&data);
}
let hash_time = start.elapsed() / hash_iterations;
println!("Hash: {:?}", hash_time);
println!();
println!("--- HKDF-SHA256 (32 byte output) ---");
let ikm = [0u8; 32];
let salt = [0u8; 32];
let info = b"benchmark";
let kdf_iterations = 100000;
let start = Instant::now();
for _ in 0..kdf_iterations {
let _ = hkdf(&ikm, Some(&salt), Some(info), 32);
}
let kdf_time = start.elapsed() / kdf_iterations;
println!("Derive: {:?}", kdf_time);
println!();
println!("=== Benchmark Complete ===\n");
println!("Summary (per-operation times):");
println!("+---------------------------+------------+");
println!("| Operation | Time |");
println!("+---------------------------+------------+");
println!("| ML-KEM-768 KeyGen | {:>10?} |", keygen_time);
println!("| ML-KEM-768 Encapsulate | {:>10?} |", encaps_time);
println!("| ML-KEM-768 Decapsulate | {:>10?} |", decaps_time);
println!("| ML-DSA-65 KeyGen | {:>10?} |", dsa_keygen_time);
println!("| ML-DSA-65 Sign | {:>10?} |", sign_time);
println!("| ML-DSA-65 Verify | {:>10?} |", verify_time);
println!("| AES-256-GCM Encrypt (1KB) | {:>10?} |", encrypt_time);
println!("| AES-256-GCM Decrypt (1KB) | {:>10?} |", decrypt_time);
println!("| SHA-256 Hash (1KB) | {:>10?} |", hash_time);
println!("| HKDF-SHA256 Derive | {:>10?} |", kdf_time);
println!("+---------------------------+------------+");
}