What's the best length for randomly generated passwords? (Security vs. compatibility)
If your passwords are n characters randomly drawn, with equal probability, from a set of 95 characters (which is about all the ASCII printable characters minus space), then each character gives you about 6.6 bits of entropy, so the strength of a random password with n characters is 6.6 × n. So:
- A 10 character password gives you about 66-bit strength;
- A 12 character password gives you about 79-bit strength;
- A 14 character password gives you about 92-bit strength;
- A 20 character password gives you about 132-bit strength.
In my judgment, you could sensibly choose any of these lengths depending on the application. For example, if you use a 66-bit password for a low-value online service, your password will still be loads stronger than nearly everybody who uses that service. But if we're talking about a password that's used to derive an encryption key on software that you run on your own hardware, you should certainly consider something stronger.
To add some additional thoughts, it pays to consider two kinds of attack:
- An attack targeted at a website (or other password-protected service) that you've enrolled in;
- An attack against you specifically.
In scenario #1, the password cracker is going to divide their computational power to cracking as many users' passwords as they can, in the hopes of finding the low-hanging fruit—users who have very weak passwords. I believe a 64- to 80-bit password is plenty to defend your passwords against such attacks.
In scenario #2, the attacker is going to dedicate all their computational power to cracking your password specifically. In that case, a powerful adversary might (or might not!) be able to crack a 66-bit password, and you could therefore justify going as far up as 19-20 characters (to match the 128-bit security strength of most ciphers).
And always keep in mind that if your password is strong enough, that just means the #2 attacker is going to probe a different weakness. Don't bother making your password inconveniently strong if you've got big holes elsewhere.
I'm going to differ from the other answers (so far) and suggest that if you're generating a unique random password per website, you don't need a really long password at all.
Lets think about the threats to passwords. We'll look at the server-side alone (i.e. we won't take account of things like keystroke logging malware on your PC as password length doesn't help much there)
So basically attacks, for which password length is relevant, fall into two categories. Online brute-force and offline brute-force.
In online brute-force, the attacker tries to guess your password against the website, so they submit one request per attempt. In reality many sites will lock out after a number of incorrect requests, but for this lets assume they don't
Now assume the attacker can make 1000 guesses per second. If you have (for example) chosen a 8 character random password using Upper, Lower and numeric characters there are 62^8 options. At that rate we're talking heat death of the universe before they guess it.
Now someone could say "what if the attacker gets a botnet to guess it, they can go much faster!", I'd suggest that you'd DoS pretty much any site before you make this fast enough to be practical.
Ok lets talk offline brute-force as it's more relevant to password length. Here the atacker has already got a copy of your password hash, so it's likely they've compromised the security of that site pretty thoroughly. Here you can make an argument that you want the password to last long enough for the site to notice they've been pwned and get you to reset your password.
To say exactly how long is kind of tricky as it very much depends on how the site stores their passwords. If they use unsalted MD5 that's a massive difference than if they're using bcrypt with a high work-factor.
However one thing to consider in all this is impact. What's the impact of this password being cracked. Well if you've used a unique random value for every site, then the impact is likely to be quite limited. you'd hope that your high value sites are all using 2FA so password alone doesn't get the attacker far and the low value sites, well what are the consequences of compromise?
All that analysis doesn't really answer your question, but as a rule of thumb I'd suggest if you're even using 10-12 characters with Upper, Lower and numeric and the passwords are really random (that's the important bit) you're a) likely to be fine and b) unlikely to run into problems with any site restrictions.
Per this article on password cracking a 10-char upper, lower, numeric password would take 83 days for a "Super computer or botnet" to crack. What you've got to ask yourself is, is it likely that an attacker will invest that cost to break a single password where they have already compromised the security of the target site to get the hash....
From my personal ad-hoc use and testing, I've found 20 random characters, using upper/lower/digits plus a few carefully-selected specials (@#$._ not including the parenthesis), to be a nice mix:
- Good length - less likely to be silently truncated (once you get above 20, more sites either start silently truncating -- just as you've seen -- or else they reject them as "too long" - 20 used to be too big for this purpose, but the landscape has shifted in the past few years)
- Very good keyspace size ((26+26+10+5)^20 = 3.32x10^36) - admittedly overkill even for nation-state time-travelers from the near future, but intended to cover almost all potential threat models (including consideration of Moore's Law and nation-state-level resources) for just about everybody, without being unmanageably long
- Meets most naive/legacy complexity requirements (including requiring at least one special character)
- Meets many "non-complexity" requirements (forbidden characters)
In other words, this is an approach that I think would fit most threat models and use cases.
I have no formal data to support this claim other than my own experimentation with my own logins over the years, but that's my take. You may have to tinker with the list of specials over time, but you get the idea.
Edit to add an example command line:
echo $(tr -d -c 'A-Za-z0-9@#$._' </dev/urandom | head -c 20)