Skip to main content

DevelopmentNodeEnvironment_MicrosoftVSCodeDependency_22NodeVersion_Bundle_Clean_Debug_ElectronProfile_EsbuildCompiler_Mountain/IPC/WindServiceHandlers/Encryption/
Key.rs

1//! Machine-stable 256-bit key derivation for AES-256-GCM.
2//!
3//! The key is derived once per process from the host's hardware UUID using
4//! SHA-256: `key = SHA-256("Land-Encryption-v1" ++ machine_id)`.
5//!
6//! If the machine ID cannot be obtained on this system, `DeriveKey` returns
7//! `Err` so callers can surface a meaningful error rather than silently
8//! falling back to a constant key that is identical on every affected machine.
9
10use std::sync::OnceLock;
11
12use ring::digest::{SHA256, digest};
13
14static DERIVED_KEY:OnceLock<Option<[u8; 32]>> = OnceLock::new();
15
16/// Returns the process-wide 256-bit encryption key.
17///
18/// Returns `Err` when no machine-bound seed is available on this system so
19/// that callers can propagate the failure instead of encrypting with a
20/// predictable constant.
21pub fn Fn() -> Result<[u8; 32], String> {
22	DERIVED_KEY
23		.get_or_init(ComputeKey)
24		.ok_or_else(|| "encryption unavailable: machine ID lookup failed".to_string())
25}
26
27fn ComputeKey() -> Option<[u8; 32]> {
28	let MachineId = ReadMachineId()?;
29
30	let Input = format!("Land-Encryption-v1{}", MachineId);
31
32	let Hash = digest(&SHA256, Input.as_bytes());
33
34	let mut Key = [0u8; 32];
35
36	Key.copy_from_slice(Hash.as_ref());
37
38	Some(Key)
39}
40
41fn ReadMachineId() -> Option<String> {
42	#[cfg(target_os = "macos")]
43	{
44		if let Ok(Out) = std::process::Command::new("ioreg")
45			.args(["-rd1", "-c", "IOPlatformExpertDevice"])
46			.output()
47		{
48			let S = String::from_utf8_lossy(&Out.stdout);
49
50			for Line in S.lines() {
51				if Line.contains("IOPlatformUUID") {
52					if let Some(Start) = Line.rfind('"') {
53						let Rest = &Line[..Start];
54
55						if let Some(End) = Rest.rfind('"') {
56							return Some(Rest[End + 1..].to_string());
57						}
58					}
59				}
60			}
61		}
62	}
63
64	#[cfg(target_os = "linux")]
65	{
66		if let Ok(Id) = std::fs::read_to_string("/etc/machine-id") {
67			let Trimmed = Id.trim().to_string();
68
69			if !Trimmed.is_empty() {
70				return Some(Trimmed);
71			}
72		}
73
74		if let Ok(Id) = std::fs::read_to_string("/var/lib/dbus/machine-id") {
75			let Trimmed = Id.trim().to_string();
76
77			if !Trimmed.is_empty() {
78				return Some(Trimmed);
79			}
80		}
81	}
82
83	#[cfg(target_os = "windows")]
84	{
85		use std::process::Command;
86
87		if let Ok(Out) = Command::new("reg")
88			.args(["query", "HKLM\\SOFTWARE\\Microsoft\\Cryptography", "/v", "MachineGuid"])
89			.output()
90		{
91			let S = String::from_utf8_lossy(&Out.stdout);
92
93			if let Some(Line) = S.lines().find(|L| L.contains("MachineGuid")) {
94				if let Some(Id) = Line.split_whitespace().last() {
95					return Some(Id.to_string());
96				}
97			}
98		}
99	}
100
101	None
102}