C# 如何生成和验证软件许可证密钥?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/599837/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to generate and validate a software license key?
提问by Riri
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.
我目前正在参与开发一个产品(用 C# 开发),该产品可以免费下载和安装,但版本非常有限。要访问所有功能,用户必须支付许可费并获得密钥。然后将该密钥输入应用程序以“解锁”完整版本。
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").
- 一般是怎么解决的?
- 如何生成密钥以及应用程序如何对其进行验证?
- 我怎样才能避免在 Internet 上发布密钥并被未支付许可证的其他人使用(基本上不是“他们的”密钥)。
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?
在这种情况下我还应该考虑什么?
采纳答案by Brent.Longborough
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:
假设您不想为每个用户进行特殊构建,则:
- Generate yourself a secret key for the product
- Take the user's name
- Concatentate the users name and the secret key and hash with (for example) SHA1
- Unpack the SHA1 hash as an alphanumeric string. This is the individual user's "Product Key"
- Within the program, do the same hash, and compare with the product key. If equal, OK.
- 为自己生成产品的密钥
- 取用户名
- 将用户名和密钥以及哈希与(例如)SHA1 连接起来
- 将 SHA1 哈希解包为字母数字字符串。这是个人用户的“产品密钥”
- 在程序中,做同样的散列,并与产品密钥进行比较。如果相等,OK。
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.
不过,我只是觉得我真的应该提到这一点;如果您打算从中获得其他东西,请注意。
回答by Mitch Wheat
回答by schooner
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.
与他们的电子邮件或类似内容相关联的简单散列代码可能就足够了。当人们需要重新安装或更新硬件时,基于硬件的 ID 总是会成为一个问题。
Good thread on the issue: http://discuss.joelonsoftware.com/default.asp?biz.5.82298.34
关于这个问题的好帖子:http: //discuss.joelonsoftware.com/default.asp?biz.5.82298.34
回答by Marius
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.
完成您所要求的一切的唯一方法是要求访问互联网并使用服务器进行验证。应用程序需要使用密钥登录服务器,然后您需要存储会话详细信息,例如 IP 地址。这将防止密钥在多台不同的机器上使用。这通常不太受应用程序用户的欢迎,除非这是一个非常昂贵和复杂的应用程序,否则不值得。
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.
您可以只拥有应用程序的许可证密钥,然后检查客户端是否密钥良好,但是很容易将此密钥分发给其他用户,并且可以使用反编译器生成新密钥。
回答by shoosh
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.skyou'll know that you succeeded in making something popular enough that somebody bothered to crack. Rejoice!
当您在astalavista.box.sk 中找到一些密钥或补丁后,您就会知道您成功地制作了一些足够受欢迎的东西,以至于有人不屑于破解。麾!
回答by Crash893
I don't know how elaborate you want to get
我不知道你想要多详细
but i believe that .net can access the hard drive serial number.
但我相信 .net 可以访问硬盘序列号。
you could have the program send you that and something eles ( like user name and mac address of the nic)
你可以让程序给你发送一些东西(比如用户名和网卡的mac地址)
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.
拿到钥匙后,他们会阻止他们切换机器。
回答by Crash893
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.
由于中间语言问题,.NET 应用程序的任何使用本质上都是易损坏的。.NET 代码的简单反汇编将向任何人开放您的产品。那时他们可以轻松绕过您的许可代码。
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.
如果您的产品很复杂,那么固有的支持问题将为您提供一些保护。
回答by Catalin S.
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.
只有您的公司应该能够为您的产品生成许可证密钥,即使有人完全对您的产品进行逆向工程(这会发生,我根据经验说)。如果您认真对待控制许可,那么在您的软件中混淆算法或隐藏加密密钥真的是不可能的。如果您的产品成功,那么在发布后几天内就会有人制作密钥生成器。
许可证密钥应该只能在一台计算机上使用(或者至少您应该能够非常严格地控制它)
许可证密钥应该简短且易于通过电话输入或口述。您不希望每个客户都致电技术支持,因为他们不知道密钥是包含“l”还是“1”。您的支持部门会为此感谢您,您将在这方面降低成本。
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.
答案很简单,但在技术上具有挑战性:使用公钥加密的数字签名。您的许可证密钥实际上应该是签名的“文档”,其中包含一些有用的数据,并使用您公司的私钥签名。签名应该是许可证密钥的一部分。产品应使用相应的公钥验证许可证密钥。这样,即使有人可以完全访问您的产品逻辑,他们也无法生成许可证密钥,因为他们没有私钥。许可证密钥看起来像这样: BASE32(CONCAT(DATA, PRIVATE_KEY_ENCRYPTED(HASH(DATA)))) 这里最大的挑战是经典的公钥算法有很大的签名大小。RSA512 具有 1024 位签名。您不希望您的许可证密钥有数百个字符。最强大的方法之一是使用椭圆曲线密码术(谨慎实施以避免现有专利)。ECC 密钥比 RSA 密钥短 6 倍,强度相同。您可以使用 Schnorr 数字签名算法等算法进一步减小签名大小(专利于 2008 年到期 - 好:))
这可以通过产品激活来实现(Windows 就是一个很好的例子)。基本上,对于拥有有效许可证密钥的客户,您需要生成一些“激活数据”,它是嵌入计算机硬件 ID 作为签名数据的签名消息。这通常是通过 Internet 完成的,但只有一次:产品将许可证密钥和计算机硬件 ID 发送到激活服务器,然后激活服务器发回已签名的消息(也可以使消息简短且易于指示)电话)。从那一刻起,产品在启动时不再检查许可证密钥,而是检查激活数据,这需要计算机相同才能验证(否则,DATA 将不同,数字签名将无法验证)。
好吧,只需从您的键中消除诸如“1”、“l”、“0”、“o”之类的冗余字符。将许可证密钥字符串拆分为字符组。
回答by gb2d
The C# / .NET engine we use for licence key generation is now maintained as open source:
我们用于许可证密钥生成的 C#/.NET 引擎现在作为开源维护:
https://github.com/appsoftware/.NET-Licence-Key-Generator.
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.
如上所述,如果您的代码可以反编译,则绕过大多数许可系统相对容易。
回答by jugg1es
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.
我已经在我公司的软件 (C# .net) 上实现了基于 Internet 的一次性激活,该软件需要一个许可证密钥,该许可证密钥是指存储在服务器数据库中的许可证。该软件使用密钥访问服务器并获得许可证信息,然后使用从客户端计算机上的某些变量(CPUID 和其他不会经常更改的东西的组合)生成的 RSA 密钥在本地加密,然后将其存储在注册表。
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.
它需要一些服务器端编码,但它对我们来说效果很好,当我们扩展到基于浏览器的软件时,我能够使用相同的系统。它还为您的销售人员提供有关谁、何地以及何时使用该软件的重要信息。任何仅在本地处理的许可系统都完全容易受到利用,尤其是在 .NET 中的反射。但是,就像其他人所说的那样,没有系统是完全安全的。
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.
在我看来,如果您不使用基于 Web 的许可,那么保护软件根本没有任何意义。由于 DRM 可能引起的头痛,对于实际为此付出代价的用户来说是不公平的。