1use ed25519_dalek::Verifier as DalekVerifier;
2use ed25519_dalek::{Signer as DalekSigner, SigningKey, VerifyingKey};
3use hotmint_types::crypto::{PublicKey, Signature};
4use hotmint_types::validator::{ValidatorId, ValidatorSet};
5use hotmint_types::{AggregateSignature, Signer, Verifier};
6
7pub struct Ed25519Signer {
9 signing_key: SigningKey,
10 validator_id: ValidatorId,
11}
12
13impl Ed25519Signer {
14 pub fn new(signing_key: SigningKey, validator_id: ValidatorId) -> Self {
15 Self {
16 signing_key,
17 validator_id,
18 }
19 }
20
21 pub fn generate(validator_id: ValidatorId) -> Self {
22 let mut rng = rand::thread_rng();
23 let signing_key = SigningKey::generate(&mut rng);
24 Self::new(signing_key, validator_id)
25 }
26
27 pub fn verifying_key(&self) -> VerifyingKey {
28 self.signing_key.verifying_key()
29 }
30}
31
32impl Signer for Ed25519Signer {
33 fn sign(&self, message: &[u8]) -> Signature {
34 let sig = self.signing_key.sign(message);
35 Signature(sig.to_bytes().to_vec())
36 }
37
38 fn public_key(&self) -> PublicKey {
39 PublicKey(self.signing_key.verifying_key().to_bytes().to_vec())
40 }
41
42 fn validator_id(&self) -> ValidatorId {
43 self.validator_id
44 }
45}
46
47pub struct Ed25519Verifier;
49
50impl Verifier for Ed25519Verifier {
51 fn verify(&self, pk: &PublicKey, msg: &[u8], sig: &Signature) -> bool {
52 let vk_bytes: [u8; 32] = match pk.0.as_slice().try_into() {
53 Ok(b) => b,
54 Err(_) => return false,
55 };
56 let vk = match VerifyingKey::from_bytes(&vk_bytes) {
57 Ok(v) => v,
58 Err(_) => return false,
59 };
60 let sig_bytes: [u8; 64] = match sig.0.as_slice().try_into() {
61 Ok(b) => b,
62 Err(_) => return false,
63 };
64 let signature = ed25519_dalek::Signature::from_bytes(&sig_bytes);
65 vk.verify(msg, &signature).is_ok()
66 }
67
68 fn verify_aggregate(&self, vs: &ValidatorSet, msg: &[u8], agg: &AggregateSignature) -> bool {
69 let mut pks = Vec::new();
74 let mut sigs = Vec::new();
75 let mut sig_idx = 0;
76
77 for (i, signed) in agg.signers.iter().enumerate() {
78 if !signed {
79 continue;
80 }
81 if sig_idx >= agg.signatures.len() {
82 return false;
83 }
84 let Some(vi) = vs.validators().get(i) else {
85 return false;
86 };
87 let pk_bytes: [u8; 32] = match vi.public_key.0.as_slice().try_into() {
88 Ok(b) => b,
89 Err(_) => return false,
90 };
91 let Ok(vk) = ed25519_dalek::VerifyingKey::from_bytes(&pk_bytes) else {
92 return false;
93 };
94 let sig_bytes: [u8; 64] = match agg.signatures[sig_idx].0.as_slice().try_into() {
95 Ok(b) => b,
96 Err(_) => return false,
97 };
98 let sig = ed25519_dalek::Signature::from_bytes(&sig_bytes);
99 pks.push(vk);
100 sigs.push(sig);
101 sig_idx += 1;
102 }
103
104 if sig_idx != agg.signatures.len() {
105 return false;
106 }
107
108 let messages: Vec<&[u8]> = vec![msg; sigs.len()];
110 ed25519_dalek::verify_batch(&messages, &sigs, &pks).is_ok()
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use super::*;
117
118 #[test]
119 fn test_sign_verify() {
120 let signer = Ed25519Signer::generate(ValidatorId(0));
121 let msg = b"test message";
122 let sig = signer.sign(msg);
123 let pk = signer.public_key();
124
125 let verifier = Ed25519Verifier;
126 assert!(verifier.verify(&pk, msg, &sig));
127 assert!(!verifier.verify(&pk, b"wrong message", &sig));
128 }
129}