How do I clear the contents of java.security.Key?

when you are using sensitive data in a Java application it is often recommended to use your primitive types - for example, use char [] instead of String ...

But with crypto keys, we usually have to use java.security.Key objects, because that's what JCE providers use. The key is very often a very sensitive piece of information and we would like to be able to minimize the window of possible attack - i.e. Create a Key object for as long as possible, perform encryption / decryption / signature, and then clear the object as soon as possible, But Key does not provide any method that makes this clearing easier.

We currently do this in such a way that we store the key in a byte array and initialize the Key object right before using it, Key goes out of scope immediately to be eligible for garbage collection, and we also clear the byte array right away, But that doesn't seem very elegant ... It also fills in creates a dichotomy in our interfaces - some take a byte array, some take key objects, and it's kind of a mess.

I am aware that Java does not provide any general mechanism for clearing objects from memory, but I am asking if there is something specifically for Keys. Alternatively, is there another approach to minimize the attack window for keys?

Thank.

+3


source to share


1 answer


Moving to Java 8, where SecretKey

it RSAPrivateKey

implements Destroyable

. However, a quick test shows that this does not work for AES keys and locally generated RSA private keys.

The following code works, but it only fails after the second init (!), So be careful that key information may be cached (AES requires subkey derivation, so additional keys may be delayed). It may be a good idea to restart any cipher with a separate (zero) key after use. In addition, it does not protect the VM itself from copying data, for example. 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 in the MyAESKey

. You can of course use a similar approach with your own interface MyDestroyable

for Java 7 and below.

The only other method I know of is using a vendor that uses a security token (HSM / TPM / smart card, etc.) where the key does not leave the device. In this case, the key also cannot be destroyed, but at least it is not available.

Providers that use their own code (which uses the correct memory type) can also allow key data to be destroyed. But even outside a virtual machine, it can be difficult to ensure that key data does not remain anywhere in the RAM or (swap) disk.

+4


source







All Articles