use crate::audit::AuditLogger;
use crate::cipher::provider::Signer;
use crate::error::{CryptoError, Result};
use crate::hardware;
use crate::key::Key;
use crate::types::Algorithm;
#[cfg(feature = "parallel")]
use rayon::prelude::*;
pub struct Ed25519Provider {
algorithm: Algorithm,
}
impl Ed25519Provider {
pub fn new(algorithm: Algorithm) -> Self {
Self { algorithm }
}
#[inline]
fn is_sha512_accelerated() -> bool {
hardware::has_sha_ni()
}
}
impl Signer for Ed25519Provider {
fn sign(&self, key: &Key, message: &[u8]) -> Result<Vec<u8>> {
if key.algorithm() != self.algorithm {
return Err(CryptoError::UnsupportedAlgorithm(
"Key algorithm mismatch".into(),
));
}
let sha_accelerated = Self::is_sha512_accelerated();
AuditLogger::log(
"ED25519_SIGN_START",
Some(self.algorithm),
None,
if sha_accelerated {
Ok(())
} else {
Err(CryptoError::HardwareAccelerationUnavailable(
"SHA-512 acceleration not available".into(),
))
},
);
let private_key = key.secret_bytes()?;
let result = hardware::accelerated_ed25519_sign(private_key.as_bytes(), message);
AuditLogger::log("ED25519_SIGN_COMPLETE", Some(self.algorithm), None, {
let r = result.as_ref();
match r {
Ok(_) => Ok(()),
Err(e) => Err((*e).clone()),
}
});
result
}
fn verify(&self, key: &Key, message: &[u8], signature: &[u8]) -> Result<bool> {
if key.algorithm() != self.algorithm {
return Err(CryptoError::UnsupportedAlgorithm(
"Key algorithm mismatch".into(),
));
}
let public_key_bytes = if let Ok(private_key) = key.secret_bytes() {
use ring::signature::{Ed25519KeyPair, KeyPair};
let key_pair = Ed25519KeyPair::from_pkcs8(private_key.as_bytes())
.map_err(|e| CryptoError::KeyError(format!("Invalid Ed25519 PKCS#8 key: {}", e)))?;
key_pair.public_key().as_ref().to_vec()
} else {
key.public_bytes()?
};
let result = hardware::accelerated_ed25519_verify(&public_key_bytes, message, signature);
AuditLogger::log("ED25519_VERIFY", Some(self.algorithm), None, {
let r = result.as_ref();
match r {
Ok(_) => Ok(()),
Err(e) => Err((*e).clone()),
}
});
result
}
}
#[cfg(feature = "parallel")]
#[derive(Clone)]
#[allow(dead_code)]
pub struct Ed25519BatchProvider {
algorithm: Algorithm,
}
#[cfg(feature = "parallel")]
#[allow(dead_code)]
impl Ed25519BatchProvider {
pub fn new(algorithm: Algorithm) -> Self {
Self { algorithm }
}
#[cfg(feature = "parallel")]
pub fn sign_batch(&self, key: &Key, messages: &[&[u8]]) -> Result<Vec<Vec<u8>>> {
if key.algorithm() != self.algorithm {
return Err(CryptoError::UnsupportedAlgorithm(
"Key algorithm mismatch".into(),
));
}
AuditLogger::log(
"ED25519_BATCH_SIGN_START",
Some(self.algorithm),
None,
Ok(()),
);
let private_key = key.secret_bytes()?;
let signatures: Result<Vec<Vec<u8>>> = messages
.par_iter()
.map(|&msg| hardware::accelerated_ed25519_sign(private_key.as_bytes(), msg))
.collect();
AuditLogger::log(
"ED25519_BATCH_SIGN_COMPLETE",
Some(self.algorithm),
None,
signatures.as_ref().map_err(|e| (*e).clone()).map(|_| ()),
);
signatures
}
pub fn sign_batch_sequential(&self, key: &Key, messages: &[&[u8]]) -> Result<Vec<Vec<u8>>> {
if key.algorithm() != self.algorithm {
return Err(CryptoError::UnsupportedAlgorithm(
"Key algorithm mismatch".into(),
));
}
let private_key = key.secret_bytes()?;
let mut signatures = Vec::with_capacity(messages.len());
for &msg in messages {
let sig = hardware::accelerated_ed25519_sign(private_key.as_bytes(), msg)?;
signatures.push(sig);
}
Ok(signatures)
}
#[cfg(feature = "parallel")]
pub fn verify_batch(
&self,
key: &Key,
messages: &[&[u8]],
signatures: &[&[u8]],
) -> Result<Vec<bool>> {
if key.algorithm() != self.algorithm {
return Err(CryptoError::UnsupportedAlgorithm(
"Key algorithm mismatch".into(),
));
}
if messages.len() != signatures.len() {
return Err(CryptoError::InvalidParameter(
"Messages and signatures must have the same length".into(),
));
}
AuditLogger::log(
"ED25519_BATCH_VERIFY_START",
Some(self.algorithm),
None,
Ok(()),
);
let public_key_bytes = if let Ok(private_key) = key.secret_bytes() {
use ring::signature::{Ed25519KeyPair, KeyPair};
let key_pair = Ed25519KeyPair::from_pkcs8(private_key.as_bytes())
.map_err(|e| CryptoError::KeyError(format!("Invalid Ed25519 PKCS#8 key: {}", e)))?;
key_pair.public_key().as_ref().to_vec()
} else {
key.public_bytes()?
};
let results: Vec<bool> = messages
.par_iter()
.zip(signatures.par_iter())
.map(|(&msg, &sig)| {
hardware::accelerated_ed25519_verify(&public_key_bytes, msg, sig).unwrap_or(false)
})
.collect();
AuditLogger::log(
"ED25519_BATCH_VERIFY_COMPLETE",
Some(self.algorithm),
None,
Ok(()),
);
Ok(results)
}
pub fn verify_batch_sequential(
&self,
key: &Key,
messages: &[&[u8]],
signatures: &[&[u8]],
) -> Result<Vec<bool>> {
if key.algorithm() != self.algorithm {
return Err(CryptoError::UnsupportedAlgorithm(
"Key algorithm mismatch".into(),
));
}
if messages.len() != signatures.len() {
return Err(CryptoError::InvalidParameter(
"Messages and signatures must have the same length".into(),
));
}
let public_key_bytes = if let Ok(private_key) = key.secret_bytes() {
use ring::signature::{Ed25519KeyPair, KeyPair};
let key_pair = Ed25519KeyPair::from_pkcs8(private_key.as_bytes())
.map_err(|e| CryptoError::KeyError(format!("Invalid Ed25519 PKCS#8 key: {}", e)))?;
key_pair.public_key().as_ref().to_vec()
} else {
key.public_bytes()?
};
let mut results = Vec::with_capacity(messages.len());
for (&msg, &sig) in messages.iter().zip(signatures.iter()) {
let result =
hardware::accelerated_ed25519_verify(&public_key_bytes, msg, sig).unwrap_or(false);
results.push(result);
}
Ok(results)
}
}