guardian_client/keystore/
ecdsa.rs1use guardian_shared::SignatureScheme;
2use miden_protocol::Word;
3use miden_protocol::crypto::dsa::ecdsa_k256_keccak::SigningKey as SecretKey;
4use miden_protocol::utils::serde::Serializable;
5
6use super::Signer;
7
8pub struct EcdsaKeyStore {
10 secret_key: std::sync::Mutex<SecretKey>,
11 commitment: Word,
12 commitment_hex: String,
13 public_key_hex: String,
14}
15
16impl EcdsaKeyStore {
17 pub fn new(secret_key: SecretKey) -> Self {
19 let public_key = secret_key.public_key();
20 let commitment = public_key.to_commitment();
21 let commitment_hex = format!("0x{}", hex::encode(commitment.to_bytes()));
22 let public_key_hex = format!("0x{}", hex::encode(public_key.to_bytes()));
23
24 Self {
25 secret_key: std::sync::Mutex::new(secret_key),
26 commitment,
27 commitment_hex,
28 public_key_hex,
29 }
30 }
31
32 pub fn generate() -> Self {
34 Self::new(SecretKey::new())
35 }
36}
37
38impl Signer for EcdsaKeyStore {
39 fn scheme(&self) -> SignatureScheme {
40 SignatureScheme::Ecdsa
41 }
42
43 fn commitment(&self) -> Word {
44 self.commitment
45 }
46
47 fn commitment_hex(&self) -> String {
48 self.commitment_hex.clone()
49 }
50
51 fn public_key_hex(&self) -> String {
52 self.public_key_hex.clone()
53 }
54
55 fn sign_word_hex(&self, message: Word) -> String {
56 format!(
57 "0x{}",
58 hex::encode(self.secret_key.lock().unwrap().sign(message).to_bytes())
59 )
60 }
61}
62
63#[cfg(test)]
64mod tests {
65 use miden_protocol::crypto::dsa::ecdsa_k256_keccak::{PublicKey, Signature};
66 use miden_protocol::utils::serde::Deserializable;
67
68 use super::*;
69
70 #[test]
71 fn generate_creates_valid_signer() {
72 let signer = EcdsaKeyStore::generate();
73 assert!(signer.commitment_hex().starts_with("0x"));
74 assert_eq!(signer.commitment_hex().len(), 66);
75 }
76
77 #[test]
78 fn new_from_secret_key_derives_correct_commitment() {
79 let secret_key = SecretKey::new();
80 let expected_commitment = secret_key.public_key().to_commitment();
81 let signer = EcdsaKeyStore::new(secret_key);
82 assert_eq!(signer.commitment(), expected_commitment);
83 }
84
85 #[test]
86 fn sign_word_hex_produces_verifiable_signature() {
87 let signer = EcdsaKeyStore::generate();
88 let message = Word::default();
89 let signature_hex = signer.sign_word_hex(message);
90 let signature_bytes = hex::decode(signature_hex.trim_start_matches("0x")).unwrap();
91 let signature = Signature::read_from_bytes(&signature_bytes).unwrap();
92 let public_key_bytes =
93 hex::decode(signer.public_key_hex().trim_start_matches("0x")).unwrap();
94 let public_key = PublicKey::read_from_bytes(&public_key_bytes).unwrap();
95 assert!(public_key.verify(message, &signature));
96 }
97}