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


90

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

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

有关:



@stukelly是在J3r3myK发表他的问题后发布的……
Dozer789 2014年

Answers:


83

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

但是要当心错误的安全感-迟早有人会简单地修补您的程序以跳过该检查,并分发修补的版本。或者,他们将制定出可以通过所有检查并分发该密钥或使时钟回溯日期等的密钥。不管您如何计划繁琐,为此,您所做的任何事情最终都会通过默默无闻而安全,并且它们将始终能够做到这一点。即使他们不会有人愿意,也将分发被黑客入侵的版本。即使您提供了加密狗,也同样适用-如果有人愿意,他们也可以为此添加支票。对您的代码进行数字签名无济于事,他们可以删除该签名,也可以辞职。

您可以通过使用一些技术来防止事情在调试器中运行,从而使事情复杂化,但是即使这样也不是防弹的。因此,您应该做到足够困难,以至于诚实的用户不会忘记付款。同样要非常小心,您的方案不会对付费用户造成干扰-与那些付费客户不能使用他们所付费用的情况相比,复制一些副本会更好。

另一种选择是进行在线检查-仅向用户提供唯一的ID,然后在线检查ID应该具有的功能,并将其缓存一段时间。但是,所有相同的警告也适用-人们可以绕过这种情况。

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

编辑:我只是想补充一点,不要为此花费太多时间,或者认为您的复杂方案将有所不同且难以破解。只要人们能够控制程序运行的硬件和操作系统,它就不会,也不会。开发人员一直在尝试为此提出更复杂的方案,认为如果他们为此开发自己的系统,则只有他们知道它,因此“更加安全”。但这确实等同于尝试制造永动机的编程。:-)


1
好总结。如果有人不相信绕过CheatEngine查找很简单,那么非程序员可以轻松地做到这一点。最好使这一层简单。
凯利

我有同样的问题,我为应用创建了一个许可证密钥,其中包含到期日期和上次记录的日期以进行验证,但是问题是我必须添加私钥来编辑文件以更新上次记录的日期,即将密钥放入代码中的巧妙方法 有什么建议吗?
多卡雷

16

你信任谁?

我一直认为这方面太重要了,以至于不能信任第三方来管理应用程序的运行时安全性。一旦针对一个应用程序破解了该组件,便针对所有应用程序破解了该组件。几年前,Discreet在使用3ds Max的第三方许可解决方案时花了五分钟,这真是好消息!

认真地考虑考虑自己滚动以完全控制算法。如果这样做,请考虑按照以下方式在密钥中使用组件:

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

然后,对它们进行校验和处理,并向其添加所需的任何(可逆)加密,以使其更难以破解。

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

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

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


3
FYI加密始终是可逆的,无法读取已加密的内容将毫无用处。散列是您可能想到的“加密”方式之一。
塞缪尔

我认为来自布鲁斯·谢尔(Bruce Scheier)(不确定)的“不要推出自己的加密方案”是可行的方法。您可能需要看看以下答案:security.stackexchange.com/questions/2202/…–
Shadok

您能否详细说明“ ..P /调用它”。我看了链接的页面,但并没有使我更明智:-/
MrCalvin

11

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

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

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


8

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

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

我个人认为有两类用户。那些谁付钱。那些没有。即使是最琐碎的保护,这样做的人也可能这样做。那些不愿意等待的人将等待裂缝或寻找其他地方。无论哪种方式,它都不会再为您赚钱。


6

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

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

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


那样就不需要禁用DEP吗?
罗兰·肖

不能。设置PAGE_EXECUTE_READWRITE是记录的正确方法,可以编写自修改代码并仅清除该页面上的NX位。
约书亚

8
这项通用技术在80年代后期非常流行。它的弱点是将“秘密”代码解密到RAM中,从而很容易从任何正在运行的软件副本中窃取。
Ray Burns 2010年

5

也有选项Microsoft软件许可和保护(SLP)服务。看过它之后,我真的希望我可以使用它。

我真的很喜欢根据许可证来阻止部分代码的想法。热门产品,也是.NET最安全的内容。有趣的阅​​读,即使您不使用它!

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

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


对于那些记起已取消的人:SLP重新启动
Michael Olesen

5

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



2

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

在C#中使用以下代码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 "/".

希望对您有所帮助。


1

诀窍是要拥有只有您自己知道的算法(这样才能在另一端进行解码)。

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

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

也可能是值得一读的答复这个问题,以及


6
“诀窍是拥有一个只有您自己知道的算法”-这几乎是默默无闻的安全定义,这是一个非常糟糕的主意。
尼克·约翰逊,

3
尽管所有许可都是通过涉及秘密的算法进行的。通常最好通过投资律师来获得许可,而不是拿出“牢不可破”的钥匙来进行军备竞赛
Rowland Shaw 2009年

+1有关通过法律手段强制许可的评论
罗布

是的,就像DRM一样,所有许可都很薄弱。但是,依靠秘密算法显然较弱
尼克·约翰逊,

1
我给了您+1以获得一个很好的答案,也希望我也给您另一个以反驳反对票。可悲的是,世界上有一些非常不成熟的小婴儿。
ProfK 2011年

1

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

例如,有OLicense套件:http ://www.olicense.de/index.php?lang=zh-CN


0

您可以检查LicenseSpot。它提供:

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

1
“免费”并不是真正的免费。免费将许可组件嵌入到您的应用中;应用实际使用许可组件并非免费的。超过10次激活后,您需要每月支付费用。它不是每个激活的百分比。对于小批量的低成本.NET应用程序,此定价模型将是不利的。它不像.NET应用程序的Apple AppStore。
Cheeso 2011年

0

我将在@frankodwyer的出色答案上piggy带一点,并更深入地研究基于在线的许可。我是Keygen(为开发人员构建的许可REST API)的创始人。

由于您提到要为您的应用程序提供2种“类型”的许可证,即“完整版”和“试用版”,因此我们可以简化此过程,并使用功能许可证模型来对应用程序的特定功能进行许可(在这种情况下,有一个“完整”功能集和一个“试用”功能集)。

首先,我们可以创建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周,这要求用户购买新的许可证。许可证到期后。

我可以进行更多研究,以将机器与用户以及类似的东西相关联,但是我想我会尽量缩短答案,只专注于向您的用户授权功能。


0

请检查以下答案: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();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.