【代码】生成一个电脑硬件指纹【C#版本】
采用C#语言实现。
特性:
跨平台(Windows / Linux / macOS) 且 无需管理员权限 的 C# 实现,功能与 Go 版本保持一致:
- 采集 CPU 特性 + 主板 UUID + 第一块物理磁盘序列号 + 第一块启用网卡 MAC
- 做 SHA-256 并取前 32 位十六进制字符作为脱敏硬件指纹
- 完全使用 托管代码 / WMI / sysfs / IOKit 包装库,不调用 shell
项目结构(单文件即可编译)
HardwareId.csproj
Program.cs
1. HardwareId.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<!-- 跨平台硬件信息库 -->
<ItemGroup>
<PackageReference Include="System.Management" Version="8.0.0" /> <!-- Windows WMI -->
<PackageReference Include="Hardware.Info" Version="15.0.0" /> <!-- 跨平台磁盘 / 网卡 -->
</ItemGroup>
</Project>
2. Program.cs(完整代码,含中文注释)
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Hardware.Info; // NuGet: Hardware.Info
using System.Management; // 仅 Windows 下用到
class Program
{
static void Main()
{
try
{
string hwId = StableHardwareID();
Console.WriteLine(hwId);
}
catch (Exception ex)
{
Console.Error.WriteLine(#34;获取硬件指纹失败: {ex}");
Environment.Exit(1);
}
}
/// <summary>
/// 生成跨平台稳定且脱敏的硬件指纹。
/// 步骤:CPU 特性 → 主板 UUID → 主硬盘序列号 → 第一块启用网卡 MAC
/// 拼接后 SHA-256,取前 32 位十六进制字符。
/// </summary>
static string StableHardwareID()
{
var sb = new StringBuilder();
// 1) CPU 特性:Vendor + Family + Model + Stepping
sb.Append(GetCpuFeatureString()).Append('|');
// 2) 主板 UUID(Windows WMI;Linux/macOS 读取 sysfs/IOKit)
sb.Append(GetMotherboardUuid()).Append('|');
// 3) 第一块非可移动磁盘序列号
sb.Append(GetFirstDiskSerial()).Append('|');
// 4) 第一块启用中、非回环 MAC 地址
sb.Append(GetFirstActiveMac());
// 5) SHA-256 并取前 32 位
using var sha = SHA256.Create();
byte[] hash = sha.ComputeHash(Encoding.UTF8.GetBytes(sb.ToString()));
return Convert.ToHexString(hash).Substring(0, 32).ToLowerInvariant();
}
#region 私有辅助函数
/// <summary>
/// 获取 CPU 的 Vendor + Family + Model + Stepping
/// </summary>
static string GetCpuFeatureString()
{
var hi = new HardwareInfo();
hi.RefreshCPUList();
var cpu = hi.CpuList.FirstOrDefault()
?? throw new Exception("无法获取 CPU 信息");
return #34;{cpu.Manufacturer}-{cpu.Family}-{cpu.Model}-{cpu.Stepping}";
}
/// <summary>
/// 主板 UUID(Windows 走 WMI;其余平台由 Hardware.Info 提供)
/// </summary>
static string GetMotherboardUuid()
{
if (OperatingSystem.IsWindows())
{
using var mc = new ManagementClass("Win32_ComputerSystemProduct");
using var moc = mc.GetInstances();
var uuid = moc.Cast<ManagementObject>()
.Select(m => m["UUID"]?.ToString())
.FirstOrDefault(u => !string.IsNullOrWhiteSpace(u));
return uuid ?? throw new Exception("无法读取主板 UUID");
}
else
{
var hi = new HardwareInfo();
hi.RefreshMotherboardList();
return hi.MotherboardList.FirstOrDefault()?.SerialNumber
?? throw new Exception("无法读取主板 UUID");
}
}
/// <summary>
/// 第一块非可移动、非 USB 磁盘的序列号
/// </summary>
static string GetFirstDiskSerial()
{
var hi = new HardwareInfo();
hi.RefreshDriveList();
var disk = hi.DriveList
.FirstOrDefault(d => !d.IsRemovable && d.Size > 0)
?? throw new Exception("未找到物理磁盘");
return disk.SerialNumber?.Trim() ?? throw new Exception("磁盘无序列号");
}
/// <summary>
/// 第一块启用中、非回环网卡的 MAC 地址(去掉冒号并小写)
/// </summary>
static string GetFirstActiveMac()
{
var hi = new HardwareInfo();
hi.RefreshNetworkAdapterList();
var nic = hi.NetworkAdapterList
.FirstOrDefault(n => n.OperationalStatus == "Up" &&
!n.MACAddress.StartsWith("00:00:00"))
?? throw new Exception("未找到可用 MAC 地址");
return nic.MACAddress.Replace(":", "").ToLowerInvariant();
}
#endregion
}
3. 编译 & 运行
# 还原依赖
dotnet restore
# 运行(Windows / Linux / macOS 均可)
dotnet run
输出示例(32 位十六进制,已脱敏):
3e8f2c4a7b91c0e5d8e3f1a2b9c4d7f6
与原 Go 实现对照
功能 | Go 实现 | C# 实现 |
CPU 信息 | gopsutil | HardwareInfo.CpuList |
主板 UUID | host.Info().HostID | WMI / HardwareInfo.MotherboardList |
磁盘序列号 | ghw | HardwareInfo.DriveList |
MAC 地址 | gopsutil | HardwareInfo.NetworkAdapterList |
哈希 | SHA-256 | System.Security.Cryptography |
跨平台 | ||
管理员权限 | 不需要 | 不需要 |
如需进一步扩展(缓存、在线校验、加密传输),可直接在 StableHardwareID() 结果之上继续封装。
相关文章
- 好消息!Delphi 的VCL & FMX 图形用户界面库在python中免费使用
- OpenGL 数学库 (GLM)_opengl函数库有哪些
- C++ Easyx图形库安装与使用_cpp图形库
- c++(图形)几何库及工具_几何c++测评
- java基础都在这了,小主们拿去吧_java基础知识总结 超详细
- Hutool JSONUtil巧妙过滤null值:JSON转Map数据清洗的终极方案
- java迭代器iterator_java迭代器使用
- HikariCP为啥这么火?SpringBoot选它的原因?
- Arrays.asList 的隐藏陷阱?一份完整的避坑指南与正确用法分享
- 编程英文 - 删除/移除/清除 (delete/remove/clear)