1use crate::{Event, EventualiError, Result};
2use base64::{Engine as _, engine::general_purpose};
3use serde::{Deserialize, Serialize};
4use sha2::{Digest, Sha256};
5use std::collections::HashMap;
6
7pub struct EventSigner {
9 key_manager: SigningKeyManager,
10}
11
12#[derive(Debug, Clone)]
14pub struct SigningKeyManager {
15 keys: HashMap<String, SigningKey>,
16 default_key_id: String,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct SigningKey {
22 pub id: String,
23 pub key_data: Vec<u8>, pub created_at: chrono::DateTime<chrono::Utc>,
25 pub algorithm: SignatureAlgorithm,
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
30pub enum SignatureAlgorithm {
31 HmacSha256,
32 HmacSha512,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
37pub struct EventSignature {
38 pub algorithm: SignatureAlgorithm,
39 pub key_id: String,
40 pub signature: Vec<u8>,
41 pub timestamp: chrono::DateTime<chrono::Utc>,
42 pub event_hash: Vec<u8>, }
44
45#[derive(Debug, Clone, Serialize, Deserialize)]
47pub struct SignedEvent {
48 pub event: Event,
49 pub signature: EventSignature,
50}
51
52impl EventSigner {
53 pub fn new(key_manager: SigningKeyManager) -> Self {
55 Self { key_manager }
56 }
57
58 pub fn with_key(key_id: String, key_data: Vec<u8>) -> Result<Self> {
60 let mut keys = HashMap::new();
61 let signing_key = SigningKey {
62 id: key_id.clone(),
63 key_data,
64 created_at: chrono::Utc::now(),
65 algorithm: SignatureAlgorithm::HmacSha256,
66 };
67 keys.insert(key_id.clone(), signing_key);
68
69 let key_manager = SigningKeyManager {
70 keys,
71 default_key_id: key_id,
72 };
73
74 Ok(Self::new(key_manager))
75 }
76
77 pub fn sign_event(&self, event: &Event) -> Result<SignedEvent> {
79 self.sign_event_with_key(event, &self.key_manager.default_key_id)
80 }
81
82 pub fn sign_event_with_key(&self, event: &Event, key_id: &str) -> Result<SignedEvent> {
84 let key = self.key_manager.get_key(key_id)?;
85 let event_bytes = self.serialize_event(event)?;
86 let event_hash = self.hash_event_data(&event_bytes);
87
88 let signature_bytes = match key.algorithm {
89 SignatureAlgorithm::HmacSha256 => self.hmac_sha256(&event_bytes, &key.key_data)?,
90 SignatureAlgorithm::HmacSha512 => self.hmac_sha512(&event_bytes, &key.key_data)?,
91 };
92
93 let signature = EventSignature {
94 algorithm: key.algorithm.clone(),
95 key_id: key_id.to_string(),
96 signature: signature_bytes,
97 timestamp: chrono::Utc::now(),
98 event_hash,
99 };
100
101 Ok(SignedEvent {
102 event: event.clone(),
103 signature,
104 })
105 }
106
107 pub fn verify_signature(&self, signed_event: &SignedEvent) -> Result<bool> {
109 let key = self.key_manager.get_key(&signed_event.signature.key_id)?;
110 let event_bytes = self.serialize_event(&signed_event.event)?;
111
112 let computed_hash = self.hash_event_data(&event_bytes);
114 if computed_hash != signed_event.signature.event_hash {
115 return Ok(false);
116 }
117
118 let expected_signature = match signed_event.signature.algorithm {
120 SignatureAlgorithm::HmacSha256 => self.hmac_sha256(&event_bytes, &key.key_data)?,
121 SignatureAlgorithm::HmacSha512 => self.hmac_sha512(&event_bytes, &key.key_data)?,
122 };
123
124 Ok(self.constant_time_compare(&expected_signature, &signed_event.signature.signature))
126 }
127
128 pub fn verify_signature_with_key(&self, signed_event: &SignedEvent, key_data: &[u8]) -> Result<bool> {
130 let event_bytes = self.serialize_event(&signed_event.event)?;
131
132 let computed_hash = self.hash_event_data(&event_bytes);
134 if computed_hash != signed_event.signature.event_hash {
135 return Ok(false);
136 }
137
138 let expected_signature = match signed_event.signature.algorithm {
140 SignatureAlgorithm::HmacSha256 => self.hmac_sha256(&event_bytes, key_data)?,
141 SignatureAlgorithm::HmacSha512 => self.hmac_sha512(&event_bytes, key_data)?,
142 };
143
144 Ok(self.constant_time_compare(&expected_signature, &signed_event.signature.signature))
146 }
147
148 pub fn sign_data(&self, data: &[u8], key_id: &str) -> Result<EventSignature> {
150 let key = self.key_manager.get_key(key_id)?;
151 let data_hash = self.hash_event_data(data);
152
153 let signature_bytes = match key.algorithm {
154 SignatureAlgorithm::HmacSha256 => self.hmac_sha256(data, &key.key_data)?,
155 SignatureAlgorithm::HmacSha512 => self.hmac_sha512(data, &key.key_data)?,
156 };
157
158 Ok(EventSignature {
159 algorithm: key.algorithm.clone(),
160 key_id: key_id.to_string(),
161 signature: signature_bytes,
162 timestamp: chrono::Utc::now(),
163 event_hash: data_hash,
164 })
165 }
166
167 pub fn verify_data_signature(&self, data: &[u8], signature: &EventSignature) -> Result<bool> {
169 let key = self.key_manager.get_key(&signature.key_id)?;
170
171 let computed_hash = self.hash_event_data(data);
173 if computed_hash != signature.event_hash {
174 return Ok(false);
175 }
176
177 let expected_signature = match signature.algorithm {
179 SignatureAlgorithm::HmacSha256 => self.hmac_sha256(data, &key.key_data)?,
180 SignatureAlgorithm::HmacSha512 => self.hmac_sha512(data, &key.key_data)?,
181 };
182
183 Ok(self.constant_time_compare(&expected_signature, &signature.signature))
184 }
185
186 fn serialize_event(&self, event: &Event) -> Result<Vec<u8>> {
188 serde_json::to_vec(event)
189 .map_err(EventualiError::Serialization)
190 }
191
192 fn hash_event_data(&self, data: &[u8]) -> Vec<u8> {
194 let mut hasher = Sha256::new();
195 hasher.update(data);
196 hasher.finalize().to_vec()
197 }
198
199 fn hmac_sha256(&self, data: &[u8], key: &[u8]) -> Result<Vec<u8>> {
201 use hmac::{Hmac, Mac};
202 type HmacSha256 = Hmac<Sha256>;
203
204 let mut mac = HmacSha256::new_from_slice(key)
205 .map_err(|e| EventualiError::Configuration(format!("Invalid HMAC key: {e}")))?;
206 mac.update(data);
207 Ok(mac.finalize().into_bytes().to_vec())
208 }
209
210 fn hmac_sha512(&self, data: &[u8], key: &[u8]) -> Result<Vec<u8>> {
212 use hmac::{Hmac, Mac};
213 use sha2::Sha512;
214 type HmacSha512 = Hmac<Sha512>;
215
216 let mut mac = HmacSha512::new_from_slice(key)
217 .map_err(|e| EventualiError::Configuration(format!("Invalid HMAC key: {e}")))?;
218 mac.update(data);
219 Ok(mac.finalize().into_bytes().to_vec())
220 }
221
222 fn constant_time_compare(&self, a: &[u8], b: &[u8]) -> bool {
224 if a.len() != b.len() {
225 return false;
226 }
227
228 let mut result = 0u8;
229 for (byte_a, byte_b) in a.iter().zip(b.iter()) {
230 result |= byte_a ^ byte_b;
231 }
232
233 result == 0
234 }
235}
236
237impl SigningKeyManager {
238 pub fn new() -> Self {
240 Self {
241 keys: HashMap::new(),
242 default_key_id: String::new(),
243 }
244 }
245
246 pub fn add_key(&mut self, key: SigningKey) -> Result<()> {
248 if key.key_data.is_empty() {
249 return Err(EventualiError::Configuration(
250 "Signing key cannot be empty".to_string()
251 ));
252 }
253
254 if self.keys.is_empty() {
255 self.default_key_id = key.id.clone();
256 }
257
258 self.keys.insert(key.id.clone(), key);
259 Ok(())
260 }
261
262 pub fn generate_key(id: String, algorithm: SignatureAlgorithm) -> Result<SigningKey> {
264 let key_data = Self::generate_random_key(algorithm.key_size())?;
265 Ok(SigningKey {
266 id,
267 key_data,
268 created_at: chrono::Utc::now(),
269 algorithm,
270 })
271 }
272
273 pub fn derive_key_from_password(
275 id: String,
276 password: &str,
277 salt: &[u8],
278 algorithm: SignatureAlgorithm,
279 ) -> Result<SigningKey> {
280 use pbkdf2::{pbkdf2_hmac};
281 use sha2::Sha256;
282
283 let key_size = algorithm.key_size();
284 let mut key_data = vec![0u8; key_size];
285 pbkdf2_hmac::<Sha256>(password.as_bytes(), salt, 100_000, &mut key_data);
286
287 Ok(SigningKey {
288 id,
289 key_data,
290 created_at: chrono::Utc::now(),
291 algorithm,
292 })
293 }
294
295 pub fn get_key(&self, key_id: &str) -> Result<&SigningKey> {
297 self.keys.get(key_id).ok_or_else(|| {
298 EventualiError::Configuration(format!("Signing key not found: {key_id}"))
299 })
300 }
301
302 pub fn set_default_key(&mut self, key_id: &str) -> Result<()> {
304 if !self.keys.contains_key(key_id) {
305 return Err(EventualiError::Configuration(
306 format!("Signing key not found: {key_id}")
307 ));
308 }
309 self.default_key_id = key_id.to_string();
310 Ok(())
311 }
312
313 pub fn list_key_ids(&self) -> Vec<String> {
315 self.keys.keys().cloned().collect()
316 }
317
318 fn generate_random_key(size: usize) -> Result<Vec<u8>> {
320 use std::time::{SystemTime, UNIX_EPOCH};
321
322 let timestamp = SystemTime::now()
324 .duration_since(UNIX_EPOCH)
325 .map_err(|e| EventualiError::Configuration(format!("Time error: {e}")))?
326 .as_nanos();
327
328 let mut key = Vec::with_capacity(size);
330 let mut current_hash = timestamp.to_be_bytes().to_vec();
331
332 while key.len() < size {
333 let mut hasher = Sha256::new();
334 hasher.update(¤t_hash);
335 hasher.update(b"eventuali-signing-key");
336 hasher.update((key.len() as u64).to_be_bytes());
337
338 let pid = std::process::id();
340 hasher.update(pid.to_be_bytes());
341
342 current_hash = hasher.finalize().to_vec();
343
344 let remaining = size - key.len();
345 if remaining >= current_hash.len() {
346 key.extend_from_slice(¤t_hash);
347 } else {
348 key.extend_from_slice(¤t_hash[..remaining]);
349 }
350 }
351
352 Ok(key)
353 }
354}
355
356impl Default for SigningKeyManager {
357 fn default() -> Self {
358 Self::new()
359 }
360}
361
362impl SignatureAlgorithm {
363 pub fn key_size(&self) -> usize {
365 match self {
366 SignatureAlgorithm::HmacSha256 => 32, SignatureAlgorithm::HmacSha512 => 64, }
369 }
370
371 pub fn signature_size(&self) -> usize {
373 match self {
374 SignatureAlgorithm::HmacSha256 => 32, SignatureAlgorithm::HmacSha512 => 64, }
377 }
378}
379
380impl SignedEvent {
382 pub fn to_base64(&self) -> String {
384 let serialized = serde_json::to_vec(self).unwrap_or_default();
385 general_purpose::STANDARD.encode(serialized)
386 }
387
388 pub fn from_base64(data: &str) -> Result<Self> {
390 let bytes = general_purpose::STANDARD
391 .decode(data)
392 .map_err(|e| EventualiError::Configuration(format!("Base64 decode error: {e}")))?;
393
394 serde_json::from_slice(&bytes)
395 .map_err(EventualiError::from)
396 }
397}
398
399impl EventSignature {
400 pub fn to_base64(&self) -> String {
402 let serialized = serde_json::to_vec(self).unwrap_or_default();
403 general_purpose::STANDARD.encode(serialized)
404 }
405
406 pub fn from_base64(data: &str) -> Result<Self> {
408 let bytes = general_purpose::STANDARD
409 .decode(data)
410 .map_err(|e| EventualiError::Configuration(format!("Base64 decode error: {e}")))?;
411
412 serde_json::from_slice(&bytes)
413 .map_err(EventualiError::from)
414 }
415}
416
417#[cfg(test)]
418mod tests {
419 use super::*;
420 use crate::{EventData, EventMetadata};
421 use uuid::Uuid;
422
423 fn create_test_event() -> Event {
424 Event {
425 id: Uuid::new_v4(),
426 aggregate_id: "test-aggregate".to_string(),
427 aggregate_type: "TestAggregate".to_string(),
428 event_type: "TestEvent".to_string(),
429 event_version: 1,
430 aggregate_version: 1,
431 data: EventData::Json(serde_json::json!({"test": "data"})),
432 metadata: EventMetadata::default(),
433 timestamp: chrono::Utc::now(),
434 }
435 }
436
437 #[test]
438 fn test_key_generation() {
439 let key = SigningKeyManager::generate_key(
440 "test-key".to_string(),
441 SignatureAlgorithm::HmacSha256
442 ).unwrap();
443
444 assert_eq!(key.key_data.len(), 32);
445 assert_eq!(key.id, "test-key");
446 assert_eq!(key.algorithm, SignatureAlgorithm::HmacSha256);
447 }
448
449 #[test]
450 fn test_password_key_derivation() {
451 let salt = b"test-salt";
452 let key = SigningKeyManager::derive_key_from_password(
453 "test-key".to_string(),
454 "test-password",
455 salt,
456 SignatureAlgorithm::HmacSha256
457 ).unwrap();
458
459 assert_eq!(key.key_data.len(), 32);
460
461 let key2 = SigningKeyManager::derive_key_from_password(
463 "test-key-2".to_string(),
464 "test-password",
465 salt,
466 SignatureAlgorithm::HmacSha256
467 ).unwrap();
468
469 assert_eq!(key.key_data, key2.key_data);
470 }
471
472 #[test]
473 fn test_event_signing_and_verification() {
474 let key = SigningKeyManager::generate_key(
475 "test-key".to_string(),
476 SignatureAlgorithm::HmacSha256
477 ).unwrap();
478
479 let signer = EventSigner::with_key("test-key".to_string(), key.key_data).unwrap();
480 let event = create_test_event();
481
482 let signed_event = signer.sign_event(&event).unwrap();
483
484 assert_eq!(signed_event.signature.algorithm, SignatureAlgorithm::HmacSha256);
485 assert_eq!(signed_event.signature.key_id, "test-key");
486 assert_eq!(signed_event.signature.signature.len(), 32);
487 assert!(!signed_event.signature.signature.is_empty());
488
489 let is_valid = signer.verify_signature(&signed_event).unwrap();
490 assert!(is_valid);
491 }
492
493 #[test]
494 fn test_signature_verification_with_different_keys() {
495 let key1 = SigningKeyManager::generate_key(
496 "key1".to_string(),
497 SignatureAlgorithm::HmacSha256
498 ).unwrap();
499
500 let key2 = SigningKeyManager::generate_key(
501 "key2".to_string(),
502 SignatureAlgorithm::HmacSha256
503 ).unwrap();
504
505 let signer1 = EventSigner::with_key("key1".to_string(), key1.key_data).unwrap();
506 let signer2 = EventSigner::with_key("key2".to_string(), key2.key_data).unwrap();
507
508 let event = create_test_event();
509 let signed_event = signer1.sign_event(&event).unwrap();
510
511 assert!(signer1.verify_signature(&signed_event).unwrap());
513
514 assert!(!signer2.verify_signature(&signed_event).unwrap_or(true));
516 }
517
518 #[test]
519 fn test_tampered_event_detection() {
520 let key = SigningKeyManager::generate_key(
521 "test-key".to_string(),
522 SignatureAlgorithm::HmacSha256
523 ).unwrap();
524
525 let signer = EventSigner::with_key("test-key".to_string(), key.key_data).unwrap();
526 let event = create_test_event();
527
528 let mut signed_event = signer.sign_event(&event).unwrap();
529
530 assert!(signer.verify_signature(&signed_event).unwrap());
532
533 signed_event.event.data = EventData::Json(serde_json::json!({"tampered": "data"}));
535
536 assert!(!signer.verify_signature(&signed_event).unwrap());
538 }
539
540 #[test]
541 fn test_hmac_sha512() {
542 let key = SigningKeyManager::generate_key(
543 "test-key".to_string(),
544 SignatureAlgorithm::HmacSha512
545 ).unwrap();
546
547 assert_eq!(key.key_data.len(), 64);
548
549 let signer = EventSigner::with_key("test-key".to_string(), key.key_data).unwrap();
550 let event = create_test_event();
551
552 let signed_event = signer.sign_event(&event).unwrap();
553
554 assert_eq!(signed_event.signature.algorithm, SignatureAlgorithm::HmacSha512);
555 assert_eq!(signed_event.signature.signature.len(), 64);
556 assert!(signer.verify_signature(&signed_event).unwrap());
557 }
558
559 #[test]
560 fn test_data_signing() {
561 let key = SigningKeyManager::generate_key(
562 "test-key".to_string(),
563 SignatureAlgorithm::HmacSha256
564 ).unwrap();
565
566 let signer = EventSigner::with_key("test-key".to_string(), key.key_data).unwrap();
567 let data = b"Hello, World!";
568
569 let signature = signer.sign_data(data, "test-key").unwrap();
570 assert!(signer.verify_data_signature(data, &signature).unwrap());
571
572 let other_data = b"Hello, World?";
574 assert!(!signer.verify_data_signature(other_data, &signature).unwrap());
575 }
576
577 #[test]
578 fn test_base64_serialization() {
579 let key = SigningKeyManager::generate_key(
580 "test-key".to_string(),
581 SignatureAlgorithm::HmacSha256
582 ).unwrap();
583
584 let signer = EventSigner::with_key("test-key".to_string(), key.key_data).unwrap();
585 let event = create_test_event();
586
587 let signed_event = signer.sign_event(&event).unwrap();
588
589 let base64_str = signed_event.to_base64();
590 assert!(!base64_str.is_empty());
591
592 let deserialized = SignedEvent::from_base64(&base64_str).unwrap();
593 assert_eq!(signed_event.signature.key_id, deserialized.signature.key_id);
594 assert_eq!(signed_event.signature.signature, deserialized.signature.signature);
595
596 assert!(signer.verify_signature(&deserialized).unwrap());
597 }
598}