Why is char[] preferred over String for passwords?
Solution 1
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.
Solution 2
While other suggestions here seem valid, there is one other good reason. With plain String
you have much higher chances of accidentally printing the password to logs, monitors or some other insecure place. char[]
is less vulnerable.
Consider this:
public static void main(String[] args) {
Object pw = "Password";
System.out.println("String: " + pw);
pw = "Password".toCharArray();
System.out.println("Array: " + pw);
}
Prints:
String: Password
Array: [C@5829428e
Solution 3
To quote an official document, the Java Cryptography Architecture guide says this about char[]
vs. String
passwords (about password-based encryption, but this is more generally about passwords of course):
It would seem logical to collect and store the password in an object of type
java.lang.String
. However, here's the caveat:Object
s of typeString
are immutable, i.e., there are no methods defined that allow you to change (overwrite) or zero out the contents of aString
after usage. This feature makesString
objects unsuitable for storing security sensitive information such as user passwords. You should always collect and store security sensitive information in achar
array instead.
Guideline 2-2 of the Secure Coding Guidelines for the Java Programming Language, Version 4.0 also says something similar (although it is originally in the context of logging):
Guideline 2-2: Do not log highly sensitive information
Some information, such as Social Security numbers (SSNs) and passwords, is highly sensitive. This information should not be kept for longer than necessary nor where it may be seen, even by administrators. For instance, it should not be sent to log files and its presence should not be detectable through searches. Some transient data may be kept in mutable data structures, such as char arrays, and cleared immediately after use. Clearing data structures has reduced effectiveness on typical Java runtime systems as objects are moved in memory transparently to the programmer.
This guideline also has implications for implementation and use of lower-level libraries that do not have semantic knowledge of the data they are dealing with. As an example, a low-level string parsing library may log the text it works on. An application may parse an SSN with the library. This creates a situation where the SSNs are available to administrators with access to the log files.
Solution 4
Character arrays (char[]
) can be cleared after use by setting each character to zero and Strings not. If someone can somehow see the memory image, they can see a password in plain text if Strings are used, but if char[]
is used, after purging data with 0's, the password is secure.
Solution 5
Some people believe that you have to overwrite the memory used to store the password once you no longer need it. This reduces the time window an attacker has to read the password from your system and completely ignores the fact that the attacker already needs enough access to hijack the JVM memory to do this. An attacker with that much access can catch your key events making this completely useless (AFAIK, so please correct me if I am wrong).
Update
Thanks to the comments I have to update my answer. Apparently there are two cases where this can add a (very) minor security improvement as it reduces the time a password could land on the hard drive. Still I think it's overkill for most use cases.
- Your target system may be badly configured or you have to assume it is and you have to be paranoid about core dumps (can be valid if the systems are not managed by an administrator).
- Your software has to be overly paranoid to prevent data leaks with the attacker gaining access to the hardware - using things like TrueCrypt (discontinued), VeraCrypt, or CipherShed.
If possible, disabling core dumps and the swap file would take care of both problems. However, they would require administrator rights and may reduce functionality (less memory to use) and pulling RAM from a running system would still be a valid concern.
Comments
-
Ahamed almost 2 years
In Swing, the password field has a
getPassword()
(returnschar[]
) method instead of the usualgetText()
(returnsString
) method. Similarly, I have come across a suggestion not to useString
to handle passwords.Why does
String
pose a threat to security when it comes to passwords? It feels inconvenient to usechar[]
. -
Joachim Sauer over 12 yearsI'd replace "completely useless" with "just a minor security improvement". For example you could get access to a memory dump if you happen to have read access to a tmp directory, a badly configured machine and a crash in your application. In that case you wouldn't be able to install a keylogger, but you could analyze the core dump.
-
Dan Is Fiddling By Firelight over 12 yearsWiping unencrypted data from memory as soon as you're done with it is considered a best practice not because it's foolproof (it's not); but because it reduces your threat exposure level. Real time attacks aren't prevented by doing this; but because it serves a a damage mitigation tool by significantly reduces the amount of data that is exposed in a retroactive attack on a memory snapshot (eg a copy of your apps memory that was written to a swap file, or that was read out of memory yanked from a running server and moved to a different one before its state failed).
-
Groo over 12 yearsI wouldn't say that the problem is that your references will or will not "escape". It's just that strings will remain unmodified in memory for some additional time, while
char[]
can be modified, and then it's irrelevant whether it's collected or not. And since string interning needs to be done explicitly for non-literals, it's the same like telling that achar[]
can be referenced by a static field. -
kingdango over 12 yearsI tend to agree with the attitude of this response. I'd venture to propose most security breaches of consequence occur at a much higher level of abstraction than the bits in memory. Sure, there are probably scenarios in hyper-secure defense systems where this may be of considerable concern but seriously thinking at this level is overkill for 99% of the applications where .NET or Java are being leveraged (as it related to garbage collection).
-
bestsss over 12 years@voo, but i doubt you'd log via direct writing to stream and concatenation. logging framework would transform the char[] into good output
-
Konrad Garus over 12 years@Thr4wn Default implementation of
toString
isclassname@hashcode
.[C
representschar[]
, the rest is hexadecimal hash code. -
Rolf Rander over 12 yearsmaybe localhost isn't what you want to protect. Maybe you have created a program running on an unsecure client and you need the password for accessing a database. If you don't trust the client and are trying to protect the database, wiping passwords from memory is good advice.
-
josefx over 12 years@RolfRander that is even worse, you should not enter passwords on an untrusted client - use a one time key (not sure this is the right term, a password that only works once and gets locked out after that use).
-
Rolf Rander over 12 yearsmost websites use passwords for login. Your credit card number and security-digits is also a kind of password.
-
josefx over 12 years@RolfRander there is nothing about websites that requires an untrusted client, if the user chooses to use a compromised system then there is nothing that you can do to protect him from the consequences.
-
Rolf Rander over 12 yearsas I said, the point might be protecting the server, not the client. My point with the website-example is that there are lots of services using passwords (for different reasons, although other mechanisms obviously would be more secure. Bottom line being that a scenario where you want to protect the server, won't trust the client and are using passwords, storing passwords in a char[] is a wise choice and this isn't really a far-fetched scenario.
-
josefx over 12 years@RolfRander somehow I get the feeling that you use a single login for all your clients and don't have any security/validation serverside. Its your duty to make sure that a user can't compromise the database (access restrictions and validation serverside) and the users duty to make sure that his account can't be compromised (his password).
-
Bruno over 12 yearsOne way around this is to use an implementation of
PrivateKey
that doesn't actually load its private content in memory: via a PKCS#11 hardware token for example. Perhaps a software implementation of PKCS#11 could take care of cleaning up the memory manually. Perhaps using something like the NSS store (which shares most of its implementation with thePKCS11
store type in Java) is better. TheKeychainStore
(OSX keystore) loads the full content of the private key into itsPrivateKey
instances, but it should not need to. (Not sure what theWINDOWS-MY
KeyStore does on Windows.) -
emboss over 12 years@Bruno Sure, hardware-based tokens do not suffer from this, but what about situations where you are more or less forced to use a software key? Not every deployment has the budget to afford an HSM. Software key stores will at some point have to load the key into memory, so IMO we should at least be given the option to clear the memory at will again.
-
Bruno over 12 yearsAbsolutely, I was just wondering whether some software implementations equivalent to an HSM might behave better in terms of cleaning up the memory. For example, when using client-auth with Safari/OSX, the Safari process never actually sees the private key, the underlying SSL library provided by the OS talks directly to the security daemon which prompts the user for using the key from the keychain. While this is all done in software, a similar separation like this may help if signing is delegated to a different entity (even software based) that would unload or clear the memory better.
-
emboss over 12 years@Bruno: Interesting idea, an additional indirection layer that takes care of clearing the memory would indeed solve this transparently. Writing a PKCS#11 wrapper for the software key store could already do the trick?
-
Rolf Rander over 12 yearsAbsolutely. But for the user to make sure his password isn't compromised, the software handling the password has to take care to reduce the chance that malware (on the client) can pick up passwords from the client application memory. To achieve that, I believe storing the password in a char[] and overwriting this afterwards is good advice.
-
bestsss over 12 yearsthis is exactly the flawed/bogus reference I talk about below Jon's answer, it's a well known source w/ a lot of criticism.
-
user961954 over 11 years@bestass can you please also cite a reference?
-
Tinman over 11 yearsI'd say that of someone understands the thinking behind the char vs sting then they are more likely to be thinking of security when configuring the servers. Not thinking is what usually introduces security holes.
-
SnakeDoc almost 10 years@bestass sorry, but
String
is pretty well understood and how it behaves in the JVM... there are good reasons to usechar[]
in place ofString
when dealing with passwords in a secure manner. -
Peter vdL almost 10 yearsAfter the Heartbleed penetration of server memory, revealing passwords, I would replace the string "just a minor security improvement" with "absolutely essential to not use String for passwords, but use a char [] instead."
-
josefx almost 10 years@PetervdL heartbleed happened because someone got the great idea that reusing memory was cheaper than allocating new (cleared) memory, you cannot reuse a String in Java, just hope that nobody ever gets the idea to put your char[] into a reuse list for better performance.
-
Peter vdL almost 10 yearsYou're missing the point completely, Josefx. The point is that heartbleed allowed remote reading of process memory, which everyone had hitherto thought very unlikely. When combined with the use of Java strings, passwords are easily revealed. Char [] allows the developer to blank out passwords, String does not even give that opportunity. Char [] + heartbleed may be harmful if coder screws up. String + heartbleed == definitely always harmful.
-
josefx almost 10 years@PetervdL heartbleed only allowed reading of a specific reused collection of buffers (used for both security critical data and network I/O without clearing in between - for performance reasons), you cannot combine this with a Java String since they are by design not reuseable. Nor can you read into random memory using Java to get at the contents of a String. The language and design problems that lead to heartbleed are just not possible with Java Strings.
-
josefx almost 10 years@PetervdL then please do not refer the "heartbleed bug in combination with Java Strings" and I am sure most I mentioned in relation to heartbleed was correct, the libreSSL developers got quite detailed on why OpenSSL was a security nightmare. There "may" be a way to use a bug in the JIT to bypass Javas build in range checks or the automatic zeroing of object memory and it "might" be possible for someone to trigger this from a remote location without crashing the JVM, however that has nothing in common with heartbleed, nor would any bug on the JVM be so simple or optimized for exploits.
-
Mohit Kanwar almost 9 yearsBut that could be there in char[] comparison as well, somewhere we would be doing the same in password validation too. so how is char[] better than string?
-
Graph Theory almost 9 yearsYou're absolutely correct, the mistake can be made either way. Knowing about the problem is the most important thing here, considering there's no explicit password-comparison method in Java for either String-based or char[]-based passwords. I'd say the temptation to use compare() for Strings is a good reason to go with char[]. That way you at least have control over how the comparison is done (without extending String, which is a pain imo).
-
DavidS almost 9 years@PetervdL It's not just not "specific" to the Heartbleed bug; it's totally inapplicable. I suggest you don't reference Heartbleed as justification for security measures until you have a better grasp of its nature. Thanks to josefx for shedding light on this often misunderstood issue.
-
mauhiz almost 9 yearsInteresting idea. I would like to point out that this does not transpose to Scala which has a meaningful toString for arrays.
-
chux - Reinstate Monica over 8 yearsBetter to do also something to prevent printing the password's length which we get from
'***********'
. -
Vishy over 8 years@chux you can use a zero width character, though this might be more confusing than useful. Its not possible to change the length of a char array without using Unsafe. ;)
-
Admin over 8 yearsI'd write a
Password
class type for this. It's less obscure, and harder to accidentally pass somewhere. -
Yeti over 8 yearsIf a process has access to memory of your application, then that is already a security breach, right?
-
Jon Skeet over 8 years@Yeti: Yes, but it's not like it's black and white. If they can only get a snapshot of the memory then you want to reduce how much damage that snapshot can do, or reduce the window during which a really serious snapshot can be taken.
-
avgvstvs about 8 yearsThey'll only be GC'd if the JVM in question is > 1.6. Prior to 1.7, all strings were stored in permgen.
-
avgvstvs about 8 yearsNot secure by default. If we're talking a web application, most web containers will pass the password into the
HttpServletRequest
object in plaintext. If the JVM version is 1.6 or lower, it'll be in permgen space. If it's in 1.7, it'll still be readable until it gets collected. (Whenever that is.) -
jamp about 8 yearsBecause of Java 8's String Deduplication, I think doing something like that can be pretty destructive... you may end up clearing other strings in your program that by chance had the same value of the password String. Unlikely, but possible...
-
Vishy about 8 years@jamp Java 9 is expected to have this feature as well as compact string (i.e. using a byte[]]). I don't believe this happens in Java 8.
-
jamp about 8 years@PeterLawrey It must be enabled with a JVM argument, but it is there. Can read about it here: blog.codecentric.de/en/2014/08/…
-
GC_ over 7 yearsWhy would someone assume the char array was going to be cast as an Object? I'm not sure I get why every likes this answer. Suppose you did this: System.out.println("Password".toCharArray());
-
Ted Hopp over 7 yearsA common attack method is to run a process that allocates lots of memory and then scans it for left-over, useful data like passwords. The process doesn't need any magical access to another process's memory space; it just relies on other processes dying without first clearing out sensitive data and the OS also not clearing memory (or page buffers) before making it available to a new process. Clearing out passwords stored in
char[]
locations cuts off that line of attack, something not possible when usingString
. -
Lucky over 7 yearsThis is redundant. This answer is a exact version of the answer written by @SrujanKumarGulla stackoverflow.com/a/14060804/1793718. Please don't copy paste or duplicate the same answer twice.
-
Holger about 7 years@avgvstvs: strings are not automatically moved to the permgen space, that only applies to intern'ed strings. Besides that, the permgen space is also subject to garbage collection, just at a lower rate. The real issue with the permgen space is it’s fixed size, which is exactly the reason why no one should mindlessly call
intern()
on arbitrary strings. But you are right in that theString
instances exist in the first place (until collected) and turning them intochar[]
arrays afterwards doesn’t change it. -
Holger about 7 yearsBesides comparing plaintext passwords isn’t the right thing anyway, the temptation to use
Arrays.equals
forchar[]
is as high as forString.equals
. If anyone cared, there was a dedicated key class encapsulating the actual password and taking care of the issues—oh wait, the real security packages have dedicated key classes, this Q&A is only about a habit outside of them, say, e.g.JPasswordField
, to usechar[]
instead ofString
(where the actual algorithms usebyte[]
anyway). -
Holger about 7 yearsSecurity relevant software should do something like
sleep(secureRandom.nextInt())
before rejecting a login attempt anyway, that’s not only removing the possibility of timing attacks, it also makes counteracts brute force attempts. -
Holger about 7 years@avgvstvs: “all strings were stored in permgen” is just dead wrong. Only interned strings were stored there and if they weren’t originating from string literals referenced by code, they were still garbage collected. Just think about it. If strings were generally never GCed in JVMs prior to 1.7, how could any Java application survive more than a few minutes?
-
avgvstvs about 7 years@Holger This is false. Interned
strings
AND theString
pool (pool of previously used strings) were BOTH stored in Permgen prior to 1.7. Also, See section 5.1: docs.oracle.com/javase/specs/jvms/se6/html/… The JVM always checkedStrings
to see if they were the same reference value, and would callString.intern()
FOR YOU. The result was that every time the JVM detected identical Strings in theconstant_pool
or heap it would move them into permgen. And I worked on several applications with "creeping permgen" until 1.7. It was a real problem. -
avgvstvs about 7 yearsSo to recap: Until 1.7, Strings started in the heap, when they were used they were put into the
constant_pool
which was located IN permgen, and then if a string was used more than once, it would be interned. -
avgvstvs about 7 years@Holger see docs.oracle.com/javase/specs/jvms/se6/html/… "Otherwise, a new instance of class String is created containing the sequence of Unicode characters given by the CONSTANT_String_info structure; that class instance is the result of string literal derivation. Finally, the intern method of the new String instance is invoked." In 1.6, the JVM would call intern for you when it detected identical sequences.
-
Holger about 7 years@avgvstvs: this is relevant to the constant pool entries of a class, describing string literals, only. The constant pool of a class contains, as the name suggests, only constant strings, which obviously must be known at compile time (how could they appear in the class file otherwise). Strings created at runtime, i.e. via
Stringbuilder
or one of the constructors ofString
are not affected. -
Holger about 7 years@avgvstvs: There is no “pool of previously used strings”. You are throwing entirely different things together. There is one runtime string pool containing string literals and explicitly interned string, but no other. And each class has its constant pool containing compile-time constants. These strings are automatically added to the runtime pool, but only these, not every string.
-
Holger about 7 yearsWhy is String-deduplication scary? It only applies when there are at least two strings having the same contents, so what danger would arise from letting these two already identical strings share the same array? Or lets ask the other way round: if there is no string-deduplication, what advantage arises from the fact that both strings have a distinct array (of the same contents)? In either case, there will be an array of that contents being alive at least as long as the longest living String of that contents is alive…
-
Oleg Mikheev about 7 years@Holger anything that's out of your control is a potential risk... for instance if two users have the same password this wonderful feature will store both of them in single char[] making it evident that they are the same, not sure if that's a huge risk but still
-
Holger about 7 yearsIf you have access to the heap memory and both string instances, it doesn’t matter whether the strings point to the same array or to two arrays of the same contents, each is easy to find out. Especially, as it is irrelevant anyway. If you are at this point, you grab both passwords, whether identical or not. The actual error lies in using plaintext passwords instead of salted hashes.
-
Oleg Mikheev about 7 years@Holger to verify password it has to be in clear text in memory for some time, 10ms, even if it's just to create a salted hash out of it. Then, if it happens that there are two identical passwords kept in memory even for 10 ms, deduplication may come into play. If it really interns strings they are kept in memory for much longer time. System that doesn't restart for months will collect lots of these. Just theorizing.
-
avgvstvs about 7 years@Holger, you are correct I conflated constant pool and string pool, but it is also false that permgen space only applied to interned strings. Prior to 1.7, both the constant_pool and the string_pool resided in permgen space. That means the only class of Strings that were allocated to the heap were as you said,
new String()
orStringBuilder.toString()
I managed applications with lots of string constants, and we had lots of permgen creep as a result. Until 1.7. -
Holger about 7 years@avgvstvs: well, string constants are, as the JLS mandates, always interned, hence the statement that interned strings ended up in the permgen space, applied to string constants implicitly. The only difference is that string constants were created in the permgen space in the first place, whereas calling
intern()
on an arbitrary string could cause the allocation of an equivalent string in the permgen space. The latter could get GC’ed, if there was no literal string of the same contents sharing that object… -
Holger about 7 yearsIt seems, you have a fundamental misunderstanding about String Deduplication. It doesn’t “intern strings”, all it does, is letting strings with the same contents point to the same array, which actually reduces the number of array instances containing the plaintext password, as all but one array instance can be reclaimed and overwritten by other objects immediately. These strings are still collected like any other string. Maybe it helps, if you understand that the de-duplication is actually done by the garbage collector, for strings that have survived multiple GC cycles only.
-
Gavin S. Yancey almost 7 yearsGiven that Java's hashcode implementation for arrays is not a secure hash, an attacker who found
[C@5829428e
in a logfile could likely bruteforce the password it came from anyways, so this provides a negligible security benefit. -
Octavia Togami almost 7 years@g.rocket The hashcode for an array does not depend on the contents of the array, it is effectively random: Online Example
-
Vaibhav_Sharma almost 7 yearsWhat is the difference between 1.) System.out.println("Character password: " + charPassword); and 2.) System.out.println(charPassword); Because it is giving the same "unknown" as output.
-
Pritam Banerjee over 6 years@fallenidol Not at all. Read carefully and you will find the differences.
-
Joshua Taylor about 6 yearsNeat to note, though, that some information about the string is still leaked (if memory can be inspected): the length of the password. With a C style string, we could just have a buffer of memory and once it's nulled out, we don't know how long the original string was. With the
char[]
in Java, we do. If an attacker can see memory, and sees that getPassword() returns achar[1]
, that indicates a much easier brute force target than one that returns achar[16]
. -
ACV about 6 yearsThis is not the reason why
char[]
is recommended instead ofString
-
ACV about 6 yearsThere is yet another case - when the JVM crashes and produces a memory dump.
-
Dawesi almost 6 yearsisn't password in memory as a string from the form post?
-
Dawesi almost 6 yearsWhy is a password stored unencrypted in the first place? It is received in memory from a request (stored in memory as string??) then immediately should be hashed, compared and discarded, or if for another system should be obtained from an external vault already encrypted then decrypted on use using a rotated key? Am I missing something here, trying to get my head around this?
-
Dawesi almost 6 yearsonce again though the password is passed as a string from the browser to the request as 'string' not char? so no matter what you do it's a string, at which point it should be acted on and discarded, never stored in memory?
-
Dawesi almost 6 yearsWhy would you store the password in in memory? external system? web or api request submits a string (ironically), so it's in memory anyway at that point. I'd never store the login password in another variable (other than the readonly one it's sent to the server with) unencrypted for any reason? Should web requests convert letters to their char number equiv to submit so the request variable is a number? As there is no char datatype from the browser?
-
Yugerten over 5 yearsch = null; you can't do this
-
Stefan L over 5 yearsAnd for completeness let's not forget the more recent meltdown and spectre attacks: meltdownattack.com which could be exploited via a web browser or shared hosting environment.
-
luis.espinal over 5 yearsThe password might not be stored unencrypted - in fact, what's stored is a securely encrypted and hashed sequence of bytes generated from a password that has been 1) nonced, 2) salted, and 3) lengthened. Let's call that byte sequence C. However, somewhere along the line, a plaintext might be handled to salt/nonce/lengthen then encrypt to compare with C. So the best approach is to always assume that passwordy-looking thingie we are about to hold is plaintext and store it as ephemerally as possible.
-
luis.espinal over 5 years@Dawesi -
At which point
- that's application specific, but the general rule is to do so as soon as you get a hold of something that is supposed to be a password (plaintext or otherwise). You get it from the browser as part of an HTTP request, for instance. You cannot control the delivery, but you can control your own storage, so as soon as you get it, put it in a char[], do what you need to do with it, then set all to '0' and let the gc reclaim it. -
Brent Bradburn over 4 years"are Spring Security guys incompetent": It's an important question in this context. I previously wondered this myself, when looking into the differences between
BCrypt
andBCryptPasswordEncoder
. Even in the simultaneous initial commit they took an inconsistent approach: takingString
forBcrypt
and takingCharSequence
forBCryptPasswordEncoder
(which callsBcrypt
). -
skomisa over 4 years@Lucky Unfortunately the older answer you linked to was plagiarized from the same blog as this answer, and has now been deleted. See meta.stackoverflow.com/questions/389144/… . This answer has simply cut and pasted from that same blog and added nothing, so it should have simply been a comment linking to the original source.
-
Tvde1 over 4 yearsBut doesn't
request.getPassword()
already create the string and add it to the pool? -
Holger over 4 yearsThere’s a high chance that the password still is in
Scanner
’s internal buffer and, since you didn’t useSystem.console().readPassword()
, in readable form in the console window. But for most practical use cases, the duration ofusePassword
’s execution is the actual problem. E.g., when making a connection to another machine, it takes a significant time and tells an attacker that it is the right time to search for the password in the heap. The only solution is to prevent attackers from reading the heap memory… -
Holger over 4 years
ch = '0'
changes the local variablech
; it has no effect on the array. And your example is pointless anyway, you start with a string instance you calltoCharArray()
on, creating a new array and even when you overwrite the new array correctly, it doesn’t change the string instance, so it has no advantage over just using the string instance. -
ACV over 4 years@Holger thanks. Corrected the char array cleanup code.
-
Holger over 4 yearsYou can simply use
Arrays.fill(pass, '0');
-
Mikko Rantalainen about 4 yearsIf OS does not clear memory before giving it to another process, the OS has major security issues! However, technically the clearing is often done with protected mode tricks and if the CPU is broken (e.g. Intel Meldown) it's still possible to read old memory contents.
-
Mikko Rantalainen about 4 yearsIf your program ever logs stack traces with function arguments, any parameter may be leaked as text.
-
Prateek Pande over 3 yearsIf using strings, password could also be there in the literal pool and can't be cleared manually.
-
Jon Skeet over 3 years@PrateekPande: It would only be in the literal pool if it were present in the source code, or explicitly interned. Those are both bad ideas in general...
-
Holger about 3 years@Prateek Pande a string can’t be cleared anyway, so it doesn’t matter whether it is referenced by the string pool or not. Since being referenced by the pool doesn’t prevent its garbage collection (which would just remove it from the pool), only strings being present as compile-time constant in the code would stay alive as long as the code is active, which should be an obvious problem even without considering how the pool works. As Jon Skeet said, it’s a bad idea in general.
-
Hakanai almost 3 yearsFunny you should say that they take great care to use
char[]
"now", because I'm looking at this nice newConnectionBuilder
class added in JDK 9, and it still haspassword(String)
and no option to passchar[]
at all. It seems that with Java there's a lot of "do what I say, not what I do". -
Hakanai almost 3 yearsWhat if the library you're dealing with already forces you to convert to
String
- is it still better to storechar[]
and create one newString
every time you have to call the library? Or is it better to live with storing the string once and reusing it? The number of so-called "security" libraries which force us to pass the password asString
is way more than I can count. :( -
Jon Skeet almost 3 years@Trejkaz: I don't feel I'm qualified to comment there, I'm afraid :(
-
Turtlefight almost 3 yearsJust a minor sidenote: Even though
char[]
can be cleared, it would still leak the length of the password or whatever was stored in it until it is garbage collected, since arrays can't be resized. (which could be used to greatly reduce the time needed to brute-force the password) -
Aleix over 2 years@Hakanai I would say that if the password
String
instance needs to be generated multiple times during the same execution I would generate it just once, and then pass it and reuse it. The more times you create theString
instance, the more different slots in memory where you could be revealing the password, so higher security dependency on the garbage collector. -
Hakanai over 2 years@Aleix that is my guess also.
-
Vyacheslav Babanin over 2 years"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." String will appear in String pool only if you have explicitly called intern() on it or it is a literal String. Anyway user password cant be a literal String and the usage of intern() method is discouraged, despite String being a password.
-
fatemeakbari over 2 yearscan we use StringBuilder instead of String? is the char[] safer than StringBuilder?
-
Jon Skeet over 2 years@fatemeakbari: I expect
StringBuilder
sometimes copies its data - and in order to get the data out of theStringBuilder
you'd still need to access it char-by-char (to avoid creating a string). Basically the abstraction (which is normally helpful) works against the security concern, where you really want to have as much control as possible. It's possible that it's fine to useStringBuilder
, but just the fact that it's hard to know for sure would worry me. -
JayK about 2 yearschar in Java is a 16 bit value and char arrays are also assumed to be UTF-16 encoded. docs.oracle.com/javase/7/docs/api/java/lang/… If you mean to store strings in different encodings, I think you must use byte arrays instead. To get differently encoded strings, there is String.getBytes.