My concern is that cryptographic keys and secrets that are managed by the garbage collector may be copied and moved around in memory without zeroization.
As a possible solution, is it enough to:
public class Key {
private char[] key;
// ...
protected void finalize() throws Throwable {
try {
for(int k = 0; k < key.length; k++) {
key[k] = '\0';
}
} catch (Exception e) {
//...
} finally {
super.finalize();
}
}
// ...
}
EDIT: Please note that my issue is regarding not only zeroization of the official (referenced) copy of the object, but also any stale copies the garbage collector may have made while it shuffles memory around for space and speed efficiency.
The simplest example is the mark-and-sweep GC, where objects are marked as 'referenced' and then all those objects are copied to another region. The rest are then garbage and so they are collected. When the copy happens, that might leave residual key data that isn't being managed anymore by the garbage collector (because the 'official' data is in the new region).
A litmus test for this would be if you use a key in the crypto module, zeroize the k开发者_开发百科ey, then inspect the entire JVM process space, you should not find that key.
The Java Cryptography Extension Reference Guide advises always using character arrays instead of strings for passwords so that they can be zeroed afterwards. They also provide a code example of how you could implement it.
You best bet is to use allocateDirect
in NIO. On a sane implementation, that should not be moved about. But it'll probably be eligible for paging out to disk (you could poll it, I guess) and hibernation.
So what if the data in memory is not overwritten at a specific time? If you have to worry about an attacker reading your machine's memory, that's the problem, not what he could find there at what time.
What actual attack scenario are you worried about where keys left somwhere in the memory of a JVM could be a serious problem? If an attacker can look at the JVM's memory, he can just as well catch those keys while you're still using them.
And if you're worried about an attacker running as a regular user on the system getting hold of memory discarded by the JVM: AFAIK all modern OSs overwrite newly allocated memory with zeroes.
So I've come to the conclusion, from @jambjo and @james, that there really isn't anything I can do to prevent keys from being copied and becoming unaccounted for.
The best strategy, as a developer, would be to drop the crypto library down into C (or any other non-managed language) and implement your stuff there.
I would be more than willing to accept an answer from someone else if they could come up with a better solution.
精彩评论