Brought Example up to spec
Some checks failed
CI / checks (push) Failing after 3m29s

This commit is contained in:
Alex Emmet 2026-07-19 00:29:24 +02:00
commit 1b796d0ce7
46 changed files with 1755 additions and 691 deletions

View file

@ -200,6 +200,35 @@ impl Keyring {
}
}
/// Generates the independent KEM, classical-signature, and PQ-signature keys concurrently.
#[cfg(all(
feature = "mlkem-tls",
feature = "ml-dsa",
feature = "ed25519-dalek",
feature = "parallel"
))]
pub async fn generate_parallel() -> Self {
let kem_handle = tokio::task::spawn_blocking(crate::kem::HybridKem::generate_keypair);
let ed_handle = tokio::task::spawn_blocking(crate::sign::Ed25519Signer::generate);
let pq_handle = tokio::task::spawn_blocking(crate::sign::MlDsaSigner::generate);
let (kem_result, ed_result, pq_result) = tokio::join!(kem_handle, ed_handle, pq_handle);
let (kem_sk, kem_pk) = kem_result.expect("key generation task must not panic");
let (_ed_signer, sig_cl_sk, sig_cl_pk) =
ed_result.expect("key generation task must not panic");
let (_pq_signer, sig_pq_sk, sig_pq_pk) =
pq_result.expect("key generation task must not panic");
Self {
kem_public_key: kem_pk,
kem_secret_key: kem_sk,
sig_pq_public_key: sig_pq_pk,
sig_pq_secret_key: sig_pq_sk,
sig_cl_public_key: sig_cl_pk,
sig_cl_secret_key: sig_cl_sk,
}
}
pub fn public_key_bundle(&self) -> PublicKeyBundle {
PublicKeyBundle {
kem_public_key: self.kem_public_key.clone(),

View file

@ -3,6 +3,10 @@ pub mod auth;
pub mod error;
pub mod keypair;
use std::sync::Once;
static CRYPTO_INIT: Once = Once::new();
#[cfg(feature = "sha2")]
pub mod hash;
@ -12,6 +16,9 @@ pub mod kdf;
#[cfg(any(feature = "ed25519-dalek", feature = "ml-dsa"))]
pub mod sign;
#[cfg(all(feature = "ed25519-dalek", feature = "ml-dsa", feature = "parallel"))]
pub mod sign_parallel;
#[cfg(any(feature = "ed25519-dalek", feature = "ml-dsa"))]
pub use sign::SigAlgorithm;
@ -59,6 +66,16 @@ pub use kem::{Encapsulated, HybridKem};
pub use enc::EncryptionType;
/// Install Rustls' AWS-LC provider once for the entire process.
///
/// Rustls only accepts one process-wide default provider. Calling this helper
/// from every TLS entry point makes that initialization idempotent.
pub fn ensure_crypto_provider() {
CRYPTO_INIT.call_once(|| {
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
});
}
#[cfg(all(feature = "mlkem-tls", feature = "hkdf"))]
pub use enc::{decrypt_with, encrypt_for};

View file

@ -0,0 +1,73 @@
//! Parallel helpers for dual (classical + post-quantum) signatures.
use std::sync::Arc;
use tokio::task;
use crate::{
CryptoError, SignaturePqPublicKey, SignaturePublicKey, SignatureScheme, verify_ed25519,
verify_ml_dsa,
};
/// Signs a message with the classical and PQ schemes concurrently on Tokio's blocking pool.
pub async fn sign_dual_parallel<S1, S2>(
ed_signer: S1,
pq_signer: S2,
message: Vec<u8>,
) -> Result<(Vec<u8>, Vec<u8>), CryptoError>
where
S1: SignatureScheme + Send + 'static,
S2: SignatureScheme + Send + 'static,
{
let ed_message = message.clone();
let ed_handle = task::spawn_blocking(move || ed_signer.sign(&ed_message));
let pq_handle = task::spawn_blocking(move || pq_signer.sign(&message));
let (ed_result, pq_result) = tokio::join!(ed_handle, pq_handle);
let ed_signature = ed_result.map_err(|_| CryptoError::SigningFailed)??;
let pq_signature = pq_result.map_err(|_| CryptoError::SigningFailed)??;
Ok((ed_signature, pq_signature))
}
/// Signs with an owned classical signer and a shared PQ signer.
///
/// This avoids reconstructing the ML-DSA signing key when a host signs both
/// the challenge and the final response in one authentication handshake.
pub async fn sign_dual_parallel_shared_pq<S1, S2>(
ed_signer: S1,
pq_signer: Arc<S2>,
message: Vec<u8>,
) -> Result<(Vec<u8>, Vec<u8>), CryptoError>
where
S1: SignatureScheme + Send + 'static,
S2: SignatureScheme + Send + Sync + 'static,
{
let ed_message = message.clone();
let ed_handle = task::spawn_blocking(move || ed_signer.sign(&ed_message));
let pq_handle = task::spawn_blocking(move || pq_signer.sign(&message));
let (ed_result, pq_result) = tokio::join!(ed_handle, pq_handle);
let ed_signature = ed_result.map_err(|_| CryptoError::SigningFailed)??;
let pq_signature = pq_result.map_err(|_| CryptoError::SigningFailed)??;
Ok((ed_signature, pq_signature))
}
/// Verifies the classical and PQ signatures concurrently on Tokio's blocking pool.
pub async fn verify_dual_parallel(
ed_public_key: SignaturePublicKey,
pq_public_key: SignaturePqPublicKey,
message: Vec<u8>,
ed_signature: Vec<u8>,
pq_signature: Vec<u8>,
) -> Result<(), CryptoError> {
let ed_message = message.clone();
let ed_handle =
task::spawn_blocking(move || verify_ed25519(&ed_public_key, &ed_message, &ed_signature));
let pq_handle =
task::spawn_blocking(move || verify_ml_dsa(&pq_public_key, &message, &pq_signature));
let (ed_result, pq_result) = tokio::join!(ed_handle, pq_handle);
ed_result.map_err(|_| CryptoError::VerificationFailed)??;
pq_result.map_err(|_| CryptoError::VerificationFailed)??;
Ok(())
}