生成一个唯一的机器ID
我需要编写一个函数来生成一个对于运行Windows操作系统的机器来说唯一的id。
目前,我正在使用WMI来查询各种硬件参数并将它们连接在一起,并将它们散列以获得唯一的ID。 我的问题是,我应该使用什么build议的参数? 目前,我正在使用bios \ cpu \ disk数据的组合来生成唯一的ID。 如果每个度量都有多个结果,那么我使用第一个结果。
但是,我遇到了一个问题,双启动到两个不同的Windows操作系统的计算机在每个操作系统上生成不同的站点代码,这应该不会发生。
作为参考,这些是我目前使用的指标:
Win32_Processor:UniqueID,ProcessorID,Name,Manufacturer,MaxClockSpeed Win32_BIOS:Manufacturer Win32_BIOS:SMBIOSBIOSVersion,IdentificationCode,SerialNumber,ReleaseDate,Version Win32_DiskDrive:Model, Manufacturer, Signature, TotalHeads Win32_BaseBoard:Model, Manufacturer, Name, SerialNumber Win32_VideoController:DriverVersion, Name
parsingSMBIOS并散列到任意长度。 有关所有可用的SMBIOS结构,请参阅PDF规范 。
要从Windows查询SMBIOS信息,您可以使用EnumSystemFirmwareEntries
, EnumSystemFirmwareTables
和GetSystemFirmwareTable
。
IIRC,来自CPUID指令的“唯一ID”从P3和更新版本被弃用。
我有同样的问题,并经过一些研究,我决定最好的是阅读registry项HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography
MachineGuid
,如@Agnusbuild议。 它是在操作系统安装过程中生成的,除非另外安装新的操作系统,否则不会更改。 根据操作系统版本的不同,它可能包含embedded式networking适配器MAC地址(加上一些其他的数字,包括随机数字)或伪随机数字,更新的操作系统版本(XP SP2之后,我相信,但不确定)的更高版本。 如果它是伪随机理论上可伪造的 – 如果两台机器具有相同的初始状态,包括实时时钟。 在实践中,这将是罕见的,但要知道,如果你期望它是一个安全的基础,可以攻击的硬核黑客。
当然,任何人都可以很容易地修改一个registry项来伪造一个机器的GUID,但是我发现这会破坏Windows的许多组件的正常运行,在大多数情况下,没有普通用户会这样做(再次,小心对于硬核黑客)。
通过我们的许可工具,我们考虑以下组件
- MAC地址
- CPU(不是序列号,但实际的CPUconfiguration文件,如步进和型号)
- 系统驱动器序列号(不是卷标)
- 记忆
- CD-ROM模型和供应商
- video卡模型和供应商
- IDE控制器
- SCSI控制器
但是,我们不仅仅是对组件进行哈希处理,而是创build一个通过/失败系统,我们创build了一个可比较的指纹 ,可以用来确定两台机器configuration文件的不同。 如果差异评级高于指定的容差,则要求用户再次激活。
我们发现,在过去的8年中,成千上万的最终用户安装使用了这种组合,即使对于虚拟机和克隆的操作系统安装,该组合也能很好地提供可靠的唯一机器ID。
我讨厌成为那个说“你只是做错了”的人(我总是讨厌那个人),但是…
是否必须重复生成独特的机器? 你可以分配标识符还是公钥/私钥? 也许如果你可以生成和存储的价值,你可以从两个操作系统安装在同一磁盘上访问它?
您可能已经探索过这些选项,但它们并不适合您,但是如果没有的话,这是需要考虑的。
如果不是用户信任问题,则可以使用MAC地址。
那么使用处理器的UniqueID呢?
您应该考虑使用网卡上的MAC地址(如果存在)。 这些通常是独特的,但可以捏造。 我已经使用了根据您的networking适配器MAC地址生成许可证文件的软件,所以它被认为是区分计算机的一种相当可靠的方法。
对于我的一个应用程序,如果它是非域计算机,或者域计算机的域计算机帐户SID,则使用计算机名称。 Mark Russinovich在这篇博客文章Machine SID中谈到:
如果分布式应用程序使用机器SID来唯一标识计算机,则SID复制将是一个问题的最后一种情况。 没有Microsoft软件这样做,并且以这种方式使用机器SID不适用于所有DC都具有相同机器SID的事实。 依赖唯一计算机标识的软件要么使用计算机名称,要么使用计算机域SID(域中的计算机帐户的SID)。
您可以通过LDAP或System.DirectoryServices
访问域计算机帐户SID。
在我的程序中,我首先检查terminal服务器,并使用WTSClientHardwareId。 否则,本地PC的MAC地址应该足够了。
如果您真的想使用您提供的属性列表, Clockspeed
Name
, DriverVersion
, Clockspeed
等,因为它可能取决于操作系统。 尝试在两个操作系统上输出相同的信息,并忽略其中的差异。
为什么不使用网卡的MAC地址?
也许作弊一点点,但机器的以太网适配器的MAC地址很less改变,如今这些主板改变。
你可以拉某种制造商的序列号或服务标签?
我们的商店是一家戴尔商店,所以我们使用每台机器独有的服务标签来识别它们。 我知道它可以从BIOS中查询,至less在Linux中,但我不知道如何在Windows中做到这一点。
硬件序列号提取器(CPU,RAM,HDD,BIOS)
查找一个选项的CPUID。 多CPU系统可能存在一些问题。
试试这个,它给出了一个唯一的硬盘ID: Delphi 7-2010的DiskId32端口 。