diff --git a/Cargo.lock b/Cargo.lock index 71a4770c28..f8e3f49368 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4337,6 +4337,7 @@ version = "0.0.3-alpha.1" source = "git+https://github.com/cryspen/libcrux#96abd9f2460ff92811a1c181662590d96c37949c" dependencies = [ "libcrux-chacha20poly1305", + "libcrux-ecdh", "libcrux-ed25519", "libcrux-hkdf", "libcrux-hmac", diff --git a/common/nym-psq-kkt/Cargo.toml b/common/nym-psq-kkt/Cargo.toml index ce6e36bbfc..007c8440dc 100644 --- a/common/nym-psq-kkt/Cargo.toml +++ b/common/nym-psq-kkt/Cargo.toml @@ -23,7 +23,7 @@ nym-crypto = { path = "../crypto", features = ["asymmetric", "serde"]} libcrux-traits = { git = "https://github.com/cryspen/libcrux" } libcrux-kem = { git = "https://github.com/cryspen/libcrux" } -libcrux-psq = { git = "https://github.com/cryspen/libcrux" } +libcrux-psq = { git = "https://github.com/cryspen/libcrux", features = ["test-utils"] } rand = "0.9.1" [dev-dependencies] diff --git a/common/nym-psq-kkt/src/lib.rs b/common/nym-psq-kkt/src/lib.rs index 72f1049626..1b236ace49 100644 --- a/common/nym-psq-kkt/src/lib.rs +++ b/common/nym-psq-kkt/src/lib.rs @@ -18,18 +18,20 @@ mod test { #[test] fn test_kkt_psq_e2e() { + let mut rng = rand::rng(); + // generate ed25519 keys let mut secret_initiator: [u8; 32] = [0u8; 32]; - rand::rng().fill_bytes(&mut secret_initiator); + rng.fill_bytes(&mut secret_initiator); let initiator_ed25519_keypair = ed25519::KeyPair::from_secret(secret_initiator, 0); let mut secret_responder: [u8; 32] = [0u8; 32]; - rand::rng().fill_bytes(&mut secret_responder); + rng.fill_bytes(&mut secret_responder); let responder_ed25519_keypair = ed25519::KeyPair::from_secret(secret_responder, 1); // generate kem keypair let (responder_kem_private_key, responder_kem_public_key) = - libcrux_kem::key_gen(libcrux_kem::Algorithm::MlKem768, &mut rand::rng()).unwrap(); + libcrux_kem::key_gen(libcrux_kem::Algorithm::MlKem768, &mut rng).unwrap(); // initialize parties let kkt_initiator: KKTInitiator = @@ -78,7 +80,7 @@ mod test { PSQResponder::init(&responder_kem_private_key, &responder_kem_public_key); let initiator_psq_msg = psq_initiator - .initiator_message(&received_responder_key) + .initiator_message(&mut rng, &received_responder_key) .unwrap(); let (responder_psk, responder_psq_msg) = psq_responder diff --git a/common/nym-psq-kkt/src/psq.rs b/common/nym-psq-kkt/src/psq.rs index 6cf3bc8b05..6199005d32 100644 --- a/common/nym-psq-kkt/src/psq.rs +++ b/common/nym-psq-kkt/src/psq.rs @@ -5,13 +5,13 @@ use std::{marker::PhantomData, time::Duration}; use libcrux_psq::{ cred::Ed25519, - impls::MlKem768, psk_registration::{Initiator, InitiatorMsg, Responder, ResponderMsg}, traits::PSQ, }; use libcrux_traits::kem::KEM; use nym_crypto::asymmetric::ed25519; +use rand::CryptoRng; use crate::error::PSQError; @@ -32,6 +32,23 @@ impl<'a, T: PSQ> PSQInitiator<'a, T> { } } + pub fn initiator_message( + &mut self, + rng: &mut impl CryptoRng, + responder_kem_public_key: &'a ::EncapsulationKey, + ) -> Result, PSQError> { + let (state, message) = Initiator::send_initial_message::( + &[0u8], + Duration::from_secs(3600), + &responder_kem_public_key, + &self.signing_keypair.private_key().to_bytes(), + &self.signing_keypair.public_key().to_bytes(), + rng, + )?; + self.state = Some(state); + Ok(message) + } + pub fn finalize(&self, responder_message: &ResponderMsg) -> Result<[u8; PSK_LENGTH], PSQError> { match &self.state { Some(state) => match state.complete_handshake(responder_message) { @@ -43,24 +60,6 @@ impl<'a, T: PSQ> PSQInitiator<'a, T> { } } -impl<'a> PSQInitiator<'a, MlKem768> { - pub fn initiator_message( - &mut self, - responder_kem_public_key: &libcrux_kem::PublicKey, - ) -> Result, PSQError> { - let (state, message) = Initiator::send_initial_message::( - &[0u8], - Duration::from_secs(3600), - &responder_kem_public_key, - &self.signing_keypair.private_key().to_bytes(), - &self.signing_keypair.public_key().to_bytes(), - &mut rand::rng(), - )?; - self.state = Some(state); - Ok(message) - } -} - pub struct PSQResponder<'a, T: PSQ> { kem_private_key: &'a ::DecapsulationKey, kem_public_key: &'a ::EncapsulationKey, @@ -77,14 +76,13 @@ impl<'a, T: PSQ> PSQResponder<'a, T> { _t: PhantomData, } } -} -impl<'a> PSQResponder<'a, MlKem768> { + pub fn responder_msg( &self, initiator_verification_key: &'a ed25519::PublicKey, - initiator_message: &InitiatorMsg, + initiator_message: &InitiatorMsg, ) -> Result<([u8; PSK_LENGTH], ResponderMsg), PSQError> { - let (registered_psk, responder_msg) = Responder::send::( + let (registered_psk, responder_msg) = Responder::send::( &[0u8], Duration::from_secs(3600), &[0u8], @@ -100,29 +98,31 @@ impl<'a> PSQResponder<'a, MlKem768> { #[cfg(test)] mod test { - use libcrux_psq::impls::MlKem768; + use libcrux_psq::impls::{MlKem768, XWingKemDraft06, X25519}; + use libcrux_psq::traits::PSQ; + use libcrux_traits::kem::KEM; use nym_crypto::asymmetric::ed25519; use rand::prelude::*; use super::{PSQInitiator, PSQResponder}; - #[test] - fn test_psq_e2e() { + fn test_helper( + rng: &mut impl CryptoRng, + responder_kem_private_key: ::DecapsulationKey, + responder_kem_public_key: ::EncapsulationKey, + ) { // generate ed25519 keys + let mut secret_initiator: [u8; 32] = [0u8; 32]; - rand::rng().fill_bytes(&mut secret_initiator); + rng.fill_bytes(&mut secret_initiator); let initiator_ed25519_keypair = ed25519::KeyPair::from_secret(secret_initiator, 0); - // generate kem keypair - let (responder_kem_private_key, responder_kem_public_key) = - libcrux_kem::key_gen(libcrux_kem::Algorithm::MlKem768, &mut rand::rng()).unwrap(); - - let mut initiator: PSQInitiator = PSQInitiator::init(&initiator_ed25519_keypair); - let responder: PSQResponder = + let mut initiator: PSQInitiator = PSQInitiator::init(&initiator_ed25519_keypair); + let responder: PSQResponder = PSQResponder::init(&responder_kem_private_key, &responder_kem_public_key); let initiator_msg = initiator - .initiator_message(&responder_kem_public_key) + .initiator_message(rng, &responder_kem_public_key) .unwrap(); let (responder_psk, responder_msg) = responder @@ -133,4 +133,50 @@ mod test { assert_eq!(initiator_psk, responder_psk); } + + #[test] + fn test_psq_e2e_mlkem() { + let mut rng = rand::rng(); + + // generate mlkem keypair + let (responder_kem_private_key, responder_kem_public_key) = + libcrux_kem::key_gen(libcrux_kem::Algorithm::MlKem768, &mut rng).unwrap(); + + test_helper::( + &mut rng, + responder_kem_private_key, + responder_kem_public_key, + ); + } + + #[test] + fn test_psq_e2e_xwing() { + let mut rng = rand::rng(); + + // generate mlkem keypair + let (responder_kem_private_key, responder_kem_public_key) = + libcrux_kem::key_gen(libcrux_kem::Algorithm::XWingKemDraft06, &mut rand::rng()) + .unwrap(); + + test_helper::( + &mut rng, + responder_kem_private_key, + responder_kem_public_key, + ); + } + + #[test] + fn test_psq_e2e_dhkem() { + let mut rng = rand::rng(); + + // generate mlkem keypair + let (responder_kem_private_key, responder_kem_public_key) = + libcrux_kem::key_gen(libcrux_kem::Algorithm::X25519, &mut rand::rng()).unwrap(); + + test_helper::( + &mut rng, + responder_kem_private_key, + responder_kem_public_key, + ); + } }