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

roo*_*ook 349 security cryptography license-key

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

Blu*_*eft 262

对于老式CD密钥,只需要编写一个算法,CD密钥(可以是任何字符串)易于生成且易于验证,但有效CD密钥与无效CD的比例-keys很小,随机猜测CD密钥不太可能让你有效.

不正确的做法:

星际争霸半条命都使用相同的校验和,其中第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;
Run Code Online (Sandbox Code Playgroud)

正确的做法

Windows XP需要相当多的信息,对其进行加密,并将字母/数字编码放在标签上.这允许MS同时验证您的密钥获得产品类型(Home,Professional等).此外,它需要在线激活.
完整的算法相当复杂,但在德国出版的这篇(完全合法!)论文中很好地概述了.

当然,无论你做什么,除非你提供在线服务(如魔兽世界),任何类型的复制保护只是一个失速:不幸的是,如果它是任何值得的游戏,有人会破坏(或至少规避) CD密钥算法,以及所有其他版权保护.

真正正确的做法:

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

  1. 生成一个非常大的加密安全随机数.
  2. 将其存储在我们的数据库中并将其打印在卡上.

    然后,当有人输入游戏时间卡号时,检查它是否在数据库中,如果是,则将该号码与当前用户关联,以便永远不会再次使用它.

对于在线服务,没有理由使用上述方案; 使用其他任何东西都可能导致问题.

  • Mathematica有一个有趣的过程.该产品附带一个唯一的密钥,安装文件会生成第二个唯一密钥(基于您的硬件).这两个密钥必须与您的姓名和注册信息一起输入在线表格,然后他们会根据实际解锁软件的两个密钥向您发送真实密钥,但仅针对特定产品密钥和特定硬件. (44认同)
  • 在线激活的问题在于,如果/当出版商破产时我们都被搞砸了.请不要这样做.这种情况发生了,有一天甚至可能会发生在微软身上. (31认同)
  • 从来不知道1234-56789-1234.相反,我们使用了十三个三分!3333333333333 (23认同)
  • 我还记得以前的一些Microsoft产品允许你使用111-1111111作为有效的cdkey(Visual Studio 6.0) (17认同)
  • 嘿,我从来不知道'1234-56789-1234`星际争霸的钥匙,但是我记得通过在键盘上捣碎并再次尝试,只需要大约五分钟来"强力"验证者. (16认同)
  • 是不是*任何*加密算法真的只是一个摊位?考虑到当前和近期的计算性能,"安全"算法只是在宇宙热死之后"停滞"的算法.+1提及星际争霸. (8认同)
  • @Mazin,不一定.Mathematica可以在数据库中保持产品密钥与随机数的不可预测的映射.尽管如此,许多软件仍然可以归结为将某个"JZ"转换为"JNZ". (7认同)
  • 当我的星际钥匙解锁我的半条命游戏时,我印象深刻. (3认同)
  • @kibibu:那么在没有互联网的情况下会有*没有*激活产品的方式,许多公司在历史上一直犹豫不决(尽管现在我们看到有几家公司没有使用互联网的电脑很少) - 这些程序不可能keygenned,但他们仍然可以轻松破解.Mathematica只是验证代码,可以通过电话激活(也可以激活keygen). (2认同)

Pau*_*ulG 55

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

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

我不是很精通数学,但让我感到震惊的是,一种方法是使用绘制图形的数学函数

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

在此输入图像描述

举个例子,我们将绘制这个图,选择四个点并编码成一个字符串为"0,-500; 100,-300; 200,-100; 100,600"

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

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

它只有相当少的代码,可以生成大量独特有效的密钥

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

  • 不,Erik不会.X是整数,Y是函数的底限. (6认同)

The*_*can 32

检查有关部分密钥验证的 tis文章,其中包含以下要求:

  • 许可证密钥必须足够容易输入.

  • 在退款或使用被盗信用卡购物的情况下,我们必须能够将许可证密钥列入黑名单(撤销).

  • 没有"打电话回家"来测试密钥.虽然这种做法越来越普遍,但我仍然不喜欢它作为用户,因此不会要求我的用户忍受它.

  • 破解者不应该拆解我们发布的应用程序并从中生成一个有效的"keygen".这意味着我们的应用程序无法完全测试验证密钥.只有部分密钥需要测试.此外,应用程序的每个版本都应该测试密钥的不同部分,以便基于早期版本的虚假密钥不会对我们软件的更高版本起作用.

  • 重要提示:合法用户不应该意外地键入一个看似有效的无效密钥,但由于印刷错误而导致未来版本失败.


And*_*ett 21

我没有任何关于人们实际生成CD密钥的经验,但是(假设你不想在网上激活的道路上)这里有一些方法可以制作密钥:

  • 要求数字可以被(例如)整除.17.如果你有许多键可以访问,那么很容易猜测,但是大多数潜在的字符串都是无效的.类似的是要求密钥的校验和与已知值匹配.

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

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

这些仍然可以攻击:程序仍在那里,可以修补以绕过检查.Cleverer可能是使用我的第三种方法中的已知值加密程序的一部分,而不是将值存储在程序中.这样你就必须在解密程序之前找到密钥的副本,但它仍然容易被解密后复制并让一个人拿走他们的合法副本并使用它来让其他人访问该软件.

  • 我真的希望无论谁想出'曾经使用过的数字'的事情都没有选择Nonce作为名字,因为每次有人建议加密时,我都会嘲笑*ahem*的负面含义. (9认同)
  • 需要注意的是第三个选项不与对称密钥cyphers工作为攻击者可能只是翻领工程师,纯文本测试,生成的东西,通过再与(已知)键和(知)加密加密.使用家庭酿造密码是没有解决方案的,因为如果你可以自己做,你应该在国家安全局找到一份工作. (2认同)

Mic*_*tum 17

CD-Keys对于任何非联网的东西都没有太大的安全性,因此从技术上讲,它们不需要安全地生成.如果你在.net上,你几乎可以使用Guid.NewGuid().

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

话虽这么说,你可能想用算法来实现两个目标:

  • 有一些校验和.这允许你的安装程序显示"Key似乎无效"消息,仅用于检测拼写错误(在安装程序中添加这样的检查实际上意味着编写密钥生成器是微不足道的,因为黑客拥有他需要的所有代码.没有检查并完全依赖服务器端验证禁用该检查,冒着让您不理解服务器不接受其CD密钥的合法客户的风险,因为他们不知道错字)
  • 使用有限的字符子集.试图键入一个CD密钥并猜测"这是一个8或一个B?一个1或一个I?一个Q或一个O或0?" - 通过使用非ambigous字符/数字的子集,您可以消除这种混淆.

话虽这么说,你仍然想要一个大的分布和一些随机性,以避免海盗只是猜测一个有效的密钥(这在你的数据库中有效,但仍然在商店货架上的一个盒子里),并拧紧碰巧购买该盒子的合法客户.

  • 这里有一些关于 CD 密钥的额外想法 http://www.codinghorror.com/blog/2007/12/software-registration-keys.html (2认同)

use*_*erx 10

如果您不是特别关心密钥的长度,那么一种非常可靠且真实的方法是使用公钥和私钥加密.

基本上有某种nonce和固定签名.

例如:0001-123456789

其中0001是你的随机数,123456789是你的固定签名.

然后使用您的私钥对其进行加密,以获取您的CD密钥,如下所示:ABCDEF9876543210

然后使用您的应用程序分发公钥.公钥可用于解密CD密钥"ABCDEF9876543210",然后您可以验证其固定签名部分.

这样就可以防止有人猜测nonce 0002的CD密钥是什么,因为它们没有私钥.

唯一的主要缺点是当使用1024位大小的私钥/公钥时,你的CD密钥会很长.您还需要选择一个足够长的随机数,这样您就不会加密大量的信息.

好的一面是,这种方法可以在没有"激活"的情况下工作,您可以使用电子邮件地址或被许可人名称等字符作为随机数.

  • 您可以使用椭圆曲线代替使用RSA.它们使用较短的键,它们的块长度较小.阅读Wiki,似乎256位ECC与AES 128一样安全. (2认同)

BCS*_*BCS 9

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

  • 很少有钥匙必须有效
  • 即使给定用户拥有的所有内容,也不得导出有效密钥.
  • 一个系统上的有效密钥不是另一个系统上的有效密钥.
  • 其他

应该给你这些的一个解决方案是使用公钥签名方案.从"系统哈希"开始(比如抓住任何网卡上的mac,排序,以及CPU-ID信息,加上其他一些东西,将它们连接在一起并获取结果的MD5(你真的不想成为处理个人身份信息,如果您不必))附加CD的序列号并拒绝启动,除非某些注册表项(或某些数据文件)具有该blob的有效签名.用户通过向您发送blob来激活程序,然后您将回溯签名.

潜在的问题包括您提出几乎任何标志,因此您需要假设某人将运行选定的纯文本和/或选择的密文攻击.这可以通过检查提供的序列号并拒绝处理来自无效序列号的请求以及拒绝在一个间隔(例如每年2个)中处理来自给定s/n的给定数量的查询来减轻

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


Cub*_*oft 6

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

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

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

然后,许可证密钥数据被加密,然后使用有限的字母数字字母表进行编码。对于在线验证,许可证服务器保存用于解密信息的秘密。对于离线验证,解密秘密与解密/验证代码一起包含在软件本身中。显然,离线验证意味着该软件对于制作注册机的人来说并不安全。

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

加密是一个复杂的话题。一般来说,AES 等标准加密算法的块大小与保持许可证密钥长度较短的目标不符。因此,大多数制作自己的许可证密钥的开发人员最终都会编写自己的加密算法(这种活动经常被劝阻)或者根本不加密密钥,这保证了有人会编写密钥生成器。可以说,良好的加密很难做到正确,而对 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

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

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

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

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