我目前正在开发一个产品(用c#开发的),可以免费下载和安装,但版本非常有限。要获得所有功能,用户必须支付许可费并获得密钥。然后,该密钥将被输入应用程序以“解锁”完整版本。
像这样使用许可密钥是很常见的,我想知道:
这个问题通常是怎么解决的?
如何生成密钥以及应用程序如何验证密钥?
我怎样才能避免一个密钥被发布在互联网上,并被其他没有支付许可证的人使用(一个基本上不是“他们的”密钥)。
我想我还应该以某种方式将密钥绑定到应用程序的版本,这样就有可能在功能版本中对新密钥收费。
在这种情况下,还有什么需要考虑的吗?
我知道这是一个老问题,但我在为我的一个应用程序重新编写许可流程时引用了这个问题。
在阅读了大量的意见并依靠过去的许可代码经验后,我想出了这个过程。
public static class LicenseGenerator
{
private static string validChars = "ACEFHJKMNPRSTUVWXYZ234579";
private static Random rnd = new Random(Guid.NewGuid().GetHashCode());
/// <summary>
/// Generate a license code
/// </summary>
/// <param name="length">length of each phrase</param>
/// <param name="number">number of phrases separated by a '-'</param>
/// <returns></returns>
public static string GetNewCode(int length, int number)
{
string license = string.Empty;
for (int numberOfPhrases = 0; numberOfPhrases < number; numberOfPhrases++)
{
license += getPhrase(length);
if (numberOfPhrases < number)
license += "-";
}
return license.TrimEnd('-');
}
/// <summary>
/// generate a phrase
/// </summary>
/// <param name="length">length of phrase</param>
/// <returns></returns>
private static string getPhrase(int length)
{
string phrase = string.Empty;
for (int loop = 0; loop < length; loop++)
{
phrase += validChars[rnd.Next(validChars.Length)];
}
return phrase;
}
}
你真的不想提供一个有相似字母的代码;当最终用户输入时,它会造成混乱。像6和G, B和8,L, I和1。当然,如果你真的想要它们,你可以随时把它们加回来……上面的代码将使用“validChars”中的字符生成类似xxxx-xxxx-xxxx-xxxx的许可证。调用GetNewCode(4,4)将返回与上面类似的代码。
我使用Azure函数注册然后验证代码。当我的应用程序注册代码时,它会生成一个加密散列,其中包含安装、设备和/或用户独有的内容。它被提供给注册函数,并与密钥一起存储在Azure的DB中。
验证重新生成密钥,并向其提供许可代码、IP地址(在我的例子中,IP地址不会改变,如果改变了,那么无论如何都需要更新)和重新生成的散列,然后Azure函数在应用程序获得许可时返回。我确实在他们的服务器上存储了一个“临时”密钥,允许应用运行一段时间而不返回。
当然,我的应用程序必须在网络上,它的工作无论如何。
因此,最终结果是一个供最终用户输入的简单密钥,以及在后端管理许可证的简单流程。如果需要,我还可以使许可证无效。
我是Cryptolens软件授权平台背后的开发人员之一,从14岁开始就一直在开发授权系统。在这个回答中,我根据多年来的经验总结了一些建议。
解决这个问题的最佳方法是设置一个许可密钥服务器,应用程序的每个实例都将调用该服务器来验证许可密钥。
许可证密钥服务器的好处
使用许可密钥服务器的优点是:
您可以随时更新或阻止许可证密钥立即生效。
每个许可密钥可以被锁定到一定数量的机器上(这有助于防止用户在线发布许可密钥供其他人使用)。
注意事项
虽然在线验证许可证可以让您更好地控制应用程序的每个实例,但internet连接并不总是存在(特别是如果您的目标是大型企业),因此我们需要另一种方式来执行许可证密钥验证。
解决方案是始终使用公钥加密系统(如RSA或ECC)对来自服务器的许可密钥响应进行签名(如果计划在嵌入式系统上运行,可能更好)。您的应用程序应该只有用于验证许可密钥响应的公钥。
因此,在没有互联网连接的情况下,您可以使用之前的许可密钥响应。确保在响应中存储日期和机器标识符,并检查它不是太旧(例如。您允许用户离线最多30天,等等),并且许可密钥响应属于正确的设备。
请注意,您应该始终检查许可密钥响应的证书,即使您连接到internet),以确保它在离开服务器后没有被更改(即使您的API到许可密钥服务器使用https,这仍然必须完成)。
保护秘密算法
大多数。net应用程序都可以很容易地进行反向工程(微软提供了一个反汇编程序来获得IL代码,一些商业产品甚至可以检索源代码,例如。c#)。当然,您总是可以混淆代码,但它永远不会是100%安全的。
在大多数情况下,任何软件许可解决方案的目的都是帮助诚实的人变得诚实(即愿意付费的诚实用户在试用期满后不会忘记付费,等等)。
然而,您可能仍然有一些您不想泄露给公众的代码(例如。预测股票价格的算法等)。在这种情况下,唯一的方法是创建一个API端点,您的应用程序将在每次执行方法时调用该端点。它需要互联网连接,但它确保你的秘密代码永远不会被客户端机器执行。
实现
如果你不想自己实现所有的东西,我建议你看看这个教程(Cryptolens的一部分)