use crate::security::{SecurityError, SecurityResult};
use base64::{engine::general_purpose, Engine as _};
use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey};
use rand::rngs::OsRng;
use serde::{Deserialize, Serialize};
#[derive(Debug)]
pub struct Ed25519KeyPair {
signing_key: SigningKey,
verifying_key: VerifyingKey,
}
impl Ed25519KeyPair {
pub fn generate() -> SecurityResult<Self> {
let signing_key = SigningKey::generate(&mut OsRng);
let verifying_key = signing_key.verifying_key();
Ok(Self {
signing_key,
verifying_key,
})
}
pub fn from_secret_key(secret_key: &[u8]) -> SecurityResult<Self> {
if secret_key.len() != 32 {
return Err(SecurityError::KeyGenerationFailed(
"Secret key must be 32 bytes".to_string(),
));
}
let mut key_bytes = [0u8; 32];
key_bytes.copy_from_slice(secret_key);
let signing_key = SigningKey::from_bytes(&key_bytes);
let verifying_key = signing_key.verifying_key();
Ok(Self {
signing_key,
verifying_key,
})
}
pub fn public_key_bytes(&self) -> [u8; 32] {
self.verifying_key.to_bytes()
}
pub fn secret_key_bytes(&self) -> [u8; 32] {
self.signing_key.to_bytes()
}
pub fn public_key_base64(&self) -> String {
general_purpose::STANDARD.encode(self.public_key_bytes())
}
pub fn secret_key_base64(&self) -> String {
general_purpose::STANDARD.encode(self.secret_key_bytes())
}
pub fn sign(&self, message: &[u8]) -> Signature {
self.signing_key.sign(message)
}
pub fn verify(&self, message: &[u8], signature: &Signature) -> bool {
self.verifying_key.verify(message, signature).is_ok()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Ed25519PublicKey {
verifying_key: VerifyingKey,
}
impl Ed25519PublicKey {
pub fn from_bytes(bytes: &[u8]) -> SecurityResult<Self> {
if bytes.len() != 32 {
return Err(SecurityError::InvalidPublicKey(
"Public key must be 32 bytes".to_string(),
));
}
let mut key_bytes = [0u8; 32];
key_bytes.copy_from_slice(bytes);
let verifying_key = VerifyingKey::from_bytes(&key_bytes)
.map_err(|e| SecurityError::InvalidPublicKey(e.to_string()))?;
Ok(Self { verifying_key })
}
pub fn from_base64(base64_key: &str) -> SecurityResult<Self> {
let bytes = general_purpose::STANDARD
.decode(base64_key)
.map_err(|e| SecurityError::InvalidPublicKey(e.to_string()))?;
Self::from_bytes(&bytes)
}
pub fn to_bytes(&self) -> [u8; 32] {
self.verifying_key.to_bytes()
}
pub fn to_base64(&self) -> String {
general_purpose::STANDARD.encode(self.to_bytes())
}
pub fn verify(&self, message: &[u8], signature: &Signature) -> bool {
self.verifying_key.verify(message, signature).is_ok()
}
}
pub struct KeyUtils;
impl KeyUtils {
pub fn generate_key_id(public_key: &Ed25519PublicKey) -> String {
use sha2::{Digest, Sha256};
let mut hasher = Sha256::new();
hasher.update(public_key.to_bytes());
let hash = hasher.finalize();
general_purpose::STANDARD.encode(&hash[..16])
}
pub fn signature_from_base64(base64_sig: &str) -> SecurityResult<Signature> {
let bytes = general_purpose::STANDARD
.decode(base64_sig)
.map_err(|e| SecurityError::InvalidSignature(e.to_string()))?;
if bytes.len() != 64 {
return Err(SecurityError::InvalidSignature(
"Signature must be 64 bytes".to_string(),
));
}
let mut sig_bytes = [0u8; 64];
sig_bytes.copy_from_slice(&bytes);
Ok(Signature::from_bytes(&sig_bytes))
}
pub fn signature_to_base64(signature: &Signature) -> String {
general_purpose::STANDARD.encode(signature.to_bytes())
}
pub fn generate_nonce() -> String {
use rand::RngCore;
let mut nonce = [0u8; 16];
OsRng.fill_bytes(&mut nonce);
general_purpose::STANDARD.encode(nonce)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_key_generation() {
let keypair = Ed25519KeyPair::generate().unwrap();
let public_bytes = keypair.public_key_bytes();
let secret_bytes = keypair.secret_key_bytes();
assert_eq!(public_bytes.len(), 32);
assert_eq!(secret_bytes.len(), 32);
let public_b64 = keypair.public_key_base64();
let secret_b64 = keypair.secret_key_base64();
assert!(!public_b64.is_empty());
assert!(!secret_b64.is_empty());
}
#[test]
fn test_signing_and_verification() {
let keypair = Ed25519KeyPair::generate().unwrap();
let message = b"Hello, world!";
let signature = keypair.sign(message);
assert!(keypair.verify(message, &signature));
let wrong_message = b"Hello, world?";
assert!(!keypair.verify(wrong_message, &signature));
}
#[test]
fn test_public_key_operations() {
let keypair = Ed25519KeyPair::generate().unwrap();
let public_bytes = keypair.public_key_bytes();
let public_key = Ed25519PublicKey::from_bytes(&public_bytes).unwrap();
let base64_key = public_key.to_base64();
let public_key2 = Ed25519PublicKey::from_base64(&base64_key).unwrap();
assert_eq!(public_key.to_bytes(), public_key2.to_bytes());
}
#[test]
fn test_key_id_generation() {
let keypair = Ed25519KeyPair::generate().unwrap();
let public_key = Ed25519PublicKey::from_bytes(&keypair.public_key_bytes()).unwrap();
let key_id = KeyUtils::generate_key_id(&public_key);
assert!(!key_id.is_empty());
let key_id2 = KeyUtils::generate_key_id(&public_key);
assert_eq!(key_id, key_id2);
}
#[test]
fn test_signature_base64_conversion() {
let keypair = Ed25519KeyPair::generate().unwrap();
let message = b"Test message";
let signature = keypair.sign(message);
let base64_sig = KeyUtils::signature_to_base64(&signature);
let parsed_sig = KeyUtils::signature_from_base64(&base64_sig).unwrap();
assert_eq!(signature.to_bytes(), parsed_sig.to_bytes());
}
#[test]
fn test_nonce_generation() {
let nonce1 = KeyUtils::generate_nonce();
let nonce2 = KeyUtils::generate_nonce();
assert!(!nonce1.is_empty());
assert!(!nonce2.is_empty());
assert_ne!(nonce1, nonce2); }
}