How do I protect OAuth keys from a user decompiling my project?
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 fr开发者_如何学编程ee providers for .NET and Java that will do string obfuscation?
There is no good or even half good way to protect keys embedded in a binary that untrusted users can access.
There are reasons to at least put a minimum amount of effort to protect yourself.
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.
Am I over reacting or is this a genuine problem (with a known solution) for desktop apps?
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 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.
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 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).
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.
精彩评论