软件许可证密钥是如何生成的?

Posted

技术标签:

【中文标题】软件许可证密钥是如何生成的?【英文标题】:How are software license keys generated? 【发布时间】:2011-03-01 10:22:30 【问题描述】:

许可证密钥是作为反盗版措施的事实标准。老实说,这让我觉得(in)Security Through Obscurity,虽然我真的不知道许可证密钥是如何生成的。什么是许可证密钥生成的好(安全)示例?他们使用什么加密原语(如果有的话)?是消息摘要吗?如果是这样,他们会散列什么数据?开发人员采用什么方法使破解者难以构建自己的密钥生成器?密钥生成器是如何制作的?

【问题讨论】:

+1 个有趣的问题,也许回答者可以发布有关该主题的一些好的资源的链接以供进一步阅读?请:) 所有 DRM 方案本质上都是模糊方案,因为程序运行所需的所有代码和数据都已提供给用户。该方案可以任意混淆以使修补变得困难,但可以肯定的是,可以对代码进行修补以避免任何检查。 CD 密钥确实是通过默默无闻的安全性。有几种方法可以构建它们,但都必须依赖于在程序中嵌入一些验证密钥所需的秘密。 它们现在被称为 product 密钥或 license 密钥,因为使用它们的大多数软件比通过 cd 更有可能在线交付。 我想做一个应用程序,有一天我不得不担心这个,童年的梦想。 Web 应用程序就是不能解决问题。 【参考方案1】:

对于老式的 CD 密钥,只需制定一个算法,使 CD 密钥(可以是任何字符串)易于生成和验证,但有效 CD 密钥与invalid-CD-keys 太小了,随机猜测 CD 密钥不太可能让你得到一个有效的。

不正确的做法:

StarcraftHalf-life 都使用相同的校验和,其中第 13 位验证前 12 位。因此,您可以为前 12 位输入任何内容,并且猜第 13 次(只有 10 种可能性),导致臭名昭著的1234-56789-1234

验证算法是公开的,看起来像这样:

x = 3;
for(int i = 0; i < 12; i++)

    x += (2 * x) ^ digit[i];

lastDigit = x % 10;

正确的做法

Windows XP 获取大量信息,对其进行加密,并将字母/数字编码放在贴纸上。这使 MS 可以同时验证您的密钥 获得产品类型(家庭、专业等)。此外,它需要在线激活。 完整的算法相当复杂,但在德国发表的this(完全合法!)论文中很好地概述了。

当然,无论您做什么,除非您提供在线服务(如魔兽世界),否则任何类型的版权保护都只是一个摊子:不幸的是,如果它值得任何游戏值,有人会破坏(或至少绕过)CD 密钥算法和所有其他版权保护。

真实正确的做法:

对于在线服务,生活要简单一些,因为即使使用二进制文件,您也需要通过他们的服务器进行身份验证才能使用它(例如,拥有一个 WoW 帐户)。魔兽世界的 CD 密钥算法 - 例如,在购买游戏卡时使用 - 可能看起来像这样:

    生成一个非常大的密码安全随机数。 将其存储在我们的数据库中并打印在卡片上。 然后,当有人输入游戏时间卡号码时,检查它是否在数据库中,如果是,则将该号码与当前用户相关联,这样就永远不会再使用它了。

对于在线服务,没有理由使用上述方案;使用其他任何东西都可以lead to problems。

【讨论】:

Mathematica 有一个有趣的过程。该产品附带一个唯一密钥,安装文件生成第二个唯一密钥(基于您的硬件)。这两个密钥都必须使用您的姓名和注册信息输入在线表格,然后他们根据实际解锁软件的这两个密钥向您发送真正的密钥,但仅限于该特定产品密钥和您的特定硬件。 嘿,我从来不知道1234-56789-1234 Starcraft 密钥,但我记得只花了大约五分钟就可以通过在键盘上捣碎并重试来“蛮力”验证器。 我还记得过去的一些 Microsoft 产品允许您使用 111-1111111 作为有效的 cdkey (Visual Studio 6.0) 从来不知道 1234-56789-1234。相反,我们使用了十三个三分! 3333333333333 在线激活的问题是,如果/当出版商倒闭时,我们都会被搞砸。请不要这样做。这种情况会发生,并且有朝一日甚至会发生在微软身上。【参考方案2】:

当我最初写这个答案时,假设问题是关于许可证密钥的“离线”验证。大多数其他答案都解决了在线验证,这更容易处理(大部分逻辑都可以在服务器端完成)。

使用离线验证,最困难的事情是确保您可以生成大量唯一的许可证密钥,并且仍然保持一个不易被破坏的强大算法(例如简单的校验位)

我不是很精通数学,但让我印象深刻的一种方法是使用绘制图表的mathematical function

绘制的线可以具有(如果您使用足够精细的频率)数千个唯一点,因此您可以通过在该图上选择随机点并以某种方式对值进行编码来生成键

作为示例,我们将绘制此图,选取四个点并将字符串编码为“0,-500;100,-300;200,-100;100,600”

我们将使用已知且固定的密钥加密字符串(非常弱,但它是有目的的),然后通过Base32 转换结果字节以生成最终密钥

然后应用程序可以反转这个过程(base32 到实数、解密、解码点),然后检查每个点是否在我们的秘密图上。

它的代码量相当少,可以生成大量唯一且有效的密钥

然而,默默无闻是非常安全的。任何花时间反汇编代码的人都可以找到图形函数和加密密钥,然后模拟密钥生成器,但它可能对减缓随意盗版非常有用。

【讨论】:

不,Erik 不会。 X 是整数,Y 是函数的底数。 这与以前的 GPS 卫星导航的工作方式没有什么不同! youtube.com/watch?v=BBOsQBuCJfs【参考方案3】:

查看Partial Key Verification 上的这篇文章,其中包含以下要求:

许可证密钥必须易于输入。

我们必须能够将许可证密钥列入黑名单(撤销),以防信用卡被盗或退款。

没有“打电话回家”来测试密钥。虽然这种做法越来越普遍,但作为用户我还是不欣赏,所以不会要求我的用户忍受。

破解者应该不可能反汇编我们发布的应用程序并从中生成一个有效的“keygen”。这意味着我们的应用程序不会完全测试密钥以进行验证。只有一些关键是要测试的。此外,应用程序的每个版本都应测试密钥的不同部分,这样基于早期版本的假密钥将无法在我们软件的后续版本中使用。

重要提示:合法用户不应意外输入无效的密钥,该密钥似乎可以工作,但由于印刷错误而在未来的版本中失败。

【讨论】:

【参考方案4】:

我对人们生成 CD 密钥的实际操作没有任何经验,但是(假设您不想走在线激活的道路)这里有几种制作密钥的方法:

要求数字可以被(比如说)17 整除。如果您可以访问许多键,那么猜测很简单,但大多数潜在的字符串将是无效的。类似的情况是要求密钥的校验和与已知值匹配。

要求键的前半部分在与已知值连接时向下散列到键的后半部分。更好,但程序仍然包含生成密钥以及验证密钥所需的所有信息。

通过加密(使用私钥)已知值 + 随机数来生成密钥。这可以通过使用相应的公钥解密并验证已知值来验证。该程序现在有足够的信息来验证密钥而无法生成密钥。

这些仍然容易受到攻击:程序仍然存在并且可以被修补以绕过检查。更聪明的做法可能是使用我的第三种方法中的已知值来加密程序的一部分,而不是将值存储在程序中。这样,您必须在解密程序之前找到密钥的副本,但它仍然很容易在解密后被复制,并且让一个人获取他们的合法副本并使用它来使其他人能够访问该软件。

【讨论】:

我真希望提出“使用一次的号码”的人没有选择 Nonce 作为名称,因为 ahem 的负面含义让我每次有人都会咯咯地笑建议加密一个。 请注意,第三个选项不适用于对称密钥密码,因为攻击者可以对纯文本进行逆向工程测试,生成通过的内容,然后使用(已知)密钥对其进行加密,然后(已知)密码。使用自制密码不是解决方案,因为如果你能自己做,你应该在 NSA 找到一份工作。 @BCS:抱歉,我应该更清楚地了解如何使用公钥加密。 使用签名方案,而不是公钥版本的加密方案。 (RSA 签名看起来有点像“用公钥加密”,但并不完全相同。还有其他签名方案没有关联的加密方案,如 DSA。) 公钥加密的问题是密钥(因此序列号)必须很长。如今,破解 512 位 RSA 密钥对并不难。与 WinXP 的键(5 组 5 个字母数字字符)相比,它只有 128 位熵,但输入起来仍然很痛苦。【参考方案5】:

CD-Keys 对于任何非联网的东西都不是很安全,所以从技术上讲,它们不需要安全地生成。如果您在 .net 上,您几乎可以使用 Guid.NewGuid()。

它们现在的主要用途是多人游戏组件,服务器可以在其中验证 CD 密钥。为此,生成它的安全性并不重要,因为它归结为“查找传入的任何内容并检查其他人是否已经在使用它”。

话虽如此,您可能希望使用一种算法来实现两个目标:

有某种校验和。这允许您的安装程序显示“密钥似乎无效”消息,仅用于检测拼写错误(在安装程序中添加这样的检查实际上意味着编写密钥生成器是微不足道的,因为黑客拥有他需要的所有代码。没有检查并仅依靠服务器端验证会禁用该检查,这可能会惹恼您的合法客户,他们不明白为什么服务器不接受他们的 CD 密钥,因为他们不知道拼写错误) 使用有限的字符子集。尝试输入 CD Key 并猜测“这是 8 还是 B?1 还是 I?Q 或 O 还是 0?” - 通过使用不含歧义的字符/数字的子集,您可以消除这种混淆。

话虽如此,您仍然需要一个大的分布和一些随机性,以避免盗版者简单地猜测一个有效的密钥(该密钥在您的数据库中有效,但仍然在商店货架上的盒子中)并搞砸了碰巧的合法客户买那个盒子。

【讨论】:

通过良好的客户服务轻松解决 - 开箱 + 购买证明 = 锁定非法用户,授予第二个用户访问权限。 这里有一些关于 CD 键的额外想法codinghorror.com/blog/2007/12/software-registration-keys.html【参考方案6】:

如果您不是特别关心密钥的长度,那么一种经过验证且真正可行的方法是使用公钥和私钥加密。

基本上有某种随机数和固定签名。

例如: 0001-123456789

0001 是你的 nonce,123456789 是你的固定签名。

然后使用您的私钥对其进行加密以获得您的 CD 密钥,类似于: ABCDEF9876543210

然后将公钥与您的应用程序一起分发。公钥可用于解密 CD 密钥“ABCDEF9876543210”,然后验证其固定签名部分。

这可以防止有人猜测随机数 0002 的 CD 密钥是什么,因为他们没有私钥。

唯一的主要缺点是使用 1024 位大小的私钥/公钥时,您的 CD 密钥会很长。您还需要选择足够长的随机数,以免加密少量信息。

好处是这种方法无需“激活”即可工作,您可以使用电子邮件地址或被许可人姓名等内容作为 nonce。

【讨论】:

请注意,我的示例严重低估了您的密钥长度。这些方案通常需要 base64 编码和复制/粘贴部署,但几乎不可能猜到与机器无关且不需要激活的密钥(对于许多类型的客户来说,这两件事非常重要) 您可以使用椭圆曲线,而不是使用 RSA。它们使用较短的密钥,并且它们的块长度更小。阅读 Wiki,似乎 256 位 ECC 与 AES 128 一样安全。 请注意,数字签名和“私钥加密”不是一回事。在 RSA 中它们看起来很相似(尽管它们不相似,因为填充方案不同),其他签名方案甚至没有相应的加密方案。 @xanatos,256 位仍然太长,无法手动输入。考虑 WinXP 使用的 25 个字符的密钥 - 它们只有 128 位熵。 @finnw 您可以使用 128 位椭圆曲线。它将与 DES 一样安全。除非您的软件非常昂贵,否则它足够安全。【参考方案7】:

密钥系统必须具有几个属性:

必须有很少的密钥是有效的 即使考虑到用户拥有的一切,有效密钥也不得派生。 一个系统上的有效密钥不是另一个系统上的有效密钥。 其他

应该为您提供这些的一个解决方案是使用public key signing scheme。从“系统哈希”开始(比如抓取任何 NIC 上的 mac,排序和 CPU-ID 信息,加上其他一些东西,将它们连接在一起并获取结果的 MD5(你真的不想成为处理personally identifiable information,如果你不需要))附加CD的序列号并拒绝启动,除非某些注册表项(或某些数据文件)具有该blob的有效签名。用户通过将 blob 发送给您来激活程序,然后您将签名寄回。

潜在的问题包括您提议签署几乎任何内容,因此您需要假设有人会发起 chosen plain text 和/或 chosen ciphertext 攻击。这可以通过检查提供的序列号并拒绝处理来自无效请求的请求以及拒绝在一个时间间隔内处理来自给定序列号的超过给定数量的查询(比如每年 2 个)来缓解。

我应该指出一些事情:首先,一个熟练而坚定的攻击者将能够绕过他们可以不受限制地访问的部分中的任何和所有安全性( CD 上的所有内容) ,您对该帐户所能做的最好的事情就是使获得非法访问比获得合法访问更难。其次,我不是专家,所以这个提议的方案可能存在严重缺陷。

【讨论】:

【参考方案8】:

我意识到这个答案晚了大约 10 年。

一个好的软件许可证密钥/序列号生成器不仅仅包含一串随机字符或来自某个曲线生成器的值。使用有限的字母数字字母表,data 可以嵌入到包含各种有用信息的短字符串(例如 XXXX-XXXX-XXXX-XXXX)中,例如:

创建日期或许可证到期日期 产品 ID、产品分类、主要和次要版本号 自定义位,如硬件哈希 每个用户的哈希校验和位(例如,用户输入他们的电子邮件地址以及许可证密钥,这两条信息都用于计算/验证哈希)。

然后使用有限的字母数字字母对许可证密钥数据进行加密和编码。对于在线验证,许可证服务器持有解密信息的秘密。对于离线验证,软件本身包含解密密钥以及解密/验证代码。显然,离线验证意味着该软件不安全,无法抵御制作注册机的人。

创建许可证密钥最困难的部分可能是弄清楚如何将尽可能多的数据塞进尽可能少的字节中。请记住,用户将手动输入他们的许可证密钥,因此每一位都很重要,用户不想输入非常长、复杂的字符串。16 到 25 个字符的许可证密钥是最常见的,并平衡了可以放置多少数据进入密钥与用户对输入密钥解锁软件的容忍度。将字节分割成比特块可以包含更多信息,但确实会增加生成器和验证器的代码复杂度。

加密是一个复杂的话题。一般来说,像 AES 这样的标准加密算法的块大小与保持许可证密钥长度较短的目标不一致。因此,大多数制作自己的许可证密钥的开发人员最终都会编写自己的加密算法 (an activity which is frequently discouraged) 或根本不加密密钥,这保证有人会编写密钥生成器。可以说,良好的加密很难做到正确,对 Feistel 网络和现有密码的工作原理有充分的了解是先决条件。

验证密钥是对字符串进行解码和解密、验证哈希/校验和、检查数据中的产品 ID 和主要和次要版本号、验证许可证是否过期以及进行任何其他检查的问题需要执行。

编写密钥生成器需要了解许可证密钥的组成,然后生成与原始密钥生成器生成的相同输出。如果许可证密钥验证算法包含在软件中并被软件使用,那么只需创建与验证过程相反的软件即可。

要查看整个过程是什么样的,这是我最近写的一篇博文,内容涉及选择许可证密钥长度、数据布局、加密算法和最终编码方案:

https://cubicspot.blogspot.com/2020/03/adventuring-deeply-into-software-serial.html

可以在此处查看博客文章中密钥生成器和密钥验证器的实用、真实的实现:

https://github.com/cubiclesoft/php-misc/blob/master/support/serial_number.php

上述类的文档:

https://github.com/cubiclesoft/php-misc/blob/master/docs/serial_number.md

可以在此处找到使用上述序列号代码生成和管理许可证密钥的生产就绪开源许可证服务器:

https://github.com/cubiclesoft/php-license-server

上述许可证服务器支持在线和离线验证模式。软件产品的存在可能始于仅在线验证。当软件产品准备退役且不再受支持时,它可以轻松地转移到离线验证,一旦用户升级到切换到离线验证的最新软件版本,所有现有密钥都会继续工作。

可以在此处找到如何将上述许可证服务器集成到网站以销售软件许可证以及可安装的演示应用程序的现场演示(网站和演示应用程序也是开源的):

https://license-server-demo.cubiclesoft.com/

完全披露:我是许可证服务器和演示站点软件的作者。

【讨论】:

【参考方案9】:

还有一些 DRM 行为将多个步骤合并到流程中。最著名的示例之一是 Adob​​e 验证其 Creative Suite 安装的方法之一。使用这里讨论的传统 CD Key 方法,然后调用 Adob​​e 的支持热线。将 CD 密钥提供给 Adob​​e 代表,他们会返回一个供用户使用的激活号。

但是,尽管被分解为多个步骤,但它还是会成为与正常过程相同的破解方法的牺牲品。用于创建激活密钥并与原始 CD 密钥进行核对的过程很快被发现,并制作了包含这两个密钥的生成器。

但是,这种方法仍然存在,作为没有互联网连接的用户验证产品的一种方式。展望未来,随着互联网接入的普及,很容易看出这些方法将如何被淘汰。

【讨论】:

【参考方案10】:

所有仅 CD 的复制保护算法都会给诚实的用户带来不便,同时不提供任何防止盗版的保护。

“盗版者”只需要访问一张合法的光盘及其访问代码,就可以制作 n 份并分发它们。

无论您制作代码的加密安全程度如何,您都需要以纯文本形式随 CD 一起提供,否则合法用户无法激活该软件。

大多数安全方案包括用户向软件供应商提供将运行该软件的机器的一些详细信息(cpu 序列号、mac 地址、IP 地址等),或者要求在线访问以在供应商网站,并作为回报获得激活令牌。第一个选项需要大量的手动管理,并且仅对于非常高价值的软件才值得,第二个选项可能会被欺骗,并且如果您的网络访问受限或者您被困在防火墙后面,这绝对是令人恼火的。

总的来说,与客户建立信任关系要容易得多!

【讨论】:

【参考方案11】:

您可以使用它在您的软件项目中非常轻松地使用和实施安全许可 API,(您需要从 https://www.systemsoulsoftwares.com/ 下载用于创建安全许可的桌面应用程序)

    根据系统硬件(CPU、主板、硬盘)为客户端软件创建唯一的 UID (UID 充当该唯一系统的私钥) 允许非常轻松地将加密的许可证字符串发送到客户端系统,它会验证许可证字符串并仅在该特定系统上工作 此方法允许软件开发人员或公司存储有关软件/开发人员/分销商服务/功能/客户端的更多信息 它可以控制锁定和解锁客户端软件功能,从而节省开发人员为具有变化功能的相同软件制作更多版本的时间 它也关心试用版的任何天数 它通过在注册期间在线检查 DateTime 来保护许可证时间表 它向开发人员解锁所有硬件信息 它具有所有预构建和自定义功能,开发人员可以在每个许可过程中访问以制作更复杂的安全代码

【讨论】:

以上是关于软件许可证密钥是如何生成的?的主要内容,如果未能解决你的问题,请参考以下文章

VEMS 下载软件,生成和访问许可证

使用 OpenSSL 生成短许可证密钥

为java项目生成许可证密钥[重复]

如何在服务器数据库中存储许可证密钥并在 python [关闭]

vmware许可证密钥

许可证方案、欺骗安全和撤销功能