We should not use string to store passwords
It seems logical and relatively easier to store a password in a String object than in a character array.Since Strings are immutable in Java if you store the password as plain text it will be available in memory until the Garbage collector clears it and since String is used in the String pool for reusability there is a pretty high chance that it will remain in memory for a long duration, which poses a security threat.
Java APIs also recommend use of char[] array
Java itself recommends using getPassword() method of JPasswordField which returns a char[] and deprecated getText() method which returns password in clear text stating security reason. Its good to follow advice from Java team and adhering to a standard rather than going against it.
Secondly, there’s always a risk of accidentally printing the password to the application logs.
String password = "password";System.out.println(password); // prints password
Why is char[] preferred over String for passwords?
We should always use a character array to collect and store sensitive information. Character arrays are mutable data structures, which can be cleared immediately after use, and the password won’t have any trace left anywhere in the application, even before the garbage collection. So, a character array is less vulnerable than a String, even though it only reduces the attack window for the successful hack and doesn’t eliminate the risk.
public class PasswordStoring { public static void main(String[] args) { char[] password = new char[]{'p', 'a', 's', 's', 'w', 'o', 'r', 'd'}; // its immediately clears the password from memory for (int i = 0; i < password.length; i++) { password[i] = '\0'; } System.out.println(Arrays.toString(password)); } }
Output::
[ , , , , , , , ] // prints nothing
Also, the toString() method of a character array won’t print the contents of the array; its memory address will get printed instead, as shown below:
public class PasswordStoring {public static void main(String[] args) { char[] password = new char[] { 'p', 'a', 's', 's', 'w', 'o', 'r', 'd' }; System.out.println("result: " + password); }}
Output::
result: [C@53d8d10a
Even this is not secure as the password can be still logged in several other ways:
public class PasswordStoring {public static void main(String[] args) { char[] password = new char[] { 'p', 'a', 's', 's', 'w', 'o', 'r', 'd' }; System.out.println(password); System.out.println(Arrays.toString(password)); }}
Output::
password[p, a, s, s, w, o, r, d]
So, we can conclude that a character array is more secure than the String object, even though it also can be exploited. To avoid any leaks, we should always encrypt a password rather than storing it in plain text and clear it from the heap as soon as the user is authenticated.