Skip to main content

rtb_telemetry/
machine.rs

1//! Machine-ID derivation with a per-tool salt.
2
3use sha2::{Digest, Sha256};
4
5/// Salted-SHA-256 derivation of the host's machine ID.
6///
7/// The raw ID obtained from `machine-uid` is never returned — callers
8/// only see the salted hash, hex-encoded. If the OS does not expose
9/// a machine ID (sandboxed container, WASI), a random UUID fills in
10/// so the pipeline never fails because of identity.
11pub struct MachineId;
12
13impl MachineId {
14    /// Compute `sha256(salt || machine_id)` as a 64-char hex string.
15    ///
16    /// `salt` MUST be per-tool — rotating the salt invalidates every
17    /// previously-recorded machine identity, which is the intended
18    /// path for "reset my telemetry identity" flows.
19    #[must_use]
20    pub fn derive(salt: &str) -> String {
21        let raw = machine_uid::get().unwrap_or_else(|_| uuid::Uuid::new_v4().to_string());
22
23        let mut hasher = Sha256::new();
24        hasher.update(salt.as_bytes());
25        hasher.update(raw.as_bytes());
26        let digest = hasher.finalize();
27
28        hex_encode(&digest)
29    }
30}
31
32fn hex_encode(bytes: &[u8]) -> String {
33    let mut out = String::with_capacity(bytes.len() * 2);
34    for b in bytes {
35        use std::fmt::Write;
36        let _ = write!(out, "{b:02x}");
37    }
38    out
39}