sentinel_crypto/sign/
ed25519.rs

1use ed25519_dalek::{Signature, SigningKey, VerifyingKey};
2use signature::{Signer, Verifier};
3use tracing::{debug, trace};
4
5use crate::{error::CryptoError, sign_trait::SignatureAlgorithm};
6
7/// Ed25519 signature implementation.
8/// Uses the Ed25519 elliptic curve signature scheme, providing high security
9/// and performance. Based on Curve25519, it's resistant to timing attacks
10/// and provides 128-bit security level.
11///
12/// Design choice: Ed25519 was chosen for its speed, security, and widespread
13/// adoption. It's a rustcrypto crate (ed25519-dalek), preferred over ring
14/// implementations for consistency. Keys are automatically zeroized when dropped.
15pub struct Ed25519Signer;
16
17impl SignatureAlgorithm for Ed25519Signer {
18    type Signature = Signature;
19    type SigningKey = SigningKey;
20    type VerifyingKey = VerifyingKey;
21
22    fn sign_hash(hash: &str, private_key: &SigningKey) -> Result<String, CryptoError> {
23        trace!("Signing hash with Ed25519");
24        let signature = private_key.sign(hash.as_bytes());
25        let sig_hex = hex::encode(signature.to_bytes());
26        debug!("Ed25519 signature created: {}", sig_hex);
27        Ok(sig_hex)
28    }
29
30    fn verify_signature(hash: &str, signature: &str, public_key: &VerifyingKey) -> Result<bool, CryptoError> {
31        trace!("Verifying signature with Ed25519");
32        let sig_bytes = hex::decode(signature).map_err(CryptoError::Hex)?;
33        let sig_array: [u8; 64] = sig_bytes
34            .as_slice()
35            .try_into()
36            .map_err(|_| CryptoError::InvalidSignatureLength)?;
37        let sig = Signature::from_bytes(&sig_array);
38        let is_valid = public_key.verify(hash.as_bytes(), &sig).is_ok();
39        debug!("Ed25519 signature verification result: {}", is_valid);
40        Ok(is_valid)
41    }
42}
43
44impl crate::sign_trait::private::Sealed for Ed25519Signer {}
45
46#[cfg(test)]
47mod tests {
48    use rand::random;
49
50    use super::*;
51
52    #[test]
53    fn test_ed25519_sign_verify() {
54        let secret: [u8; 32] = random();
55        let private_key = SigningKey::from_bytes(&secret);
56        let public_key = private_key.verifying_key();
57
58        let hash = "some_hash_value";
59        let signature = Ed25519Signer::sign_hash(hash, &private_key).unwrap();
60
61        let is_valid = Ed25519Signer::verify_signature(hash, &signature, &public_key).unwrap();
62        assert!(is_valid);
63
64        let is_valid_wrong = Ed25519Signer::verify_signature("wrong", &signature, &public_key).unwrap();
65        assert!(!is_valid_wrong);
66    }
67}