我目前正在开发一个产品(用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函数在应用程序获得许可时返回。我确实在他们的服务器上存储了一个“临时”密钥,允许应用运行一段时间而不返回。
当然,我的应用程序必须在网络上,它的工作无论如何。
因此,最终结果是一个供最终用户输入的简单密钥,以及在后端管理许可证的简单流程。如果需要,我还可以使许可证无效。
我知道这是一个老问题,但我在为我的一个应用程序重新编写许可流程时引用了这个问题。
在阅读了大量的意见并依靠过去的许可代码经验后,我想出了这个过程。
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函数在应用程序获得许可时返回。我确实在他们的服务器上存储了一个“临时”密钥,允许应用运行一段时间而不返回。
当然,我的应用程序必须在网络上,它的工作无论如何。
因此,最终结果是一个供最终用户输入的简单密钥,以及在后端管理许可证的简单流程。如果需要,我还可以使许可证无效。
你可以使用免费的第三方解决方案来解决这个问题,比如Quantum-Key。Net它是免费的,通过paypal为你创建的网络销售页面处理支付,通过电子邮件发放钥匙,并将钥匙锁定到特定的计算机以防止盗版。
你还应该注意混淆/加密你的代码,或者它可以很容易地使用De4dot和. netreflector等软件进行逆向工程。ConfuserEx是一个很好的免费代码混淆器,它使用起来快速简单,比昂贵的替代品更有效。
你应该通过De4Dot和. netreflector运行你完成的软件来逆向工程它,看看黑客会看到什么,如果他们做同样的事情,并确保你没有留下任何重要的代码暴露或未伪装。
你的软件仍然是可以被破解的,但对于那些偶然的破解者来说,这可能足以让他们望而却步,这些简单的步骤也可以防止你的代码被提取和重用。
https://quantum-key.net
如何使用ConfuserEx?
https://github.com/0xd4d/de4dot
https://www.red-gate.com/dynamic/products/dotnet-development/reflector/download