94

如何为我的 C# 应用程序创建产品密钥?

我需要创建一个每年更新的产品(或许可证)密钥。此外,我需要为试用版创建一个。

有关的:

4

14 回答 14

83

您可以执行一些操作,例如创建一条记录,其中包含您要向应用程序验证的数据。这可能包括您想要的任何内容 - 例如启用的程序功能、到期日期、用户名(如果您想将其绑定到用户)。然后使用具有固定密钥的某种加密算法对其进行加密或对其进行哈希处理。然后你只需在你的程序中验证它。分发许可证文件(在 Windows 上)的一种方法是将其作为更新注册表的文件提供(无需用户键入)。

不过要小心错误的安全感——迟早有人会简单地修补您的程序以跳过该检查,然后分发修补版本。或者,他们将制定出一个通过所有检查的密钥并分发它,或者回溯时钟等。无论您的计划多么复杂,您为此所做的任何事情最终都将通过默默无闻来确保安全,他们将永远能够做到这一点。即使他们不能,也有人会分发被黑的版本。即使您提供加密狗也同样适用 - 如果有人愿意,他们也可以为此修补检查。对您的代码进行数字签名将无济于事,他们可以删除该签名或将其辞职。

您可以通过使用技术来防止程序在调试器等中运行,从而使事情复杂化,但这也不是防弹的。因此,您应该让它变得足够困难,以至于诚实的用户不会忘记付款。还要非常小心,不要让您的计划对付费用户造成干扰——最好有一些盗版的副本,而不是让您的付费客户无法使用他们所支付的费用。

另一种选择是进行在线检查 - 只需为用户提供一个唯一 ID,并在线检查该 ID 应具有哪些功能,并将其缓存一段时间。但是,所有相同的警告都适用-人们可以绕过这样的任何事情。

还要考虑必须与忘记密钥的用户打交道的支持成本等。

编辑:我只是想补充一点,不要在这方面投入太多时间,或者认为你的复杂方案会有所不同且无法破解。只要人们控制您的程序运行的硬件和操作系统,它就不会,也不可能。开发人员一直试图为此提出更复杂的方案,认为如果他们为此开发自己的系统,那么只有他们自己知道,因此“更安全”。但这实际上是一种相当于尝试构建永动机的编程。:-)

于 2009-01-17T09:54:06.667 回答
16

你信任谁?

我一直认为这个领域太重要了,不能信任第三方来管理应用程序的运行时安全性。一旦该组件针对一个应用程序被破解,它就会针对所有应用程序被破解。几年前,当Discreet使用3ds Max的第三方许可解决方案时,他们在五分钟内发生了这种情况……好时光!

说真的,考虑自己滚动以完全控制您的算法。如果这样做,请考虑在密钥中使用以下组件:

  • 许可证名称 - 您授权的客户名称(如果有)。对管理公司部署很有用 - 让他们在您提供的许可证信息中使用“个性化”名称感到特别。
  • 执照到期日期
  • 在同一许可下运行的用户数。这假设您有一种以服务器方式跟踪站点上正在运行的实例的方法
  • 功能代码 - 让您可以跨多个功能和多个产品使用相同的许可系统。当然,如果它为一种产品破解,它对所有产品都破解。

然后对它们进行校验和,并添加您想要的任何(可逆)加密,以使其更难破解。

要制作试用许可证密钥,只需将上述值设置为“试用模式”即可。

并且由于这现在可​​能是您的应用程序/公司中最重要的代码,因此除了混淆之外/而不是考虑将解密例程放在本机 DLL 文件中并简单地对其进行P/Invoke

我工作过的几家公司为此采用了通用方法并取得了巨大成功。或者也许这些产品不值得破解;)

于 2009-01-17T10:21:37.127 回答
11

如果您询问可以输入的密钥,例如 Windows 产品密钥,那么它们是基于一些检查的。如果您谈论的是必须复制粘贴的密钥,那么它们是基于数字签名(私钥加密)的。

一个简单的产品密钥逻辑可以首先说产品密钥由四个 5 位组组成,例如abcde-fghij-kljmo-pqrst,然后继续指定内部关系,例如 f+k+p 应该等于 a,这意味着 2 的第一个数字, 3 和 4 组应该总计为一个。这意味着 8xxxx-2xxxx-4xxxx-2xxxx 有效,8xxxx-1xxxx-0xxxx-7xxxx 也是有效的。当然,还有其他关系,包括复杂的关系,比如如果第一组的第二个数字是奇数,那么最后一个数字的最后一个数字也应该是奇数。这样就会有产品密钥的生成器,并且产品密钥的验证将简单地检查它是否符合所有规则。

加密通常是有关使用私钥(== 数字签名)加密并转换为Base64的许可证的信息字符串。公钥与应用程序一起分发。当 Base64 字符串到达​​时,它由公钥验证(==解密),如果发现有效,则激活产品。

于 2009-01-18T04:50:40.880 回答
10

无论它是微不足道的还是难以破解的,我都不确定它是否真的有很大的不同。

您的应用程序被破解的可能性与其实用性成正比,而不是产品密钥处理的强度。

就个人而言,我认为有两类用户。付钱的人。那些没有。即使是最微不足道的保护,那些这样做的人也可能会这样做。那些不这样做的人会等待裂缝或寻找其他地方。无论哪种方式,它都不会让您获得更多的钱。

于 2009-01-17T14:59:40.810 回答
6

我不得不承认我会做一些相当疯狂的事情。

  1. 查找 CPU 瓶颈并将其提取到P/Invokeable DLL 文件中。
  2. 作为构建后操作,使用 XOR 加密密钥加密 DLL 文件的一部分。
  3. 选择公钥/私钥方案,在 DLL 文件中包含公钥
  4. 安排使解密产品密钥和将两半异或在一起产生 DLL 的加密密钥。
  5. 在 DLL 的 DllMain 代码中,禁用保护 (PAGE_EXECUTE_READWRITE) 并使用密钥对其进行解密。
  6. 创建一个 LicenseCheck() 方法,对许可证密钥和参数进行完整性检查,然后对整个 DLL 文件进行校验和,从而引发许可证违规。哦,在这里做一些其他的初始化。

当他们找到并删除 LicenseCheck 后,当 DLL 开始出现分段错误时,将会有什么乐趣。

于 2009-01-18T06:26:12.840 回答
5

还可以选择Microsoft 软件许可和保护(SLP) 服务。在阅读了它之后,我真的希望我可以使用它。

我真的很喜欢根据许可证阻止部分代码的想法。热门的东西,对于 .NET 来说是最安全的。即使你不使用它也很有趣!

Microsoft® 软件许可和保护 (SLP) 服务是一项软件激活服务,使独立软件供应商 (ISV) 能够为其客户采用灵活的许可条款。Microsoft SLP 服务采用独特的保护方法,有助于保护您的应用程序和许可信息,使您能够更快地进入市场,同时提高客户合规性。

注意:这是我发布带有敏感代码(例如有价值的算法)的产品的唯一方法。

于 2009-01-18T04:53:58.330 回答
5

如果您想要一个简单的解决方案来创建和验证序列号,请尝试 Ellipter。它使用椭圆曲线密码学并具有“到期日期”功能,因此您可以创建试用版或有时间限制的注册密钥。

于 2009-12-12T11:32:25.713 回答
2

另一个用于产品密钥和激活的物美价廉的工具是名为 InstallKey 的产品。看看www.lomacons.com

于 2010-03-19T20:32:04.443 回答
2

一种简单的方法是使用全局唯一标识符(GUID)。GUID 通常存储为 128 位值,通常显示为 32 位十六进制数字,组之间用连字符分隔,例如{21EC2020-3AEA-4069-A2DD-08002B30309D}.

在 C# 中使用以下代码 by System.Guid.NewGuid()

getKey = System.Guid.NewGuid().ToString().Substring(0, 8).ToUpper(); //Will generate a random 8 digit hexadecimal string.

_key = Convert.ToString(Regex.Replace(getKey, ".{4}", "$0/")); // And use this to separate every four digits with a "/".

我希望它有所帮助。

于 2014-06-04T16:32:59.620 回答
1

诀窍是要有一个只有你知道的算法(这样它就可以在另一端被解码)。

有一些简单的事情,例如“选择一个质数并添加一个幻数”

更复杂的选项,例如对一组二进制数据(可能包括唯一标识符、版本号等)使用非对称加密,并将加密数据作为密钥分发。

也可能值得阅读对这个问题的回答

于 2009-01-17T09:24:22.077 回答
1

有一些可用的工具和 API。但是,我认为您不会免费找到一个;)

例如 OLicense 套件: http ://www.olicense.de/index.php?lang=en

于 2009-01-17T09:25:51.933 回答
1

请检查这个答案:https ://stackoverflow.com/a/38598174/1275924

这个想法是使用Cryptolens作为许可证服务器。这是一个分步示例(在 C# 和 VB.NET 中)。我还在下面(在 C# 中)附加了一个用于密钥验证的代码片段:

var licenseKey = "GEBNC-WZZJD-VJIHG-GCMVD";
var RSAPubKey = "{enter the RSA Public key here}";

var auth = "{access token with permission to access the activate method}";
var result = Key.Activate(token: auth, parameters: new ActivateModel()
{
    Key = licenseKey,
    ProductId = 3349,
    Sign = true,
    MachineCode = Helpers.GetMachineCode()
});

if (result == null || result.Result == ResultType.Error ||
    !result.LicenseKey.HasValidSignature(RSAPubKey).IsValid())
{
    // an error occurred or the key is invalid or it cannot be activated
    // (eg. the limit of activated devices was achieved)
    Console.WriteLine("The license does not work.");
}
else
{
    // everything went fine if we are here!
    Console.WriteLine("The license is valid!");
}

Console.ReadLine();
于 2016-07-26T19:22:31.753 回答
0

您可以检查LicenseSpot。它提供:

  • 免费许可组件
  • 在线激活
  • 用于集成您的应用程序和在线商店的 API
  • 序列号生成
  • 吊销许可证
  • 订阅管理
于 2011-03-11T15:20:53.183 回答
0

我将借鉴@frankodwyer 的出色回答,并更深入地研究基于在线的许可。我是Keygen的创始人,这是一个为开发人员构建的许可 REST API。

由于您提到您的应用程序需要两种“类型”的许可证,即“完整版”和“试用版”,我们可以简化它并使用功能许可证模型,您可以在其中许可应用程序的特定功能(在这种情况下,有一个“完整”功能集和一个“试用”功能集)。

首先,我们可以创建 2种许可证类型(在 Keygen 中称为策略),每当用户注册帐户时,您都可以为他们生成“试用”许可证(“试用”许可证实施我们的“试用”功能策略) ,您可以使用它在应用程序中进行各种检查,例如用户可以使用Trial-Feature-ATrial-Feature-B

在此基础上,每当用户购买您的应用程序(无论您使用的是 PayPal、Stripe 等),您都可以生成一个实施“完整”功能策略的许可证,并将其与用户的帐户相关联。现在在您的应用程序中,您可以检查用户是否拥有可以执行Pro-Feature-XPro-Feature-Y的“完整”许可证(通过执行类似的操作user.HasLicenseFor(FEATURE_POLICY_ID))。

我提到允许您的用户创建用户帐户——我的意思是什么?我在其他几个答案中对此进行了详细介绍,但简要说明了为什么我认为这是一种验证和识别用户的优越方法:

  1. 用户帐户可让您将多个许可证多台计算机关联到一个用户,让您深入了解客户的行为并提示他们进行“应用内购买”,即购买您的“完整”版本(有点像移动应用程序)。
  2. 我们不应该要求我们的客户输入长的许可证密钥,这既输入乏味又难以跟踪,即它们很容易丢失。(尝试在 Twitter 上搜索“丢失的许可证密钥”!)
  3. 客户习惯使用电子邮件/密码;我认为我们应该做人们习惯做的事情,这样我们才能提供良好的用户体验(UX)。

当然,如果您不想处理用户帐户并且希望您的用户输入许可证密钥,那完全可以(并且 Keygen也支持这样做)。我只是提供另一种处理许可方面的方法,并希望为您的客户提供良好的用户体验。

最后,由于您还提到您希望每年更新这些许可证,您可以在策略上设置一个持续时间,以便“完整”许可证将在一年后到期,而“试用”许可证持续 2 周,要求您的用户购买新的许可证到期后。

I could dig in more, getting into associating machines with users and things like that, but I thought I'd try to keep this answer short and focus on simply licensing features to your users.

于 2017-05-13T22:12:37.393 回答