如何唯一标识一台计算机?

66

我正在为一个客户开发一些桌面软件以供转售。客户希望限制软件,使注册码只能用于一个特定的计算机。

除了使用网络卡的MAC地址外,还有没有其他技术(适用于Windows和Mac OS X),可以唯一地识别一台计算机?


11
不要使用MAC地址作为识别标志。不仅网络适配器可能会更换,而且在Windows中通过设备管理器很容易更改MAC地址。 - TheAgent
14个回答

45
另一个解决方案是使用带有dongle的许可证技术。这是一种小设备,插入主机上的USB或另一个I/O端口,并作为唯一的物理密钥来激活软件。
第三个解决方案是提供许可证管理器。也就是说,当软件启动时,它会查询网络上的服务器(在客户的局域网上或通过互联网访问您公司的服务器),以验证客户对软件的使用是否合法。这是“并发许可证”的良好解决方案,因此客户可以在许多主机上安装您的软件,但您只授权其在有限数量的主机上同时使用。 FLEXnet Publisher是许可证管理解决方案的一个示例。
网络卡的MAC地址是我上次为一家授权软件在特定主机上运行的公司使用的解决方案。
但我想提出警告:如果您使用此类许可证,您必须预期将成为追踪客户许可证的持续行政烦恼。一旦您有了几百个客户,您将惊奇地发现自己经常接到电话请求更改密钥。

"我们将服务器升级到千兆网适配器,现在许可证无法使用,因为新适配器具有不同的MAC地址。"

或者客户可能更换整台机器,并需要更新的许可证才能在新机器上运行您的软件。我曾在工作的公司几乎每天都会接到这些电话。
您还需要信任客户,在给他们提供新密钥时停止在旧计算机(或网络适配器)上使用您的软件。如果您一开始就不能信任他们遵守许可证,那么您如何相信他们会丢弃旧密钥?如果你没有计划如何支持这个管理活动,不要以这种方式授权你的产品。这只会给本来愿意合作的好客户带来不便。

绝对同意维护/管理部分。许多公司似乎只关注技术方面,而不是“人”的方面。我记得购买的一款软件与我的机器绑定,当我升级时,我必须等待3周才能获得新的密钥! - Nicholas Head
我完全同意客户支持的问题,这也是我最初建议客户不要使用特定于计算机的代码的原因。但他们认为这很重要。 - Paul Lefebvre
虽然Dongles可以被破解,但是软件可以模拟正确密钥的Dongle连接,尽管如果你不向公众发布(只有一个客户端),这种情况可能很少见。 - alex
2
Dongles很容易破解 - 您不需要模拟它们,只需对代码进行二进制编辑以删除检查即可。这是俄罗斯黑客入门课程。 - paxdiablo
9
没问题,如果你考虑到二进制编辑代码的盗版者,则任何软件密钥解决方案都是可以破解的。你越试图打击盗版,就只会让合法客户使用软件更加不便。 - Bill Karwin

11

最好的方法是使用C#在Windows中获取UUID。

唯一标识Windows机器的最佳方法

public string GetUUID()
{
    var procStartInfo = new ProcessStartInfo("cmd", "/c " + "wmic csproduct get UUID")
    {
        RedirectStandardOutput = true,
        UseShellExecute = false,
        CreateNoWindow = true
    };

    var proc = new Process() { StartInfo = procStartInfo };
    proc.Start();

    return proc.StandardOutput.ReadToEnd().Replace("UUID", string.Empty).Trim().ToUpper();
}

3
在新的Windows安装中,UUID是否会保留? - Camadas
但是,这将需要计算机上的管理员权限,对吗?如果您的软件旨在供非管理员使用,则可能无法帮助。!! - Emran Hussain
1
并非所有供应商都提供UUID。此外,如果软件正在虚拟机上运行并且克隆了该虚拟机,则UUID将相同。这些限制在https://www.nextofwindows.com/the-best-way-to-uniquely-identify-a-windows-machine的评论部分中有概述。 - John Rocha

10
我正在考虑的想法是使用与硬件相关的一些序列号或唯一标识,并将它们哈希在一起。
经常升级的内容: -内存 -MAC地址(可以伪造,插入USB适配器等)
不经常升级的内容: -CPU -BIOS -主板
使用WMIC可以很好地获取一些信息,我建议首先选择那些不经常更改的内容,然后尝试获取至少2个序列号或设备的指纹以用于生成注册密钥。
wmic cpu get DeviceId /format:value

这将获取CPU ID,您可以运行该命令:

1 - CPU (cpu: DeviceID) 2 - 主板 (baseboard: serialnumber) 3 - BIOS (bios: serialnumber)

如果您没有至少两个填充值,则获取

4 - 网络适配器 - (nic: MACAddress) 5 - RAM - (memphysical: SerialNumber)

根据您的业务逻辑,您可以使用前两个可用的序列号创建您的注册号码,如果始终按照相同的顺序进行,则在重新安装时注册号码仍将起作用,但是如果设备更改或用户尝试在辅助计算机上安装,则 ID 会更改,从而使注册号码失效。为了减少技术支持电话的数量,指纹识别的硬件越少,头痛就越少,如果尝试对最不可能升级的项目进行指纹识别,那么进一步减少了头痛。我喜欢上面的顺序。

您可以使用Diffie-Hellman密钥交换方案,让用户生成带有其硬件ID作为有效负载的私钥/公钥对,然后将此信息传递到注册服务器,注册服务器将使用公共/私人密钥解密有效负载并计算返回给最终用户的注册密钥。我喜欢使用JWT来传递公钥,并将其包含在JWT的有效负载中。希望这有所帮助。

上面提到了UUID,这是一个很好的想法,您可以通过使用以下命令从Windows cmd.exe获取:

wmic csproduct get UUID /format:value      

免责声明,这些命令仅适用于Windows 2000及以上版本,但您需要进行验证,它们可能适用于低于2000的系统,但在那种情况下,我真的不建议支持那些设备。祝好运。 *看起来WMI正在被弃用,而PowerShell是更好的替代方案,因此为了使本帖子保持最新,这里提供PowerShell命令。

Get-CimInstance -ClassName Win32_Processor | Select SerialNumber

Get-CimInstance -ClassName Win32_BaseBoard | Select SerialNumber

Get-CimInstance -ClassName Win32_Bios | Select SerialNumber

Get-NetAdapter -Physical | Where-Object Status -like Up | Select-Object MacAddress

Get CimInstance -ClassName Win32_PhysicalMemory | Select SerialNumber

网络适配器 cmdlet 只会检查物理适配器,因此无法使用和操作虚拟适配器。我喜欢使用第一个正在使用或处于启用状态的适配器,以防止备用网卡在安装过程中被更换。

在 Mac 上:

system_profiler | grep "Serial Number (system)"

在Linux(Debian)上:

sudo dmidecode -t system | grep "Serial Number"

dmidecode和system_profiler有其他组件可以从中获取类似于Windows中的wmic的序列号。我不使用mac,因此无法确认确切规格的列表,但是可以创建一个LCD(最小公分母)列表,其中包含三个命令都可以访问的部件的序列号,并整理到最不可能升级或更改的部件。然后,将前2-3个数字的组合哈希可以生成一个更加强大的唯一机器ID,即使在更新其操作系统的设备上也可以激活跨平台应用程序。


5

如果假设一台计算机由许多可以被替换的部件组成,那么没有确切的方法可以唯一地识别一台计算机。

一些硬件部件 - MAC地址、HDD磁盘序列号、甚至主板序列号等等 - 是一些好的“唯一性”来源,但是如果客户决定升级部件,而许可证依赖于这些部件,那么就要为一些客户支持做好准备。同时需要注意的是,有些部件可以被欺骗(MAC地址就是其中之一)。

在线许可证检查是另一个不错的选择 - 你可以在服务器端管理所有内容,甚至为其定义自己的规则(每个客户/安装程序的许可证数量、并发性等等),但需要注意的重要问题是当连接无法建立时会发生什么?


5
我建议您使用MAC地址生成请求密钥,然后要求用户在您的客户端进行注册。您的客户端将有一个特殊的应用程序,该应用程序会接受该请求密钥并生成激活密钥,用户随后可以使用该密钥激活软件。一旦激活,软件就能正常工作 - 不需要定期打电话验证等操作。
这是如果这是一个真实的要求。我的第一个任务是试图说服客户这是个坏主意。
原因是这些方案实际上几乎从不防止您的代码被破解。它们确实使您的真正客户的生活更加困难。我很难想象还有哪个行业会费尽心思地用方案来惹恼其真正的客户,而这些方案却从未实现它们的目标(当然除了政府服务)。
如果您必须这样做,我只会做出象征性的努力来满足合同义务(但不要告诉客户)。以MAC地址(或者如果计算机没有网络卡,使用随机数)作为请求密钥,并使用程序将其与ASCII字符串进行XOR运算以获取激活密钥,似乎是可行的方法。我还会存储两个密钥,因为您不希望软件在用户更换网络卡(甚至主板)时停用 - 他们仍然认为这是同一台计算机,如果软件停止工作,他们会感到不满意。
无论如何,您的代码都将被破解(除非程序很差,我相信这不是情况)- 这种方法将为您的真正客户提供一种在某些情况下将其软件移动到另一台计算机的途径(例如,如果您的客户公司变得不负责任,停止支持,破产等等)。
所有依赖于硬件位唯一性的方案的主要问题在于客户可能选择更改该位硬件:
将磁盘内容复制到更大的硬盘上会导致硬盘序列号发生变化。
使用CPU序列号意味着升级到最新的英特尔大型CPU会使您的软件失效。
使用MAC地址意味着他们不能更改其NIC。
可以通过在安装时使用这些值创建密钥并仅检查该密钥而不是六个月后更改的值来修复所有这些问题。这意味着您必须存储请求和激活值,但升级不需要您的用户经历重新激活其软件的过程。相信我,他们会因此而鄙视您。

1
邪恶的公司可能只是在每台新电脑上连接一个USB WLAN适配器,许可证它,然后将其搬到下一台计算机上,再次许可证。因此,您应该考虑处理发现多个网络适配器的情况。 - tmighty

3

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography

"MachineGuid"键在Windows安装期间唯一生成,即使更换硬件(除了替换安装操作系统的可启动硬盘),也不会改变。我不确定这一点。

我的建议

您可以使用MachineGuid、硬盘序列号、主板序列号和UUID将它们一起使用SHA 256或任何其他HASH函数进行哈希处理。

UUID - wmic csproduct get UUID

MachineGuid - HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography

硬盘序列号 - wmic diskdrive get serialnumber

BIOS序列号 - wmic bios get serialnumber

主板序列号 - wmic baseboard get serialnumber


3
这些值适用于物理机器,但不适用于虚拟机。如果克隆虚拟机,这些值也将被复制。对于物理机器,通过克隆硬盘并在另一台机器上使用,UUID/MachineGuid将保持相同(但对所有值进行哈希处理将解决裸机情况)。 - John Rocha

2

可以创建一个串行密钥,用户需要输入一次。它应该包括用户的电子邮件地址(类似于someuser@mailprovider.com-9828372-398232)。这将防止许多人试图篡改它或将其交给其他人。 在激活期间,软件应根据在线数据库检查序列号是否存在。


恐惧是有市场的。我有点喜欢这个想法。 - vicsar

2
如何使用主板唯一序列号?

2

打开注册表并导航到

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography

找到名为“MachineGuid”的键,该键在 Windows 安装期间生成唯一,并且不会更改,无论进行任何硬件交换(除了替换安装操作系统的可启动硬盘)。这意味着,如果您想跟踪每个操作系统的安装情况,这是另一种选择。它只有在您重新安装 Windows 时才会更改。


4
如果你克隆你的操作系统,这个全局唯一标识符(GUID)会保持不变。 - Telson Alva

1

我有一些相关经验。 我们在向客户销售产品时发放服务密钥。

客户安装应用程序时,通过读取客户机的主板序列号生成密钥。 客户应该通过电子邮件向我们的组织发送激活产品所需的服务密钥和安装生成的密钥。

我们在组织中维护一个管理应用程序来发放激活密钥。 我们只为特定服务密钥提供一个激活密钥。

我们已经销售了许多副本,并且它们运行得很顺利。 但是后来我们发现有些计算机没有提供主板序列号。这些计算机将主板序列号返回null值。我们仍在努力解决这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接