Digital Signatures and preventing hacking - java

I have developed a system using Digital Signatures
The program is written in Java
Provider = "BC"
SIGNATURE_ALGORITHM = "SHA256withRSA"
Keys
The Client holds the public key
The Server holds the private key
License Generation
Clients request a license from the server
Server decides if they should get a licenses
Creates a signed object and sends it back to the client
I am wondering about easy ways to hack a system like this and what I can do to prevent it.
How can I prevent a user from decompiling my code and inserting their own code? (I am aware of proguard but hear that it can be worked around). I am also a little worried about a user creating a false licensing server and somehow modifying the source code to point to their server (because I will be releasing the licensing and server code to the public).

When dealing with cryptography and security - if it's of any real importance to you - never use anything home-made.
Always use a proper library.
The margin for bugs and mistakes in this field are huge. Your applications security deserves better.

How can I prevent a user from decompiling my code and inserting their own code?
The short answer is that you can't. You can make it harder (e.g. obfuscation) but you simply cannot prevent it. The fact that most computer games are cracked within days of release is evidence of this.
Turning to the rest of your question: the design looks fine. It's hard to prevent a fake licensing server, but maybe it's not going to be a likely attack anyway. The attacker could just remove the license check from the client instead.
As #Yuval points out, rolling your own crypto is a Bad Idea, but you seem to be doing it the right way by using BouncyCastle. Just make sure you always "sign what you mean", that is sign the license itself rather than, say, encrypting the license and signing the encrypted version.
BouncyCastle's lightweight API provides tools for signing arbitrary blobs of data; I'd recommend you use that rather than Java's cumbersome "provider" interface.
You should also take care to ensure the physical security of the private key. If that gets compromised then you're in real trouble. It may be worth thinking about a mechanism for revoking compromised licences and replacing them with new ones.

Related

What is the best way to encrypt a seed?

I've been struggling with a simple problem for hours now. I am working on a desktop application (a wallet) which needs a seed phrase to operate.
Naturally, the seed needs to be encrypted with a password and stored into a config file. I've found Jasypt which enables me to encrypt a String easily but apparently Jaspyt's PBEStringencryptor is supposed to be unsafe/deprecated. Since there's only one password, salting it wouldn't make any sense (would it?).
I've found many other methods on stackoverflock but I keep saying experts showing up and claiming how unsecure method x is.
To sum up my question: since I am only dealing with a single seed phrase, would using Jasypt's Stringencryptor be sufficient or should I use a different method?
The reason you are struggling to find a secure solution is probably that there is no secure solution that works in general.
Let me restate the problem that I think you are trying to solve:
Your application needs a "secret" to operate.
You cannot trust the user. (If you could, then you could in theory get the user to supply the secret each time they use the system.)
You cannot rely on operating system access control to keep the "secret" safe, because of one or more of the following:
the operating system is inadequate or buggy
you don't trust the operators / administrators
you can't be sure that the system hasn't been hacked, or
the system is not physically secured. (If someone can get undetected physical access to the hardware for long enough, they can circumvent OS security.)
Given the above assumptions, there is no secure solution. No matter what your application code does, it is possible for someone with sufficient OS-level privilege (assigned properly, or acquired nefariously) to watch what your code is doing and intercept the secret.
So what is the solution?
If you can assume that the platform is secure and the operators are trusted, there are technical ways to keep the secret secure ... from a non-privileged user.
There are mitigations for some kinds of security attacks. For example, you could use a Hardware Security Module to hold the secret so that it doesn't need to be stored in the file system.
Otherwise ... run the software on your (secure) infrastructure rather than the user's PC or your customer's servers.
seed needs to be encrypted with a password and stored into a config file..
Seems you are correct, the most reasonable way to encrypt the seed would be using some sort of password based encryption (PBE..).
Since there's only one password, salting it wouldn't make any sense (would it?).
you are storing the encrypted seed value itself, so in this case you may be ok with some application-wide static salt
PBEStringencryptor is supposed to be unsafe/deprecated.
would using Jasypt's Stringencryptor be sufficient
I am not aware of Jasyp being unsecure, it depends more on used parameters (any reference?). I usually use pure Java with standard PBKDF2 a few examples. However, Jasyp makes encryption done properly without deeper knowledge. The problem with cryptography is that it's easy to completely break security just using wrong set of parameters or using it wrong way. If you are just starting, using PBEStringencryptor may be safer option.
Someone mentioned using a hardware module (e. g. smartcard, TPM,.. ), could be safer, but less portable
I'am not an Java developer but as per described, what I would do in your case is to use asymmetric encryption of your seed with the desired password before storing it into a config file.
You could use Rivest Shamir Adleman (RSA), Elliptic Curve Cryptography (ECC) to name a few algorithms.
Cheers

Making sure that a malicious apk isn't talking to my server

I'm trying to make sure that someone can't recompile my obfuscated application and then send malicious data to my server. I am doing an SSLed PHP_POST of my application's versionCode and packageName. These POSTED variables are all encrypted via asymmetrical encryption along with signature verification which will be changed per every version upgrade. I have thought of using checksums but those methods are not supported officially by Google and research has shown that they are not error-proof meaning that they could potentially disrupt legitimate users.
On top of all of this is a ban-on-site via IP/Mac Address/IMEI/Serial/Android_ID/etc when something is detected that is 100% not legit.
I understand that nothing could be 100% secured and the difference between a good security and a bad one is the time/money/effort it takes to break a security is valued higher than the item being protected by the security. With this in mind, are there any other methods I could use to protect my application or any ideas I should implement to add onto current security?
On a side-note, how easy is it to decompile/recompile an apk(jar) that's been obfuscated and would it be easier once its been done once? (aka, it doesn't matter how many times I change the key because the application is already compromised and the decompiler can simply look at the same spot where my last key was)
First thing, first, don't do your own crypto. If you are properly(!) doing SSL that is probably enough to protect data in transit against tampering, etc. What you need to do is authenticate your app somehow which is generally tricky, because you need to keep the credentials in the app. There are different ways around that, but currently the standard (and Google-endorsed way) is to use Google Play services to obtain a token and verify it in your server app. Details here: http://android-developers.blogspot.jp/2013/01/verifying-back-end-calls-from-android.html
This not perfect, but is probably better than most non-standard solutions you can come up with.
Decompiling is generally easy, and obfuscation doesn't change much, since it is trivial to find the places where you are calling system APIs (to get MAC addresses, hash, encrypt, etc.)

Securing java runtime data on an untrusted client

I'm not even sure if this is possible, but is it feasible to secure, end-to-end runtime data on an uncontrolled client?
Specifically, is there any functionality in Java to take in encrypted data, process it and send it back out encrypted, all without exposing the data in plaintext to a curious 3rd party that has full access to the client?
Also, I know that code obfuscation is merely an annoyance to a dedicated individual with a decompiler, so I'm assuming for this scenario that the attack party has full source/operating knowledge.
I'm interested in answers either way. If there is no existing functionality, would it be feasible given Java's architecture? If Java can't do it, is there another language/platform that could? I'm fearing this may require special hardware.
To have a chance at doing what you are talking about, you need special hardware. You can't have a secure layer "on top" of an insecure layer. For example, if the attacker has full control over the hardware, he can always compromise the OS running on that host.
The special hardware is called a "Trusted Platform Module," or TPM. This supports remote attestation, which would allow you to verify that a client has not been tampered with. Some parts of the TPM are available on many computers (my Dell laptop, for example). In fact, I think all computers purchased by the US federal government are required to have a TPM. However, most consumers do not enable the TPM, and there's a lot of hostility toward TPM from privacy advocates. I'm also unsure how many machines with a TPM include the remote attestation capability.
Anyway, the bottom line is that you can't give someone a secret, and the key to the secret, and expect it to remain a secret. You have to retain control over the whole stack, top-to-bottom. Trusted Treacherous Computing allows you do do that, even if you don't legally own the hardware in question.
It is fundamentally not possible to be completely secure if the client is not locked down. At some point the bytes will exist in memory, and that memory can be read by hostile applications.
If your goal isn't to make it completely secure but merely inconvenient for the casually curious, then just be sure to not write the data to temporary files or anywhere else that would be trivial to examine.
Not only "can't be done", but "easy to compromise".
Look at 'aspect-oriented programming' and byte-compiler classes. This is normally used for things like inserting database transactions, performance logging, logging statements (so you can drop the calls from the source code and make it a lot cleaner), access control (so you separate the implementation and authorization), etc. There are a lot of extremely useful things you can do if you can quietly wrap one class with another.
But that also means it's trivial to wrap your classes to capture all of the unencrypted messages within your application, encryption keys, etc. I think I can get in even if you do everything in a single long procedure, although it might take a little more effort.

Retrieve bytecode from in-memory to prevent hacking

How can I retrieve the bytecode and make a hash to see if someone has manipulated my bytecode in-memory or on file?
EDIT:
Does signing the binaries protect the code from being modified and executed? As much as I want to protect my users from making sure they are running my software. I would also like to protect the program (server) from being used by a hacked client.
How do I detect from the server side if someone tampered with my client?
So you are trying to prevent some process with the same (or higher) privilege level than your application from manipulating your application?
That's a task that's doomed to fail. Because if you add your security checks, what would prevent the attacker from modifying your isSecure() method by replacing it with a simple return true;?
I think you need to clarify your requirements (at least I'm having trouble understanding what you are looking for).
In security-related areas, you always need to answer two questions, befor you can even start to tackle a problem:
What am I trying to protect?
What capabilities does an attacker have?
In your case, I believe you are trying to protect a Java client's class files from being modified. In that case the answer depends on what the (potential) attacker can do.
If the attacker actually has admin privileges on the machine the client is running on, then there is essentially nothing you can do. As saua above points out, if you cannot trust the the system you're running on, you're doomed.
If the attacker can only modify the class files before they reach the client maching, then signing your JAR files will let your clients detect the manipulation.
Maybe you want to sign your jar files instead?
What you want should be possible via Intrumentation, by adding custom Transformer. See http://java.sun.com/j2se/1.5.0/docs/api/java/lang/instrument/package-summary.html
Custom classloader also does the job, as it gets bytecode when class is defined.
How do i server side detect if someone tampered with my client?
You can not. On the internet nobody knows if you're a dog ;-)
Seriously: the only option server-side for making any assumptions about the client, is in the information sent back over the network. By encrypting the protocol and making it sufficiently hard to reverse-engineer, you can make it hard for an intruder to hack the client, but not impossible.
NGSCB (formerly known as Palladium) is designed to make this more secure, but this has its own set of issues.
You can create your own classloader and do the checking manually, or you can sign your code and let the java runtime do the job for you.
Signing the jars will protect the code from being modified. Signing involves creating a signature based on your private key. The public key is embedded in the jar with these signatures. Java will validate the signatures against your public key and refuse to load modified classes.
A hacked client will be a little harder to prevent. First an attacked would have to reverse engineer your protocol. You could take a step toward preventing this with a java obfuscator, but ultimately the attacker could just watch the wire and reverse engineer the protocol from the traffic. Even if you encrypt the client-server comms (this isn't exactly easy, considering using a protocol that already does it for you ... SSH or HTTPS) you will ultimately still be suceptible to a man-in-the-middle attack.
What exactly are you trying to protect against?
On the client, you can call getResourceAsStream with the path name to the class file in your jar.
That answers one part of your question ("How can i retrieve the bytecode"). Other answers cover the larger issues well.

How to lock compiled Java classes to prevent decompilation?

How do I lock compiled Java classes to prevent decompilation?
I know this must be very well discussed topic on the Internet, but I could not come to any conclusion after referring them.
Many people do suggest obfuscator, but they just do renaming of classes, methods, and fields with tough-to-remember character sequences but what about sensitive constant values?
For example, you have developed the encryption and decryption component based on a password based encryption technique. Now in this case, any average Java person can use JAD to decompile the class file and easily retrieve the password value (defined as constant) as well as salt and in turn can decrypt the data by writing small independent program!
Or should such sensitive components be built in native code (for example, VC++) and call them via JNI?
Some of the more advanced Java bytecode obfuscators do much more than just class name mangling. Zelix KlassMaster, for example, can also scramble your code flow in a way that makes it really hard to follow and works as an excellent code optimizer...
Also many of the obfuscators are also able to scramble your string constants and remove unused code.
Another possible solution (not necessarily excluding the obfuscation) is to use encrypted JAR files and a custom classloader that does the decryption (preferably using native runtime library).
Third (and possibly offering the strongest protection) is to use native ahead of time compilers like GCC or Excelsior JET, for example, that compile your Java code directly to a platform specific native binary.
In any case You've got to remember that as the saying goes in Estonian "Locks are for animals". Meaning that every bit of code is available (loaded into memory) during the runtime and given enough skill, determination and motivation, people can and will decompile, unscramble and hack your code... Your job is simply to make the process as uncomfortable as you can and still keep the thing working...
As long as they have access to both the encrypted data and the software that decrypts it, there is basically no way you can make this completely secure. Ways this has been solved before is to use some form of external black box to handle encryption/decryption, like dongles, remote authentication servers, etc. But even then, given that the user has full access to their own system, this only makes things difficult, not impossible -unless you can tie your product directly to the functionality stored in the "black box", as, say, online gaming servers.
Disclaimer: I am not a security expert.
This sounds like a bad idea: You are letting someone encrypt stuff with a 'hidden' key that you give him. I don't think this can be made secure.
Maybe asymmetrical keys could work:
deploy an encrypted license with a public key to decrypt
let the customer create a new license and send it to you for encryption
send a new license back to the client.
I'm not sure, but I believe the client can actually encrypt the license key with the public key you gave him. You can then decrypt it with your private key and re-encrypt as well.
You could keep a separate public/private key pair per customer to make sure you actually are getting stuff from the right customer - now you are responsible for the keys...
No matter what you do, it can be 'decompiled'. Heck, you can just disassemble it. Or look at a memory dump to find your constants. You see, the computer needs to know them, so your code will need to too.
What to do about this?
Try not to ship the key as a hardcoded constant in your code: Keep it as a per-user setting. Make the user responsible for looking after that key.
#jatanp: or better yet, they can decompile, remove the licensing code, and recompile. With Java, I don't really think there is a proper, hack-proof solution to this problem. Not even an evil little dongle could prevent this with Java.
My own biz managers worry about this, and I think too much. But then again, we sell our application into large corporates who tend to abide by licensing conditions--generally a safe environment thanks to the bean counters and lawyers. The act of decompiling itself can be illegal if your license is written correctly.
So, I have to ask, do you really need hardened protection like you are seeking for your application? What does your customer base look like? (Corporates? Or the teenage gamer masses, where this would be more of an issue?)
If you're looking for a licensing solution, you can check out the TrueLicense API. It's based on the use of asymmetrical keys. However, it doesn't mean your application cannot be cracked. Every application can be cracked with enough effort. What really important is, as Stu answered, figuring out how strong protection you need.
You can use byte-code encryption with no fear.
The fact is that the cited above paper “Cracking Java byte-code encryption” contains a logic fallacy. The main claim of the paper is before running all classes must be decrypted and passed to the ClassLoader.defineClass(...) method. But this is not true.
The assumption missed here is provided that they are running in authentic, or standard, java run-time environment. Nothing can oblige the protected java app not only to launch these classes but even decrypt and pass them to ClassLoader. In other words, if you are in standard JRE you can't intercept defineClass(...) method because the standard java has no API for this purpose, and if you use modified JRE with patched ClassLoader or any other “hacker trick” you can't do it because protected java app will not work at all, and therefore you will have nothing to intercept. And absolutely doesn't matter which “patch finder” is used or which trick is used by hackers. These technical details are a quite different story.
I don't think there exists any effective offline antipiracy method. The videogame industry has tried to find that many times and their programs has always been cracked. The only solution is that the program must be run online connected with your servers, so that you can verify the lincense key, and that there is only one active connecion by the licensee at a time. This is how World of Warcraft or Diablo works. Even tough there are private servers developed for them to bypass the security.
Having said that, I don't believe that mid/large corporations use illegal copied software, because the cost of the license for them is minimal (perhaps, I don't know how much you are goig to charge for your program) compared to the cost of a trial version.
Q: If I encrypt my .class files and use a custom classloader to load and decrypt them on the fly, will this prevent decompilation?
A: The problem of preventing Java byte-code decompilation is almost as old the language itself. Despite a range of obfuscation tools available on the market, novice Java programmers continue to think of new and clever ways to protect their intellectual property. In this Java Q&A installment, I dispel some myths around an idea frequently rehashed in discussion forums.
The extreme ease with which Java .class files can be reconstructed into Java sources that closely resemble the originals has a lot to do with Java byte-code design goals and trade-offs. Among other things, Java byte code was designed for compactness, platform independence, network mobility, and ease of analysis by byte-code interpreters and JIT (just-in-time)/HotSpot dynamic compilers. Arguably, the compiled .class files express the programmer's intent so clearly they could be easier to analyze than the original source code.
Several things can be done, if not to prevent decompilation completely, at least to make it more difficult. For example, as a post-compilation step you could massage the .class data to make the byte code either harder to read when decompiled or harder to decompile into valid Java code (or both). Techniques like performing extreme method name overloading work well for the former, and manipulating control flow to create control structures not possible to represent through Java syntax work well for the latter. The more successful commercial obfuscators use a mix of these and other techniques.
Unfortunately, both approaches must actually change the code the JVM will run, and many users are afraid (rightfully so) that this transformation may add new bugs to their applications. Furthermore, method and field renaming can cause reflection calls to stop working. Changing actual class and package names can break several other Java APIs (JNDI (Java Naming and Directory Interface), URL providers, etc.). In addition to altered names, if the association between class byte-code offsets and source line numbers is altered, recovering the original exception stack traces could become difficult.
Then there is the option of obfuscating the original Java source code. But fundamentally this causes a similar set of problems.
Encrypt, not obfuscate?
Perhaps the above has made you think, "Well, what if instead of manipulating byte code I encrypt all my classes after compilation and decrypt them on the fly inside the JVM (which can be done with a custom classloader)? Then the JVM executes my original byte code and yet there is nothing to decompile or reverse engineer, right?"
Unfortunately, you would be wrong, both in thinking that you were the first to come up with this idea and in thinking that it actually works. And the reason has nothing to do with the strength of your encryption scheme.

Categories