use crate::error::CryptoError;
use ed25519_dalek::{Signer as Ed25519SignerTrait, SigningKey, VerifyingKey};
use memsecurity::EncryptedMem;
use std::{fmt, sync::Arc};
use zeroize::Zeroize;
use super::{DSA, DSAlgorithm, SignatureIdentifier};
pub const ED25519_ID: u8 = b'E';
pub const ED25519_PUBLIC_KEY_LENGTH: usize = 32;
pub const ED25519_SECRET_KEY_LENGTH: usize = 32;
pub const ED25519_SIGNATURE_LENGTH: usize = 64;
#[derive(Default, Clone)]
pub struct Ed25519Signer {
public_key: VerifyingKey,
secret_key: Option<Arc<EncryptedMem>>,
}
impl Ed25519Signer {
fn decrypt_secret_bytes(&self) -> Result<Vec<u8>, CryptoError> {
match &self.secret_key {
Some(encrypted) => {
let bytes = encrypted.decrypt().map_err(|e| {
CryptoError::InvalidSecretKey(format!(
"Failed to decrypt secret key: {:?}",
e
))
})?;
Ok(Vec::from(bytes.as_ref()))
}
None => Err(CryptoError::MissingSecretKey),
}
}
fn create_encrypted_secret(
secret_key: &[u8],
) -> Result<Arc<EncryptedMem>, CryptoError> {
let mut encrypted = EncryptedMem::new();
encrypted.encrypt(&secret_key.to_vec()).map_err(|e| {
CryptoError::InvalidSecretKey(format!(
"Failed to encrypt secret key: {:?}",
e
))
})?;
Ok(Arc::new(encrypted))
}
pub fn generate() -> Result<Self, CryptoError> {
let mut seed = [0u8; 32];
getrandom::fill(&mut seed).map_err(|e| {
CryptoError::InvalidSecretKey(format!(
"Failed to generate random seed: {}",
e
))
})?;
Self::from_seed(&seed)
}
pub fn derive_from_data(data: &[u8]) -> Result<Self, CryptoError> {
if data.is_empty() {
return Err(CryptoError::InvalidSecretKey(
"Cannot derive keys from empty data. Use generate() for random keys".to_string(),
));
}
use crate::hash::{Blake3Hasher, Hash as HashTrait};
let hasher = Blake3Hasher;
let hash = hasher.hash(data);
let seed_bytes = hash.hash_bytes();
let key_array: [u8; 32] = seed_bytes
.try_into()
.expect("Blake3 always produces 32 bytes");
Self::from_seed(&key_array)
}
pub fn from_seed(seed: &[u8; 32]) -> Result<Self, CryptoError> {
let signing_key = SigningKey::from_bytes(seed);
let public_key = signing_key.verifying_key();
let encrypted_secret = Self::create_encrypted_secret(seed)?;
Ok(Self {
public_key,
secret_key: Some(encrypted_secret),
})
}
pub fn from_secret_key(secret_key: &[u8]) -> Result<Self, CryptoError> {
let key_bytes: [u8; 32] = secret_key.try_into().map_err(|_| {
CryptoError::InvalidSecretKey(format!(
"Invalid secret key length: expected {} bytes, got {}",
ED25519_SECRET_KEY_LENGTH,
secret_key.len()
))
})?;
Self::from_seed(&key_bytes)
}
pub fn from_public_key(public_key: &[u8]) -> Result<Self, CryptoError> {
if public_key.len() != ED25519_PUBLIC_KEY_LENGTH {
return Err(CryptoError::InvalidPublicKey(format!(
"Invalid public key length: expected {} bytes, got {}",
ED25519_PUBLIC_KEY_LENGTH,
public_key.len()
)));
}
let key_bytes: [u8; 32] = public_key.try_into().map_err(|_| {
CryptoError::InvalidPublicKey("Invalid length".to_string())
})?;
let verifying_key = VerifyingKey::from_bytes(&key_bytes)
.map_err(|e| CryptoError::InvalidPublicKey(e.to_string()))?;
Ok(Self {
public_key: verifying_key,
secret_key: None,
})
}
pub const fn public_key(&self) -> VerifyingKey {
self.public_key
}
pub fn secret_key_bytes(&self) -> Result<Vec<u8>, CryptoError> {
self.decrypt_secret_bytes()
}
}
impl fmt::Debug for Ed25519Signer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use crate::common::base64_encoding;
f.debug_struct("Ed25519Signer")
.field(
"public_key",
&base64_encoding::encode(self.public_key().as_bytes()),
)
.finish_non_exhaustive()
}
}
impl DSA for Ed25519Signer {
fn algorithm_id(&self) -> u8 {
ED25519_ID
}
fn signature_length(&self) -> usize {
ED25519_SIGNATURE_LENGTH
}
fn sign(&self, message: &[u8]) -> Result<SignatureIdentifier, CryptoError> {
let mut secret_bytes = self.decrypt_secret_bytes()?;
let key_array: [u8; 32] = secret_bytes
.as_slice()
.try_into()
.expect("Secret key should always be 32 bytes");
let signing_key = SigningKey::from_bytes(&key_array);
let signature = signing_key.sign(message);
let signature_bytes = signature.to_bytes();
secret_bytes.zeroize();
SignatureIdentifier::new(DSAlgorithm::Ed25519, signature_bytes.to_vec())
}
fn algorithm(&self) -> DSAlgorithm {
DSAlgorithm::Ed25519
}
fn public_key_bytes(&self) -> Vec<u8> {
self.public_key.as_bytes().to_vec()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ed25519_sign_verify() {
let signer = Ed25519Signer::generate().unwrap();
let message = b"Hello, World!";
let signature = signer.sign(message).unwrap();
assert_eq!(signature.algorithm(), DSAlgorithm::Ed25519);
let public_key = signer.public_key();
assert!(signature.verify(message, public_key.as_bytes()).is_ok());
}
#[test]
fn test_derive_from_data() {
let short_data = b"hello";
let signer1 = Ed25519Signer::derive_from_data(short_data).unwrap();
let signer2 = Ed25519Signer::derive_from_data(short_data).unwrap();
assert_eq!(signer1.public_key_bytes(), signer2.public_key_bytes());
let different_data = b"world";
let signer3 = Ed25519Signer::derive_from_data(different_data).unwrap();
assert_ne!(signer1.public_key_bytes(), signer3.public_key_bytes());
let long_data =
b"this is a very long passphrase that is much longer than 32 bytes";
let signer4 = Ed25519Signer::derive_from_data(long_data).unwrap();
assert_ne!(signer1.public_key_bytes(), signer4.public_key_bytes());
let empty_data = b"";
let result = Ed25519Signer::derive_from_data(empty_data);
assert!(result.is_err());
}
#[test]
fn test_from_seed() {
let seed = [42u8; 32];
let signer1 = Ed25519Signer::from_seed(&seed).unwrap();
let signer2 = Ed25519Signer::from_seed(&seed).unwrap();
assert_eq!(signer1.public_key_bytes(), signer2.public_key_bytes());
let signer3 = Ed25519Signer::derive_from_data(&seed).unwrap();
assert_ne!(signer1.public_key_bytes(), signer3.public_key_bytes());
}
#[test]
fn test_from_public_key() {
let signer = Ed25519Signer::generate().unwrap();
let message = b"Test message";
let signature = signer.sign(message).unwrap();
let verifier =
Ed25519Signer::from_public_key(&signer.public_key_bytes()).unwrap();
assert_eq!(verifier.public_key_bytes(), signer.public_key_bytes());
assert!(verifier.sign(message).is_err());
assert!(
signature
.verify(message, verifier.public_key().as_bytes())
.is_ok()
);
}
#[test]
fn test_encrypted_secret_key() {
let seed = [42u8; 32];
let signer = Ed25519Signer::from_seed(&seed).unwrap();
let secret = signer.secret_key_bytes().unwrap();
assert_eq!(secret.len(), 32);
let signer2 = Ed25519Signer::from_seed(&seed).unwrap();
let secret2 = signer2.secret_key_bytes().unwrap();
assert_eq!(secret, secret2);
}
#[test]
fn test_invalid_key_lengths() {
let invalid_secret = vec![0u8; 16]; let result = Ed25519Signer::from_secret_key(&invalid_secret);
assert!(result.is_err());
let invalid_public = vec![0u8; 16]; let result = Ed25519Signer::from_public_key(&invalid_public);
assert!(result.is_err());
}
#[test]
fn test_concurrent_signing() {
use std::sync::Arc;
use std::thread;
let signer = Arc::new(Ed25519Signer::generate().unwrap());
let mut handles = vec![];
for i in 0..10 {
let signer_clone = Arc::clone(&signer);
let msg = format!("message {}", i);
let handle = thread::spawn(move || {
let signature = signer_clone.sign(msg.as_bytes()).unwrap();
let public_key = signer_clone.public_key();
assert!(
signature
.verify(msg.as_bytes(), public_key.as_bytes())
.is_ok()
);
signature
});
handles.push(handle);
}
let signatures: Vec<_> =
handles.into_iter().map(|h| h.join().unwrap()).collect();
assert_eq!(signatures.len(), 10);
for i in 0..signatures.len() {
for j in i + 1..signatures.len() {
assert_ne!(
signatures[i], signatures[j],
"Signatures for different messages should be different"
);
}
}
}
#[test]
fn test_send_sync_traits() {
fn assert_send<T: Send>() {}
fn assert_sync<T: Sync>() {}
assert_send::<Ed25519Signer>();
assert_sync::<Ed25519Signer>();
}
#[test]
fn test_concurrent_key_generation() {
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;
let counter = Arc::new(AtomicUsize::new(0));
let mut handles = vec![];
for _ in 0..5 {
let counter_clone = Arc::clone(&counter);
let handle = thread::spawn(move || {
let signer = Ed25519Signer::generate().unwrap();
let message = b"test";
let signature = signer.sign(message).unwrap();
let public_key = signer.public_key();
assert!(
signature.verify(message, public_key.as_bytes()).is_ok()
);
counter_clone.fetch_add(1, Ordering::SeqCst);
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
assert_eq!(counter.load(Ordering::SeqCst), 5);
}
#[test]
fn test_clone_shares_arc() {
let signer = Ed25519Signer::generate().unwrap();
let signer_clone = signer.clone();
assert_eq!(signer.public_key_bytes(), signer_clone.public_key_bytes());
let message = b"test message";
let sig1 = signer.sign(message).unwrap();
let sig2 = signer_clone.sign(message).unwrap();
assert_eq!(sig1, sig2);
if let Some(ref secret) = signer.secret_key {
assert_eq!(Arc::strong_count(secret), 2);
}
}
#[test]
fn test_clone_verification_only() {
let full_signer = Ed25519Signer::generate().unwrap();
let verifier =
Ed25519Signer::from_public_key(&full_signer.public_key_bytes())
.unwrap();
let verifier_clone = verifier.clone();
assert_eq!(
verifier.public_key_bytes(),
verifier_clone.public_key_bytes()
);
let message = b"test";
assert!(verifier.sign(message).is_err());
assert!(verifier_clone.sign(message).is_err());
assert!(verifier.secret_key.is_none());
assert!(verifier_clone.secret_key.is_none());
}
}