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

Rir*_*iri 220 c# license-key

我目前正在开发一种产品(用C#开发),可以免费下载和安装,但版本非常有限.要访问所有功能,用户必须支付许可费并获得密钥.然后将该密钥输入应用程序以"解锁"完整版本.

因为使用像这样的许可证密钥,我想知道:

  1. 通常如何解决?
  2. 如何生成密钥以及如何通过应用程序验证密钥?
  3. 我怎样才能避免让密钥在互联网上发布并被没有支付许可证的其他人使用(一个基本上不是"他们的"的密钥).

我想我也应该以某种方式将密钥绑定到应用程序的版本,这样就可以在功能版本中为新密钥收费.

在这种情况下我还应该考虑其他什么吗?

Bre*_*ugh 122

警告:你不能阻止用户盗版,但只能让诚实用户更容易做正确的事情.

假设您不想为每个用户进行特殊构建,那么:

  • 为自己生成产品的密钥
  • 取用户名
  • 使用(例如)SHA1连接用户名和密钥以及哈希
  • 将SHA1哈希解包为字母数字字符串.这是个人用户的"产品密钥"
  • 在程序中,执行相同的哈希,并与产品密钥进行比较.如果相等,那好吧.

但是,我再说一遍:这不会阻止盗版


我最近读到这种方法在加密方面不是非常合理.但是这个解决方案已经很弱了(因为软件本身必须在某个地方包含密钥),所以我不认为这个发现会使解决方案无效.

只是想我真的应该提到这个; 如果你打算从中获得其他东西,请注意.

  • @Steven:是的,因为我希望我能非常清楚地暗示两次. (22认同)
  • 使用非对称加密方法(如RSA)生成和解码产品密钥,以避免在代码中嵌入秘密. (20认同)
  • 如果程序包含密钥(如上述步骤所暗示的那样),则破解它是微不足道的 (13认同)
  • 我认为,当有人黑客攻击您的代码(可能是在汇编级别)找到您的密钥时,他们可能也处于完全绕过您的支票的水平.我不认为有一种注册方法如此安全,以至于它可以在本地运行程序的好黑客中存活下来.正如最初的评论所说的那样,所有这些都使得它比简单地复制文件更难一步.如今很多游戏都放弃了版权保护,只是简单地将游戏内容放到网上,在这种情况下代码不在黑客手中. (6认同)
  • @Brent.Longborough 只有作者(或生成许可证密钥的一方)拥有它。查找非对称密码学。 (3认同)
  • 编辑得更加明显; 不能过分强调基本的东西;-) (2认同)
  • 在许可证密钥中包含限制是否常见?例如,时间限制、并发用户数、要安装的模块等? (2认同)
  • @Brent.Longborough 有许多不同类型的安全措施。有了 exe 中的公钥,就无法出售欺骗性的许可证。与 pib/priv 相比,哈希方法没有任何优点,而且还有缺点。私钥不必位于 exe 中 (2认同)

小智 89

有许多方法可以生成许可证密钥,但这些方法中很少有真正安全的方法.而且很遗憾,因为对于公司而言,许可证密钥与真实现金的价值几乎相同.

理想情况下,您希望许可证密钥具有以下属性:

  1. 只有您的公司应该能够为您的产品生成许可证密钥,即使有人完全对您的产品进行逆向工程(这将会发生,我会根据经验说话).如果您认真控制许可,那么模糊算法或在您的软件中隐藏加密密钥是不可能的.如果您的产品成功,有人会在发布后的几天内生成密钥生成器.

  2. 许可证密钥应该只能在一台计算机上使用(或者至少你应该能够非常严格地控制它)

  3. 许可证密钥应该简短,易于通过电话键入或指示.您不希望每个客户都致电技术支持,因为他们不知道密钥是否包含"l"或"1".您的支持部门会为此感谢您,您将在此领域降低成本.

那么你如何解决这些挑战呢?

  1. 答案很简单但技术上具有挑战性:使用公钥加密技术的数字签名.您的许可证密钥实际上应该是签名的"文档",其中包含一些有用的数据,并使用您公司的私钥签名.签名应该是许可证密钥的一部分.产品应使用相应的公钥验证许可证密钥.这样,即使某人拥有对产品逻辑的完全访问权限,他们也无法生成许可证密钥,因为他们没有私钥.许可证密钥如下所示:BASE32(CONCAT(DATA,PRIVATE_KEY_ENCRYPTED(HASH(DATA))))这里最大的挑战是经典公钥算法具有大的签名大小.RSA512具有1024位签名.您不希望许可证密钥包含数百个字符.最强大的方法之一是使用椭圆曲线加密(仔细实施以避免现有专利).ECC密钥比RSA密钥短6倍,强度相同.你可以使用像Schnorr数字签名算法这样的算法进一步减少签名大小(专利于2008年到期 - 好:))

  2. 这可以通过产品激活来实现(Windows就是一个很好的例子).基本上,对于具有有效许可证密钥的客户,您需要生成一些"激活数据",这是一个嵌入计算机硬件ID作为签名数据的签名消息.这通常是通过互联网完成的,但仅限于ONCE:产品将许可证密钥和计算机硬件ID发送到激活服务器,激活服务器发送回签名的消息(也可以缩短并轻松指示电话).从那一刻开始,产品在启动时不检查许可证密钥,而是激活数据,需要计算机才能进行验证(否则,DATA将不同,数字签名将无法验证).请注意,激活数据检查不需要通过Internet进行验证:使用已嵌入产品中的公钥验证激活数据的数字签名就足够了.

  3. 好吧,只需从键中删除多余的字符,如"1","l","0","o".将许可证密钥字符串拆分为多个字符组.

  • 难道他们只是编辑软件添加/删除代码,以便完全跳过检查? (7认同)
  • 我想指出这个答案与其他杂乱无章的事情相比有多么优越。 (4认同)
  • 值得注意的是,即使使用不对称加密私钥/公钥,仍然可以生成假许可证,只需将软件中附带的公钥替换为另一个公钥,并使用其相应的私钥来签署假许可证即可。这就是为什么我们拥有并且需要值得信赖的证书颁发机构,他们将公钥与身份绑定。因此,虽然这可能会增加一个需要跳过的障碍,但它本身并不能保证第一。 (2认同)
  • @Saeb Amini,受信任的证书颁发机构将保护公钥,只有用户无法将新证书添加到存储中。黑客可以将自己的证书注册为受信任的 CA,并用其证书签名的公钥替换程序中的公钥。这使得黑客攻击变得更加困难。 (2认同)
  • @Pacerier 我认为拥有安全许可证密钥与修改 EXE 相比的好处是,这意味着黑客必须分发非法修改的软件,而不仅仅是分发他们自己生成的密钥。如果您的 EXE 已签名,这似乎是一个非常重要的优势。 (2认同)

sch*_*ner 73

简单的答案 - 无论您使用什么方案,都可以破解.

不要用一个旨在防止黑客的系统来惩罚诚实的客户,因为黑客无论如何都会破解它.

与他们的电子邮件或类似相关联的简单散列代码可能已经足够好了.当人们需要重新安装或更新硬件时,基于硬件的ID始终会成为一个问题.

关于这个问题的好线程:http: //discuss.joelonsoftware.com/default.asp ?biz.5.82298.34

  • +1.你对不惩罚用户的评论是现场. (41认同)
  • pub/priv 密钥签名方案无法被“破解”,无法为想要运行从发布者站点下载的签名代码(而不是破解软件)的用户生成新的有效密钥。而散列/对称方案可以被破解以产生与无效许可证无法区分的新的有效许可证密钥。差异巨大。 (5认同)
  • 同意,你不想打扰实际购买你产品的用户!(注意m $,苹果等...) (2认同)
  • MS,Apple等可以随身携带,因为它们很大并且提供难以在其他地方获得的核心产品,或者拥有可以用来强迫人们的巨大市场阴影.小开发不能. (2认同)
  • 线程链接现已失效。这是存档版本 - > https://web.archive.org/web/20181006064951/http://discuss.joelonsoftware.com/default.asp?biz.5.82298.34 (2认同)

sho*_*osh 56

生成密钥时,不要忘记将版本号和内部版本号连接到计算哈希值的字符串上.这样就没有一把钥匙可以解锁你发布的所有东西.

在你找到一些漂浮在astalavista.box.sk中的键或补丁后,你就会知道你成功地创造了足够受欢迎的东西,以至于有人不愿意破解.麾!

  • "不要忘记将版本和内部版本编号连接到您计算哈希值的字符串" - 但是当用户更新到次要修补程序版本时,这不会导致密钥中断吗? (8认同)
  • @thomthom 那么如何将最大版本与密钥相关联?版本想法本身是合理的,并增加了更多的安全性 (3认同)
  • @MarvinThobejane 关联一个最大版本,您可以签署允许的最大版本,并让代码迭代它的版本。但 sigs 中不允许使用 >= 操作。 (2认同)

小智 22

除了已经说过的......

由于中间语言问题,任何.NET应用程序的使用本质上都是易碎的.对.NET代码的简单反汇编将向任何人开放您的产品.他们可以在此时轻松绕过您的许可代码.

您甚至无法使用硬件值来创建密钥.虚拟机现在允许某人创建"许可"计算机的映像并在他们选择的任何平台上运行它.

如果它是昂贵的软件,还有其他解决方案.如果不是这样,那么对于随意的黑客来说就足够了.并接受最终会有无牌副本的事实.

如果您的产品很复杂,固有的支持问题将为您创造一些保护.

  • +1用于防止因虚拟机而导致硬件值出现弱点. (9认同)
  • 这就是用于PE签名的.NET和Authenticode的强命名.如果有人反编译,修改并重建了您的库,它将不会被签名,应用程序将无法运行..NET虚拟机不允许它. (3认同)
  • 签名用于验证您将运行的程序的来源。如果用户因为知道它被修改和破解而不关心来源,破解者就会剥离签名,甚至用自己的签名签名。签名不会将可信程序集与不可信程序集混合在一起。 (2认同)

gb2*_*b2d 11

我们用于生成许可证密钥的C#/ .NET引擎现在作为开源维护:

https://github.com/appsoftware/.NET-Licence-Key-Generator.

它基于"部分密钥验证"系统,这意味着只有用于生成密钥的密钥的子集必须编译到您的可分发中.您可以自行创建密钥,因此许可证实施对于您的软件是唯一的.

如上所述,如果您的代码可以被反编译,那么绕过大多数许可系统相对容易.


小智 7

我坚信,只有基于公钥加密的许可系统才是正确的方法,因为您不必将许可证生成所需的基本信息包含到源代码中。

过去,我多次使用过Treek 的许可库,因为它满足了这个要求并且提供了非常好的价格。它对最终用户和自身使用相同的许可证保护,直到现在还没有人破解它。您还可以在网站上找到避免盗版和破解的好提示。


Art*_*tem 7

我是Cryptolens软件许可平台背后的开发人员之一,并且从14岁起就开始从事许可系统的开发。在此答案中,我根据自己多年的经验提供了一些技巧。

解决此问题的最佳方法是设置一个许可证密钥服务器,应用程序的每个实例都将调用该服务器以验证许可证密钥。

许可证密钥服务器的好处

许可证密钥服务器的优点在于:

  1. 您始终可以立即更新或阻止许可证密钥。
  2. 每个许可证密钥可以锁定到一定数量的计算机上(这有助于防止用户在线发布许可证密钥供他人使用)。

注意事项

尽管在线验证许可证使您可以更好地控制应用程序的每个实例,但是并不总是存在Internet连接(尤其是针对大型企业时),因此我们需要另一种执行许可证密钥验证的方法。

解决方案是始终使用诸如RSA或ECC之类的公共密钥密码系统对服务器的许可证密钥响应进行签名(如果计划在嵌入式系统上运行,则可能会更好)。您的应用程序应仅具有公共密钥来验证许可证密钥响应。

因此,如果没有互联网连接,则可以改用以前的许可证密钥响应。确保在响应中同时存储日期机器标识符,并检查日期是否太旧(例如,您允许用户最多30天处于离线状态,等等),并且许可证密钥响应属于正确的设备。

请注意,即使您已连接到Internet,也应始终检查许可证密钥响应证书,以确保自从它离开服务器以来未对其进行更改(即使您的API仍要这样做,也必须这样做)。许可证密钥服务器使用https)

保护秘密算法

大多数.NET应用程序都可以很容易地进行逆向工程(Microsoft提供了一个双汇编程序来获取IL代码,某些商业产品甚至可以检索C#等源代码)。当然,您始终可以混淆代码,但是它永远不是100%安全的。

在大多数情况下,任何软件许可解决方案的目的都是为了帮助诚实的人诚实(即,愿意付款的诚实用户不要在试用期满后忘记付款,等等)。

但是,您可能仍然有一些绝对不希望泄漏给公众的代码(例如,预测股价的算法等)。在这种情况下,唯一的方法是创建一个API端点,应用程序将在每次执行该方法时调用该端点。它需要Internet连接,但可以确保客户端计算机永远不会执行您的密码。

实作

如果您不想自己实现所有功能,建议您看一下本教程Cryptolens的一部分)

  • @AmirMahdiNassiri 对于问题 1:如果 PC 永久离线,您可以使用实时时钟 (RTC) 加密狗作为可信时间源。对于问题 2:由于响应是使用供应商的私钥签名的(并使用应用程序内的公钥进行验证),因此攻击者需要在不知道私钥的情况下重新签名文件,在撰写本文时,私钥是2048 位 RSA 密钥不可能实现。 (2认同)

Mit*_*eat 6

我过去使用过Crypkey.这是许多可用的之一.

您只能通过任何许可方案保护软件到一定程度.


Cra*_*893 6

我不知道你想要多精细

但我相信.net可以访问硬盘序列号.

你可以让程序发送给你和eles的东西(比如nic的用户名和mac地址)

您根据该计算代码并通过电子邮件将其发回给密钥.

他们在拥有钥匙后会让他们免于切换机器.

  • 并阻止他们在其他方面取代死老鼠,导致沮丧.遗憾的是,没有简单的答案,您需要平衡信任与基本许可机制. (4认同)