vb.net 我的 (WinForms) 应用程序的许可系统。这是否足够安全?(在合理范围内)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15618060/
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
A licensing system for my (WinForms) application. Would this be secure enough? (Within reason)
提问by SolaGratia
I have researched on each element or system that I am willing to implement into a generic software licensing system for my soon-to-be apps (irrelevant, as this should work, or be usable on all of my applications).
我已经研究了我愿意为即将推出的应用程序实施到通用软件许可系统中的每个元素或系统(无关紧要,因为这应该有效,或可用于我的所有应用程序)。
I have created a DLL with my licensing class in it. It is as follows:
我已经创建了一个包含我的许可类的 DLL。如下:
(1)
(1)
I have applied the InternalsVisibleTo()attribute main class (with child classes), which makes all of the internal classes, and their methods, which are declared Friend, visible to external assemblies with the sepcified PublicKey.
我已经应用了InternalsVisibleTo()属性主类(带有子类),它使所有内部类及其声明的方法Friend对具有 sepcified PublicKey 的外部程序集可见。
I have made the reference to the app name, and it's PublicKey. (Both the licensing, and the external assembly, are signed with the same key (.snkfile)
我已经引用了应用程序名称,它是 PublicKey。(许可和外部程序集都使用相同的密钥(.snk文件)签名
(2)
(2)
All (where possible) members, properties etc. are delcared Friendor Privateor just Dim...ed .
所有(如果可能)的成员,属性等等都delcaredFriend或Private或只是Dim......编辑。
(3)
(3)
My licensing class has a Stringvariable; declared:
我的许可类别有一个String变量;声明:
Private Shared _Key As String = "H58N2-00V93"
This variable is the special password, if you will, of my DLL, and is required to access the methods in my DLL.
如果您愿意,这个变量是我的 DLL 的特殊密码,并且需要访问我的 DLL 中的方法。
There is also a Public Stringvariable (let's call it "AccessKey"), which should be initialized with the main class, like so:
还有一个Public String变量(我们称之为“ AccessKey”),它应该用主类初始化,如下所示:
Dim licDLL As New LicensingAssemblyName.LicensingMainClass With {.AccessKey="H58N2-00V93"}
(4)
(4)
Then, I have a Function(let's call it "CheckKey"), which checks whether the Public, initialized variable ("AccessKey" is equal to the pre-defined, Friendkey ("_Key"), whereupon an exception will be thrown, if they are not equal - preventing method from continued/used.
然后,我有一个Function(我们称之为“ CheckKey”),它检查Public初始化变量(“ AccessKey”)是否等于预定义的Friend键(“ _Key”),如果它们不相等,则会抛出异常 -防止方法继续/使用。
(5)
(5)
At each first line of every Sub, Functionetc., I have inserted a call to this function.
在每一行的第一行Sub,Function等等,我都插入了对这个函数的调用。
These are just the 'security' measures I've taken to prevent external assemblies from using my DLL in another app, to perhaps exploit the system or generate keys.
这些只是我为防止外部程序集在另一个应用程序中使用我的 DLL 来利用系统或生成密钥而采取的“安全”措施。
Now for the licensing measures.
现在是许可措施。
(1)
(1)
I have a key generator (very basic), which generates codes upon a given format (Like: "#-$" for a number, a dash, followed by a letter.)
我有一个密钥生成器(非常基本),它根据给定的格式生成代码(例如:“ #-$” 表示数字,破折号,后跟一个字母。)
I have included an encryption class in this program, which uses Rijndaenal, and applies salt.
我在这个程序中包含了一个加密类,它使用Rijndaenal,并应用盐。
I have set the key generator to encrypt each separate key upon generation, then append it to a new line of a file, which we'll call "my_licenses.txt".
我已将密钥生成器设置为在生成时加密每个单独的密钥,然后将其附加到文件的新行中,我们将其称为“ my_licenses.txt”。
I use the same password for each one (obviously). It is quite long, and includes many different characters (if that makes ANY difference). I considered this to be a secure way since I didn't think ANYONE could decrypt a string without the password, until I was told by another programmer, who advised against using plain text encryption as a method to secure these keys. Please help me with this.
我为每个人使用相同的密码(显然)。它很长,包括许多不同的字符(如果这有什么不同的话)。我认为这是一种安全的方式,因为我不认为任何人都可以在没有密码的情况下解密字符串,直到另一位程序员告诉我,他建议不要使用纯文本加密作为保护这些密钥的方法。请帮我解决一下这个。
(2)
(2)
In my licensing DLL, I have a declaration:
在我的许可 DLL 中,我有一个声明:
Friend Shared Function IsKeyValid(ByVal KeyDB As String, ByVal Key As String) As BooleanThis function decrypts each key in the file (the specified database, using the same pass code used when encrypting them in the key generation program).
此函数解密文件中的每个密钥(指定的数据库,使用在密钥生成程序中加密它们时使用的相同密码)。
Then I do a For Each, Nextloop to, determining whether the specified "Key" value equals any in the key 'database', "my_licenses.txt". But here's the catch.
然后我做了For Each,Next环路,确定指定的“是否Key”值等于任何在关键的“数据库”,“ my_licenses.txt”。但问题就在这里。
I have an Functionwhich returns a unique code for the computer it's running on (using hardware IDs etc.). This Functionhelps me protect against the use of the same key on multiple computers (unless I implement a system for allowing this, limited times) and is required as the last 5 characters of the "Key".
我有一个Function返回它运行的计算机的唯一代码(使用硬件 ID 等)。这Function有助于我防止在多台计算机上使用相同的密钥(除非我实现了一个允许这样做的系统,有限的时间)并且需要作为“密钥”的最后 5 个字符。
After checking, this Function returns a value of the result (Trueor False).
检查后,此函数返回结果的值(True或False)。
Finally (phew), each assembly (the licensing one, and any external ones which utilize it) are obfuscated -and likewise signed (all assemblies, with the same key (.snk) file)- by CodePlex's Confuser(A free, and highly recommended obfuscator for .NET).
最后(唷),每个组件(许可之一,并利用它的任何外部的)会被混淆-和同样签署(所有的组件,使用相同的密钥(.SNK)文件) -通过CodePlex上的Confuser(免费,且高度.NET 的推荐混淆器)。
I hope this hasn't been too long/not detailed enough/difficult to understand. (If so, tell me what you don't understand).
我希望这不会太长/不够详细/难以理解。(如果是这样,请告诉我你不明白的地方)。
This is my first post/question of any kind, so be nice. Also thank you for reading.
这是我的第一篇文章/任何类型的问题,所以要友善。也感谢您的阅读。
I hope you can help.
我希望你能帮忙。
And just to confirm, my question is this: Would this system be secure enough to protect against the average hacker?
只是为了确认,我的问题是:这个系统是否足够安全以抵御普通黑客?
P.S. I am only a beginner, so answers for a beginner would be especially appreciated ;)
PS我只是一个初学者,所以初学者的答案将特别感激;)
*UPDATE: I have actually reduced the length of this question, and improved its understandability (believe it or not). So this is the best I can do.
*更新:我实际上减少了这个问题的长度,并提高了它的可理解性(信不信由你)。所以这是我能做的最好的事情。
回答by Nik Bougalis
That's an insane wall of text so you kind of lost me. And, to be honest I stopped reading seriously when I saw you had a hardcoded key inside the binary that you plan to distribute... But there are two questions you ought to ask yourself:
那是一堵疯狂的文字墙,所以你有点失去了我。而且,老实说,当我看到您计划分发的二进制文件中有一个硬编码的密钥时,我就不再认真阅读了……但是您应该问自己两个问题:
Is your application likely to be so successful that there is sufficient demand for it so that people with the appropriate skillset will be inclined to reverse it and release a keygen and/or pirated version?
And wouldn't your time be better spent adding cool featuresto the application instead of licensing code which does nothing to improve the application itself?
您的应用程序是否可能如此成功,以至于对其有足够的需求,从而使具有适当技能的人倾向于逆转它并发布密钥生成器和/或盗版版本?
难道您的时间花在向应用程序添加很酷的功能而不是许可代码上,这对改进应用程序本身没有任何好处,难道不是更好吗?
Don't get me wrong. I'm all for people getting paid for their work and I don't object to people licensing their software; as a matter of fact, one of the projects I worked on was a custom licensing engine which was tracking a little over 100,000 licenses last I checked. But make sure that if you decide to implement licensing that the effort you put into it doesn't exceed the effort you put into the actual software you're licensing.
不要误会我的意思。我完全支持人们为他们的工作获得报酬,我不反对人们许可他们的软件;事实上,我参与的其中一个项目是一个自定义许可引擎,我上次检查时跟踪了超过 100,000 个许可。但是请确保如果您决定实施许可,您投入的精力不会超过您投入到许可的实际软件中的努力。
With all that said, here's what I would do:
综上所述,这就是我要做的:
- Generate a lot of licensing keys (using whatever format you want)
- Hash those keys using something like SHA-256 or SHA-512.
- Create an array (using whatever syntax is appropriate to your language of choice) that contains the key hashes.
- Include the array inside your application.
- 生成大量许可密钥(使用您想要的任何格式)
- 使用 SHA-256 或 SHA-512 之类的方法散列这些密钥。
- 创建一个包含密钥散列的数组(使用适合您选择的语言的任何语法)。
- 将数组包含在您的应用程序中。
With that setup, to verify a license, all you need to do is:
通过该设置,要验证许可证,您需要做的就是:
- Hash the input using the same algorithm as before.
- Iterate the array, comparing it with the result of the hash. If they match, the key is licensed. If they don't, continue.
- If you get to the end of the table the key is not licensed.
- Do not immediately exit the application if the key isn't licensed. Instead set a flag that prevents the use of important commands (e.g. "Save") or set a timer for 60 seconds plus a random number of to exit the application.
- 使用与之前相同的算法对输入进行哈希处理。
- 迭代数组,将它与散列的结果进行比较。如果它们匹配,则密钥被许可。如果他们不这样做,请继续。
- 如果您到达表的末尾,则该密钥未获得许可。
- 如果密钥未获得许可,请不要立即退出应用程序。而是设置一个标志,以防止使用重要命令(例如“保存”)或设置一个计时器 60 秒加上随机数退出应用程序。
Compile and then digitally sign your application with Authenticode. Have the application itself validate the signature to try and discourage casual tampering.
编译并使用 Authenticode 对您的应用程序进行数字签名。让应用程序本身验证签名以尝试阻止随意篡改。
If you are so inclined, you could even encrypt the hashes, although that is unlikely to help against the sort of attack that someone would mount against this scheme.
如果您愿意,您甚至可以对散列进行加密,尽管这不太可能有助于抵御有人针对此方案发起的那种攻击。
To be clear: this is notbulletproof (then again, no licensing mechanism is) and it's possible for someone sufficiently skilled to break it in a number of ways. But it's almost certainly going to be more than good enough for your project.
需要明确的是:这不是万无一失的(再说一次,没有许可机制),并且足够熟练的人有可能以多种方式破解它。但几乎可以肯定,它对您的项目来说已经足够好了。
回答by Sten Petrov
Security doesn't have an absolute value, it has to be measured against the payoff. If your app is holding some nuclear codes I'd say go pay a specialized consultant for this. If you're storing grandma's secret recipes - you're good to go.
安全性没有绝对价值,它必须根据回报来衡量。如果您的应用程序持有一些核代码,我会说为此请一位专业顾问。如果您要储存祖母的秘方,那就可以了。
I read the whole post and it's still not clear what's the purpose of the hard-coded key or how do you manage the individual encryption keys for each license: encryption is not just about how strong an algorithm you use or how long your password is; it's also about how do you hide your passwords, how do you transmit them, what do you do in edge cases (interrupted connection, failed decryption etc) and many other things.
我阅读了整篇文章,但仍然不清楚硬编码密钥的目的是什么,或者您如何管理每个许可证的单独加密密钥:加密不仅仅是您使用的算法的强度或密码的长度;它还涉及如何隐藏密码、如何传输密码、在极端情况下(连接中断、解密失败等)以及许多其他事情。
From the looks of it I'd say you're in the "good to go" category only because your app doesn't sound like a high-profile target to crack and you mostly want to deter the casual cracking attempt from a frustrated developer who doesn't like your licensing scheme (: and the obfuscation alone would deter most when it comes to reverse-engineering your code. I'm not familiar with your code to tell if there's any other, easier ways to bypass licensing, such as the popular method of copying the licensing file itself if it's not tied to the machine or user profile...
从它的外观来看,我会说您属于“可以使用”类别只是因为您的应用程序听起来不像是一个引人注目的破解目标,而且您主要是想阻止沮丧的开发人员的随意破解尝试谁不喜欢您的许可方案(:当涉及到对您的代码进行逆向工程时,仅靠混淆就会最受阻。我不熟悉您的代码,无法判断是否还有其他更简单的方法可以绕过许可,例如如果许可文件与机器或用户配置文件无关,则复制许可文件本身的流行方法......
回答by panpernicek
There are many workarounds online, but only hashing system described here or something based on public key cryptography can be secure enough to serve licensing.
网上有很多变通方法,但只有这里描述的散列系统或基于公钥加密的东西才能足够安全以提供许可。
I personally prefer and use commercial product: http://www.treekslicensinglibrary.com- Treek's Licensing Library. It's cheap, easy to setup and really secure as it uses previously meant public key cryptography to work with license.
我个人更喜欢并使用商业产品:http: //www.treekslicensinglibrary.com- Treek's Licensing Library。它便宜、易于设置且非常安全,因为它使用以前意味着的公钥密码术来处理许可证。
Edit: To compare with hashes of serial numbers - this solution does not require to predefine accepted serial numbers. 1000 hashes in apps = 1000 licenses, for more you need to update your app. Public key cryptography based license systems do not have this disadvantage.
编辑:与序列号的散列进行比较 - 此解决方案不需要预定义接受的序列号。应用程序中的 1000 个哈希值 = 1000 个许可证,更多您需要更新您的应用程序。基于公钥密码的许可证系统没有这个缺点。
回答by Visual Basic Designer TM
You can use a .NET Obfuscate application to secure it. All .NET application may decompile with .NET Reflector, so search in your browser the application to obfuscate .net application. This will work as i know, everyone that want to decompile your application will prevent by the obfuscate
您可以使用 .NET Obfuscate 应用程序来保护它。所有 .NET 应用程序都可能使用 .NET Reflector 进行反编译,因此请在浏览器中搜索应用程序以混淆 .net 应用程序。据我所知,这将起作用,每个想要反编译您的应用程序的人都将通过混淆来阻止

