寻找一个许可证密钥算法

38

在Stack Overflow上有很多与许可证密钥相关的问题,但它们没有回答这个问题。

有人能够提供一个简单的许可证密钥算法吗?它应该是技术无关的,并且不需要数学文凭才能理解。

许可证密钥算法类似于公钥加密。我只需要一些简单的东西,可以在任何.NET/Java平台上实现,并使用像字符之类的简单数据。

以伪代码编写的答案是完美的。

因此,如果一个人提供了一个字符串,就可以生成一个互补的字符串作为授权码。以下是常见的场景。

  1. 客户下载软件,在初始启动/安装时生成唯一的密钥。
  2. 软件在试用期间运行。
  3. 在试用期结束时需要授权码。
  4. 客户前往指定的网站,输入他们的代码并获取授权码以启用软件(付款后):)

不要害怕把你的答案描述得好像你在向一个5岁的孩子说话一样,因为我不是数学家。


3
我认为关键是“不需要数学文凭就能理解,且不容易被攻破而变得毫无意义”,如果是这种情况,答案通常是否定的。 - Rex M
@GregS。这就是精神!哈哈...我已经做了一些谷歌搜索,但没有成功找到一个合理的算法。希望有人能提供一个有价值的链接。 - angryITguy
2
谢谢匿名的懦夫,尽管有15个赞成,14个收藏和21个赞成的批准答案,却仍然对问题进行了下投票。我不介意社区管理员将该问题标记为“离题”。 - angryITguy
虽然在我的端口许可方面,我只是创建了一个许可服务器,并将其嵌入到我的代码中,其中包含一些系统的标识信息,这些信息保持静态,并使用OpenSSL生成的密钥来确保该软件在该设备上得到验证。一旦激活,密钥就不能再次使用,而且在所有启动时,它都会从服务器验证一切。 - Muneeb Ahmad Khurram
7个回答

55

没有可靠的许可算法,真的没有。即使是你能购买到的最流行、最昂贵的专有软件,你也可以找到“密钥生成器”和破解版,它们不需要许可证。

与其担心如何做到“牢不可破”,不如采用一些简单的方法。一个常见的机制是,在购买时询问用户的姓名,然后给他一个基于加密哈希(例如MD5总和)的许可证密钥,或者在其基础上进行一些变化。然后,在软件中再次要求输入他们的姓名,以及注册密钥(那个MD5衍生的东西);您检查它们是否匹配,这将激活软件。

这样会被破解吗?绝对会。一旦有人弄清楚了你如何生成许可证密钥,他们就可以自己生成。但是如果您保留了迄今为止生成的“官方”许可证密钥的数据库,至少以后您将能够识别欺诈者(也许当他们尝试下载“高级”内容之类的东西时)。

但是不要过分担心阻止黑客破解您的代码。这种情况肯定会发生,但是他们只占市场的一小部分,不会对您的整体销售产生重大影响。


2
名称和购买日期是常见的组合。当它们续订时,您必须生成一个新的密钥。您将明文名称记录在文件中,文件修改时间也是用于创建许可证密钥的哈希字符串的一部分。 - S.Lott
1
@giulio:要实现过期功能,只需将开始和结束日期编码到产品密钥中即可。 - tylerl
我已经想出了一些非常简单的东西。基本上使用TEA(http://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm)和一个组合密钥来唯一标识设备。我使用base16编码将密钥信息传输到授权服务器。如果我想启用时间限制,我还包括一个时间戳。 - angryITguy
2
如果有人弄清楚了你生成许可证密钥的方式,他们就可以自己生成。但是,如果你的许可证密钥包括数字签名,那么即使知道如何生成也无济于事。黑客仍然需要破解数字签名算法,这是值得发表科学论文的成就! - Roman Starkov
@romkyns,如果您正在使用私钥签署密钥,则是正确的。但是,如果您只是对一个值进行哈希(例如电子邮件地址加上其他内容),那么如果他们已经解决了您正在使用的哈希算法并且知道任何电子邮件地址的哈希值,他们就可以开始为任何电子邮件地址生成密钥。 - Paul Taylor
显示剩余2条评论

9
我使用这样的系统:
• 使用Windows许可密钥和试用期结束日期创建字符串。
• 从字符串生成哈希(Sha / md5)。
• 将试用结束日期转换为整数(例如天数)。
• 密钥变成试用结束日期+哈希的一部分。
• 将密钥转换为仅大写字符,以使输入更容易。
ABCD-DEFG-HIJK...
验证的工作方式如下:
• 再次将密钥转换为字节。
• 提取试用结束日期。
• 从Windows许可密钥和试用结束日期创建字符串。
• 哈希
• 将哈希与密钥的其余部分进行比较。
对于我的受众来说,这已经足够复杂了。

1
谢谢。这种方法与我一直在研究的非常相似。我需要加入一些元素,使其可重复,并且对于包含到期日期和其他信息的安装是独特的。 - angryITguy

6
答案是没有一种安全的许可证密钥算法,不需要数学学位就可以理解。
最好的许可证密钥是使用非对称加密算法进行数字签名的密钥。您使用私有加密密钥对密钥数据进行签名,并将签名嵌入密钥中,密钥验证(其中包括签名验证等)使用公共密钥进行。这样,除非他们拥有私钥(即私人密钥),否则没有人可以创建许可证密钥。问题是,很少有(且难以)算法具有足够短的签名大小,以嵌入产品密钥中。RSA不是其中之一(RSA512的签名大小为1024位-太大了)。
您可以查看SoftActivate Licensing SDK,它使用椭圆曲线加密生成短的数字签名许可证密钥(C++/C#源代码可用)。

8
另外,如果你在网上搜索SoftActivate,你会发现针对它的注册机破解。这应该能告诉你它到底有多有用。 - Andrew Barber

5
说实话,你试图做的事情是毫无意义的。不管你花多少时间编写验证/加密/密钥系统,估计有一半的时间别人就能破解它。即使你加密最终的可执行文件。然而,作为一种延迟措施或减少人们获取盗版的优质支持的机会,这将有所帮助。还可以用于简单的买家跟踪。或者只是为了好玩。 :p 无论如何,你可以通过以下几种方式来处理它。 很多软件使用名称(可能还包括公司)字符串和哈希函数生成一个密钥。这样做的好处是它是恒定的(只要名称相同,哈希值就相同,因此密钥也相同)。这也是一个非常简单的系统,特别是如果你使用一个众所周知的哈希函数,比如MD5。
hash = md5(name);

一些高级应用程序使用内部函数生成某种验证代码,当您将其与给定名称组合时,就可以创建(并发送回)哈希值。
validCode = getCode(name);
hash = myHash(name ^ validCode);

有些系统使用基于系统的代码(Windows是一个很好的例子),它会抽样硬件位并从中构建标识符。如果您可以获得处理器名称或速度或其他任何东西,那么可以运行类似的程序。唯一的问题是系统更改可能会使代码无效,因此您可以警告用户(并泄露部分过程)或让他们意外发现(不好)。

sysID = processor_name() | ram_Speed();
hash = md5(sysID & name);

您可以使用任意组合的哈希函数、数据获取、字符串输入、布尔运算等。需要考虑的一件事是,您不需要能够反转该过程。只要您能够用相同的结果复制它(任何好的哈希函数都可以),您就可以将哈希结果相互比对,并确保其有效性。您输入的内容越多,它就会变得更加复杂,但也就越难破解。

希望这能回答您的问题。


1
在要进行哈希的字符串中包含一个秘密值是值得的。任何攻击者都可以简单地将其自己的名称进行MD5,但添加一个秘密值(并使用更安全的哈希算法,例如SHA-2)会使攻击难度大大增加。当然,需要将秘密值包含在软件中,并且可以被提取出来。将其与另一个字符串(最好看起来像是软件中使用的字符串)进行异或运算将有助于掩盖它。 - Martin

2
在安全方面,不要重复使用已知并经过测试的算法,并尝试创建自己的算法(缺乏数学知识)是自杀性的行为。
声明:我完全没有数学学位来创建这样的算法,坦白地说,我个人也不认识任何拥有它的人。

我在寻求一个伪算法,可以将其调整为标准编程语言,并将字符串概念应用于其中。我发现如果尝试进行字节级别的翻译,它会变得“自杀式”。 - angryITguy
6
我确实拥有数学学位,并专攻于数论(许多此类算法的根源所在),我完全同意。 - Anthony Potts
4
“不要重新发明轮子而是使用一个已经被验证的算法”,这不就是他在这里提问的原因吗?你知道的,为了避免做你告诉他不要做的事情。 - pc1oad1etter
3
他只是在询问如何使用现有的算法来实现许可证,而不是试图创建新的算法。 - Paul Taylor

1

由于你所编写的任何算法都可能会出现问题,因此我建议你做一些简单的事情,比如这样:

const string secretMumboJumbo = "sdfkldafskjlfajmkldsfjaewumaskldfladkkldsfklj"

//For you to generate keys
string GenerateLicenceKey(int idNr)
{
    return Sha1Hmac(key=secretMumboJumbo, messageToEncode=idNr)
}

//For clients to check if key is valid, 
bool IsKeyValid(string key)
{
   for(int i=0;i<maxNrOfLicenceKeys;i++)
      if(key == GenerateLicenceKey(i))
         return true;
   return false;
}

或许检查可能会变得太慢,因为它必须尝试每个可能的密钥,但这也可以成为避免暴力破解的好方法。

大多数框架应该都有SHA1或其他哈希函数的HMAC函数。在最坏的情况下,您可以用md5(key + id)替换它。

不要太认真地对待这个算法,它只是一个示例,很可能很容易被破解,因为生成密钥必须包含在客户端中,即使它在二进制文件的某个地方隐藏起来了。


谢谢,我已经研究了SHA-1并发现它会对性能造成重大影响,md5是一个选择。我一直在研究纯J2SE编写的类。它们不够安全,但性能提升很显著。 - angryITguy
1
@giulio 性能受损? 每秒需要生成多少个密钥? 对于输入密钥的用户来说,这是一次性(或每次加载一次)事件。对于生成它们...好吧,我希望运行销售软件的业务成为关注性能的问题。许多密钥生成算法故意表现不佳以防止暴力攻击。但是,如果您正在执行暴力攻击,那么这种性能损失通常只会成为瓶颈。 - Martin

-2

在我诚实的看法中,许可证密钥是相当无用的。
有什么能阻止你的客户将该密钥分发给其他人呢?当然,您可以设置一个许可证密钥服务器来记录激活次数,但这需要花费金钱,如果它崩溃或消失了会发生什么呢?

在我的专业意见中,创建一个独特品牌的软件(当然要在程序内加密)。例如,如果您进入软件的帮助->关于,则显示该人的姓名、电话和可能的地址。这样,如果他们将其上传到某种盗版网站,不仅其他人会知道这个人的个人信息...而且您也会为了收取更多的许可证费用或起诉他而知道他的信息。


2
我能够从用户的技术环境中提取独特的信息,用于生成他们的密钥。因此,如果其他人打算使用它,系统会进行检查,停止并提示基于新环境的有效密钥。是的,你可以破解最复杂的许可系统。微软曾经试过并失败了,他们有足够的资金来投入其中。但这真的是对抗偶发盗版的一道屏障。如果有人真的非常想破解它,他们会尝试。但考虑到软件的用途和目标市场,这种风险相当低。 - angryITguy

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