use crate::algorithms::{HybridCrypto, MlDsa44, MlKem768};
use crate::bridge::{CryptographyBridge, KeyEncapsulationBridge};
use crate::errors::{CryptoError, Result};
use crate::types::{
Algorithm, ClassicalAlgorithm, HybridKeyPair, HybridPolicy, HybridPublicBundle,
PostQuantumAlgorithm, PublicKey, SecurityLevel, TransitionMode,
};
use zeroize::Zeroizing;
pub struct QuantumSigner {
bridge: MlDsa44,
public_key: <MlDsa44 as CryptographyBridge>::PublicKey,
secret_key: <MlDsa44 as CryptographyBridge>::SecretKey,
}
impl QuantumSigner {
pub fn new() -> Result<Self> {
let bridge = MlDsa44;
let (public_key, secret_key) = bridge.key_generator()?;
Ok(Self {
bridge,
public_key,
secret_key,
})
}
pub fn sign(&self, message: &[u8]) -> Result<Vec<u8>> {
let signature = self.bridge.sign(&self.secret_key, message)?;
Ok(self.bridge.signature_to_bytes(&signature))
}
pub fn verify(&self, message: &[u8], signature: &[u8]) -> Result<bool> {
let sig_vec = signature.to_vec();
self.bridge.verify(&self.public_key, message, &sig_vec)
}
pub fn public_key_bytes(&self) -> Vec<u8> {
self.bridge.public_key_to_bytes(&self.public_key)
}
}
pub struct HybridSigner {
hybrid_crypto: HybridCrypto,
hybrid_keypair: HybridKeyPair,
}
impl HybridSigner {
pub fn new() -> Result<Self> {
let hybrid_crypto = HybridCrypto::new_default();
let hybrid_keypair = hybrid_crypto.generate_hybrid_keypair()?;
Ok(Self {
hybrid_crypto,
hybrid_keypair,
})
}
pub fn with_policy(policy: HybridPolicy) -> Result<Self> {
let hybrid_crypto = HybridCrypto::new(policy);
let hybrid_keypair = hybrid_crypto.generate_hybrid_keypair()?;
Ok(Self {
hybrid_crypto,
hybrid_keypair,
})
}
pub fn sign(&self, message: &[u8]) -> Result<Vec<u8>> {
let signature = self
.hybrid_crypto
.sign_hybrid(&self.hybrid_keypair, message)?;
serde_json::to_vec(&signature).map_err(|_| {
CryptoError::SerializationError("Failed to serialize signature".to_string())
})
}
pub fn sign_compact(&self, message: &[u8]) -> Result<Vec<u8>> {
let compressed_sig = self
.hybrid_crypto
.sign_hybrid_compressed(&self.hybrid_keypair, message)?;
serde_json::to_vec(&compressed_sig).map_err(|_| {
CryptoError::SerializationError("Failed to serialize compressed signature".to_string())
})
}
pub fn verify(&self, message: &[u8], signature: &[u8]) -> Result<bool> {
let sig = serde_json::from_slice(signature).map_err(|_| {
CryptoError::SerializationError("Failed to deserialize signature".to_string())
})?;
self.hybrid_crypto
.verify_hybrid(&self.hybrid_keypair, message, &sig)
}
pub fn verify_compact(&self, message: &[u8], compressed_signature: &[u8]) -> Result<bool> {
let compressed_sig = serde_json::from_slice(compressed_signature).map_err(|_| {
CryptoError::SerializationError(
"Failed to deserialize compressed signature".to_string(),
)
})?;
self.hybrid_crypto
.verify_hybrid_compressed(&self.hybrid_keypair, message, &compressed_sig)
}
pub fn classical_signature(&self, message: &[u8]) -> Result<Vec<u8>> {
use crate::algorithms::EcdsaCrypto;
let sig = EcdsaCrypto::sign(&self.hybrid_keypair.classical_keypair.private_key, message)?;
Ok(sig.bytes)
}
pub fn classical_public_key(&self) -> Vec<u8> {
self.hybrid_keypair
.classical_keypair
.public_key
.bytes
.clone()
}
pub fn public_keys(&self) -> (&[u8], &[u8]) {
(
&self.hybrid_keypair.classical_keypair.public_key.bytes,
&self.hybrid_keypair.post_quantum_keypair.public_key.bytes,
)
}
pub fn public_key_bundle(&self) -> HybridPublicBundle {
HybridPublicBundle {
classical_public_key: self.hybrid_keypair.classical_keypair.public_key.clone(),
post_quantum_public_key: self
.hybrid_keypair
.post_quantum_keypair
.public_key
.clone(),
security_level: self.hybrid_keypair.security_level,
transition_mode: self.hybrid_crypto.get_policy().transition_mode,
}
}
pub fn verifier(&self) -> HybridVerifier {
HybridVerifier::from_bundle(self.public_key_bundle())
}
}
pub struct QuantumEncryptor {
bridge: MlKem768,
public_key: <MlKem768 as KeyEncapsulationBridge>::PublicKey,
secret_key: <MlKem768 as KeyEncapsulationBridge>::SecretKey,
}
impl QuantumEncryptor {
pub fn new() -> Result<Self> {
let bridge = MlKem768;
let (public_key, secret_key) = bridge.kem_keygen()?;
Ok(Self {
bridge,
public_key,
secret_key,
})
}
pub fn encapsulate(&self) -> Result<(Vec<u8>, Vec<u8>)> {
let (ciphertext, shared_secret) = self.bridge.encapsulate(&self.public_key)?;
use fips203::traits::SerDes;
Ok((ciphertext.into_bytes().to_vec(), shared_secret))
}
pub fn decapsulate(&self, ciphertext_bytes: &[u8]) -> Result<Zeroizing<Vec<u8>>> {
use fips203::ml_kem_768::{CipherText, CT_LEN};
use fips203::traits::SerDes;
let ct_array: [u8; CT_LEN] = ciphertext_bytes
.try_into()
.map_err(|_| CryptoError::Generic("Invalid ciphertext size".to_string()))?;
let ciphertext = CipherText::try_from_bytes(ct_array)
.map_err(|_| CryptoError::Generic("Invalid ciphertext".to_string()))?;
let shared_secret = self.bridge.decapsulate(&self.secret_key, &ciphertext)?;
Ok(Zeroizing::new(shared_secret))
}
pub fn public_key_bytes(&self) -> Vec<u8> {
self.bridge.kem_public_key_to_bytes(&self.public_key)
}
}
pub struct QuantumVerifier {
public_key: PublicKey,
}
impl QuantumVerifier {
pub fn from_bytes(public_key_bytes: &[u8]) -> Result<Self> {
Ok(Self {
public_key: PublicKey {
bytes: public_key_bytes.to_vec(),
algorithm: Algorithm::MlDsa44,
},
})
}
pub fn verify(&self, message: &[u8], signature: &[u8]) -> Result<bool> {
use crate::algorithms::MlDsaCrypto;
use crate::types::Signature;
let sig = Signature { bytes: signature.to_vec(), algorithm: Algorithm::MlDsa44 };
MlDsaCrypto::verify(&self.public_key, message, &sig)
}
}
pub struct HybridVerifier {
bundle: HybridPublicBundle,
hybrid_crypto: HybridCrypto,
}
impl HybridVerifier {
pub fn from_bundle(bundle: HybridPublicBundle) -> Self {
let classical_algorithm = match bundle.classical_public_key.algorithm {
Algorithm::EcdsaK256 => ClassicalAlgorithm::EcdsaK256,
Algorithm::EcdsaP256 => ClassicalAlgorithm::EcdsaP256,
Algorithm::Schnorr => ClassicalAlgorithm::Schnorr,
_ => ClassicalAlgorithm::EcdsaK256,
};
let post_quantum_algorithm = match bundle.post_quantum_public_key.algorithm {
Algorithm::MlDsa44 => PostQuantumAlgorithm::MlDsa44,
Algorithm::SlhDsaSha2128f => PostQuantumAlgorithm::SlhDsaSha2128f,
_ => PostQuantumAlgorithm::MlDsa44,
};
let policy = HybridPolicy {
security_level: bundle.security_level,
transition_mode: bundle.transition_mode,
classical_algorithm,
post_quantum_algorithm,
compression_enabled: false,
compression_config: None,
};
Self {
bundle,
hybrid_crypto: HybridCrypto::new(policy),
}
}
pub fn verify(&self, message: &[u8], signature: &[u8]) -> crate::errors::Result<bool> {
let sig = serde_json::from_slice(signature).map_err(|_| {
crate::errors::CryptoError::SerializationError(
"Failed to deserialize signature".to_string(),
)
})?;
self.hybrid_crypto.verify_hybrid_bundle(&self.bundle, message, &sig)
}
pub fn verify_compact(
&self,
message: &[u8],
compressed_signature: &[u8],
) -> crate::errors::Result<bool> {
let compressed_sig = serde_json::from_slice(compressed_signature).map_err(|_| {
crate::errors::CryptoError::SerializationError(
"Failed to deserialize compressed signature".to_string(),
)
})?;
self.hybrid_crypto
.verify_hybrid_bundle_compressed(&self.bundle, message, &compressed_sig)
}
}
pub mod qurox {
use super::*;
pub fn quantum_signer() -> Result<QuantumSigner> {
QuantumSigner::new()
}
pub fn hybrid_signer() -> Result<HybridSigner> {
HybridSigner::new()
}
pub fn quantum_encryptor() -> Result<QuantumEncryptor> {
QuantumEncryptor::new()
}
pub fn secure_signer() -> Result<HybridSigner> {
let policy = HybridPolicy {
security_level: SecurityLevel::Hybrid,
transition_mode: TransitionMode::HybridRequired,
classical_algorithm: ClassicalAlgorithm::EcdsaK256,
post_quantum_algorithm: PostQuantumAlgorithm::MlDsa44,
compression_enabled: true,
compression_config: None,
};
HybridSigner::with_policy(policy)
}
pub fn compact_signer() -> Result<HybridSigner> {
let policy = HybridPolicy {
security_level: SecurityLevel::Hybrid,
transition_mode: TransitionMode::HybridOptional,
classical_algorithm: ClassicalAlgorithm::EcdsaK256,
post_quantum_algorithm: PostQuantumAlgorithm::MlDsa44,
compression_enabled: true,
compression_config: None,
};
HybridSigner::with_policy(policy)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_quantum_signer() {
let signer = QuantumSigner::new().unwrap();
let message = b"quantum test message";
let signature = signer.sign(message).unwrap();
let is_valid = signer.verify(message, &signature).unwrap();
assert!(is_valid);
assert!(!signature.is_empty());
assert!(!signer.public_key_bytes().is_empty());
}
#[test]
fn test_hybrid_signer() {
let signer = HybridSigner::new().unwrap();
let message = b"hybrid test message";
let signature = signer.sign(message).unwrap();
let is_valid = signer.verify(message, &signature).unwrap();
assert!(is_valid);
assert!(!signature.is_empty());
}
#[test]
fn test_compact_signing() {
let signer = HybridSigner::new().unwrap();
let message = b"compact test message";
let compact_sig = signer.sign_compact(message).unwrap();
let is_valid = signer.verify_compact(message, &compact_sig).unwrap();
assert!(is_valid);
assert!(!compact_sig.is_empty());
}
#[test]
fn test_quantum_encryptor() {
let encryptor = QuantumEncryptor::new().unwrap();
let (ciphertext, shared_secret1) = encryptor.encapsulate().unwrap();
let shared_secret2 = encryptor.decapsulate(&ciphertext).unwrap();
assert_eq!(shared_secret1.as_slice(), shared_secret2.as_slice());
assert!(!ciphertext.is_empty());
assert!(!shared_secret1.is_empty());
}
#[test]
fn test_quantum_verifier_cross_party() {
let alice = QuantumSigner::new().unwrap();
let message = b"signed by alice";
let sig = alice.sign(message).unwrap();
let bob = QuantumVerifier::from_bytes(&alice.public_key_bytes()).unwrap();
assert!(bob.verify(message, &sig).unwrap());
assert!(!bob.verify(b"not alice's message", &sig).unwrap());
}
#[test]
fn test_hybrid_verifier_cross_party() {
let alice = HybridSigner::new().unwrap();
let message = b"hybrid signed by alice";
let sig = alice.sign(message).unwrap();
let bob = alice.verifier();
assert!(bob.verify(message, &sig).unwrap());
assert!(!bob.verify(b"tampered", &sig).unwrap());
}
#[test]
fn test_hybrid_verifier_compact_cross_party() {
let alice = HybridSigner::new().unwrap();
let message = b"compact hybrid signed by alice";
let compact_sig = alice.sign_compact(message).unwrap();
let bob = alice.verifier();
assert!(bob.verify_compact(message, &compact_sig).unwrap());
}
#[test]
fn test_hybrid_verifier_rejects_wrong_signer() {
let alice = HybridSigner::new().unwrap();
let eve = HybridSigner::new().unwrap();
let message = b"signed by alice";
let sig = alice.sign(message).unwrap();
let eve_verifier = eve.verifier();
assert!(!eve_verifier.verify(message, &sig).unwrap());
}
#[test]
fn test_qurox_api() {
let quantum = qurox::quantum_signer().unwrap();
let hybrid = qurox::hybrid_signer().unwrap();
let encryptor = qurox::quantum_encryptor().unwrap();
let secure = qurox::secure_signer().unwrap();
let compact = qurox::compact_signer().unwrap();
let message = b"qurox api test";
let q_sig = quantum.sign(message).unwrap();
assert!(quantum.verify(message, &q_sig).unwrap());
let h_sig = hybrid.sign(message).unwrap();
assert!(hybrid.verify(message, &h_sig).unwrap());
let s_sig = secure.sign(message).unwrap();
assert!(secure.verify(message, &s_sig).unwrap());
let c_sig = compact.sign_compact(message).unwrap();
assert!(compact.verify_compact(message, &c_sig).unwrap());
let (ct, ss1) = encryptor.encapsulate().unwrap();
let ss2 = encryptor.decapsulate(&ct).unwrap();
assert_eq!(ss1.as_slice(), ss2.as_slice());
}
}