5

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.

qbd
  • 533
  • 1
  • 6
  • 18
  • [Useful post](http://stackoverflow.com/a/15801787/2982225) – Infinite Recursion Sep 03 '14 at 11:22
  • No, there's nothing specifically for keys. Java is not the language to implement software which *requires* secure memory.The best you can do is implement the minimal core functionality in native code and use JNI to access this code. – President James K. Polk Sep 03 '14 at 11:38
  • There's also the risk that key material is copied, so even if you clear your object, it still might be somewhere else in memory. I have looked at this before in Java and was unable to find a way to really guarantee that the key material was wiped. Even if you use JNI, you need fairly good knowledge of the native crypto implementation to guarantee anything. It can be done fairly easily with secure hardware though, and there are also crypto techniques like multi-party computation that mitigate the effects of a compromised client (but that's probably beyond the scope of this question). – Mikkel K. Sep 03 '14 at 11:53

1 Answers1

6

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.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263