<

I just announced the new Spring 5 modules in REST With Spring:

>> CHECK OUT THE COURSE

1. Overview

In this article, we’ll explain why we should use char[] array for representing passwords instead of String in Java.

Please note that this tutorial focuses on the ways of manipulating passwords in the memory, not on the actual ways of storing them, which usually is handled in the persistence layer.

We also assume that we can’t control the format of the password (e.g. the password comes from the 3rd party API in the form of the String). Although it’d seem obvious to use object of type java.lang.String for manipulating passwords, it’s recommended by Java team themselves to use char[] instead. 

For instance, if we have a look at the JPasswordField of javax.swing, we can see that the method getText() which returns String is deprecated since Java 2 and is replaced by getPassword() method which returns char[].

So, let’s explore a few strong reasons why that’s the case.

2. Strings are Immutable

Strings in Java are immutable which means that we cannot change them using any high-level APIs. Any change on a String object will produce a new String, keeping the old one in memory.

Therefore, the password stored in a String will be available in memory until Garbage Collector clears it. We cannot control when it happens, but this period can be significantly longer than for regular objects since Strings are kept in a String Pool for re-usability purpose.

Consequently, anyone with access to the memory dump can retrieve the password from memory.

With a char[] array instead of the String, we can explicitly wipe data after we finish with intended work. This way, we’ll ensure that password is removed from memory even before garbage collection takes place.

Let’s now take a look at code snippets, which demonstrate what we’ve just discussed.

First for String:

System.out.print("Original String password value: ");
System.out.println(stringPassword);
System.out.println("Original String password hashCode: "
  + Integer.toHexString(stringPassword.hashCode()));

String newString = "********";
stringPassword.replace(stringPassword, newString);

System.out.print("String password value after trying to replace it: ");
System.out.println(stringPassword);
System.out.println(
  "hashCode after trying to replace the original String: "
  + Integer.toHexString(stringPassword.hashCode()));

The output will be:

Original String password value: password
Original String password hashCode: 4889ba9b
String value after trying to replace it: password
hashCode after trying to replace the original String: 4889ba9b

Now for char[]:

char[] charPassword = new char[]{'p', 'a', 's', 's', 'w', 'o', 'r', 'd'};

System.out.print("Original char password value: ");
System.out.println(charPassword);
System.out.println(
  "Original char password hashCode: " 
  + Integer.toHexString(charPassword.hashCode()));

Arrays.fill(charPassword, '*');

System.out.print("Changed char password value: ");
System.out.println(charPassword);
System.out.println(
  "Changed char password hashCode: " 
  + Integer.toHexString(charPassword.hashCode()));

The output is:

Original char password value: password
Original char password hashCode: 7cc355be
Changed char password value: ********
Changed char password hashCode: 7cc355be

As we can see, after we tried to replace the content of original String, the value remains the same and hashCode() method didn’t return a different value in the same execution of the application, meaning that the original String stayed intact.

And for the char[] array, we were able to change the data in the same object.

3. We Can Accidentally Print Passwords

Another benefit of working with passwords in char[] array is the prevention of accidental logging of the password in consoles, monitors or other more or less insecure places.

Let’s check out the next code:

String passwordString = "password";
char[] passwordArray = new char[]{'p', 'a', 's', 's', 'w', 'o', 'r', 'd'};
System.out.println("Printing String password -> " + passwordString);
System.out.println("Printing char[] password -> " + passwordArray);

With the output:

Printing String password -> password
Printing char[] password -> [[email protected]

We see that the content itself is printed in the first case, while in the second case, the data is not so useful, which makes char[] less vulnerable.

4. Conclusion

In this quick article, we emphasized several reasons why we shouldn’t use Strings for collecting passwords and why we should use char[] arrays instead.

As always, code snippets can be found over on GitHub.

I just announced the new Spring 5 modules in REST With Spring:

>> CHECK OUT THE LESSONS

4
Leave a Reply

avatar
2 Comment threads
2 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
3 Comment authors
Loredana CrusoveanuNoorVictor Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
Victor
Guest
Victor

Why does replace do nothing in the first example? That doesn’t sound like an expected behavior.

Loredana Crusoveanu
Editor

The replace() method doesn’t change the original String – it returns a new String with the replaced values.

For example, if you have:

String s1 = "fun";
String s2 = s1.replace("f","s");

The result is: s1 = “fun”, s2 = “sun”

More info: https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replace(java.lang.CharSequence,%20java.lang.CharSequence)

Noor
Guest

Storing password as character Array is secure but what if I want to send this password as part of a JSON, then this will not work or it has to be converted to string.

Loredana Crusoveanu
Editor

Yes, if you interact with other frameworks/APIs, then you may not have full control over how the passwords are represented.