Mountain/IPC/Encryption/
SecureChannel.rs1use ring::{
36 aead::{self, AES_256_GCM, LessSafeKey, UnboundKey},
37 hmac,
38 rand::{SecureRandom, SystemRandom},
39};
40use serde::{Deserialize, Serialize};
41
42use super::super::Message::TauriIPCMessage;
43use crate::dev_log;
44
45#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct EncryptedMessage {
71 pub nonce:Vec<u8>,
73
74 pub ciphertext:Vec<u8>,
76
77 pub hmac_tag:Vec<u8>,
79}
80
81impl EncryptedMessage {
82 pub fn new(nonce:Vec<u8>, ciphertext:Vec<u8>, hmac_tag:Vec<u8>) -> Self { Self { nonce, ciphertext, hmac_tag } }
84
85 pub fn is_valid(&self) -> bool {
87 self.nonce.len() == 12 && !self.ciphertext.is_empty()
89 && !self.hmac_tag.is_empty()
90 }
91}
92
93pub struct SecureMessageChannel {
157 encryption_key:LessSafeKey,
159
160 hmac_key:Vec<u8>,
162}
163
164impl SecureMessageChannel {
165 pub fn new() -> Result<Self, String> {
180 dev_log!("encryption", "[SecureMessageChannel] Creating new secure channel");
181
182 let rng = SystemRandom::new();
183
184 let mut encryption_key_bytes = vec![0u8; 32];
186 rng.fill(&mut encryption_key_bytes)
187 .map_err(|e| format!("Failed to generate encryption key: {}", e))?;
188
189 let unbound_key = UnboundKey::new(&AES_256_GCM, &encryption_key_bytes)
190 .map_err(|e| format!("Failed to create unbound key: {}", e))?;
191
192 let encryption_key = LessSafeKey::new(unbound_key);
193
194 let mut hmac_key = vec![0u8; 32];
196 rng.fill(&mut hmac_key)
197 .map_err(|e| format!("Failed to generate HMAC key: {}", e))?;
198
199 dev_log!("encryption", "[SecureMessageChannel] Secure channel created successfully");
200
201 Ok(Self { encryption_key, hmac_key })
202 }
203
204 pub fn encrypt_message(&self, message:&TauriIPCMessage) -> Result<EncryptedMessage, String> {
222 dev_log!(
223 "encryption",
224 "[SecureMessageChannel] Encrypting message on channel: {}",
225 message.channel
226 );
227
228 let serialized_message =
230 serde_json::to_vec(message).map_err(|e| format!("Failed to serialize message: {}", e))?;
231
232 let mut nonce = [0u8; 12];
234 SystemRandom::new()
235 .fill(&mut nonce)
236 .map_err(|e| format!("Failed to generate nonce: {}", e))?;
237
238 let mut in_out = serialized_message.clone();
240 self.encryption_key
241 .seal_in_place_append_tag(aead::Nonce::assume_unique_for_key(nonce), aead::Aad::empty(), &mut in_out)
242 .map_err(|e| format!("Encryption failed: {}", e))?;
243
244 let hmac_key = hmac::Key::new(hmac::HMAC_SHA256, &self.hmac_key);
246 let hmac_tag = hmac::sign(&hmac_key, &in_out);
247
248 let encrypted_message =
249 EncryptedMessage { nonce:nonce.to_vec(), ciphertext:in_out, hmac_tag:hmac_tag.as_ref().to_vec() };
250
251 dev_log!(
252 "encryption",
253 "[SecureMessageChannel] Message encrypted: {} bytes -> {} bytes",
254 serialized_message.len(),
255 encrypted_message.ciphertext.len()
256 );
257
258 Ok(encrypted_message)
259 }
260
261 pub fn decrypt_message(&self, encrypted:&EncryptedMessage) -> Result<TauriIPCMessage, String> {
279 dev_log!("encryption", "[SecureMessageChannel] Decrypting message");
280
281 let hmac_key = hmac::Key::new(hmac::HMAC_SHA256, &self.hmac_key);
283 hmac::verify(&hmac_key, &encrypted.ciphertext, &encrypted.hmac_tag)
284 .map_err(|_| "HMAC verification failed - message may be tampered".to_string())?;
285
286 let nonce_slice:&[u8] = &encrypted.nonce;
288 let nonce_array:[u8; 12] = nonce_slice
289 .try_into()
290 .map_err(|_| "Invalid nonce length - must be 12 bytes".to_string())?;
291
292 let nonce = aead::Nonce::assume_unique_for_key(nonce_array);
293
294 let mut in_out = encrypted.ciphertext.clone();
296 self.encryption_key
297 .open_in_place(nonce, aead::Aad::empty(), &mut in_out)
298 .map_err(|e| format!("Decryption failed: {}", e))?;
299
300 let plaintext_len = in_out.len() - AES_256_GCM.tag_len();
302 in_out.truncate(plaintext_len);
303
304 let message:TauriIPCMessage =
306 serde_json::from_slice(&in_out).map_err(|e| format!("Failed to deserialize message: {}", e))?;
307
308 dev_log!(
309 "encryption",
310 "[SecureMessageChannel] Message decrypted successfully on channel: {}",
311 message.channel
312 );
313
314 Ok(message)
315 }
316
317 pub fn rotate_keys(&mut self) -> Result<(), String> {
332 dev_log!("encryption", "[SecureMessageChannel] Rotating encryption keys");
333
334 *self = Self::new()?;
335
336 dev_log!("encryption", "[SecureMessageChannel] Keys rotated successfully");
337
338 Ok(())
339 }
340
341 pub fn hmac_tag_length(&self) -> usize {
343 32 }
345
346 pub fn nonce_length(&self) -> usize {
348 12 }
350
351 pub fn auth_tag_length(&self) -> usize { AES_256_GCM.tag_len() }
353
354 pub fn key_length(&self) -> usize {
356 32 }
358}
359
360#[cfg(test)]
361#[allow(unused_imports)]
362mod tests {
363 use super::*;
364
365 fn create_test_message() -> TauriIPCMessage {
366 TauriIPCMessage::new(
367 "test_channel".to_string(),
368 serde_json::json!({
369 "data": "sensitive information that should be encrypted",
370 "id": 12345
371 }),
372 Some("test_sender".to_string()),
373 )
374 }
375
376 #[test]
377 fn test_secure_channel_creation() {
378 let channel = SecureMessageChannel::new();
379 assert!(channel.is_ok());
380 }
381
382 #[test]
383 fn test_encrypt_and_decrypt() {
384 let channel = SecureMessageChannel::new().unwrap();
385 let original_message = create_test_message();
386
387 let encrypted = channel.encrypt_message(&original_message).unwrap();
389 assert!(encrypted.is_valid());
390
391 let decrypted = channel.decrypt_message(&encrypted).unwrap();
393
394 assert_eq!(decrypted.channel, original_message.channel);
396 assert_eq!(decrypted.data, original_message.data);
397 assert_eq!(decrypted.sender, original_message.sender);
398 }
399
400 #[test]
401 fn test_encryption_produces_different_outputs() {
402 let channel = SecureMessageChannel::new().unwrap();
403 let message = create_test_message();
404
405 let encrypted1 = channel.encrypt_message(&message).unwrap();
406 let encrypted2 = channel.encrypt_message(&message).unwrap();
407
408 assert_ne!(encrypted1.nonce, encrypted2.nonce);
410 assert_ne!(encrypted1.ciphertext, encrypted2.ciphertext);
411 }
412
413 #[test]
414 fn test_tampered_message_fails_hmac_verification() {
415 let channel = SecureMessageChannel::new().unwrap();
416 let message = create_test_message();
417
418 let mut encrypted = channel.encrypt_message(&message).unwrap();
419
420 if !encrypted.ciphertext.is_empty() {
422 encrypted.ciphertext[0] ^= 0xFF;
423 }
424
425 let result = channel.decrypt_message(&encrypted);
427 assert!(result.is_err());
428 assert!(result.unwrap_err().contains("HMAC verification failed"));
429 }
430
431 #[test]
432 fn test_invalid_nonce_length() {
433 let channel = SecureMessageChannel::new().unwrap();
434 let message = create_test_message();
435
436 let mut encrypted = channel.encrypt_message(&message).unwrap();
437
438 encrypted.nonce = vec![0u8; 16]; let result = channel.decrypt_message(&encrypted);
442 assert!(result.is_err());
443 assert!(result.unwrap_err().contains("Invalid nonce length"));
444 }
445
446 #[test]
447 fn test_message_channel_key_lengths() {
448 let channel = SecureMessageChannel::new().unwrap();
449
450 assert_eq!(channel.key_length(), 32);
451 assert_eq!(channel.nonce_length(), 12);
452 assert_eq!(channel.auth_tag_length(), 16); assert_eq!(channel.hmac_tag_length(), 32); }
455
456 #[test]
457 fn test_key_rotation() {
458 let mut channel = SecureMessageChannel::new().unwrap();
459 let message = create_test_message();
460
461 let encrypted1 = channel.encrypt_message(&message).unwrap();
463
464 let result = channel.rotate_keys();
466 assert!(result.is_ok());
467
468 let decrypted1 = channel.decrypt_message(&encrypted1).unwrap();
470 assert_eq!(decrypted1.channel, message.channel);
471
472 let encrypted2 = channel.encrypt_message(&message).unwrap();
474 let decrypted2 = channel.decrypt_message(&encrypted2).unwrap();
475 assert_eq!(decrypted2.channel, message.channel);
476
477 assert_ne!(encrypted1.nonce, encrypted2.nonce);
479 }
480
481 #[test]
482 fn test_empty_message() {
483 let channel = SecureMessageChannel::new().unwrap();
484 let message = TauriIPCMessage::new("test".to_string(), serde_json::json!(null), None);
485
486 let encrypted = channel.encrypt_message(&message).unwrap();
487 let decrypted = channel.decrypt_message(&encrypted).unwrap();
488
489 assert_eq!(decrypted.channel, "test");
490 }
491}