use crate::hybrid::sig_hybrid::{
self, HybridSigPublicKey, HybridSigSecretKey, HybridSignature, HybridSignatureError,
};
use crate::unified_api::error::{CoreError, Result};
use crate::unified_api::zero_trust::SecurityMode;
use crate::primitives::resource_limits::validate_signature_size;
pub fn generate_hybrid_signing_keypair(
mode: SecurityMode,
) -> Result<(HybridSigPublicKey, HybridSigSecretKey)> {
mode.validate()?;
sig_hybrid::generate_keypair().map_err(|e| {
CoreError::SignatureFailed(format!("Hybrid signing keypair generation failed: {}", e))
})
}
pub fn sign_hybrid(
message: &[u8],
sk: &HybridSigSecretKey,
mode: SecurityMode,
) -> Result<HybridSignature> {
mode.validate()?;
validate_signature_size(message.len())
.map_err(|e| CoreError::ResourceExceeded(e.to_string()))?;
sig_hybrid::sign(sk, message).map_err(hybrid_sig_error_to_core)
}
pub fn verify_hybrid_signature(
message: &[u8],
signature: &HybridSignature,
pk: &HybridSigPublicKey,
mode: SecurityMode,
) -> Result<bool> {
mode.validate()?;
validate_signature_size(message.len())
.map_err(|e| CoreError::ResourceExceeded(e.to_string()))?;
sig_hybrid::verify(pk, message, signature).map_err(hybrid_sig_error_to_core)
}
#[inline]
pub fn generate_hybrid_signing_keypair_with_config(
config: &crate::unified_api::CoreConfig,
mode: SecurityMode,
) -> Result<(HybridSigPublicKey, HybridSigSecretKey)> {
config.validate()?;
generate_hybrid_signing_keypair(mode)
}
#[inline]
pub fn sign_hybrid_with_config(
message: &[u8],
sk: &HybridSigSecretKey,
config: &crate::unified_api::CoreConfig,
mode: SecurityMode,
) -> Result<HybridSignature> {
config.validate()?;
sign_hybrid(message, sk, mode)
}
#[inline]
pub fn verify_hybrid_signature_with_config(
message: &[u8],
signature: &HybridSignature,
pk: &HybridSigPublicKey,
config: &crate::unified_api::CoreConfig,
mode: SecurityMode,
) -> Result<bool> {
config.validate()?;
verify_hybrid_signature(message, signature, pk, mode)
}
#[inline]
pub fn generate_hybrid_signing_keypair_unverified()
-> Result<(HybridSigPublicKey, HybridSigSecretKey)> {
generate_hybrid_signing_keypair(SecurityMode::Unverified)
}
#[inline]
pub fn sign_hybrid_unverified(message: &[u8], sk: &HybridSigSecretKey) -> Result<HybridSignature> {
sign_hybrid(message, sk, SecurityMode::Unverified)
}
#[inline]
pub fn verify_hybrid_signature_unverified(
message: &[u8],
signature: &HybridSignature,
pk: &HybridSigPublicKey,
) -> Result<bool> {
verify_hybrid_signature(message, signature, pk, SecurityMode::Unverified)
}
fn hybrid_sig_error_to_core(e: HybridSignatureError) -> CoreError {
match e {
HybridSignatureError::MlDsaError(msg) => {
CoreError::SignatureFailed(format!("Hybrid ML-DSA error: {}", msg))
}
HybridSignatureError::Ed25519Error(msg) => {
CoreError::SignatureFailed(format!("Hybrid Ed25519 error: {}", msg))
}
HybridSignatureError::VerificationFailed(_msg) => CoreError::VerificationFailed,
HybridSignatureError::InvalidKeyMaterial(msg) => {
CoreError::InvalidKey(format!("Hybrid key material error: {}", msg))
}
HybridSignatureError::CryptoError(msg) => {
CoreError::SignatureFailed(format!("Hybrid crypto error: {}", msg))
}
}
}
#[cfg(test)]
#[allow(
clippy::panic,
clippy::unwrap_used,
clippy::expect_used,
clippy::indexing_slicing,
clippy::arithmetic_side_effects,
clippy::panic_in_result_fn,
clippy::unnecessary_wraps,
clippy::redundant_clone,
clippy::useless_vec,
clippy::cast_possible_truncation,
clippy::cast_sign_loss,
clippy::clone_on_copy,
clippy::len_zero,
clippy::single_match,
clippy::unnested_or_patterns,
clippy::default_constructed_unit_structs,
clippy::redundant_closure_for_method_calls,
clippy::semicolon_if_nothing_returned,
clippy::unnecessary_unwrap,
clippy::redundant_pattern_matching,
clippy::missing_const_for_thread_local,
clippy::get_first,
clippy::float_cmp,
clippy::needless_borrows_for_generic_args,
unused_qualifications
)]
mod tests {
use super::*;
#[test]
fn test_hybrid_sig_roundtrip_unverified_roundtrip() -> Result<()> {
let (pk, sk) = generate_hybrid_signing_keypair_unverified()?;
let message = b"Hello, hybrid signatures!";
let signature = sign_hybrid_unverified(message, &sk)?;
let valid = verify_hybrid_signature_unverified(message, &signature, &pk)?;
assert!(valid, "Hybrid signature roundtrip should succeed");
Ok(())
}
#[test]
fn test_hybrid_sig_roundtrip_with_mode_roundtrip() -> Result<()> {
let (pk, sk) = generate_hybrid_signing_keypair(SecurityMode::Unverified)?;
let message = b"SecurityMode test";
let signature = sign_hybrid(message, &sk, SecurityMode::Unverified)?;
let valid = verify_hybrid_signature(message, &signature, &pk, SecurityMode::Unverified)?;
assert!(valid);
Ok(())
}
#[test]
fn test_hybrid_sig_with_config_succeeds() -> Result<()> {
let config = crate::unified_api::CoreConfig::default();
let (pk, sk) =
generate_hybrid_signing_keypair_with_config(&config, SecurityMode::Unverified)?;
let message = b"Config test";
let signature = sign_hybrid_with_config(message, &sk, &config, SecurityMode::Unverified)?;
let valid = verify_hybrid_signature_with_config(
message,
&signature,
&pk,
&config,
SecurityMode::Unverified,
)?;
assert!(valid);
Ok(())
}
#[test]
fn test_hybrid_sig_wrong_message_fails() -> Result<()> {
let (pk, sk) = generate_hybrid_signing_keypair_unverified()?;
let signature = sign_hybrid_unverified(b"correct message", &sk)?;
let result = verify_hybrid_signature_unverified(b"wrong message", &signature, &pk);
assert!(result.is_err(), "Wrong message should fail verification");
Ok(())
}
#[test]
fn test_hybrid_sig_wrong_key_fails() -> Result<()> {
let (_pk1, sk1) = generate_hybrid_signing_keypair_unverified()?;
let (pk2, _sk2) = generate_hybrid_signing_keypair_unverified()?;
let message = b"cross-key test";
let signature = sign_hybrid_unverified(message, &sk1)?;
let result = verify_hybrid_signature_unverified(message, &signature, &pk2);
assert!(result.is_err(), "Wrong key should fail verification");
Ok(())
}
#[test]
fn test_hybrid_sig_empty_message_succeeds() -> Result<()> {
let (pk, sk) = generate_hybrid_signing_keypair_unverified()?;
let message = b"";
let signature = sign_hybrid_unverified(message, &sk)?;
let valid = verify_hybrid_signature_unverified(message, &signature, &pk)?;
assert!(valid, "Empty message should sign and verify");
Ok(())
}
#[test]
fn test_hybrid_sig_large_message_succeeds() -> Result<()> {
let (pk, sk) = generate_hybrid_signing_keypair_unverified()?;
let message = vec![0xAB; 10_000];
let signature = sign_hybrid_unverified(&message, &sk)?;
let valid = verify_hybrid_signature_unverified(&message, &signature, &pk)?;
assert!(valid, "Large message should sign and verify");
Ok(())
}
#[test]
fn test_hybrid_sig_verified_session_succeeds() -> Result<()> {
let (auth_pk, auth_sk) = crate::unified_api::convenience::keygen::generate_keypair()?;
let session = crate::unified_api::zero_trust::VerifiedSession::establish(
auth_pk.as_slice(),
auth_sk.as_ref(),
)?;
let (pk, sk) = generate_hybrid_signing_keypair(SecurityMode::Verified(&session))?;
let message = b"Verified session test";
let signature = sign_hybrid(message, &sk, SecurityMode::Verified(&session))?;
let valid =
verify_hybrid_signature(message, &signature, &pk, SecurityMode::Verified(&session))?;
assert!(valid);
Ok(())
}
}