Skip to main content

DevelopmentNodeEnvironment_MicrosoftVSCodeDependency_22NodeVersion_Bundle_Clean_Debug_ElectronProfile_EsbuildCompiler_Mountain/IPC/Enhanced/SecureMessageChannel/
EncryptionKey.rs

1//! Wrapper around `ring::aead::LessSafeKey` plus metadata -
2//! creation timestamp, random key id, and a usage counter the
3//! channel bumps on each encrypt. Private constructors are
4//! exposed via `pub(super)` so the channel can manage rotation
5//! while keeping callers out of the raw key material.
6
7use std::time::{Duration, SystemTime};
8
9use ring::{
10	aead::{AES_256_GCM, LessSafeKey, UnboundKey},
11	rand::{SecureRandom, SystemRandom},
12};
13
14#[derive(Debug, Clone)]
15pub struct Struct {
16	pub(super) key:LessSafeKey,
17
18	pub(super) created_at:SystemTime,
19
20	pub(super) key_id:String,
21
22	pub(super) usage_count:usize,
23}
24
25impl Struct {
26	pub(super) fn new(key_bytes:&[u8]) -> Result<Self, String> {
27		let unbound_key =
28			UnboundKey::new(&AES_256_GCM, key_bytes).map_err(|e| format!("Failed to create unbound key: {}", e))?;
29
30		Ok(Self {
31			key:LessSafeKey::new(unbound_key),
32			created_at:SystemTime::now(),
33			key_id:Self::generate_key_id(),
34			usage_count:0,
35		})
36	}
37
38	fn generate_key_id() -> String {
39		let rng = SystemRandom::new();
40
41		let mut id_bytes = [0u8; 8];
42
43		rng.fill(&mut id_bytes).unwrap();
44
45		hex::encode(id_bytes)
46	}
47
48	pub(super) fn is_expired(&self, rotation_interval:Duration) -> bool {
49		self.created_at.elapsed().unwrap_or_default() > rotation_interval
50	}
51
52	pub(super) fn increment_usage(&mut self) { self.usage_count += 1; }
53}