Update keytypes and remove lifetime specifier for mceliece keys

This commit is contained in:
Georgio Nicolas
2026-01-26 13:20:18 +01:00
parent d1a5342625
commit 2109beeef6
8 changed files with 504 additions and 421 deletions
Generated
+464 -374
View File
File diff suppressed because it is too large Load Diff
+4 -1
View File
@@ -23,7 +23,10 @@ libcrux-chacha20poly1305 = { git = "https://github.com/cryspen/libcrux" }
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 = { git = "https://github.com/georgio/classic-mceliece-rust", features = ["mceliece460896f", "zeroize"] }
classic-mceliece-rust = { version = "3.1.0", features = [
"mceliece460896f",
"zeroize"] }
libcrux-psq = { git = "https://github.com/cryspen/libcrux", features = ["classic-mceliece"] }
+12 -10
View File
@@ -3,18 +3,17 @@
use crate::error::KKTError;
use libcrux_kem::Algorithm;
use std::fmt::Debug;
pub use nym_kkt_ciphersuite::*;
pub enum EncapsulationKey<'a> {
pub enum EncapsulationKey {
MlKem768(libcrux_kem::MlKem768PublicKey),
XWing(libcrux_kem::PublicKey),
X25519(libcrux_kem::PublicKey),
McEliece(classic_mceliece_rust::PublicKey<'a>),
McEliece(libcrux_psq::classic_mceliece::PublicKey),
}
impl<'a> Debug for EncapsulationKey<'a> {
impl Debug for EncapsulationKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::MlKem768(_) => f.debug_tuple("MlKem768").finish(),
@@ -24,7 +23,7 @@ impl<'a> Debug for EncapsulationKey<'a> {
}
}
}
impl<'a> EncapsulationKey<'a> {
impl EncapsulationKey {
pub(crate) fn decode(kem: KEM, bytes: &[u8]) -> Result<Self, KKTError> {
match kem {
KEM::McEliece => {
@@ -38,7 +37,7 @@ impl<'a> EncapsulationKey<'a> {
// Size must be correct due to KKTFrame::from_bytes(message_bytes)?
public_key_bytes.clone_from_slice(bytes);
Ok(EncapsulationKey::McEliece(
classic_mceliece_rust::PublicKey::from(public_key_bytes),
libcrux_psq::classic_mceliece::PublicKey::from(public_key_bytes),
))
}
}
@@ -65,18 +64,21 @@ impl<'a> EncapsulationKey<'a> {
EncapsulationKey::XWing(public_key) | EncapsulationKey::X25519(public_key) => {
public_key.encode()
}
EncapsulationKey::McEliece(public_key) => Vec::from(public_key.as_array()),
EncapsulationKey::McEliece(public_key) => {
let bytes_ref: &[u8] = public_key.as_ref();
Vec::from(bytes_ref)
}
EncapsulationKey::MlKem768(public_key) => Vec::from(public_key.as_slice()),
}
}
}
pub enum DecapsulationKey<'a> {
pub enum DecapsulationKey {
MlKem768(libcrux_kem::MlKem768PrivateKey),
XWing(libcrux_kem::PrivateKey),
X25519(libcrux_kem::PrivateKey),
McEliece(classic_mceliece_rust::SecretKey<'a>),
McEliece(libcrux_psq::classic_mceliece::SecretKey),
}
impl<'a> Debug for DecapsulationKey<'a> {
impl Debug for DecapsulationKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::MlKem768(_) => f.debug_tuple("MlKem768").finish(),
+6 -7
View File
@@ -1,8 +1,6 @@
use crate::ciphersuite::HashFunction;
use std::collections::HashMap;
use classic_mceliece_rust::keypair_boxed;
use libcrux_kem::{MlKem768PrivateKey, MlKem768PublicKey};
use nym_kkt_ciphersuite::{DEFAULT_HASH_LEN, KEMKeyDigests};
use rand::{CryptoRng, RngCore};
@@ -60,18 +58,19 @@ where
}
// (decapsulation_key, encapsulation_key)
pub fn generate_keypair_mceliece<'a, R>(
pub fn generate_keypair_mceliece<R>(
rng: &mut R,
) -> (
classic_mceliece_rust::SecretKey<'a>,
classic_mceliece_rust::PublicKey<'a>,
libcrux_psq::classic_mceliece::SecretKey,
libcrux_psq::classic_mceliece::PublicKey,
)
where
// this is annoying because mceliece lib uses rand 0.8.5...
R: RngCore + CryptoRng,
{
let (encapsulation_key, decapsulation_key) = keypair_boxed(rng);
(decapsulation_key, encapsulation_key)
let kp = libcrux_psq::classic_mceliece::KeyPair::generate_key_pair(rng);
(kp.sk, kp.pk)
}
pub fn hash_key_bytes(
+3 -3
View File
@@ -98,13 +98,13 @@ pub fn request_kem_key<R: CryptoRng + RngCore>(
/// )?;
/// // Use gateway_kem_key for PSQ
/// ```
pub fn validate_kem_response<'a>(
pub fn validate_kem_response(
context: &mut KKTContext,
session_secret: &KKTSessionSecret,
responder_vk: &ed25519::PublicKey,
expected_key_hash: &[u8],
encrypted_response_bytes: &[u8],
) -> Result<EncapsulationKey<'a>, KKTError> {
) -> Result<EncapsulationKey, KKTError> {
let (responder_frame, responder_context) =
decrypt_kkt_response_frame(session_secret, encrypted_response_bytes)?;
@@ -159,7 +159,7 @@ pub fn handle_kem_request<'a, R>(
initiator_vk: Option<&ed25519::PublicKey>,
responder_signing_key: &ed25519::PrivateKey,
responder_dh_private_key: &x25519::PrivateKey,
responder_kem_key: &EncapsulationKey<'a>,
responder_kem_key: &EncapsulationKey,
) -> Result<Vec<u8>, KKTError>
where
R: RngCore + CryptoRng,
+8 -8
View File
@@ -10,12 +10,12 @@ use crate::{
key_utils::validate_encapsulation_key,
};
pub fn initiator_process<'a, R>(
pub fn initiator_process<R>(
rng: &mut R,
mode: KKTMode,
ciphersuite: Ciphersuite,
signing_key: &ed25519::PrivateKey,
own_encapsulation_key: Option<&EncapsulationKey<'a>>,
own_encapsulation_key: Option<&EncapsulationKey>,
) -> Result<(KKTContext, KKTFrame), KKTError>
where
R: CryptoRng + RngCore,
@@ -72,13 +72,13 @@ where
Ok((context, KKTFrame::new(context_bytes, &[], session_id, &[])))
}
pub fn initiator_ingest_response<'a>(
pub fn initiator_ingest_response(
own_context: &mut KKTContext,
remote_frame: &KKTFrame,
remote_context: &KKTContext,
remote_verification_key: &ed25519::PublicKey,
expected_hash: &[u8],
) -> Result<EncapsulationKey<'a>, KKTError> {
) -> Result<EncapsulationKey, KKTError> {
check_compatibility(own_context, remote_context)?;
match remote_context.status() {
KKTStatus::Ok => {
@@ -124,12 +124,12 @@ pub fn initiator_ingest_response<'a>(
// todo: figure out how to handle errors using status codes
pub fn responder_ingest_message<'a>(
pub fn responder_ingest_message(
remote_context: &KKTContext,
remote_verification_key: Option<&ed25519::PublicKey>,
expected_hash: Option<&[u8]>,
remote_frame: &KKTFrame,
) -> Result<(KKTContext, Option<EncapsulationKey<'a>>), KKTError> {
) -> Result<(KKTContext, Option<EncapsulationKey>), KKTError> {
let own_context = remote_context.derive_responder_header()?;
match remote_context.role() {
@@ -200,11 +200,11 @@ pub fn responder_ingest_message<'a>(
}
}
pub fn responder_process<'a>(
pub fn responder_process(
own_context: &mut KKTContext,
session_id: KKTSessionId,
signing_key: &ed25519::PrivateKey,
encapsulation_key: &EncapsulationKey<'a>,
encapsulation_key: &EncapsulationKey,
) -> Result<KKTFrame, KKTError> {
let body = encapsulation_key.encode();
+5 -14
View File
@@ -62,13 +62,14 @@ 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_digests = match &self.mlkem {
let expected_kem_key_digests = match &self.kem_psq {
None => HashMap::new(),
Some(kem_keys) => {
let hashes = nym_kkt::key_utils::produce_key_digests(kem_keys.1.as_slice());
let hashes =
nym_kkt::key_utils::produce_key_digests(kem_keys.public_key().as_bytes());
let mut digests = HashMap::new();
digests.insert(KEM::MlKem768, hashes);
digests.insert(KEM::X25519, hashes);
digests
}
};
@@ -81,7 +82,7 @@ impl LpLocalPeer {
// this is only exposed in tests as ideally we should be storing the proper types to begin with
#[cfg(test)]
pub fn encapsulate_kem_key(&self) -> Option<nym_kkt::ciphersuite::EncapsulationKey<'_>> {
pub fn encapsulate_kem_key(&self) -> Option<nym_kkt::ciphersuite::EncapsulationKey> {
let pk_bytes = self.kem_psq.as_ref()?.public_key().to_bytes();
let libcrux_pk =
libcrux_kem::PublicKey::decode(libcrux_kem::Algorithm::X25519, &pk_bytes).ok()?;
@@ -106,16 +107,6 @@ impl Debug for LpLocalPeer {
}
),
)
// .field(
// "mceliece",
// &format!(
// "mceliece_public_key: {}",
// match &self.mceliece {
// Some(keypair) => format!("{:?}", keypair.1.as_slice()),
// None => format!("None"),
// }
// ),
// )
.finish()
}
}
+2 -4
View File
@@ -90,7 +90,7 @@ pub enum KKTState {
/// KKT exchange completed (initiator received and validated KEM key).
Completed {
/// Responder's KEM public key for PSQ encapsulation
kem_pk: Box<EncapsulationKey<'static>>,
kem_pk: Box<EncapsulationKey>,
},
/// Responder processed a KKT request and sent response.
@@ -538,9 +538,7 @@ impl LpSession {
// TODO: missing Zeroize
/// Convert local KEM PSQ keys to typed EncapsulationKey / EncapsulationKey
pub fn encapsulated_kem_keys(
&self,
) -> Result<(DecapsulationKey<'_>, EncapsulationKey<'_>), LpError> {
pub fn encapsulated_kem_keys(&self) -> Result<(DecapsulationKey, EncapsulationKey), LpError> {
let kem_keys = self
.local_peer
.kem_psq