如何生成和验证软件许可证密钥?
我目前正在开发一个产品(用 C# 开发),该产品可以免费下载和安装,但版本非常有限。 要访问所有功能,用户必须支付许可费并获得密钥。 然后将该密钥输入到应用程序中以“解锁”完整版本。
由于使用这样的许可证密钥很常见,我想知道:
- 这通常是如何解决的?
- 如何生成密钥以及应用程序如何验证它?
- 我怎样才能避免密钥在互联网上发布并被未支付许可证费用的其他人使用(密钥基本上不是“他们的”)。
我想我还应该以某种方式将密钥与应用程序的版本联系起来,这样就可以对功能版本中的新密钥进行收费。
在这种情况下我还应该考虑什么?
I'm currently involved in developing a product (developed in C#) that'll be available for downloading and installing for free but in a very limited version. To get access to all the features the user has to pay a license fee and receive a key. That key will then be entered into the application to "unlock" the full version.
As using a license key like that is kind of usual I'm wondering :
- How's that usually solved?
- How can I generate the key and how can it be validated by the application?
- How can I also avoid having a key getting published on the Internet and used by others that haven't paid the license (a key that basically isn't "theirs").
I guess I should also tie the key to the version of application somehow so it'll be possible to charge for new keys in feature versions.
Anything else I should think about in this scenario?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
警告:您无法阻止用户盗版,而只能让诚实的用户更容易做正确的事情。
假设您不想为每个用户进行特殊构建,则:
但是,我再说一遍:这不会防止盗版
我最近读到,这种方法在密码学上并不是很可靠。 但这个解决方案已经很弱了(因为软件本身必须在某个地方包含密钥),所以我不认为这一发现会使该解决方案失效。
只是觉得我真的应该提一下这一点; 如果您打算从中获得其他东西,请小心。
Caveat: you can't prevent users from pirating, but only make it easier for honest users to do the right thing.
Assuming you don't want to do a special build for each user, then:
But, I repeat: this won't prevent piracy
I have recently read that this approach is not cryptographically very sound. But this solution is already weak (as the software itself has to include the secret key somewhere), so I don't think this discovery invalidates the solution as far as it goes.
Just thought I really ought to mention this, though; if you're planning to derive something else from this, beware.
生成许可证密钥的方法有很多,但真正安全的方法很少。 这很遗憾,因为对于公司来说,许可证密钥几乎与真正的现金具有相同的价值。
理想情况下,您希望您的许可证密钥具有以下属性:
只有您的公司才能为您的产品生成许可证密钥,即使有人对您的产品进行完全逆向工程(根据我的经验,这种情况将会发生)。 如果您认真控制许可,那么在软件中混淆算法或隐藏加密密钥确实是不可能的。 如果您的产品成功,有人将在发布后几天内制作密钥生成器。
许可证密钥应该只能在一台计算机上使用(或者至少您应该能够非常严格地控制它)
许可证密钥应该简短且易于通过电话键入或口述。 您不希望每个客户都致电技术支持,因为他们不明白密钥中是否包含“l”或“1”。 您的支持部门会为此向您表示感谢,并且您在这方面的成本将会降低。
那么您如何解决这些挑战呢?
答案很简单,但在技术上具有挑战性:使用公钥加密技术的数字签名。 您的许可证密钥实际上应该是签名的“文档”,其中包含一些有用的数据,并使用您公司的私钥签名。 签名应该是许可证密钥的一部分。 产品应使用相应的公钥验证许可证密钥。 这样,即使有人可以完全访问您的产品逻辑,他们也无法生成许可证密钥,因为他们没有私钥。 许可证密钥如下所示: BASE32(CONCAT(DATA, PRIVATE_KEY_ENCRYPTED(HASH(DATA))))
这里最大的挑战是经典的公钥算法具有很大的签名大小。 RSA512 具有 1024 位签名。 您不希望您的许可证密钥有数百个字符。
最强大的方法之一是使用椭圆曲线加密技术(仔细实施以避免现有专利)。 对于相同的强度,ECC 密钥比 RSA 密钥短 6 倍。 您可以使用 Schnorr 数字签名算法(专利于 2008 年过期 - 好:))等算法进一步减小签名大小
这可以通过产品激活来实现(Windows 就是一个很好的例子)。 基本上,对于拥有有效许可证密钥的客户,您需要生成一些“激活数据”,这是一条嵌入计算机硬件 ID 作为签名数据的签名消息。 这通常通过互联网完成,但仅一次:产品将许可证密钥和计算机硬件 ID 发送到激活服务器,激活服务器发回签名消息(该消息也可以变得简短且易于通过电话)。 从那时起,产品在启动时不再检查许可证密钥,而是检查激活数据,这需要计算机相同才能验证(否则,DATA将不同,数字签名将无法验证)。 请注意,激活数据检查不需要通过 Internet 进行验证:使用已嵌入产品中的公钥来验证激活数据的数字签名就足够了。
好吧,只需从键中删除“1”、“l”、“0”、“o”等冗余字符即可。 将许可证密钥字符串拆分为字符组。
There are many ways to generate license keys, but very few of those ways are truly secure. And it's a pity, because for companies, license keys have almost the same value as real cash.
Ideally, you would want your license keys to have the following properties:
Only your company should be able to generate license keys for your products, even if someone completely reverse engineers your products (which WILL happen, I speak from experience). Obfuscating the algorithm or hiding an encryption key within your software is really out of the question if you are serious about controlling licensing. If your product is successful, someone will make a key generator in a matter of days from release.
A license key should be useable on only one computer (or at least you should be able to control this very tightly)
A license key should be short and easy to type or dictate over the phone. You don't want every customer calling the technical support because they don't understand if the key contains a "l" or a "1". Your support department would thank you for this, and you will have lower costs in this area.
So how do you solve these challenges ?
The answer is simple but technically challenging: digital signatures using public key cryptography. Your license keys should be in fact signed "documents", containing some useful data, signed with your company's private key. The signatures should be part of the license key. The product should validate the license keys with the corresponding public key. This way, even if someone has full access to your product's logic, they cannot generate license keys because they don't have the private key. A license key would look like this: BASE32(CONCAT(DATA, PRIVATE_KEY_ENCRYPTED(HASH(DATA))))
The biggest challenge here is that the classical public key algorithms have large signature sizes. RSA512 has an 1024-bit signature. You don't want your license keys to have hundreds of characters.
One of the most powerful approaches is to use elliptic curve cryptography (with careful implementations to avoid the existing patents). ECC keys are like 6 times shorter than RSA keys, for the same strength. You can further reduce the signature sizes using algorithms like the Schnorr digital signature algorithm (patent expired in 2008 - good :) )
This is achievable by product activation (Windows is a good example). Basically, for a customer with a valid license key, you need to generate some "activation data" which is a signed message embedding the computer's hardware id as the signed data. This is usually done over the internet, but only ONCE: the product sends the license key and the computer hardware id to an activation server, and the activation server sends back the signed message (which can also be made short and easy to dictate over the phone). From that moment on, the product does not check the license key at startup, but the activation data, which needs the computer to be the same in order to validate (otherwise, the DATA would be different and the digital signature would not validate). Note that the activation data checking do not require verification over the Internet: it is sufficient to verify the digital signature of the activation data with the public key already embedded in the product.
Well, just eliminate redundant characters like "1", "l", "0", "o" from your keys. Split the license key string into groups of characters.
答案很简单——无论你使用什么方案,它都可以被破解。
不要用旨在防止黑客的系统来惩罚诚实的客户,因为黑客无论如何都会破解它。
与他们的电子邮件或类似内容相关联的简单散列代码可能就足够了。 当人们需要重新安装或更新硬件时,基于硬件的 ID 总是成为一个问题。
关于这个问题的好线索:
http://discuss .joelonsoftware.com/default.asp?biz.5.82298.34
Simple answer - No matter what scheme you use it can be cracked.
Don't punish honest customers with a system meant to prevent hackers, as hackers will crack it regardless.
A simple hashed code tied to their email or similar is probably good enough. Hardware based IDs always become an issue when people need to reinstall or update hardware.
Good thread on the issue:
http://discuss.joelonsoftware.com/default.asp?biz.5.82298.34
生成密钥时,不要忘记将版本和内部版本号连接到计算哈希值的字符串。 这样就不会有一把钥匙可以解锁您发布的所有内容。
当你发现 astalavista.box.sk 中漂浮着一些密钥或补丁后,你就会知道你成功地让某些东西流行起来足以让有人费心去破解。 麾!
When generating the key, don't forget to concatenate the version and build number to the string you calculate the hash on. That way there won't be a single key that unlocks all everything you ever released.
After you find some keys or patches floating in astalavista.box.sk you'll know that you succeeded in making something popular enough that somebody bothered to crack. Rejoice!
我是 Cryptolens 软件许可平台的开发人员之一,从 14 岁起就一直致力于许可系统的开发。在这个答案中,我根据多年来获得的经验提供了一些提示。
解决此问题的最佳方法是设置一个许可证密钥服务器,应用程序的每个实例都将调用该服务器来验证许可证密钥。
许可证密钥服务器的优点
许可证密钥服务器的优点是:
注意事项
虽然在线验证许可证可以让您更好地控制应用程序的每个实例,但互联网连接并不总是存在(特别是如果您的目标是大型企业),因此我们需要另一种方法来执行许可证密钥验证。
解决方案是始终使用公钥加密系统(例如 RSA 或 ECC)对来自服务器的许可证密钥响应进行签名(如果您计划在嵌入式系统上运行,可能会更好)。 您的应用程序应该仅具有公钥来验证许可证密钥响应。
因此,如果没有互联网连接,您可以使用以前的许可证密钥响应。 确保在响应中存储日期和机器标识符,并检查它是否太旧(例如,您允许用户最多离线 30 天等) )并且许可证密钥响应属于正确的设备。
保护秘密算法
大多数 .NET 应用程序都可以很容易地进行逆向工程(微软提供了一个反汇编程序来获取 IL 代码,一些商业产品甚至可以检索源代码)例如 C#)。 当然,您始终可以混淆代码,但它永远不是 100% 安全的。
在大多数情况下,任何软件许可解决方案的目的都是帮助诚实的人诚实(即愿意付费的诚实用户不要忘记在试用期满后付费等)。
但是,您可能仍然拥有一些您绝对不想泄露给公众的代码(例如预测股票价格的算法等)。 在这种情况下,唯一的方法是创建一个 API 端点,您的应用程序将在每次执行该方法时调用该端点。 它需要互联网连接,但它确保您的秘密代码永远不会被客户端计算机执行。
实现
如果您不想自己实现所有内容,我建议您查看本教程< /a> (Cryptolens 的一部分)
I'm one of the developers behind the Cryptolens software licensing platform and have been working on licensing systems since the age of 14. In this answer, I have included some tips based on experience acquired over the years.
The best way of solving this is by setting up a license key server that each instance of the application will call in order to verify a license key.
Benefits of a license key server
The advantages with a license key server is that:
Considerations
Although verifying licenses online gives you more control over each instance of the application, internet connection is not always present (especially if you target larger enterprises), so we need another way of performing the license key verification.
The solution is to always sign the license key response from the server using a public-key cryptosystem such as RSA or ECC (possibly better if you plan to run on embedded systems). Your application should only have the public key to verify the license key response.
So in case there's no internet connection, you can use the previous license key response instead. Make sure to store both the date and the machine identifier in the response and check that it's not too old (eg. you allow users to be offline at most 30 days, etc) and that the license key response belongs to the correct device.
Protecting secret algorithms
Most .NET applications can be reverse engineered quite easily (there is both a diassembler provided by Microsoft to get the IL code and some commercial products can even retrieve the source code in eg. C#). Of course, you can always obfuscate the code, but it's never 100% secure.
I most cases, the purpose of any software licensing solution is to help honest people being honest (i.e. that honest users who are willing to pay don't forget to pay after a trial expires, etc).
However, you may still have some code that you by no means want to leak out to the public (eg. an algorithm to predict stock prices, etc). In this case, the only way to go is to create an API endpoint that your application will call each time the method should be executed. It requires internet connection but it ensures that your secret code is never executed by the client machine.
Implementation
If you don't want to implement everything yourself, I would recommend to take a look at this tutorial (part of Cryptolens)
除了已经陈述过的内容之外……
由于中间语言问题,.NET 应用程序的任何使用本质上都是脆弱的。 .NET 代码的简单反汇编将向任何人开放您的产品。 那时他们可以轻松绕过您的许可代码。
您甚至不能再使用硬件值来创建密钥。 虚拟机现在允许某人创建“许可”机器的映像并在他们选择的任何平台上运行它。
如果它是昂贵的软件,还有其他解决方案。 如果不是,那么就让普通黑客变得足够困难即可。 并接受这样一个事实:最终将会出现未经许可的副本。
如果您的产品很复杂,固有的支持问题将为您提供一些保护。
Besides what has already been stated....
Any use of .NET applications are inherently breakable because of the intermediate language issues. A simple disassembly of the .NET code will open your product to anyone. They can easily bypass your licensing code at that point.
You can't even use hardware values to create a key anymore. Virtual machines now allow someone to create an image of a 'licensed' machine and run it on any platform they choose.
If it's expensive software there are other solutions. If it's not, just make it difficult enough for the casual hacker. And accept the fact that there will be unlicensed copies out there eventually.
If your product is complicated, the inherent support issues will be create some protection for you.
我们用于生成许可证密钥的 C# / .NET 引擎现在作为开源维护:
https ://github.com/appsoftware/.NET-Licence-Key-Generator。
它基于“部分密钥验证”系统,这意味着只需将用于生成密钥的密钥的子集编译到可分发文件中。 您可以自行创建密钥,因此许可证实施对于您的软件来说是唯一的。
如上所述,如果您的代码可以被反编译,那么绕过大多数许可系统就相对容易。
The C# / .NET engine we use for licence key generation is now maintained as open source:
https://github.com/appsoftware/.NET-Licence-Key-Generator.
It's based on a "Partial Key Verification" system which means only a subset of the key that you use to generate the key has to be compiled into your distributable. You create the keys your self, so the licence implementation is unique to your software.
As stated above, if your code can be decompiled, it's relatively easy to circumvent most licencing systems.
我坚信,只有基于公钥加密的许可系统才是正确的方法,因为您不必将许可证生成所需的基本信息包含到源代码中。
过去,我曾多次使用Treek 的许可库,因为它满足了这一点要求并提供非常优惠的价格。 它对最终用户和自身使用相同的许可证保护,直到现在还没有人破解它。 您还可以在网站上找到避免盗版和破解的好提示。
I strongly believe, that only public key cryptography based licensing system is the right approach here, because you don't have to include essential information required for license generation into your sourcecode.
In the past, I've used Treek's Licensing Library many times, because it fullfills this requirements and offers really good price. It uses the same license protection for end users and itself and noone cracked that until now. You can also find good tips on the website to avoid piracy and cracking.
我不知道你想要多详细,
但我相信.net 可以访问硬盘驱动器序列号。
您可以让程序向您发送该信息和一些其他信息(例如网卡的用户名和 MAC 地址),
您可以根据该信息计算代码,然后通过电子邮件将密钥发回给他们。
他们会阻止他们在拿到钥匙后开关机器。
I don't know how elaborate you want to get
but i believe that .net can access the hard drive serial number.
you could have the program send you that and something eles ( like user name and mac address of the nic)
you compute a code based off that and email them back the key.
they will keep them from switching machines after they have the key.
您可以使用免费的第三方解决方案来为您处理此问题,例如 Quantum-Key.Net 它是免费的,可以通过为您创建的 Web 销售页面通过 PayPal 处理付款,通过电子邮件发放密钥,并将密钥使用锁定到特定计算机防止盗版。
您还应该注意混淆/加密您的代码,否则可以使用 De4dot 和 .NetReflector 等软件轻松对其进行逆向工程。 ConfuserEx 是一个很好的免费代码混淆器,它快速且易于使用,并且比昂贵的替代品更有效。
您应该通过 De4Dot 和 .NetReflector 运行您完成的软件,对其进行逆向工程,看看黑客如果做了同样的事情会看到什么,并确保您没有留下任何暴露或未伪装的重要代码。
您的软件仍然是可破解的,但对于休闲破解者来说,这可能足以让他们望而却步,这些简单的步骤也将防止您的代码被提取和重新使用。
https://quantum-key.net
如何使用 ConfuserEx?
https://github.com/ 0xd4d/de4dot
https://www.red- gateway.com/dynamic/products/dotnet-development/reflector/download
You can use a free third party solution to handle this for you such as Quantum-Key.Net It's free and handles payments via paypal through a web sales page it creates for you, key issuing via email and locks key use to a specific computer to prevent piracy.
Your should also take care to obfuscate/encrypt your code or it can easily be reverse engineered using software such as De4dot and .NetReflector. A good free code obfuscator is ConfuserEx wich is fast and simple to use and more effective than expensive alternatives.
You should run your finished software through De4Dot and .NetReflector to reverse-engineer it and see what a cracker would see if they did the same thing and to make sure you have not left any important code exposed or undisguised.
Your software will still be crackable but for the casual cracker it may well be enough to put them off and these simple steps will also prevent your code being extracted and re-used.
https://quantum-key.net
How to use ConfuserEx?
https://github.com/0xd4d/de4dot
https://www.red-gate.com/dynamic/products/dotnet-development/reflector/download
我已经在我公司的软件 (C# .net) 上实现了基于 Internet 的一次性激活,该软件需要一个许可证密钥,该许可证密钥引用存储在服务器数据库中的许可证。 该软件使用密钥访问服务器,并获得许可证信息,然后使用客户端计算机上的某些变量(CPUID 和其他不会经常更改的内容的组合)生成的 RSA 密钥在本地进行加密,然后将其存储在注册表。
它需要一些服务器端编码,但它对我们来说非常有效,当我们扩展到基于浏览器的软件时,我能够使用相同的系统。 它还为您的销售人员提供有关软件使用人、地点和时间的重要信息。 任何仅在本地处理的许可系统都非常容易受到攻击,尤其是在 .NET 中进行反射。 但是,正如其他人所说,没有一个系统是完全安全的。
在我看来,如果您不使用基于网络的许可,那么保护软件根本没有任何意义。 DRM 可能会带来令人头疼的问题,这对于真正付费的用户来说是不公平的。
I've implemented internet-based one-time activation on my company's software (C# .net) that requires a license key that refers to a license stored in the server's database. The software hits the server with the key and is given license information that is then encrypted locally using an RSA key generated from some variables (a combination of CPUID and other stuff that won't change often) on the client computer and then stores it in the registry.
It requires some server-side coding, but it has worked really well for us and I was able to use the same system when we expanded to browser-based software. It also gives your sales people great info about who, where and when the software is being used. Any licensing system that is only handled locally is fully vulnerable to exploitation, especially with reflection in .NET. But, like everyone else has said, no system is wholly secure.
In my opinion, if you aren't using web-based licensing, there's no real point to protecting the software at all. With the headache that DRM can cause, it's not fair to the users who have actually paid for it to suffer.
完成您所要求的一切的唯一方法是需要互联网访问和服务器验证。 应用程序需要使用密钥登录服务器,然后需要存储会话详细信息,例如 IP 地址。 这将防止密钥在多台不同的机器上使用。 这通常不受应用程序用户的欢迎,除非这是一个非常昂贵且复杂的应用程序,否则不值得。
您可以只拥有应用程序的许可证密钥,然后检查客户端密钥是否良好,但很容易将此密钥分发给其他用户,并且可以使用反编译器生成新密钥。
The only way to do everything you asked for is to require an internet access and verification with a server. The application needs to sign in to the server with the key, and then you need to store the session details, like the IP address. This will prevent the key from being used on several different machines. This is usually not very popular with the users of the application, and unless this is a very expensive and complicated application it's not worth it.
You could just have a license key for the application, and then check client side if the key is good, but it is easy to distribute this key to other users, and with a decompiler new keys can be generated.
我知道这是一个老问题,但当我为我的一个应用程序重写许可流程时,我引用了这个问题。
在阅读了很多意见并依靠过去使用许可证代码的经验后,我想出了这个过程。
您确实不想提供具有相似字母的代码; 当最终用户输入时,它会变得一团糟。像 6 和 G、B 和 8、L、I 和 1 这样的字母。当然,如果您确实需要它们,您可以随时将它们添加回...上面的代码将使用“validChars”中的字符生成类似 xxxx-xxxx-xxxx-xxxx 的许可证。 调用 GetNewCode(4, 4) 将返回类似上面的代码。
我正在使用 Azure 函数来注册然后验证代码。 当我的应用程序注册代码时,它会生成一个加密的哈希值,其中包含安装、设备和/或用户特有的内容。 它提供给注册函数,并与密钥一起存储在 Azure 的数据库中。
验证会重新生成密钥并为其提供许可证代码、IP 地址(在我的情况下不会更改,如果发生更改,则无论如何都需要更新)以及重新生成的哈希,然后如果应用程序是,则 Azure 函数返回领有牌照。 我确实在他们的服务器上存储了一个“临时”密钥,允许应用程序运行一段时间而无需回复。
当然,无论如何,我的应用程序都必须联网才能运行。
因此,最终结果是最终用户输入一个简单的密钥,以及在后端管理许可证的简单过程。 如果需要的话,我还可以使许可证失效。
I know this is an old question, but I referenced this when I was re-writing my licensing process for one of my applications.
After reading a lot of opinions out there and relying on past experience with license codes I came up with this process.
You really don't want to provide a code that has similar letters; it makes for a mess when the end user goes to enter it in. Letters like 6 and G, B and 8, L, I, and 1. Of course if you do want them, you can always add them back in... The above code will generate a license like xxxx-xxxx-xxxx-xxxx using the characters in "validChars". Calling GetNewCode(4, 4) will return a code like above.
I'm using Azure functions to register then validate the code. When my app registers the code, it generates an encrypted hash with things that are unique to the install, device and/or user. That is provided to the registration function and is stored with the key in the DB in Azure.
The validate regenerates the key and provides it with the license code, IP address (which in my case will not change and if it does then it will need to be updated anyway), and the regenerated hash then the Azure function returns if the application is licensed. I do store a "temporary" key on their server that allows the app to run for a period of time without talking back up.
Of course, my app must be on the net for it to work regardless.
So, the end result is a simple key for the end user to type in and an easy process to manage the license on the backend. I can also invalidate a license if need be.
我通过将程序与不和谐服务器连接来解决这个问题,在特定的聊天中检查用户输入的产品密钥是否存在并且仍然有效。 通过这种方式来接收产品密钥,用户将被迫破解discord,这是非常困难的。
I solved it by interfacing my program with a discord server, where it checks in a specific chat if the product key entered by the user exists and is still valid. In this way to receive a product key the user would be forced to hack discord and it is very difficult.