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

时间:2009-03-01 13:41:30

标签: c# license-key

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

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

  1. 通常如何解决?
  2. 如何生成密钥以及如何通过应用程序验证?
  3. 我怎样才能避免让密钥在互联网上发布并被未支付许可证的其他人使用(一个基本上不是“他们的”的密钥)。
  4. 我想我也应该以某种方式将密钥绑定到应用程序的版本,以便在功能版本中为新密钥收费。

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

16 个答案:

答案 0 :(得分:118)

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

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

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

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


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

但是我以为我真的应该提到这一点;如果你打算从中获得其他东西,请注意。

答案 1 :(得分:82)

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

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

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

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

  3. 许可证密钥应简短,易于通过电话输入或指示。您不希望每个客户都致电技术支持,因为他们不了解密钥是否包含“l”或“1”。您的支持部门会对此表示感谢,您将在这方面降低成本。

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

    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”。将许可证密钥字符串拆分为多个字符组。

答案 2 :(得分:69)

简单回答 - 无论您使用何种方案,都可以破解。

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

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

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

答案 3 :(得分:53)

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

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

答案 4 :(得分:22)

除了已经说过的内容之外......

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

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

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

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

答案 5 :(得分:11)

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

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

它基于“部分密钥验证”系统,这意味着只有用于生成密钥的密钥的一部分必须编译到您的可分发中。您可以自行创建密钥,因此许可证实施对您的软件来说是独一无二的。

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

答案 6 :(得分:6)

我过去曾使用Crypkey。这是众多可用的产品之一。

您只能使用任何许可方案保护软件。

答案 7 :(得分:6)

我不知道你想要多么精致

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

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

您根据此计算代码并通过电子邮件将密钥发回给我们。

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

答案 8 :(得分:4)

完成所要求的一切的唯一方法是要求使用服务器进行互联网访问和验证。应用程序需要使用密钥登录服务器,然后您需要存储会话详细信息,如IP地址。这将防止密钥在几台不同的机器上使用。这通常不是很受应用程序用户欢迎,除非这是一个非常昂贵和复杂的应用程序,否则它是不值得的。

您可以拥有应用程序的许可证密钥,然后检查客户端是否正常密钥,但是很容易将此密钥分发给其他用户,并且可以使用反编译器生成新密钥。

答案 9 :(得分:4)

我在我公司的软件(C#.net)上实施了基于互联网的一次性激活,该软件需要一个许可证密钥,该密钥引用存储在服务器数据库中的许可证。软件使用密钥命中服务器并获得许可证信息,然后使用从某些变量(CPUID和其他经常不会更改的东西的组合)生成的RSA密钥在本地加密,然后将其存储在注册表。

它需要一些服务器端编码,但它对我们来说非常有效,当我们扩展到基于浏览器的软件时,我能够使用相同的系统。它还为您的销售人员提供有关软件使用者,地点和时间的详细信息。任何仅在本地处理的许可系统完全容易受到攻击,尤其是在.NET中的反射。但是,就像其他人所说的那样,没有一个系统是完全安全的。

在我看来,如果你没有使用基于网络的许可,那么根本就没有保护软件的真正意义。由于DRM可能导致头痛,对实际付费的用户来说,这是不公平的。

答案 10 :(得分:4)

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

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

许可证密钥服务器的优点

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

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

注意事项

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

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

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

  

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

保护秘密算法

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

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

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

实施

如果您不想自己实现所有功能,建议您看看this tutorialCryptolens的一部分)

答案 11 :(得分:3)

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

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

答案 12 :(得分:3)

与其他一些人提到的一样,我是一个巨大的对手,默认情况下对客户持敌视态度 - 许可行业因此而臭名昭着。因此,我将为您的问题扩展一个良好的解决方案,还提供了良好的客户用户体验

首先,您提到您拥有一个“有限”版本的软件,您正在尝试将客户转换为“升级”以获得其他功能。因此,您正在寻找的产品是功能许可,例如:客户可以购买 feature-X feature-Y 的许可证。

我在构建Keygen时考虑到了这种许可。 Keygen是一种许可REST API,允许您管理用户帐户,许可证以及跟踪机器使用/关联。

我要做的是设置2个许可证类型(Keygen中的策略),其中一个是有限免费版本的基本策略,另一个是付费版本的政策。

我不确定您用于付款的是什么,但我们假设您正在使用提供 webhooks 的Stripe(现在非常标准)。 Keygen也有webhooks(无论你是否使用它,所有这些仍然适用)。您可以使用双方的webhooks集成Keygen与您的支付提供商进行交流(请注意:customer.created - >为客户创建基本许可,license.created - >向新客户收取新许可费。

因此,通过利用webhooks,我们可以为新客户自动创建许可证。那么应用程序本身的许可证验证呢?这可以通过多种方式完成,但最常用的方法是要求您的客户在输入字段中输入长许可证密钥,然后您可以对其进行验证;我认为这是一种糟糕的方式来处理应用程序中的许可证验证。

为什么我这么认为?首先,您要求您的客户输入用于机器消耗的冗长冗长的许可证密钥,然后要求您和您的客户跟踪所述冗长的许可证密钥。< / p>

好的,那又有什么选择呢?我认为最好的替代方案是做所有客户习惯的事情:允许他们使用电子邮件/密码为您的产品创建帐户。然后,您可以将所有许可证及其计算机与该帐户相关联。因此,现在他们只需使用他们的凭据登录,而不是输入许可证密钥。

这给你带来了什么好处?首先,它消除了你和你的客户跟踪许可证密钥的需要,因为它全部是在幕后处理的他们的用户帐户,最重要的是:您现在可以为您的客户提供自助服务许可证和机器激活!即由于他们的所有许可证和机器都与其用户帐户相关联,因此您可以当他们在无法识别的机器上启动您的应用程序时,提示他们购买许可证。

现在进入许可证验证:只要您的客户使用他们的电子邮件/密码登录您的应用程序,您就可以向他们的用户帐户查询他们拥有的许可证,以确定他们是否可以使用功能 - X 功能-Y 。由于您的应用程序现在是自助式,您可以允许您的客户直接从您的应用程序中购买其他功能!

所以我们已经向我们的许可系统引入了 ton 自动化,我们可以许可个人功能(即有限版和完整版),我们已经提供为我们的客户提供了一个 awesome 用户体验,我们也减轻了支持请求的一个主要原因:许可证密钥恢复。

无论如何,这很长,但希望它有助于某人!

答案 13 :(得分:2)

无法完全阻止软件盗版。您可以防止随意盗版,这就是他们所做的所有许可解决方案。

如果要防止重复使用许可证密钥,最好使用节点(计算机)锁定许可。我已经使用Cryptlex大约一年了我的软件。它还有一个免费计划,所以如果您不希望有太多客户,您可以免费使用它。

答案 14 :(得分:0)

您可以使用免费的第三方解决方案为您处理此问题,例如Quantum-Key.Net它是免费的,并通过Paypal通过它为您创建的网络销售页面处理付款,通过电子邮件发送密钥和锁定密切使用特定的计算机,以防止盗版。

您还应该注意对代码进行模糊处理/加密,或者使用De4dot和.NetReflector等软件轻松进行逆向工程。一个好的免费代码混淆器是ConfuserEx,它使用起来快速且简单,并且比昂贵的替代品更有效。

您应该通过De4Dot和.NetReflector运行已完成的软件对其进行逆向工程,看看如果他们做同样的事情,并确保您没有留下任何重要的代码暴露或不加掩饰,那么破解者会看到什么。

你的软件仍然是可以破解的,但对于偶然的破解者来说,它可能足以让它们关闭,这些简单的步骤也会阻止你的代码被提取和重复使用。

https://quantum-key.net

How to use ConfuserEx?

https://github.com/0xd4d/de4dot

https://www.red-gate.com/dynamic/products/dotnet-development/reflector/download

答案 15 :(得分:-3)

我通过将我的程序与 Discord 服务器连接来解决这个问题,如果用户输入的产品密钥存在并且仍然有效,它会在特定聊天中检查。以这种方式接收产品密钥,用户将被迫破解discord,非常困难。