Although What is the best way to store password in memory (RAM) in Java? covers the same territory, this question has the aspect of noticing what other people do and wondering why. The question on SO: https://stackoverflow.com/questions/8881291/why-is-char-preferred-over-string-for-passwords is a better duplicate, though that does not work cross-SE-site!
I note that in Java, the String type is immutable and safe, yet using char[] for password handling is pretty common.
Two concrete examples are:
- https://docs.oracle.com/javase/7/docs/api/java/security/KeyStore.html#getKey(java.lang.String,%20char[])
- https://docs.oracle.com/javase/7/docs/api/javax/security/auth/callback/PasswordCallback.html#getPassword()
I mean, look at this code, (taken from the JAAS tutorial) ... mostly avoidable if PasswordCallback#getPassword() would just return a String.
callbackHandler.handle(callbacks);
char[] tmpPassword = ((PasswordCallback)callbacks[1]).getPassword();
if (tmpPassword == null) {
// treat a NULL password as an empty password
tmpPassword = new char[0];
}
password = new char[tmpPassword.length];
System.arraycopy(tmpPassword, 0,
password, 0, tmpPassword.length);
((PasswordCallback)callbacks[1]).clearPassword();
I feel like I'm missing why smart system-programmers go to such trouble (at least, they did in the late 90's, in the infancy of Java). But to me the above hoo-hah just achieves moving the information from one char[] on the heap to another char[] that's presently only on the stack? (I'm not sure enough of my JVM primitive array allocations, to really be sure of this).
Is this:
- just a habit brought across from C/C++ where an improperly terminated string could cause a buffer-overflow
- a way to force programmers to avoid string literals that would be 'interned' by the compiler when testing for 'does the input match the hard-coded-secret' (which isn't going to happen except in throwaway code anyway)
- a strong and reasonable commitment to ensuring that 'insofar as it depends on me', clear-text secrets are kept clear in memory for the absolute shortest amount of time, in case of an attacker with permissions to inspect memory? (That degree of access by an attacker is basically game-over anyway: sure, we can make it just that little bit more hard for them, but really, this is called doubting the integrity of your execution environment, and that's ... a really heavy burden for an application!)
What design force am I not seeing?