1use wasm_bindgen::prelude::*;
2use wasm_bindgen::JsValue;
3use serde::{Serialize, Deserialize};
4use sha2::{Sha256, Digest}; use k256::ecdsa::{Signature, VerifyingKey};
6use web_sys::console;
7use k256::ecdsa::signature::Verifier; #[derive(Debug, Serialize, Deserialize)]
12pub enum ECDSAError {
13 InvalidSignatureFormat,
14 InvalidSignatureLength,
15 InvalidSignatureRecovery,
16 InvalidPublicKey,
17}
18
19impl std::fmt::Display for ECDSAError {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 match *self {
22 ECDSAError::InvalidSignatureFormat => write!(f, "Invalid signature format"),
23 ECDSAError::InvalidSignatureLength => write!(f, "Invalid signature length"),
24 ECDSAError::InvalidSignatureRecovery => write!(f, "Failed to recover public key"),
25 ECDSAError::InvalidPublicKey => write!(f, "Invalid public key"),
26 }
27 }
28}
29
30#[wasm_bindgen]
32pub struct ECDSAVerifier;
33
34#[wasm_bindgen]
35impl ECDSAVerifier {
36 #[wasm_bindgen(constructor)]
38 pub fn new() -> ECDSAVerifier {
39 ECDSAVerifier
40 }
41
42 pub fn verify_signature(
55 &self,
56 message: &str,
57 signature: &str,
58 public_key: &str,
59 ) -> Result<bool, JsValue> {
60 console::log_1(&"Starting signature verification...".into());
62
63 let msg_hash = self.hash_message(message);
65
66 let signature_bytes = hex::decode(signature).map_err(|_| JsValue::from_str("Invalid signature format"))?;
68 if signature_bytes.len() != 64 {
69 return Err(JsValue::from_str("Signature length is invalid"));
70 }
71
72 let pubkey_bytes = hex::decode(public_key).map_err(|_| JsValue::from_str("Invalid public key format"))?;
73 if pubkey_bytes.len() != 33 {
74 return Err(JsValue::from_str("Public key length is invalid"));
75 }
76
77 let sig = Signature::from_der(&signature_bytes).map_err(|_| JsValue::from_str("Invalid signature"))?;
79 let pubkey = VerifyingKey::from_sec1_bytes(&pubkey_bytes).map_err(|_| JsValue::from_str("Invalid public key"))?;
80
81 pubkey.verify(&msg_hash, &sig).map_err(|e| JsValue::from_str(&e.to_string()))?;
83
84 console::log_1(&"Verification complete.".into());
85
86 Ok(true)
87 }
88
89 pub fn hash_message(&self, message: &str) -> Vec<u8> {
92 let mut hasher = Sha256::new();
93 hasher.update(message.as_bytes());
94 hasher.finalize().to_vec() }
96}
97
98#[cfg(test)]
101mod tests {
102 use super::*;
103
104 #[test]
105 fn test_verify_signature() {
106 let verifier = ECDSAVerifier::new();
107 let message = "Test message";
108 let signature = "3045022100ebf..."; let public_key = "03a0..."; let result = verifier.verify_signature(message, signature, public_key);
112 assert!(result.is_ok());
113 assert!(result.unwrap());
114 }
115
116 #[test]
117 fn test_invalid_signature() {
118 let verifier = ECDSAVerifier::new();
119 let message = "Test message";
120 let invalid_signature = "invalid_sig";
121 let public_key = "03a0..."; let result = verifier.verify_signature(message, invalid_signature, public_key);
124 assert!(result.is_err());
125 }
126
127 #[test]
128 fn test_invalid_public_key() {
129 let verifier = ECDSAVerifier::new();
130 let message = "Test message";
131 let signature = "3045022100ebf..."; let invalid_public_key = "invalid_pubkey";
133
134 let result = verifier.verify_signature(message, signature, invalid_public_key);
135 assert!(result.is_err());
136 }
137}