Why character array is better than String for storing a password in Java was a recent question asked to one of my friends in a java interview. he was interviewing for a Technical lead position and has over 6 years of experience. Both Character array and String can be used to store text data but choosing one over the other is a difficult question if you haven't faced the situation already. But as my friend said any question related to String must have a clue on a special property of Strings like immutability and he used that to convince the interviewer. here we will explore some reasons why should you use char[] for storing passwords than String.
This article is in continuation of my earlier interview question post on String e.g. Why String is immutable in Java or How Substring can cause a memory leak in Java if you haven't read those you may find them interesting.
Here are a few reasons which make sense to believe that character array is a better choice for storing the password in Java than String:
This article is in continuation of my earlier interview question post on String e.g. Why String is immutable in Java or How Substring can cause a memory leak in Java if you haven't read those you may find them interesting.
Here are a few reasons which make sense to believe that character array is a better choice for storing the password in Java than String:
1) 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.
Since anyone who has access to memory dump can find the password in clear text and that's another reason you should always use an encrypted password than plain text. Since Strings are immutable there is no way the contents of Strings can be changed because any change will produce new String, while if you char[] you can still set all his elements as blank or zero. So Storing the password in a character array clearly mitigates security risk of stealing passwords.
Since anyone who has access to memory dump can find the password in clear text and that's another reason you should always use an encrypted password than plain text. Since Strings are immutable there is no way the contents of Strings can be changed because any change will produce new String, while if you char[] you can still set all his elements as blank or zero. So Storing the password in a character array clearly mitigates security risk of stealing passwords.
2) 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.
3) With String there is always a risk of printing plain text in a log file or console but if use Array you won't print contents of the array instead its memory location gets printed. though not a real reason still makes sense.
String strPassword="Unknown";
char[] charPassword= new char[]{'U','n','k','w','o','n'};
System.out.println("String password: " + strPassword);
System.out.println("Character password: " + charPassword);
String password: Unknown
Character password: [C@110b053
char[] charPassword= new char[]{'U','n','k','w','o','n'};
System.out.println("String password: " + strPassword);
System.out.println("Character password: " + charPassword);
String password: Unknown
Character password: [C@110b053
That's all on why character array is a better choice than String for storing passwords in Java. Though using char[] is not just enough you need to erase content to be more secure. I also suggest working with hash'd or encrypted password instead of plain text and clearing it from memory as soon as authentication is completed.
Other Java Interview Questions you may like
25 comments :
Added to the above reasons Class String is also Serializable. So by using character array we also avoid the risk of serializing the password.
well said sarat, Indeed a worth noting point.
Using char[] instead of String for passwords is (IMHO) a bad idea for a few reasons:
1. That's going to massively complicate things. Strings maintain information about character encodings - char[] (obviously) does not. So if you use char[], you have to be very careful to always use the same encoding. This is critical if you support non-US English users (and you should always do that!).
2. If a malicious user gets access to read core dump files in /tmp, it's game over anyways. At that point, it means that not only has a malicious user gained access to your server, but he's also gained either root or application user access - so he's fully compromised the system.
3. char[] are not pinned to RAM. The OS swaps char[] data just as easily as String data, writing it to disk in the swap file.
4. Strings may be immutable, making it more likely that they hang around for a while in memory due to string internment, but char[]'s aren't guaranteed to be removed from memory either due to the uncertainties of garbage collections. You can never be sure any memory is cleared in Java, nor can you tell Java to clear any memory.
Using char[] instead of String makes your code buggier, harder to maintain, harder to write, and only more secure in a totally impractical sense.
Now I am confused between char[] and String to store password ? Which one I should use char[] or String ?
This is awesome. Points noted and very mind blowing. Java needs further reading
There are a few mistakes here. First, there is no real "danger" of a password String being logged, since it would only happen if you explicitly log it.
Second, you can easily print the contents of an array using Arrays.toString(), so if you're afraid your fingers will type logger.info(password), well, they might also accidentally type logger.info(Arrays.toString(password)).
Finally, there is no safety from serialization using an array instead of a String. Yes, it's true that Strings are Serializable; so are arrays.
System.out.println(charPassword);
The above line prints password in clear text.
public class printPwd {
public static void main(String[] args) {
String strPassword = "Unknown";
char[] charPassword = new char[] { 'U', 'n', 'k', 'w', 'o', 'n' };
System.out.println("String password: " + strPassword);
System.out.println("Character password: " + String.valueOf(charPassword));
}
}
surprize output is
String password: Unknown
Character password: Unkwon
Strings don't keep any information about encoding -- they just have a char[], and a char is a unicode code point in utf-16. You can create a String from a byte[] and an encoding, and given a String you can get a byte[] if you give it an encoding -- but the String itself has no encoding other than the utf-16 of its chars.
There is API provided by Java itself to get the characters in an array. Please have a look at below code snippet, there is no use of array over string other in this scenario but memory wise yes it is:
System.out.println("Character password: " + Arrays.toString(charPassword));
Character password: ['U','n','k','w','o','n']
As you said that if someone who have acess to memory dump can know the passwords if it is string form,and in char array it will be known only the address, As he know the memory dump Wont he able to find the passsowrd using that address which he knows.
"String are used in String pool for reusability" is generally not correct in this case.
Only certain types of strings are interned in the permanent generation. Strings created dynamically at runtime, i.e. strings in a HTTP request, are not. Consider this: if every String pulled in a HTTP request was interned, you'd consume all of the permanent gen quickly.
This may be different for nonstandard JVMs, but for the Oracle VM this is correct.
Hi.Can u plz explain us the below code more Clearly.
char[] charPassword = new char[] { 'U', 'n', 'k', 'w', 'o', 'n' };
Character password: [C@110b053
How is this output possible in case of Char Array.??
Why would you store the password in the first place!!! Its a bad design in itself IMHO.
Defer it to authentication system (webserver/ldap etc) or store it's hash or in any other encrypted form.
Then you wouldn't have to care about char[] or String, i personally do not see any threat of using String.
Someone, who can access memory dump, could as well run remote debug / implement code manipulation APIs to view passwords right on screen.
Design your system well.
In reply to Craig points, about the use of char[] being a bad idea, I would reply
1. yes, using char can complicate things, but then a password is just a sequence of characters, so a char array is suitable to store a password.
2 and 3. the char array data could indeed get into a core dump, or be swapped to virtual memory. However, the password will not be accessible in RAM, so it does reduce the risk. Also, by using a char array, you can delete the password data immediately, before the garbage collector removes the array object.
4. True, the char[] array object would hang around in memory until removed by the garbage collector. However, the point is that the data inside the array should be explicitly cleared out, for example
// password data
char [] charPassword = {'s', 'e', 'c', 'r', 'e', 't'};
// empty the password array
Arrays.fill(charPassword, '\0');
Also it is worth noting that the Swing class JPasswordField has deprecated the getText method using String, for security reasons. The new method getPassword instead returns a char array.
The only reason passwords is done in char[] is for performance. You don't get any more secure using char[] as String store all data internally as char[] anyway. You always store the password (in char[]) in encrypted format in memory, you can NEVER get the password from dumping on snooping. The only way to check the password is calling a function that checks and immediately discard the information.
It is true that string store the charactor sequence in a char array but problem with this is it stores this data in the string pool for a very long time if not until the application shut down. This value can be acquired from dump with some effort. Brut force hack become much easier for me if thus memory dump is available with me.
Valid points
Storing the password as plain text, either in char[] or String is bad practice and insecure. You _always_ should use hash, this way the password is never visible in memory.
Authentication tokens in a typical java webapp such as passwords in html forms / http params, authorization headers, or session cookies are always handled with the String type in the servlet api. This discussion is far from reality as long as you do not start rewriting the world.
In earlier Java versions, String is being stored on String pool which makes it vulnurable for accidental changes. Though , this is a very rare case but still a possibility of accidental override.
Have doubt.array allows similar type of data types.then how can it store different types in password?
It is char array, so it can hold alphabet, numbers, etc.
I know this is old, I wanted to point out that you can overwrite char values with something else to erase the actual characters. You can't do that with String in Java. In c, I'd just wipe the memory with null.
It's 2022 and still this question makes sense today. Really good discussion on post as well as on comment sections. Thanks Javarevisited.
Post a Comment