Introduce newer mlkem key types
This commit is contained in:
@@ -25,6 +25,9 @@ zeroize = { workspace = true, features = ["zeroize_derive"] }
|
||||
classic-mceliece-rust = { git = "https://github.com/georgio/classic-mceliece-rust", features = ["mceliece460896f", "zeroize"] }
|
||||
|
||||
|
||||
libcrux-psq = { git = "https://github.com/cryspen/libcrux", features = ["classic-mceliece"] }
|
||||
libcrux-ml-kem = { git = "https://github.com/cryspen/libcrux"}
|
||||
|
||||
[dev-dependencies]
|
||||
rand_chacha = "0.9.0"
|
||||
anyhow = { workspace = true }
|
||||
|
||||
@@ -12,7 +12,10 @@ use nym_kkt::{
|
||||
ciphersuite::{Ciphersuite, EncapsulationKey, HashFunction, KEM, SignatureScheme},
|
||||
context::KKTMode,
|
||||
frame::KKTFrame,
|
||||
key_utils::{generate_keypair_libcrux, generate_keypair_mceliece, hash_encapsulation_key},
|
||||
key_utils::{
|
||||
generate_keypair_libcrux, generate_keypair_mceliece, generate_keypair_mlkem,
|
||||
hash_encapsulation_key,
|
||||
},
|
||||
session::{
|
||||
anonymous_initiator_process, initiator_ingest_response, initiator_process,
|
||||
responder_ingest_message, responder_process,
|
||||
@@ -69,8 +72,8 @@ pub fn kkt_benchmark(c: &mut Criterion) {
|
||||
|
||||
let (responder_kem_public_key, initiator_kem_public_key) = match kem {
|
||||
KEM::MlKem768 => (
|
||||
EncapsulationKey::MlKem768(generate_keypair_libcrux(&mut rng, kem).unwrap().1),
|
||||
EncapsulationKey::MlKem768(generate_keypair_libcrux(&mut rng, kem).unwrap().1),
|
||||
EncapsulationKey::MlKem768(generate_keypair_mlkem(&mut rng).1),
|
||||
EncapsulationKey::MlKem768(generate_keypair_mlkem(&mut rng).1),
|
||||
),
|
||||
KEM::XWing => (
|
||||
EncapsulationKey::XWing(generate_keypair_libcrux(&mut rng, kem).unwrap().1),
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
// Copyright 2025 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::error::KKTError;
|
||||
use libcrux_kem::{Algorithm, MlKem768PublicKey};
|
||||
use nym_crypto::asymmetric::ed25519;
|
||||
use std::fmt::Display;
|
||||
|
||||
use crate::error::KKTError;
|
||||
use std::fmt::{Debug, Display};
|
||||
|
||||
pub const DEFAULT_HASH_LEN: usize = 32;
|
||||
const _: () = assert!(DEFAULT_HASH_LEN <= u8::MAX as usize);
|
||||
@@ -34,17 +33,20 @@ impl Display for HashFunction {
|
||||
}
|
||||
|
||||
pub enum EncapsulationKey<'a> {
|
||||
MlKem768(libcrux_kem::PublicKey),
|
||||
MlKem768(libcrux_kem::MlKem768PublicKey),
|
||||
XWing(libcrux_kem::PublicKey),
|
||||
X25519(libcrux_kem::PublicKey),
|
||||
McEliece(classic_mceliece_rust::PublicKey<'a>),
|
||||
}
|
||||
|
||||
pub enum DecapsulationKey<'a> {
|
||||
MlKem768(libcrux_kem::PrivateKey),
|
||||
XWing(libcrux_kem::PrivateKey),
|
||||
X25519(libcrux_kem::PrivateKey),
|
||||
McEliece(classic_mceliece_rust::SecretKey<'a>),
|
||||
impl<'a> Debug for EncapsulationKey<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::MlKem768(_) => f.debug_tuple("MlKem768").finish(),
|
||||
Self::XWing(_) => f.debug_tuple("XWing").finish(),
|
||||
Self::X25519(_) => f.debug_tuple("X25519").finish(),
|
||||
Self::McEliece(_) => f.debug_tuple("McEliece").finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a> EncapsulationKey<'a> {
|
||||
pub(crate) fn decode(kem: KEM, bytes: &[u8]) -> Result<Self, KKTError> {
|
||||
@@ -68,10 +70,13 @@ impl<'a> EncapsulationKey<'a> {
|
||||
map_kem_to_libcrux_kem(kem)?,
|
||||
bytes,
|
||||
)?)),
|
||||
KEM::MlKem768 => Ok(EncapsulationKey::MlKem768(libcrux_kem::PublicKey::decode(
|
||||
map_kem_to_libcrux_kem(kem)?,
|
||||
bytes,
|
||||
)?)),
|
||||
KEM::MlKem768 => Ok(EncapsulationKey::MlKem768(
|
||||
libcrux_kem::MlKem768PublicKey::try_from(bytes).map_err(|_| {
|
||||
KKTError::DecodingError {
|
||||
info: "MlKem Encapsulation Key Decoding Failure",
|
||||
}
|
||||
})?,
|
||||
)),
|
||||
KEM::XWing => Ok(EncapsulationKey::XWing(libcrux_kem::PublicKey::decode(
|
||||
map_kem_to_libcrux_kem(kem)?,
|
||||
bytes,
|
||||
@@ -81,10 +86,27 @@ impl<'a> EncapsulationKey<'a> {
|
||||
|
||||
pub fn encode(&self) -> Vec<u8> {
|
||||
match self {
|
||||
EncapsulationKey::XWing(public_key)
|
||||
| EncapsulationKey::MlKem768(public_key)
|
||||
| EncapsulationKey::X25519(public_key) => public_key.encode(),
|
||||
EncapsulationKey::XWing(public_key) | EncapsulationKey::X25519(public_key) => {
|
||||
public_key.encode()
|
||||
}
|
||||
EncapsulationKey::McEliece(public_key) => Vec::from(public_key.as_array()),
|
||||
EncapsulationKey::MlKem768(public_key) => Vec::from(public_key.as_slice()),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub enum DecapsulationKey<'a> {
|
||||
MlKem768(libcrux_kem::MlKem768PrivateKey),
|
||||
XWing(libcrux_kem::PrivateKey),
|
||||
X25519(libcrux_kem::PrivateKey),
|
||||
McEliece(classic_mceliece_rust::SecretKey<'a>),
|
||||
}
|
||||
impl<'a> Debug for DecapsulationKey<'a> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::MlKem768(_) => f.debug_tuple("MlKem768").finish(),
|
||||
Self::XWing(_) => f.debug_tuple("XWing").finish(),
|
||||
Self::X25519(_) => f.debug_tuple("X25519").finish(),
|
||||
Self::McEliece(_) => f.debug_tuple("McEliece").finish(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,9 @@ pub enum KKTError {
|
||||
#[error("{}", info)]
|
||||
AEADError { info: &'static str },
|
||||
|
||||
#[error("{}", info)]
|
||||
DecodingError { info: &'static str },
|
||||
|
||||
#[error("Generic libcrux error")]
|
||||
LibcruxError,
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::ciphersuite::HashFunction;
|
||||
|
||||
use classic_mceliece_rust::keypair_boxed;
|
||||
|
||||
use libcrux_kem::{MlKem768PrivateKey, MlKem768PublicKey};
|
||||
use libcrux_sha3;
|
||||
use rand::{CryptoRng, RngCore};
|
||||
|
||||
@@ -37,9 +38,6 @@ where
|
||||
R: RngCore + CryptoRng,
|
||||
{
|
||||
match kem {
|
||||
crate::ciphersuite::KEM::MlKem768 => {
|
||||
Ok(libcrux_kem::key_gen(libcrux_kem::Algorithm::MlKem768, rng)?)
|
||||
}
|
||||
crate::ciphersuite::KEM::XWing => Ok(libcrux_kem::key_gen(
|
||||
libcrux_kem::Algorithm::XWingKemDraft06,
|
||||
rng,
|
||||
@@ -52,6 +50,14 @@ where
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_keypair_mlkem<R>(rng: &mut R) -> (MlKem768PrivateKey, MlKem768PublicKey)
|
||||
where
|
||||
R: RngCore + CryptoRng,
|
||||
{
|
||||
libcrux_ml_kem::mlkem768::rand::generate_key_pair(rng).into_parts()
|
||||
}
|
||||
|
||||
// (decapsulation_key, encapsulation_key)
|
||||
pub fn generate_keypair_mceliece<'a, R>(
|
||||
rng: &mut R,
|
||||
|
||||
@@ -28,7 +28,7 @@ mod test {
|
||||
frame::KKTFrame,
|
||||
key_utils::{
|
||||
generate_keypair_ed25519, generate_keypair_libcrux, generate_keypair_mceliece,
|
||||
generate_keypair_x25519, hash_encapsulation_key,
|
||||
generate_keypair_mlkem, generate_keypair_x25519, hash_encapsulation_key,
|
||||
},
|
||||
session::{
|
||||
anonymous_initiator_process, initiator_ingest_response, initiator_process,
|
||||
@@ -63,12 +63,8 @@ mod test {
|
||||
|
||||
let (responder_kem_public_key, initiator_kem_public_key) = match kem {
|
||||
KEM::MlKem768 => (
|
||||
EncapsulationKey::MlKem768(
|
||||
generate_keypair_libcrux(&mut rng, kem).unwrap().1,
|
||||
),
|
||||
EncapsulationKey::MlKem768(
|
||||
generate_keypair_libcrux(&mut rng, kem).unwrap().1,
|
||||
),
|
||||
EncapsulationKey::MlKem768(generate_keypair_mlkem(&mut rng).1),
|
||||
EncapsulationKey::MlKem768(generate_keypair_mlkem(&mut rng).1),
|
||||
),
|
||||
KEM::XWing => (
|
||||
EncapsulationKey::XWing(generate_keypair_libcrux(&mut rng, kem).unwrap().1),
|
||||
@@ -269,12 +265,8 @@ mod test {
|
||||
|
||||
let (responder_kem_public_key, initiator_kem_public_key) = match kem {
|
||||
KEM::MlKem768 => (
|
||||
EncapsulationKey::MlKem768(
|
||||
generate_keypair_libcrux(&mut rng, kem).unwrap().1,
|
||||
),
|
||||
EncapsulationKey::MlKem768(
|
||||
generate_keypair_libcrux(&mut rng, kem).unwrap().1,
|
||||
),
|
||||
EncapsulationKey::MlKem768(generate_keypair_mlkem(&mut rng).1),
|
||||
EncapsulationKey::MlKem768(generate_keypair_mlkem(&mut rng).1),
|
||||
),
|
||||
KEM::XWing => (
|
||||
EncapsulationKey::XWing(generate_keypair_libcrux(&mut rng, kem).unwrap().1),
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
// Copyright 2026 - Nym Technologies SA <contact@nymtech.net>
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use libcrux_kem::{MlKem768PrivateKey, MlKem768PublicKey};
|
||||
use nym_crypto::asymmetric::{ed25519, x25519};
|
||||
use std::fmt::Debug;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Representation of a local Lewes Protocol peer
|
||||
/// encapsulating all the known information and keys.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct LpLocalPeer {
|
||||
/// Local Ed25519 keys for PSQ authentication
|
||||
pub(crate) ed25519: Arc<ed25519::KeyPair>,
|
||||
@@ -14,8 +16,11 @@ pub struct LpLocalPeer {
|
||||
/// Local x25519 keys (Noise static key)
|
||||
pub(crate) x25519: Arc<x25519::KeyPair>,
|
||||
|
||||
/// Local KEM key used for PSQ
|
||||
/// Local KEM key used for PSQ (x25519: to deprecate)
|
||||
pub(crate) kem_psq: Option<Arc<x25519::KeyPair>>,
|
||||
|
||||
/// Local MlKem keypair used for PSQ
|
||||
pub(crate) mlkem: Option<(Arc<MlKem768PrivateKey>, Arc<MlKem768PublicKey>)>,
|
||||
}
|
||||
|
||||
impl LpLocalPeer {
|
||||
@@ -24,15 +29,26 @@ impl LpLocalPeer {
|
||||
ed25519,
|
||||
x25519,
|
||||
kem_psq: None,
|
||||
mlkem: None,
|
||||
// mceliece: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
// #[must_use]
|
||||
pub fn with_kem_psq_key(mut self, key: Arc<x25519::KeyPair>) -> Self {
|
||||
self.kem_psq = Some(key);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_mlkem_keypair(
|
||||
mut self,
|
||||
decapsulation_key: Arc<MlKem768PrivateKey>,
|
||||
encapsulation_key: Arc<MlKem768PublicKey>,
|
||||
) -> Self {
|
||||
self.mlkem = Some((decapsulation_key, encapsulation_key));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn ed25519(&self) -> &Arc<ed25519::KeyPair> {
|
||||
&self.ed25519
|
||||
}
|
||||
@@ -44,12 +60,12 @@ impl LpLocalPeer {
|
||||
/// Convert this `LpLocalPeer` into a valid `LpRemotePeer` that can be used within tests
|
||||
#[doc(hidden)]
|
||||
pub fn as_remote(&self) -> LpRemotePeer {
|
||||
let expected_kem_key_digest = match &self.kem_psq {
|
||||
let expected_kem_key_digest = match &self.mlkem {
|
||||
None => Vec::new(),
|
||||
Some(kem_keys) => nym_kkt::key_utils::hash_key_bytes(
|
||||
&nym_kkt::ciphersuite::HashFunction::Blake3,
|
||||
nym_kkt::ciphersuite::DEFAULT_HASH_LEN,
|
||||
kem_keys.public_key().as_bytes(),
|
||||
kem_keys.1.as_slice(),
|
||||
),
|
||||
};
|
||||
LpRemotePeer {
|
||||
@@ -70,6 +86,36 @@ impl LpLocalPeer {
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for LpLocalPeer {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("LpLocalPeer")
|
||||
.field("ed25519", &self.ed25519)
|
||||
.field("x25519", &self.x25519)
|
||||
.field("kem_psq", &self.kem_psq)
|
||||
.field(
|
||||
"mlkem",
|
||||
&format!(
|
||||
"mlkem_public_key: {}",
|
||||
match &self.mlkem {
|
||||
Some(keypair) => format!("{:?}", keypair.1.as_slice()),
|
||||
None => format!("None"),
|
||||
}
|
||||
),
|
||||
)
|
||||
// .field(
|
||||
// "mceliece",
|
||||
// &format!(
|
||||
// "mceliece_public_key: {}",
|
||||
// match &self.mceliece {
|
||||
// Some(keypair) => format!("{:?}", keypair.1.as_slice()),
|
||||
// None => format!("None"),
|
||||
// }
|
||||
// ),
|
||||
// )
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// Representation of a remote Lewes Protocol peer
|
||||
/// encapsulating all the known information and keys.
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -117,15 +163,21 @@ pub fn mock_peer() -> LpLocalPeer {
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn random_peer<R: rand::CryptoRng + rand::RngCore>(rng: &mut R) -> LpLocalPeer {
|
||||
pub fn random_peer<'a, R: rand::CryptoRng + rand::RngCore>(rng: &mut R) -> LpLocalPeer {
|
||||
use nym_kkt::key_utils::generate_keypair_mlkem;
|
||||
|
||||
let ed25519 = Arc::new(ed25519::KeyPair::new(rng));
|
||||
let x25519 = Arc::new(ed25519.to_x25519());
|
||||
let kem_psq = Some(x25519.clone());
|
||||
|
||||
let mlkem_keypair = generate_keypair_mlkem(&mut rand09::rng());
|
||||
|
||||
LpLocalPeer {
|
||||
ed25519,
|
||||
x25519,
|
||||
kem_psq,
|
||||
mlkem: Some((Arc::new(mlkem_keypair.0), Arc::new(mlkem_keypair.1))),
|
||||
// mceliece: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user