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

Posted

技术标签:

【中文标题】如何为我的 C# 应用程序创建产品密钥?【英文标题】:How can I create a product key for my C# application? 【发布时间】:2010-10-01 23:14:21 【问题描述】:

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

相关:

How do I best obfuscate my C# product license verification code? How do you protect your software from illegal distribution?

【问题讨论】:

相关:***.com/questions/715251/… @stukelly 在 J3r3myK 发布他的问题后发布... 【参考方案1】:

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

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

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

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

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

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

【讨论】:

很好的总结。如果有人不相信绕过查找 CheatEngine 很简单,那么非程序员也可以轻松做到。最好让这一层变得简单。 我有同样的问题,我为我的应用程序制作了一个许可证密钥,其中包含到期日期和最后记录的验证日期,但问题是我必须添加私钥才能编辑文件更新最后记录的日期,这不是将密钥放入代码的聪明方法。有什么建议吗?【参考方案2】:

你信任谁?

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

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

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

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

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

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

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

【讨论】:

仅供参考,加密始终是可逆的,无法读取已加密的内容将毫无用处。散列是您可能想到的一种“加密”方式。 “不要推出自己的加密方案”,我认为这是来自 Bruce Scheier(不确定),是要走的路。你可能想看看这个答案:security.stackexchange.com/questions/2202/… 您能否详细说明“..P/Invoke to it”。我查看了链接页面,但并没有让我变得更聪明:-/【参考方案3】:

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

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

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

【讨论】:

【参考方案4】:

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

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

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

【讨论】:

【参考方案5】:

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

    查找 CPU 瓶颈并将其提取到 P/Invokeable DLL 文件中。 作为构建后操作,使用 XOR 加密部分 DLL 文件 加密密钥。 选择公钥/私钥方案,在 DLL 文件中包含公钥 安排以便解密产品密钥并对两者进行异或 将两半合并为 DLL 的加密密钥。 在 DLL 的 DllMain 代码中,禁用保护 (PAGE_EXECUTE_READWRITE) 并用密钥解密。 创建一个 LicenseCheck() 方法,对 许可证密钥和参数,然后校验和整个 DLL 文件,抛出 违反许可证。哦,做一些其他的初始化 在这里。

当他们找到并删除 LicenseCheck 后,会有什么好玩的 当 DLL 启动时segmentation faulting。

【讨论】:

那不需要禁用 DEP 吗? 没有。设置 PAGE_EXECUTE_READWRITE 是编写自修改代码并仅清除该页面上的 NX 位的记录正确方法。 这种通用技术在 80 年代后期非常流行。它的弱点是“秘密”代码被解密到 RAM 中,因此很容易从任何正在运行的软件副本中窃取。【参考方案6】:

还有Microsoft Software Licensing and Protection (SLP) 服务选项。读完之后,我真的希望我能使用它。

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

Microsoft® 软件许可和 保护 (SLP) 服务是一种 软件激活服务 使独立的软件供应商 (ISV) 采用灵活的许可 条款为他们的客户。微软 SLP 服务采用独特的 有助于保护的保护方法 您的申请和许可 允许您访问的信息 市场在增长的同时更快 客户合规性。

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

【讨论】:

对于那些记得它已取消的人:SLP 再次重新启动【参考方案7】:

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

【讨论】:

【参考方案8】:

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

【讨论】:

【参考方案9】:

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

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

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 "/".

希望对你有帮助。

【讨论】:

【参考方案10】:

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

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

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

也可能值得阅读对this question 的回复

【讨论】:

“诀窍是拥有一个只有你知道的算法”——这几乎是对安全性的模糊定义,而且是一个非常糟糕的主意。 所有许可都是通过涉及秘密的算法进行的。通常最好通过投资律师来获得许可,而不是通过军备竞赛来提供“牢不可破”的密钥 +1 对通过法律手段执行许可的评论 是的,所有许可都很弱,就像 DRM 一样。不过,依靠秘密算法显然较弱 我给了你一个好的答案,希望我给你另一个反对票。可悲的是,世界上有一些非常不成熟的小婴儿。【参考方案11】:

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

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

【讨论】:

【参考方案12】:

请查看此答案:https://***.com/a/38598174/1275924

这个想法是使用Cryptolens 作为许可证服务器。这是step-by-step example(在 C# 和 VB.NET 中)。我还在下面(在 C# 中)附加了一个用于密钥验证的代码 sn-p:

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();

【讨论】:

【参考方案13】:

您可以查看LicenseSpot。它提供:

免费许可组件 在线激活 用于集成您的应用和在线商店的 API 序列号生成 吊销许可证 订阅管理

【讨论】:

“免费”并不是真正免费的。将许可组件嵌入您的应用程序是免费的;应用程序实际上使用许可组件并不是免费的。超过 10 次激活,您需要支付月费。它不是每次激活百分比。对于小批量低成本 .NET 应用程序,这种定价模式将是一个劣势。它不像用于 .NET 应用的 Apple AppStore。【参考方案14】:

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

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

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

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

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

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

当然,如果您不想要处理用户帐户并且想要您的用户输入许可证密钥,那完全没问题(以及 Keygen supports doing that as well) .我只是提供另一种处理许可方面的方法,并希望为您的客户提供良好的用户体验。

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

我可以深入挖掘,将机器与用户相关联以及诸如此类的事情,但我想我会尽量简短地回答这个问题,并专注于简单地向用户授权功能。

【讨论】:

以上是关于如何为我的 C# 应用程序创建产品密钥?的主要内容,如果未能解决你的问题,请参考以下文章

如何为 netbeans java 添加 jxbrowser 的许可证密钥?

如何为 Google App Signing 生成上传密钥?

如何为 React Native 应用程序生成 reCAPTCHA 站点密钥

如何为 Identity Server 4 生成和添加签名密钥?

C# - 如何为程序创建“保护进程”并确保它始终运行?

如何为文件类型创建所有文件关联(友好的应用程序名称和可执行文件)的 C# 列表