Files
honey-biscuit-workshop/workshop-deviceid/src/lib.rs
T
2025-11-09 17:27:18 +08:00

165 lines
5.8 KiB
Rust

// device_id_generator.rs
use serde::Serialize;
mod device_info;
use crate::device_info::{DeviceInfo, DeviceInfoCollector};
use sha2::{Sha256, Digest};
use std::collections::HashMap;
pub struct DeviceIdGenerator;
impl DeviceIdGenerator {
/// 生成设备ID - 主要方法
pub fn generate_device_id() -> Result<String, ()> {
let device_info = DeviceInfoCollector::collect_device_info()?;
Self::calculate_device_hash(&device_info)
}
/// 生成设备ID - 带自定义元数据
pub fn generate_device_id_with_metadata(
additional_metadata: &HashMap<String, String>
) -> Result<String, ()> {
let mut device_info = DeviceInfoCollector::collect_device_info()?;
// 合并额外的元数据
for (key, value) in additional_metadata {
device_info.system_metadata.insert(key.clone(), value.clone());
}
Self::calculate_device_hash(&device_info)
}
/// 计算设备信息的SHA256哈希
fn calculate_device_hash(device_info: &DeviceInfo) -> Result<String, ()> {
let data_string = Self::serialize_device_info(device_info);
let hash = Self::calculate_sha256(&data_string);
Ok(hash)
}
/// 将设备信息序列化为字符串用于哈希计算
fn serialize_device_info(device_info: &DeviceInfo) -> String {
// 按照固定顺序拼接关键信息,确保一致性
let mut components = Vec::new();
// 基础标识信息
components.push(format!("username:{}", device_info.username));
components.push(format!("hostname:{}", device_info.hostname));
components.push(format!("os_name:{}", device_info.os_name));
components.push(format!("os_version:{}", device_info.os_version));
components.push(format!("architecture:{}", device_info.architecture));
// CPU标识信息 - 这些是相对稳定的
components.push(format!("cpu_vendor:{}", device_info.cpu_info.vendor_id));
components.push(format!("cpu_brand:{}", device_info.cpu_info.brand));
components.push(format!("cpu_family:{}", device_info.cpu_info.family));
components.push(format!("cpu_model:{}", device_info.cpu_info.model));
components.push(format!("cpu_stepping:{}", device_info.cpu_info.stepping));
// 按字母顺序添加CPU特性,确保一致性
let mut sorted_features = device_info.cpu_info.features.clone();
sorted_features.sort();
components.push(format!("cpu_features:{}", sorted_features.join(",")));
if let Some(cache_size) = device_info.cpu_info.cache_size {
components.push(format!("cpu_cache:{}", cache_size));
}
// 按字母顺序添加系统元数据,确保一致性
let mut sorted_metadata: Vec<_> = device_info.system_metadata.iter().collect();
sorted_metadata.sort_by_key(|(k, _)| *k);
for (key, value) in sorted_metadata {
components.push(format!("{}:{}", key, value));
}
components.join("|")
}
/// 计算SHA256哈希值
fn calculate_sha256(data: &str) -> String {
let mut hasher = Sha256::new();
hasher.update(data.as_bytes());
let result = hasher.finalize();
// 转换为十六进制字符串
result.iter()
.map(|byte| format!("{:02x}", byte))
.collect()
}
/// 验证设备ID是否匹配当前设备
pub fn verify_device_id(device_id: &str) -> Result<bool, ()> {
let current_device_id = Self::generate_device_id()?;
Ok(current_device_id == device_id)
}
/// 获取设备ID的短版本(前16字符)
pub fn generate_short_device_id() -> Result<String, ()> {
let full_id = Self::generate_device_id()?;
Ok(full_id[..16].to_string())
}
/// 获取设备信息的详细报告
pub fn generate_device_report() -> Result<DeviceReport, ()> {
let device_info = DeviceInfoCollector::collect_device_info()?;
let device_id = Self::calculate_device_hash(&device_info)?;
Ok(DeviceReport {
device_id,
device_info,
generated_at: chrono::Utc::now().to_string(),
})
}
}
#[derive(Debug, Clone, Serialize)]
pub struct DeviceReport {
pub device_id: String,
pub device_info: DeviceInfo,
pub generated_at: String,
}
#[cfg(test)]
mod tests {
use DeviceIdGenerator;
use super::*;
#[test]
fn test_device_id_generation() {
let device_id = DeviceIdGenerator::generate_device_id().unwrap();
assert_eq!(device_id.len(), 64); // SHA256应该是64字符
// 验证设备ID一致性
let device_id2 = DeviceIdGenerator::generate_device_id().unwrap();
assert_eq!(device_id, device_id2);
}
#[test]
fn test_device_verification() {
let device_id = DeviceIdGenerator::generate_device_id().unwrap();
let is_valid = DeviceIdGenerator::verify_device_id(&device_id).unwrap();
assert!(is_valid);
// 验证错误的设备ID
let fake_id = "a".repeat(64);
let is_valid = DeviceIdGenerator::verify_device_id(&fake_id).unwrap();
assert!(!is_valid);
}
#[test]
fn test_device_report() {
let report = DeviceIdGenerator::generate_device_report().unwrap();
println!("Device ID: {}", report.device_id);
println!("Username: {}", report.device_info.username);
println!("Hostname: {}", report.device_info.hostname);
println!("OS: {} {}", report.device_info.os_name, report.device_info.os_version);
println!("CPU: {} {}", report.device_info.cpu_info.vendor_id, report.device_info.cpu_info.brand);
assert!(!report.device_id.is_empty());
assert!(!report.device_info.username.is_empty());
assert!(!report.device_info.hostname.is_empty());
}
}