如何保护 OAuth 密钥免遭用户反编译我的项目?
我正在编写第一个使用 OAuth 的应用程序。这是针对桌面应用程序,而不是网站或移动设备,因为访问二进制文件会更困难,所以我关心如何保护我的应用程序密钥和秘密。我觉得查看编译的文件并找到存储密钥的字符串是很简单的。
我是否反应过度,或者这是桌面应用程序的真正问题(具有已知的解决方案)?
该项目是用 Java 编写的,但我也是一名 C# 开发人员,因此任何针对 .NET 的解决方案也将受到赞赏。
编辑: 我知道没有完美的解决方案,我只是在寻找缓解方案。
EDIT2:我知道几乎唯一的解决方案是使用某种形式的混淆。是否有任何免费的 .NET 和 Java 提供程序可以进行字符串混淆?
I am writing my first application to use OAuth. This is for a desktop application, not a website or a mobile device where it would be more difficult to access the binary, so I am concerned on how to protect my application key and secret. I feel it would be trivial to look at the complied file and find the string that stores the key.
Am I over reacting or is this a genuine problem (with a known solution) for desktop apps?
This project is being coded in Java but I am also a C# developer so any solutions for .NET would be appreciated too.
EDIT:
I know there is no perfect solution, I am just looking for mitigating solutions.
EDIT2: I know pretty much only solution is use some form of obfuscation. Are there any free providers for .NET and Java that will do string obfuscation?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
没有好的甚至半好的方法来保护嵌入在不受信任的用户可以访问的二进制文件中的密钥。
最低限度的努力不会有效果。对于只有几个小时空闲时间的熟练逆向工程师/黑客来说,即使付出最大的努力也无法有效。
如果您不希望 OAuth 密钥被黑客入侵,请不要将它们放入分发给不受信任的用户的代码中。时期。
这是一个真正的问题,没有已知(有效)的解决方案。 Java 中不存在,C# 中不存在,Perl 中不存在,C 中不存在,任何东西都没有。把它想象成物理定律。
您的替代方案是:
强制您的用户使用仅执行加密签名代码的可信平台。 (提示:这对于您的应用程序来说很可能不切实际,因为当前一代 PC 不能以这种方式工作。如果有合适的设备,甚至 TPS 也可能被黑客攻击。)
将您的应用程序转变为服务并在计算机上运行它/ 您控制访问的机器。 (提示:听起来 OAuth 2.0 可能会删除此要求。)
使用一些不需要分发永久密钥的身份验证机制。
让您的用户签署具有法律约束力的合同,不得对您的代码进行逆向工程,如果他们违反合同,则起诉他们。弄清楚哪些用户入侵了您的密钥就靠您的想象力了……(提示:这不会阻止黑客攻击,但如果黑客拥有资产,可能会让您挽回损失。)
顺便说一下,类比论证这是一个巧妙的修辞技巧,但逻辑上并不合理。前门上的物理锁可以阻止人们窃取您的东西(在某种程度上),这一观察结果并不能说明在可执行文件中安全嵌入私人信息的技术可行性。
并且忽略类比论证是不合理的事实,这个特定的类比因以下原因而失败。物理锁并非坚不可摧。你前门上的锁“起作用”,因为必须有人站在你的房子前面,从马路上可以看到,摆弄你的锁一分钟左右……或者用大锤子敲打它。这样做的人冒着被观察并报警的风险。银行金库之所以“工作”,是因为进入它们需要几个小时,而且还有其他警报器、保安等等。相比之下,黑客可以花费几分钟、几小时甚至几天的时间试图破坏您的技术保护措施,而被观察/检测到的风险实际上为零。
There is no good or even half good way to protect keys embedded in a binary that untrusted users can access.
The minimum amount of effort won't be effective. Even the maximum amount of effort won't be effective against a skilled reverse engineer / hacker with just a few hours of spare time.
If you don't want your OAuth keys to be hacked, don't put them in code that you distribute to untrusted users. Period.
It is a genuine problem with no known (effective) solution. Not in Java, not in C#, not in Perl, not in C, not in anything. Think of it as if it was a Law of Physics.
Your alternatives are:
Force your users to use a trusted platform that will only execute crypto signed code. (Hint: this is most likely not practical for your application because current generation PC's don't work this way. And even TPS can be hacked given the right equipment.)
Turn your application into a service and run it on a machine / machines that you control access to. (Hint: it sounds like OAuth 2.0 might remove this requirement.)
Use some authentication mechanism that doesn't require permanent secret keys to be distributed.
Get your users to sign a legally binding contract to not reverse engineer your code, and sue them if they violate the contract. Figuring out which of your users has hacked your keys is left to your imagination ... (Hint: this won't stop hacking, but may allow you to recover damages, if the hacker has assets.)
By the way, argument by analogy is a clever rhetorical trick, but it is not logically sound. The observation that physical locks on front doors stop people stealing your stuff (to some degree) says nothing whatsoever about the technical feasibility of safely embedding private information in executables.
And ignoring the fact that argument by analogy is unsound, this particular analogy breaks down for the following reason. Physical locks are not impenetrable. The lock on your front door "works" because someone has to stand in front of your house visible from the road fiddling with your lock for a minute or so ... or banging it with a big hammer. Someone doing that is taking the risk that he / she will be observed, and the police will be called. Bank vaults "work" because the time required to penetrate them is a number of hours, and there are other alarms, security guards, etc. And so on. By contrast, a hacker can spend minutes, hours, even days trying to break your technical protection measures with effectively zero risk of being observed / detected doing it.
OAuth 不适用于您所描述的情况,即其目的不是向服务器或其他设备验证客户端设备。它的设计目的是允许一台服务器将其资源的访问权限委托给已由第一台服务器信任的另一台服务器进行身份验证的用户。所涉及的秘密旨在在两台服务器上保持安全。
我认为您正在尝试解决不同的问题。如果您试图找到一种方法让服务器验证是否只有您的客户端代码正在访问您的服务器,那么您将面临一项非常艰巨的任务。
OAuth is not designed to be used in the situation you described, i.e. its purpose is not to authenticate a client device to a server or other device. It is designed to allow one server to delegate access to its resources to a user who has been authenticated by another server, which the first server trusts. The secrets involved are intended to be kept secure at the two servers.
I think you're trying to solve a different problem. If you're trying to find a way for the server to verify that it is only your client code that is accessing your server, you're up against a very big task.
编辑:让我说清楚;这不是将密钥安全存储在二进制文件中的解决方案,正如许多其他人提到的那样,没有办法做到这一点。
我所描述的是一种减轻这样做的危险的方法。
/编辑
这只是部分解决方案,但它可以根据您的设置起作用;它在我们大学的内部网络中运作良好。
这个想法是你创建一个只能由计算机访问的服务。
例如,经过身份验证的 WCF 服务,不仅要求您登录(使用存储在可执行文件中的凭据),还要求您传递一个与时间相关的值(例如您为网上银行获得的小工具之一)或特定数据库行的值,或多个选项。
这个想法确实很简单,您无法完全保护凭据,但您可以使它们只是问题的一部分。
我们为一个使用学生数据存储的 Windows 应用程序执行此操作,正如您可以想象的那样,它必须非常安全。
我们的想法是,我们有一个连接提供程序作为服务在某处运行,并且我们有一个心跳系统,每 30 秒左右生成一个新密钥。
获得正确连接信息的唯一方法是向连接提供者进行身份验证并提供当前的与时间相关的心跳。它非常复杂,以至于人类无法坐在那里手动打开连接并提供正确的结果,但其性能足以在我们的内部网络中工作。
当然,有人仍然可以反汇编你的代码,找到你的凭证,破译你的心跳等等;但如果有人有能力并准备好这样做,那么保护您的计算机的唯一方法就是将其从网络上拔下!
希望这能激励您找到某种解决方案!
Edit: Let me be clear; this is not a solution for safely storing your keys in a binary, as many others have mentioned, there is no way of doing this.
What I am describing is a method of mitigating some of the danger of doing so.
/Edit
This is only a partial solution, but it can work depending on your setup; it worked well for us in our university internal network.
The idea is that you make a service that is only likely to be accessed by a computer.
For example, an authenticated WCF service, that not only requires you to log in (using the credentials that are stored in your executable) but also requires you to pass a time dependant value (like one of the gadgets you get for your online banking) or a the value of a specific database row, or a number of options.
The idea is simple really, you cannot totally secure the credentials, but you can make them only part of the problem.
We did this for a windows app that uses a student data store, which as you can imagine, had to be pretty secure.
The idea was that we had a connection provider running as a service somewhere and we had a heartbeat system that generated a new key every 30 seconds or so.
The only way you could get the correct connection information was to authenticate with the connection provider and provide the current time-dependant heartbeat. It was complex enough so that a human couldn't sit there and open a connection by hand and provide the correct results, but was performant enough to work in our internal network.
Of course, someone could still disassemble your code, find your credentials, decipher your heartbeat and so on; but if someone is capable and prepared to go to those lengths, then then only way of securing your machine is unplugging it from the network!
Hope this inspires you to some sort of solution!
Eazfuscator.NET 和其他 .NET 混淆器会进行字符串加密,这使得其他人看到起来稍微不那么简单像 Reflector 这样的反混淆程序中的字符串文字。我说的稍微不那么简单,因为用于加密字符串的密钥仍然存储在您的二进制文件中,因此攻击者仍然可以很容易地解密字符串(只需要找到密钥,然后确定使用哪种加密算法来加密字符串)字符串,并且它们解密了您的字符串文字)。
Eazfuscator.NET and other .NET obfuscators do string encryption, which makes slightly less trivial for someone to see your string literals in a de-obfuscation program like Reflector. I say slightly less trivial because the key used to encrypt the strings is still stored in your binary, so an attacker can still decrypt the strings quite easily (just need to find the key, and then determine which crypto algo is being used to encrypt the strings, and they have your string literals decrypted).
无论平台如何,你所要求的永远都是不可能的。无论您为需要此功能做了什么,都是您的应用程序出了问题。你永远不能相信这样的客户。也许您正在寻找(in)通过模糊实现安全性。
It doesn't matter the platform, what you are asking will always be impossible. Whatever you have done to need this feature is whats wrong with your application. You can never trust a client like this. Perhaps you are looking for (in)Security Through Obscurity.