The title is probably a bit misleading. No there will be nothing about how to securely hash and store a password, salt etc. Instead, I wanted to emphasize one little thing that is often missed when implementing password handling, that is which data structure should be used for this purpose.
The obvious choice is of course String. This happens however not to be the best one, as char array will serve the same purpose better. Why? Because of the security.
Java String is immutable. Therefore once created, can't be modified (cleared). There is of course a way to bypass immutability using reflection, but it should never be recommended as String is JVM class and internal (private) implementation can be changed anytime. Even once the reference is abandoned, there is no way to make GC run or actually erase the data (underlying char[]). Well-known Runtime::gc() method is only a request, not a command to JVM. What is more - it's possible that a garbage collection will mark location as empty, without actually erasing the data. On the other hand, char[] can be simply zeroed.
Above is especially important nowadays, once meltdown and spectre attacks have been uncovered. If there is a chance that a malicious process can read the data kept on heap, real programmers are enforced to minimise the risk and shrink window of opportunity for such attacks.
So, how this should be done? Well, I'd personally implement a small class (eg Password) that keeps the data as char[] and provides a dispose method, zeroing internal structure once it's no longer needed. Of course the class should be used right from the API level, so that there is no intermediate String instance keeping the password before it's copied into Password. The only issue is that caller of this class needs to remember to call the method and dispose the password data explicitely. Unfortunately as we all know, Object::finalize() method can't be relied upon, as there is completely no guarantee that such method will be ever called (and even if it does - only by GC!).
The obvious choice is of course String. This happens however not to be the best one, as char array will serve the same purpose better. Why? Because of the security.
Java String is immutable. Therefore once created, can't be modified (cleared). There is of course a way to bypass immutability using reflection, but it should never be recommended as String is JVM class and internal (private) implementation can be changed anytime. Even once the reference is abandoned, there is no way to make GC run or actually erase the data (underlying char[]). Well-known Runtime::gc() method is only a request, not a command to JVM. What is more - it's possible that a garbage collection will mark location as empty, without actually erasing the data. On the other hand, char[] can be simply zeroed.
Above is especially important nowadays, once meltdown and spectre attacks have been uncovered. If there is a chance that a malicious process can read the data kept on heap, real programmers are enforced to minimise the risk and shrink window of opportunity for such attacks.
So, how this should be done? Well, I'd personally implement a small class (eg Password) that keeps the data as char[] and provides a dispose method, zeroing internal structure once it's no longer needed. Of course the class should be used right from the API level, so that there is no intermediate String instance keeping the password before it's copied into Password. The only issue is that caller of this class needs to remember to call the method and dispose the password data explicitely. Unfortunately as we all know, Object::finalize() method can't be relied upon, as there is completely no guarantee that such method will be ever called (and even if it does - only by GC!).
2 komentarze:
How about making this class Autoclosable and finalizing it after try-with-resources is ended?
That's a neat idea as well! However makes you remember that it has to be used in t-w-r clause, which is also "implicit contract". By the way, such stateful class has to throw IllegalStateExc if password is accessed after it was closed (either manually of via t-w-r).
Prześlij komentarz