1#[cfg(feature = "signing")]
26use hmac::{Hmac, Mac};
27#[cfg(feature = "signing")]
28use sha2::Sha256;
29
30use std::fmt;
31
32#[derive(Debug, Clone, PartialEq, Eq)]
34pub enum SignatureError {
35 InvalidSignature,
37 VerificationFailed,
39 InvalidKeyLength,
41}
42
43impl fmt::Display for SignatureError {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 match self {
46 SignatureError::InvalidSignature => write!(f, "Invalid signature format"),
47 SignatureError::VerificationFailed => write!(f, "Signature verification failed"),
48 SignatureError::InvalidKeyLength => write!(f, "Invalid key length"),
49 }
50 }
51}
52
53impl std::error::Error for SignatureError {}
54
55#[cfg(feature = "signing")]
56type HmacSha256 = Hmac<Sha256>;
57
58#[cfg(feature = "signing")]
63pub struct MessageSigner {
64 key: Vec<u8>,
65}
66
67#[cfg(feature = "signing")]
68impl MessageSigner {
69 pub fn new(key: &[u8]) -> Self {
75 Self { key: key.to_vec() }
76 }
77
78 pub fn sign(&self, message: &[u8]) -> Result<Vec<u8>, SignatureError> {
89 let mut mac =
90 HmacSha256::new_from_slice(&self.key).map_err(|_| SignatureError::InvalidKeyLength)?;
91 mac.update(message);
92 Ok(mac.finalize().into_bytes().to_vec())
93 }
94
95 pub fn verify(&self, message: &[u8], signature: &[u8]) -> Result<(), SignatureError> {
106 let mut mac =
107 HmacSha256::new_from_slice(&self.key).map_err(|_| SignatureError::InvalidKeyLength)?;
108 mac.update(message);
109
110 mac.verify_slice(signature)
111 .map_err(|_| SignatureError::VerificationFailed)
112 }
113
114 pub fn sign_hex(&self, message: &[u8]) -> Result<String, SignatureError> {
124 let sig = self.sign(message)?;
125 Ok(hex::encode(sig))
126 }
127
128 pub fn verify_hex(&self, message: &[u8], signature_hex: &str) -> Result<(), SignatureError> {
139 let signature_bytes =
140 hex::decode(signature_hex).map_err(|_| SignatureError::InvalidSignature)?;
141 self.verify(message, &signature_bytes)
142 }
143}
144
145#[cfg(not(feature = "signing"))]
147pub struct MessageSigner;
148
149#[cfg(not(feature = "signing"))]
150impl MessageSigner {
151 pub fn new(_key: &[u8]) -> Self {
152 Self
153 }
154}
155
156#[cfg(all(test, feature = "signing"))]
157mod tests {
158 use super::*;
159
160 #[test]
161 fn test_sign_and_verify() {
162 let secret = b"my-secret-key";
163 let signer = MessageSigner::new(secret);
164
165 let message = b"test message";
166 let signature = signer.sign(message).expect("signing should not fail");
167
168 assert!(signer.verify(message, &signature).is_ok());
169 }
170
171 #[test]
172 fn test_verify_invalid_signature() {
173 let secret = b"my-secret-key";
174 let signer = MessageSigner::new(secret);
175
176 let message = b"test message";
177 let wrong_signature = vec![0u8; 32];
178
179 assert!(signer.verify(message, &wrong_signature).is_err());
180 }
181
182 #[test]
183 fn test_verify_wrong_message() {
184 let secret = b"my-secret-key";
185 let signer = MessageSigner::new(secret);
186
187 let message = b"test message";
188 let signature = signer.sign(message).expect("signing should not fail");
189
190 let wrong_message = b"different message";
191 assert!(signer.verify(wrong_message, &signature).is_err());
192 }
193
194 #[test]
195 fn test_sign_hex() {
196 let secret = b"my-secret-key";
197 let signer = MessageSigner::new(secret);
198
199 let message = b"test message";
200 let signature_hex = signer.sign_hex(message).expect("signing should not fail");
201
202 assert!(hex::decode(&signature_hex).is_ok());
204
205 assert!(signer.verify_hex(message, &signature_hex).is_ok());
207 }
208
209 #[test]
210 fn test_verify_hex_invalid() {
211 let secret = b"my-secret-key";
212 let signer = MessageSigner::new(secret);
213
214 let message = b"test message";
215 let invalid_hex = "not-valid-hex!!";
216
217 assert_eq!(
218 signer.verify_hex(message, invalid_hex),
219 Err(SignatureError::InvalidSignature)
220 );
221 }
222
223 #[test]
224 fn test_signature_deterministic() {
225 let secret = b"my-secret-key";
226 let signer = MessageSigner::new(secret);
227
228 let message = b"test message";
229 let sig1 = signer.sign(message).expect("signing should not fail");
230 let sig2 = signer.sign(message).expect("signing should not fail");
231
232 assert_eq!(sig1, sig2);
233 }
234
235 #[test]
236 fn test_different_keys_different_signatures() {
237 let message = b"test message";
238
239 let signer1 = MessageSigner::new(b"key1");
240 let signer2 = MessageSigner::new(b"key2");
241
242 let sig1 = signer1.sign(message).expect("signing should not fail");
243 let sig2 = signer2.sign(message).expect("signing should not fail");
244
245 assert_ne!(sig1, sig2);
246 }
247
248 #[test]
249 fn test_signature_error_display() {
250 assert_eq!(
251 SignatureError::InvalidSignature.to_string(),
252 "Invalid signature format"
253 );
254 assert_eq!(
255 SignatureError::VerificationFailed.to_string(),
256 "Signature verification failed"
257 );
258 assert_eq!(
259 SignatureError::InvalidKeyLength.to_string(),
260 "Invalid key length"
261 );
262 }
263}