1use ed25519_dalek::{Signature, Signer as EdSigner, SigningKey, Verifier, VerifyingKey};
5use rsa::rand_core::OsRng;
6
7use crate::{Signer, SignerError};
8
9pub struct Ed25519Signer {
11 signing_key: SigningKey,
12 cached_public_key: [u8; 32],
13}
14
15impl Ed25519Signer {
16 pub fn generate() -> Result<Self, SignerError> {
17 let signing_key = SigningKey::generate(&mut OsRng);
18 let cached_public_key = signing_key.verifying_key().to_bytes();
19 Ok(Self {
20 signing_key,
21 cached_public_key,
22 })
23 }
24
25 pub fn from_pem(pem: &str) -> Result<Self, SignerError> {
26 use crate::pem_loader::{PemKind, classify_pem};
27
28 match classify_pem(pem) {
29 PemKind::Pkcs8 => Self::from_pkcs8_pem(pem),
30 PemKind::OpenSsh => Self::from_openssh_pem(pem),
31 PemKind::Ed25519HexSeed => {
32 let bytes = hex::decode(pem.trim()).map_err(|e| SignerError::Pem(e.to_string()))?;
33 Self::from_seed(&bytes)
34 }
35 PemKind::Ed25519Base64Seed => {
36 use base64::Engine;
37 let bytes = base64::engine::general_purpose::STANDARD
38 .decode(pem.trim())
39 .map_err(|e| SignerError::Pem(e.to_string()))?;
40 if bytes.len() == 64 {
41 Self::from_seed(&bytes[..32])
42 } else {
43 Self::from_seed(&bytes)
44 }
45 }
46 _ => Err(SignerError::UnknownKeyFormat),
47 }
48 }
49
50 pub fn from_seed(seed: &[u8]) -> Result<Self, SignerError> {
51 let seed_bytes: [u8; 32] = seed
52 .try_into()
53 .map_err(|_| SignerError::InvalidKey("seed must be 32 bytes".to_string()))?;
54 let signing_key = SigningKey::from_bytes(&seed_bytes);
55 let cached_public_key = signing_key.verifying_key().to_bytes();
56 Ok(Self {
57 signing_key,
58 cached_public_key,
59 })
60 }
61
62 fn from_pkcs8_pem(pem: &str) -> Result<Self, SignerError> {
63 use pkcs8::DecodePrivateKey;
64
65 let signing_key = SigningKey::from_pkcs8_pem(pem)?;
66 let cached_public_key = signing_key.verifying_key().to_bytes();
67 Ok(Self {
68 signing_key,
69 cached_public_key,
70 })
71 }
72
73 fn from_openssh_pem(_pem: &str) -> Result<Self, SignerError> {
74 Err(SignerError::Pem(
75 "OpenSSH Ed25519 private keys are not yet supported".to_string(),
76 ))
77 }
78
79 pub fn to_pem(&self) -> Result<String, SignerError> {
80 use pkcs8::EncodePrivateKey;
81
82 self.signing_key
83 .to_pkcs8_pem(pkcs8::LineEnding::LF)
84 .map(|pem| pem.to_string())
85 .map_err(|e| SignerError::Pkcs8(e.to_string()))
86 }
87
88 pub fn verify_with_public_key(
89 data: &[u8],
90 public_key: &[u8],
91 signature: &[u8],
92 ) -> Result<(), SignerError> {
93 let verifying_key = VerifyingKey::from_bytes(public_key.try_into().map_err(|_| {
94 SignerError::InvalidPublicKey("public key must be 32 bytes".to_string())
95 })?)?;
96 let signature = Signature::from_slice(signature)
97 .map_err(|_| SignerError::InvalidSignature("signature must be 64 bytes".to_string()))?;
98 verifying_key
99 .verify(data, &signature)
100 .map_err(|_| SignerError::VerificationFailed)
101 }
102}
103
104impl Signer for Ed25519Signer {
105 fn algorithm(&self) -> &'static str {
106 "ed25519"
107 }
108
109 fn public_key(&self) -> &[u8] {
110 &self.cached_public_key
111 }
112
113 fn sign(&self, data: &[u8]) -> Result<Vec<u8>, SignerError> {
114 let signature = self.signing_key.sign(data);
115 Ok(signature.to_bytes().to_vec())
116 }
117
118 fn verify(&self, data: &[u8], signature: &[u8]) -> Result<(), SignerError> {
119 Self::verify_with_public_key(data, self.public_key(), signature)
120 }
121}