Why Is Char[] Preferred Over String For Passwords

Why is char[] preferred over String for passwords?

Strings are immutable. That means once you've created the String, if another process can dump memory, there's no way (aside from reflection) you can get rid of the data before garbage collection kicks in.

With an array, you can explicitly wipe the data after you're done with it. You can overwrite the array with anything you like, and the password won't be present anywhere in the system, even before garbage collection.

So yes, this is a security concern - but even using char[] only reduces the window of opportunity for an attacker, and it's only for this specific type of attack.

As noted in the comments, it's possible that arrays being moved by the garbage collector will leave stray copies of the data in memory. I believe this is implementation-specific - the garbage collector may clear all memory as it goes, to avoid this sort of thing. Even if it does, there's still the time during which the char[] contains the actual characters as an attack window.

Why we should not use String for Storing password in Java but can use String for Storing password in C language?

In Java, Strings are immutable, so once you use String to store a password, there is no way that content can be changed because any change will produce new String.
And the String which contains the password, will be available in memory until it got garbage collected. So it will be remain in memory for long duration which might be a security risk.

But, in C language, String is a null terminated character array and you can set all the array elements as blank or zero, therefore the password will not be remain in memory.

Is there any scenario where character array is better than Strings in Java

Character arrays have some slight advantage over plain strings when it comes to storing security sensitive data. There's a lot of resources on that, for example this question: Why is char[] preferred over String for passwords? (with an answer by Jon Skeet himself).

In general it boils down to two things:

  • You have very little influence on how long a String stays in memory. Because of that you might leak sensitive data through a memory dump.
  • Leaking sensitive data accidentally in application logs as clear text is much more likely with plain strings

More reading:

  • Why we read password from console in char array instead of String
  • https://www.codebyamir.com/blog/use-character-arrays-to-store-sensitive-data-java
  • https://www.geeksforgeeks.org/use-char-array-string-storing-passwords-java/amp/
  • https://www.baeldung.com/java-storing-passwords
  • https://javarevisited.blogspot.com/2012/03/why-character-array-is-better-than.html
  • https://javainsider.wordpress.com/2012/12/10/character-array-is-better-than-string-for-storing-password-in-java/amp/

Using char array instead of String

So the reason the security recommendation is to store the password as a character array is because, unlike arrays, Strings are immutable. This basically means once you've created the String it's in memory, even if you overwrote it, until such time that the garbage collection removes it. This means that a another process can dump memory (before the GC runs) and potentially get your password. With Arrays on the other hand you can go and specifically overwrite the array and no other process will be able to get it.

With an array, you can explicitly wipe the data after you're done with it. You can overwrite the array with anything you like, and the password won't be present anywhere in the system, even before garbage collection.

Had a look at org.apache.http.auth.UsernamePasswordCredentials and the UsernamePasswordCredentials only supports String. So potentially I would just store the password as a char array as per your security recommendation and then just convert it to String when calling this class. Then if you that paranoid, dispose the class once your done with it and immediately run the GC (this may run up your memory usage).

Also, if security is such a serious concern then your administrators should look at other alternatives, such as disabling core dumps.

Why we read password from console in char array instead of String

As you said, strings are immutable, meaning that once you've created the string, if another process can dump memory, there's no way (ok, may with reflection) you can get rid of the data before GC kicks in.

With an array, you can explicitly wipe the data after you're done with it: you can overwrite the array with anything you like, and the password won't be present anywhere in the system, even before garbage collection.

For security, is it safe to pass new String(char[]) as an argument for passwords to a method that only accepts string as parameter?

I've read that for passwords, it's more ideal to use char[] since Strings are immutable.

That's not the (whole) reason. The actual reasoning is:

  1. You are using passwords for security.

  2. A bad guy may be able to get a memory dump of a running JVM ... or extract a partial dump from the disk blocks that hold (or held) the JVM's memory pages. That dump may contain passwords in clear text.

  3. To mitigate this, one can (should) overwrite the memory containing the passwords when they are no longer required.

  4. It is hard to overwrite a String since it is immutable.

But if you examine each of those points, there are assumptions that can be questioned.

  1. Passwords are not a good way of implementing security. For high grade security you should be using public/private key or secret key authentication. So either you are talking about passwords that are "less important" to your system ... or you have a bigger problem than the one you are trying to address here.

  2. If the bad guy can read JVM memory or the page file, they are pretty deep into your infrastructure. You are already fatally compromised. Furthermore, if they are in this deep, they can most likely find other ways to steal the passwords; e.g. stealing your SSL Cert's private key and snooping / decoding the encrypted network traffic.

  3. This is only a mitigation:

    • The passwords will be in the clear in the char[] for a period.
    • Before the passwords arrive at your code, they will most likely have been converted to String objects by the servlet stack (or whatever framework you use).
    • Besides, this mitigation is only effective if you do overwrite the content of the char[] in your code after using it.
  4. In fact, if you are really worried about this, it is possible to use reflection to erase a String; i.e. to mutate a String object. In general, this is a dangerous thing to do. For passwords / password checking, this might be acceptable.

In short, I would argue that using char[] instead of String is too expensive to implement in Java .... unless you are prepared to completely re-engineer your web framework. Furthermore, the benefit of doing this debatable, given the other ways that someone with deep access could steal the passwords.


Now to your specific question:

Is it safe to do .add("password", new String(password))

If you consider it to be risky to use a String for a password, then that code doesn't help. In fact, assuming that password is a String you now have two String objects in memory that contain the password text.

  • If the API you are using requires you to provide the password as a String you have a problem.

  • If the source of the password (i.e. how you get it from the user interface, servlet framework, whatever) is a String, you have a problem.

  • Both cases it will be necessary to rework aspects of the code that you are interacting with to solve the problem. This may be difficult.

And:

I know it's probably bad that the web api is just accepting a password as it is instead of accepting a base64 version or whatever.

Base64 won't slow the bad guy down for more than a minute or so. Ditto for any reversible encoding. But I hope that you are insisting that the password only be sent over SSL / TLS secured connections.

Java sensitive data: char[] vs String? What is the point?

It seems to me that it's a security problem in the design of the API of the password provider that it returns a String.

But, if you have to work with that API, converting to char[] immediately means that you aren't preventing the String instance from being GC'd, because you're not holding a reference to it for any longer than is absolutely necessary.

So, it makes sense to use char[] here because you "aren't making it worse".

char[] or StringBuilder for passwords?

No, because when you overflow the char[] used by the StringBuilder, it is replaced by a larger array, but the original array (with part of your password in it) remains in memory until it is garbage-collected.

Why char[] performs better than String ?- Java

In Oracle's JDK a String has four instance-level fields:

  • A character array
  • An integral offset
  • An integral character count
  • An integral hash value

That means that each String introduces an extra object reference (the String itself), and three integers in addition to the character array itself. (The offset and character count are there to allow sharing of the character array among String instances produced through the String#substring() methods, a design choice that some other Java library implementers have eschewed.) Beyond the extra storage cost, there's also one more level of access indirection, not to mention the bounds checking with which the String guards its character array.

If you can get away with allocating and consuming just the basic character array, there's space to be saved there. It's certainly not idiomatic to do so in Java though; judicious comments would be warranted to justify the choice, preferably with mention of evidence from having profiled the difference.



Related Topics



Leave a reply



Submit