diff --git a/common/nym-kkt/Cargo.toml b/common/nym-kkt/Cargo.toml index bd3a95bc98..3ba5189c35 100644 --- a/common/nym-kkt/Cargo.toml +++ b/common/nym-kkt/Cargo.toml @@ -23,7 +23,6 @@ libcrux-chacha20poly1305 = { workspace = true } rand = "0.9.2" zeroize = { workspace = true, features = ["zeroize_derive"] } -# classic-mceliece-rust = { git = "https://github.com/georgio/classic-mceliece-rust", features = ["mceliece460896f", "zeroize"] } classic-mceliece-rust = { version = "3.1.0", features = [ "mceliece460896f", "zeroize"] } diff --git a/common/nym-kkt/src/encryption.rs b/common/nym-kkt/src/encryption.rs index 8e62ba839e..8a5076e903 100644 --- a/common/nym-kkt/src/encryption.rs +++ b/common/nym-kkt/src/encryption.rs @@ -4,34 +4,28 @@ use crate::{KKT_INITIAL_FRAME_AAD, context::KKTContext, error::KKTError, frame::KKTFrame}; use blake3::Hasher; use libcrux_chacha20poly1305::{NONCE_LEN, TAG_LEN}; -use libcrux_psq::handshake::types::{DHPrivateKey, DHPublicKey}; -use nym_crypto::asymmetric::x25519; +use libcrux_psq::handshake::types::{DHKeyPair, DHPrivateKey, DHPublicKey}; +use nym_kkt_ciphersuite::x25519; use rand::{CryptoRng, RngCore}; -use zeroize::{Zeroize, Zeroizing}; +use zeroize::Zeroize; #[derive(Clone, Copy, Zeroize)] pub struct KKTSessionSecret([u8; 32]); impl KKTSessionSecret { + // We just return the ephemeral public key to send because this is a use-once session secret. + // The responder needs the returned ephemeral public key and their long term private key + // to compute the shared secret. + // We don't zeroize this, but it's ok because this key will just encrypt a public KEM key. pub fn new(rng: &mut R, remote_public_key: &DHPublicKey) -> (Self, DHPublicKey) where R: RngCore + CryptoRng, { - let mut private_key_bytes = Zeroizing::new([0u8; x25519::PRIVATE_KEY_SIZE]); - rng.fill_bytes(private_key_bytes.as_mut()); - // clamp - private_key_bytes[0] &= 248u8; - private_key_bytes[31] &= 127u8; - private_key_bytes[31] |= 64u8; - - // SAFETY: bytes got correctly clamped - #[allow(clippy::unwrap_used)] - let ephemeral_private_key = DHPrivateKey::from_bytes(&private_key_bytes).unwrap(); - let ephemeral_public_key = ephemeral_private_key.to_public(); + let ephemeral_keypair = DHKeyPair::new(rng); ( - Self::derive(&ephemeral_private_key, remote_public_key), - ephemeral_public_key, + Self::derive(ephemeral_keypair.sk(), remote_public_key), + ephemeral_keypair.pk, ) } pub fn from_bytes(secret: [u8; 32]) -> Self { @@ -40,7 +34,7 @@ impl KKTSessionSecret { fn try_derive(private_key: &DHPrivateKey, public_key: &[u8]) -> Result { let mut pub_key: [u8; 32] = [0u8; 32]; - pub_key.copy_from_slice(&public_key[0..x25519::PUBLIC_KEY_SIZE]); + pub_key.copy_from_slice(&public_key[0..x25519::PUBLIC_KEY_LENGTH]); // Todo: check validity of pk... let pk = DHPublicKey::from_bytes(&pub_key); @@ -48,7 +42,7 @@ impl KKTSessionSecret { } pub fn derive(private_key: &DHPrivateKey, public_key: &DHPublicKey) -> Self { - let mut shared_secret = private_key + let shared_secret = private_key .diffie_hellman(public_key) .expect("TODO: error handling"); @@ -79,7 +73,7 @@ where let mut encrypted_frame = encrypt_kkt_frame(rng, &session_secret_key, kkt_frame, KKT_INITIAL_FRAME_AAD)?; - let mut output_buffer = Vec::with_capacity(encrypted_frame.len() + x25519::PUBLIC_KEY_SIZE); + let mut output_buffer = Vec::with_capacity(encrypted_frame.len() + x25519::PUBLIC_KEY_LENGTH); output_buffer.extend_from_slice(ephemeral_public_key.as_ref()); output_buffer.append(&mut encrypted_frame); @@ -92,19 +86,19 @@ pub fn decrypt_initial_kkt_frame( responder_private_key: &DHPrivateKey, encrypted_frame_bytes: &[u8], ) -> Result<(KKTSessionSecret, KKTFrame, KKTContext), KKTError> { - if encrypted_frame_bytes.len() < x25519::PUBLIC_KEY_SIZE + TAG_LEN + NONCE_LEN { + if encrypted_frame_bytes.len() < x25519::PUBLIC_KEY_LENGTH + TAG_LEN + NONCE_LEN { Err(KKTError::AEADError { info: "Encrypted KKT Frame is too short.", }) } else { let shared_secret = KKTSessionSecret::try_derive( responder_private_key, - &encrypted_frame_bytes[0..x25519::PUBLIC_KEY_SIZE], + &encrypted_frame_bytes[0..x25519::PUBLIC_KEY_LENGTH], )?; let (kkt_frame, kkt_context) = decrypt_kkt_frame( &shared_secret, - &encrypted_frame_bytes[x25519::PUBLIC_KEY_SIZE..], + &encrypted_frame_bytes[x25519::PUBLIC_KEY_LENGTH..], KKT_INITIAL_FRAME_AAD, )?; Ok((shared_secret, kkt_frame, kkt_context)) @@ -202,11 +196,11 @@ mod test { let responder_x25519_keypair = generate_keypair_x25519(&mut rng); let (session_secret_key, ephemeral_public_key) = - KKTSessionSecret::new(&mut rng, responder_x25519_keypair.public_key()); + KKTSessionSecret::new(&mut rng, &responder_x25519_keypair.pk); let shared_secret = KKTSessionSecret::try_derive( - responder_x25519_keypair.private_key(), - ephemeral_public_key.as_bytes().as_slice(), + responder_x25519_keypair.sk(), + ephemeral_public_key.as_ref(), ) .unwrap(); diff --git a/common/nym-kkt/src/key_utils.rs b/common/nym-kkt/src/key_utils.rs index 839a216cc4..fa31891208 100644 --- a/common/nym-kkt/src/key_utils.rs +++ b/common/nym-kkt/src/key_utils.rs @@ -2,6 +2,7 @@ use crate::ciphersuite::HashFunction; use std::collections::HashMap; use libcrux_kem::{MlKem768PrivateKey, MlKem768PublicKey}; +use libcrux_psq::handshake::types::DHKeyPair; use nym_kkt_ciphersuite::{DEFAULT_HASH_LEN, KEMKeyDigests}; use rand::{CryptoRng, RngCore}; @@ -17,15 +18,11 @@ where nym_crypto::asymmetric::ed25519::KeyPair::from_secret(secret_initiator, index.unwrap_or(0)) } -pub fn generate_keypair_x25519(rng: &mut R) -> nym_crypto::asymmetric::x25519::KeyPair +pub fn generate_keypair_x25519(rng: &mut R) -> DHKeyPair where R: RngCore + CryptoRng, { - let mut secret_initiator: [u8; 32] = [0u8; 32]; - rng.fill_bytes(&mut secret_initiator); - - let private_key = nym_crypto::asymmetric::x25519::PrivateKey::from_secret(secret_initiator); - private_key.into() + DHKeyPair::new(rng) } // (decapsulation_key, encapsulation_key) diff --git a/common/nym-kkt/src/lib.rs b/common/nym-kkt/src/lib.rs index a9a4fcdaa3..d24b295b0c 100644 --- a/common/nym-kkt/src/lib.rs +++ b/common/nym-kkt/src/lib.rs @@ -309,18 +309,14 @@ mod test { // encryption - initiator frame - let (i_session_secret, i_bytes) = encrypt_initial_kkt_frame( - &mut rng, - responder_x25519_keypair.public_key(), - &i_frame, - ) - .unwrap(); + let (i_session_secret, i_bytes) = + encrypt_initial_kkt_frame(&mut rng, &responder_x25519_keypair.pk, &i_frame) + .unwrap(); // decryption - initiator frame let (r_session_secret, i_frame_r, i_context_r) = - decrypt_initial_kkt_frame(responder_x25519_keypair.private_key(), &i_bytes) - .unwrap(); + decrypt_initial_kkt_frame(responder_x25519_keypair.sk(), &i_bytes).unwrap(); let (mut r_context, _) = responder_ingest_message(&i_context_r, None, None, &i_frame_r).unwrap(); @@ -367,18 +363,14 @@ mod test { // encryption - initiator frame - let (i_session_secret, i_bytes) = encrypt_initial_kkt_frame( - &mut rng, - responder_x25519_keypair.public_key(), - &i_frame, - ) - .unwrap(); + let (i_session_secret, i_bytes) = + encrypt_initial_kkt_frame(&mut rng, &responder_x25519_keypair.pk, &i_frame) + .unwrap(); // decryption - initiator frame let (r_session_secret, i_frame_r, r_context) = - decrypt_initial_kkt_frame(responder_x25519_keypair.private_key(), &i_bytes) - .unwrap(); + decrypt_initial_kkt_frame(responder_x25519_keypair.sk(), &i_bytes).unwrap(); let (mut r_context, r_obtained_key) = responder_ingest_message( &r_context, @@ -433,18 +425,14 @@ mod test { // encryption - initiator frame - let (i_session_secret, i_bytes) = encrypt_initial_kkt_frame( - &mut rng, - responder_x25519_keypair.public_key(), - &i_frame, - ) - .unwrap(); + let (i_session_secret, i_bytes) = + encrypt_initial_kkt_frame(&mut rng, &responder_x25519_keypair.pk, &i_frame) + .unwrap(); // decryption - initiator frame let (r_session_secret, i_frame_r, i_context_r) = - decrypt_initial_kkt_frame(responder_x25519_keypair.private_key(), &i_bytes) - .unwrap(); + decrypt_initial_kkt_frame(responder_x25519_keypair.sk(), &i_bytes).unwrap(); let (mut r_context, r_obtained_key) = responder_ingest_message( &i_context_r,