use sha2::{Digest, Sha256};
pub fn get() -> String {
let raw = get_raw_identifier();
let hash = Sha256::digest(raw.as_bytes());
hex::encode(&hash[..16])
}
fn get_raw_identifier() -> String {
#[cfg(target_os = "windows")]
{
if let Some(guid) = read_machine_guid_windows() {
return guid;
}
}
let hostname = std::env::var("COMPUTERNAME")
.or_else(|_| std::env::var("HOSTNAME"))
.unwrap_or_else(|_| "unknown-host".to_string());
let username = std::env::var("USERNAME")
.or_else(|_| std::env::var("USER"))
.unwrap_or_else(|_| "unknown-user".to_string());
format!("{}_{}", hostname, username)
}
#[cfg(target_os = "windows")]
fn read_machine_guid_windows() -> Option<String> {
use crate::security::strings;
use winapi::shared::minwindef::HKEY;
use winapi::um::winnt::KEY_READ;
use winapi::um::winreg::{
RegCloseKey, RegGetValueW, RegOpenKeyExW, HKEY_LOCAL_MACHINE, RRF_RT_REG_SZ,
};
let subkey_str = strings::decode(&strings::REG_MACHINE_GUID_PATH);
let subkey_clean = subkey_str.trim_end_matches('\0');
let value_str = strings::decode(&strings::REG_MACHINE_GUID_KEY);
let subkey_wide: Vec<u16> = subkey_clean.encode_utf16().chain(Some(0)).collect();
let value_wide: Vec<u16> = value_str.encode_utf16().chain(Some(0)).collect();
unsafe {
let mut hkey: HKEY = std::ptr::null_mut();
let ret = RegOpenKeyExW(
HKEY_LOCAL_MACHINE,
subkey_wide.as_ptr(),
0,
KEY_READ,
&mut hkey,
);
if ret != 0 {
return None;
}
let mut buf = [0u16; 64];
let mut buf_size = std::mem::size_of_val(&buf) as u32;
let ret = RegGetValueW(
hkey,
std::ptr::null(),
value_wide.as_ptr(),
RRF_RT_REG_SZ,
std::ptr::null_mut(),
buf.as_mut_ptr() as *mut _,
&mut buf_size,
);
RegCloseKey(hkey);
if ret != 0 {
return None;
}
let guid_wide: Vec<u16> = buf.iter().take_while(|&&c| c != 0).copied().collect();
let guid = String::from_utf16_lossy(&guid_wide);
if guid.is_empty() {
None
} else {
Some(guid)
}
}
}