Why not encrypt the Java bytecode instead of obfuscate it? - java

Looking at the of effort some oragnizations do to obfuscate Java bytecode to avoid others to decompile it and extract secret information from the code, taking in account the limitations of this practice):
Wouldn't it be feasible to use asymmetric encryption to face this problem? I mean, wouldn't it be possible for Oracle to equip the JVM with a certificate and a ClassLoader capable of decrypt encrypted class files using the private key of this certificate?
Of course, the classes would have been encrypted using the public key of this "unique oracle certificate".
The private key would be inside the JVM.
I suppose that maybe it is not mathematically possible to protect this private key inside the JVM (encrypting it in turn...), and that it would be eventually hacked... is this the case???

If the private key is inside the JVM it will take literally minutes to hackers and crackers to get what that key is using reverse engineering.
Besides, classloader will probably be very slow if it has to use asymmetric encryption every time it needs to load a class.

I suppose that maybe it is not mathematically possible to protect this private key inside the JVM (encrypting it in turn...), and that it would be eventually hacked... is this the case???
Essentially, yes.
If you use symmetric algorithms and store the key in the JVM, it will be trivial to reverse engineer and find those. If you employ obfuscation to hide them, it becomes less trivial, but it can still be done.
With public key crypto, the key doing the decrypting needs to be stored somewhere again. This is essentially a key storage problem and the only difficult to reverse engineer problems are in hardware; even then, they get broken.
My answer on IT security concerning effective DRM protection methods covers this in a little more detail.

In any case, it's impossible to protect private certificate at the client machine (e.g. in JVM). How do you imagine it? If it was a plain text file, obviously it could be extracted. If it was encrypted, the "second level" key would have to be on client machine as well so that JVM could use the private cert for code protection. So you would be able to extract that key, and consequently the private cert, as well.

For the signing scheme to be hard to break, the key needs to be inaccessible.
If you have the complete program this is not hard to extract for a programmer. Any platform which can actually do this, has the key outside of reach for programmers.
You might find this story about getting the private key from an Airport Express interesting: http://mafipulation.org/blagoblig/2011/04/08#shairport

Don't forget that the oracle JVM isn't the only JVM around. every JVM must adhere to a standard (Java Virtual Machine Specification) to ensure a very basic principle of java: "write once, run anywhere". a private key like this would cause the oracle jvm to behave differently than all other implementations

If code is encrypted it must be decrypted at some point. It is a simple tautology. Obfuscation however is in many cases irreversible.

Related

Obfuscation to hide some algorithm

I am working on a java client/server application. Every user must be able to create and modify files (containing some sensitive data) through the client application (marking them with a digital signature) or manually (marking them with a 99.99999% chance wrong signature). The signature does not use client identity, only the content of the file, which mean two distant clients creating the exact same file would end up with two files with the exact same signature).
After doing pros and cons, I ended up thinking about using obfuscation to protect from malicious users than would use reverse-engineering to find the algorithm delivering digital signature for a given file.
But if I've understood it correctly, obfuscation makes code harder to read for human, harder to understand, but my goal is more about hiding the algorithm behind digital signature. Any idea on how to make it:
Hard to read?
Hard to find?
At the moment my idea are:
Using very random names and some useless treatments
Putting it in a random class at a random place and using stuff from random places
Remove comments
Randomize
Also I'm not sure to understand how compiling and reverse engineering work.
When a code is compiled, I ever thought variables were nicknamed in the "method area", and that a reverse engineering would give us back a code with variables named a, b, c... etc. But it appears not to be the case and it makes sense now that I think about it, since reflection is possible in java, am I right on that last part?
To conclude, I'm not sure to understand how this would prevent user to reverse my code (except for variable names' part).
I ended up thinking about using obfuscation to protect from malicious users than would use reverse-engineering to find the algorithm delivering digital signature for a given file.
I think this is misguided for the following reasons.
There are a few well-known cryptographic hashing functions that are understood to be sufficiently secure against reverse engineering, given the current "state of the art" in cryptography. You can read about some of the common ones here:
https://en.wikipedia.org/wiki/Cryptographic_hash_function
You can combine a cryptographic hash function with public key encryption to provide digital signatures that are (should be) secure enough for your use-case. For example:
https://en.wikipedia.org/wiki/Digital_Signature_Algorithm
There are solid implementations of these technologies available for Java. There is no need to implement your own.
Designing and implementing your own digital signature algorithm is unwise. Unless you are an expert in the mathematics of cryptography, your algorithm is likely to have weaknesses that you are unaware of. And you are an expert, you will fully understand the difficulty in creating a strong system.
Obfuscation is not an adequate protection against reverse engineering to extract secrets (such as an algorithm) from code. Indeed, in the case of Java it is little more than a "speed bump" for a skilled hacker.
OK, I'm just struggling to understand how my app will be able to determine that the signature of "a" is equals to some word while a user can't find the same algorithm on the internet to do exactly the same and find the same signature.
You have a point. If the "text" that you are creating a hash for is known to be very short and/or easy to "guess", then it will be feasible to brute-force its hash, assuming that the algorithm is known. (For example, Gravatar's approach of using hashes of email addresses for privacy is flawed, because it is not hard to assemble a list of known email addresses, generate their hashes and store them in a database that can be queried.)
However, once you have gotten beyond a few tens of random bytes of data, or a few tens words of text, brute-force (and rainbow table) attacks become impractical. So, you can can start with your document, add an "envelop" with a timestamp, other identifying information, and (if necessary) some random junk to pad out the source text. Then hash the lot. The other end merely needs to repeat the process and see if they get the same hash.
(There is more stuff you need to do to create a full digital signature ... but read the link above.)
Let's clarify your misconceptions about obfuscation:
You don't do it on your source code. In the java world, if at all you obfuscate the binary delivery, in other words: your class files. Or to be precise: it is mostly about class file obfuscation, there are commercial tools for source code obfuscation.
Obfuscation is still used within the Android realm, but "pure" java shops, it is rarely used these days
And most importantly: "security by obscurity" rarely works.
If you are really serious about running your code at the client side (where you have no control over it), it might be better to do that part in native code, and to deliver machine compiled binaries for that part.

How to clear content of java.security.Key?

when you use sensitive data in Java application, it is often advised to your primitive types - e.g. use char[] instead of String ...
But with cryptography keys we generally need to use java.security.Key objects because that's what JCE providers use. Key is very often very sensitive piece of information and we'd like to be able to minimize the window of possible attack - i.e. create Key object as late as possible , do the encryption/decryption/signing and then as soon as possible clear the object. But Key doesn't provide any method which would facilite this clearing.
Currently we're doing it in a way that we keep the key in byte array and initialize the Key object right before using it, Key immediately falls out of scope to be eligible for garbage collection and we also immediately clear the byte array. But this doesn't seem very elegant ... It also fills creates a dichotomy in our interfaces - some accept byte array, some accept Key objects and it's kind of a mess.
I am aware of the fact that Java doesn't provide any general mechanism to clear objects from memory, but I'm asking if there is something specifically for Keys. Alternatively, is there some other approach to minimize attack window for Keys?
Thanks.
Upgrade to Java 8 where SecretKey and RSAPrivateKey implements Destroyable. However, a quick test shows that this doesn't work for AES keys nor RSA private keys generated locally.
The following code does work, but it fails only after the second init (!) so beware that key information may be cached (AES requires sub-key derivation, so the sub keys may linger on). It may be a good idea to re-init any cipher with a separate (zero) key after use. Furthermore, it does not protect against copying of the data by the VM itself, e.g. during memory compaction after garbage collection.
MyAESKey myAESKey = new MyAESKey(new byte[16]);
Cipher aes = Cipher.getInstance("AES");
aes.init(Cipher.ENCRYPT_MODE, myAESKey);
aes.doFinal("owlstead".getBytes());
myAESKey.destroy();
aes.doFinal("owlstead".getBytes());
aes.init(Cipher.ENCRYPT_MODE, myAESKey);
aes.doFinal("owlstead".getBytes());
where MyAESKey implements both SecretKey and Destroyable. Don't forget to destroy the input to the MyAESKey as well though. You could of course use a similar approach with your own MyDestroyable interface for Java 7 and below.
The only other method that I know of is to use a provider that uses a security token (HSM / TPM / smart card etc.) where the key does not leave the device. In that case the key may not be destroyed either, but it is at least not available.
Providers that use native code (which uses the right kind of memory) may also allow for destruction of key data. But even outside the VM it may be hard to ensure that the key data is not left anywhere in RAM or (swap) disk.

Assistance with Public Key Cryptography

I am trying to make my Server more secure, using public key cryptography. I'm not looking for examples on how this works, I understand it. I need help actually encrypting my strings that i'm sending...
So, currently, I'm simply making a public/private key string by taking the current nano time, and converting it into a hexidecimal string, 20 times. It makes an output like:
8ebe14df8ebe14df8ebe14df8ebe14df8ebe14df8ebe14df8ebe14df8ebe14df8ebe14df8ebe14df8ebe14df8ebe14df8ebe14df8ebe14df8ebe14df8ebe14df8ebe14df8ebe14df8ebe14df8ebe14df
which is fine. But how would i encrypt my message, say "hi", with this key? I've tried converting both into binary, and multiplying them, but then i couldnt un-convert them, because to do that, there have to be spaces in the binary number, but to multiply them, there cant be. can anyone help me?
Thanks in advance!
Also, let me know if you need any more info!
Take a look at this example: http://stilius.net/java/java_ssl.php
Don't try to invent your own cryptographic algorithm, I know that it sounds interesting but it's also not very safe. Try to use already implemented algorithms and protocols. I suggest you to take a look at the link. Though if you do this just for the fun of it then go ahead, if it's for a client or for something that others (than you at least) use then stick to the known protocols.
It's not just an issue of formatting or playing with binary or hexadecimal numbers here. You don't make a public/private key the way you suggested, as it wouldn't have the necessary cryptographic properties that public/private keys usually have. Also, using the current time in nano s is hardly worthy of being used as any kind of an encryption key. If you want to do this in Java, there are libraries that can do public key crypto for you, such as BouncyCastle (http://bouncycastle.org/). It's quite easy to use and implement some amount of cryptographic security into your application with it.

Creative/secure ways to protect data based on a shared secret in Java

I've been experimenting with some basic cryptography techniques in Java (my preferred programming language) and have a simple example that uses modular exponentiation to generate a shared secret between two client pairs.
But, given a shared secret, what are some simple-to-implement (yet secure) methods for actually using this secret to encrypt/decrypt or scramble/unscramble data being sent over the wire?
For example, if I have the String:
"So long, and thanks for all the fish"
And the shared secret (BigInteger):
1110278255331388386297296974141977
How can the String be sent over the wire in a way that allows for the clients to understand each other, while ensuring that without the shared secret, no middle man can interpret it?
I'm not asking for a finished implementation, just ideas or references to algorithms/techniques that can be used. I'm also avoiding relying on existing programs or APIs (like public/private keys) since this is just a side project for my own educational purposes.
There is a standard way of doing what you are after and that is called password-based key derivation. You need to use a secure symmetric encryption algorithm. You can of course go for asymmetric ones like RSA, but with a shared secret, that is redundant.
However, you don't want to use your shared secret directly.
Your shared secret may have an inappropriate size to be used as a key. For example, AES, as a good choice, accepts 128-bit and 256-bit keys and the shared secret may not be a good match.
The key for your symmetric algorithm of choice should be secure enough, which means that it should have a secure level of randomness which your shared secret may lack.
This is exactly the case algorithms like PBKDF2 (password-based key derivation function 2) are invented for. PBKDF2 is already implemented in standard java and you may use it. It generates a secure key with arbitrary size based on a "passphrase", which is simply the shared secret in this case. These family of algorithms have a iteration parameter, which indicates how many times a hash function is applied to derive the key. Make sure to set it to a high number like a few thousand.
I should note though that security (confidentiality and integrity of transmitted data) in this cases relies on your shared secret to be actually secret. I don't know how you are generating it, but you need to make sure that the process is secure. Diffie-Hellman Key Exchange is a good example. If you are not familiar with this, I recommend you to take a look and see what is does to ensure that the process is safe.
As it is already stated in the comments, you don't need to (and also should not) innovate in cryptography for a practical application. You will find anything you need already implemented and proven secure. Take my last sentence with a grain of salt though.

How to use Skipjack (skip32) in Java to randomize sequential integers from a database

Based on a previous question, I am using a sequential integer as a record ID in my database. I want to obfuscate the integer IDs using Skip32. I found a Java implementation but I am uncertain of how to initialize it using the standard JCE APIs. I need to encrypt an integer and decrypt it as necessary. Can anyone show me an example of this?
The code you found belongs to the Cryptix project. You need not just this one file, but you should take the whole package. Take the JCE package, install it as a provider. Then you should be able to use
Cipher c = Cipher.getInstance("SKIPJACK");
But actually, instead of using an unsupported library like Cryptix, using the BouncyCastle library (or parts thereof) might be more recommendable. They have lots of documentation, and a SkipJack-implementation, too.
I'm not sure why you would need to use Skipjack instead of any cipher which comes with your JRE, though - just for the smaller block size?
If I understand right, Skip32 is a separate cipher (working on 4-byte blocks), just build by similar principles like Skipjack (which works on 8-byte blocks). I didn't find any specification of it, only some C and Perl source code, so I doubt there will be some Java implementation available. Have a look at Format-preserving encryption on Wikipedia, or Can you create a strong blockcipher with small blocksize, given a strong blockcipher of conventional blocksize? on Cryptography Stack Exchange, which show other ways of building a small-block cipher from a larger one.
You might find this blog post on secure permutations with block ciphers useful in figuring out how to implement it. Any block cipher with a sufficiently short block size will suffice.

Categories

Resources