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.
Related
I'm working on a Groovy application that has to provide users with a link containing encrypted query parameters. Currently we use the AES encryption algorithm with the same IV used for all links. We know this is bad (hence the reason we want to switch), but the reason this was done was to limit the size of the query parameters (including a base64 encoded 16 byte initialization vector with each query parameter makes the links very long). We'd like to switch to a non deterministic algorithm so that we have the required randomness in the query data but don't have to store the IV in the query parameters.
Since we're working with Groovy we can use anything from Java. Having not done much encryption work though I'm not sure which algorithm to start looking into. Ideally we'd want one that's available in Java SE or as a freely usable Java library. Also any links with details on how to implement these algorithms is highly appreciated.
The aim is to not use the same initialization vector twice. If you have something unique in the request that the server know when decrypting, you might use that as the initialization vector.
Otherwise, you could simply use a counter as the initialization vector. Keep a central counter that you increase each time you encrypt something, and put that counter in front of the encrypted data. Then expand this counter to a 16 byte initialization vector.
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.
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.
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.
I implemented Diffie–Hellman key exchange in Java with some large groups from RFC 3526. My output is a fairly large array of bytes. Is it safe to use the first 448 bits (56 bytes) of the output for a blowfish key? Should I transform the bytes in any way, or pick any specific bytes for the key?
From a theoretical point of view, no, it is not safe. Not that I could pinpoint an actual attack; but the output of a Diffie-Hellman key exchange is an element of a group consisting in q elements and offering sqrt(q) security at most. Truncating parts of the encoding of that element does not look like a good idea...
The "proper" way is to use a one-way key derivation function. In simple words, process the Diffie-Hellman output with a good hash function such as SHA-256 and use the hash result as key. Hashing time will be negligible with regards to the Diffie-Hellman step. Java already includes fine implementations of SHA-256 and SHA-512, and if you are after compatibility with very old Java implementations (e.g. the Microsoft JVM which was coming with Internet Explorer 5.5) then you can use an independent Java implementation of SHA-2 such as the one in sphlib. Or possibly reimplement it from the spec (that's not hard): FIPS 180-3 (a PDF file).
If you need more than 128 bits for your key then this means that you are a time-traveler from year 2050 or so; 128 bits are (much) more than enough to protect you for the time being, assuming that you use a proper symmetric encryption scheme.
Speaking of which: Blowfish is not really recommended anymore. It has 64-bit blocks, which implies trouble when the encrypted data length reaches a few gigabytes, a size which is not that big nowadays. You would be better off using a 128-bit block cipher such as the AES. Also, in any serious symmetric encryption system you will need a keyed integrity check. This can be done with a MAC (Message Authentication Code) such as HMAC, itself built over a hash function (then again, easy to implement, and there is a Java implementation in sphlib). Or, even better, use the AES in a combined encryption/MAC mode which will handle the tricky details for you (because using a block cipher properly is not easy); lookup CWC and GCM (both are patent-free; the latter has been approved by NIST).
The solution that you propose depends on whether the most significant bits of a Diffie-Hellman exchange are hard core. There are some small results known that show that the most significant bits are unpredictable, but I'm not aware of a paper that is strong enough to show that your approach is correct.
However, there are several proposals for a key derivation from Diffie-Hellman keys.
E.g. a nice paper is NIST SP 800-135. So far this is only a draft and can be found here. However, it reviews some existing standards. Of course, using a standard is always preferable to develop it yourself.
While Thomas Pornin's proposal looks reasonable it is nonetheless an ad hoc solution. And to be on the safe side you should probably not use it. Rather I'd use something that has been analyzed (e.g. the key derivation scheme use in TLS version 1.2).