It's easy to say "use bcrypt" or "use scrypt," but I think it's important to acknowledge the challenges of deploying those functions in large scale high performance environments.<p>It's straightforward and effective when password hashing happens client-side (like local encryption for a bitcoin wallet), but using scrypt or bcrypt <i>server-side</i> at effective difficulty levels will either destroy your L1/L2 cache or exceed your CPU budget.<p>In practice, from what I've seen, this means scrypt is never used, and bcrypt is used with a work factor that's tuned low. I think this is just a fundamental asymmetry, and that at the end of the day people use bcrypt so that they can say "we used bcrypt!" and get a nod when their entire user database is compromised, even though it provides very little value the way it's deployed.
This article says salting hashes is only useful against rainbow tables. That does not make sense to me. Say you have a password database with 10,000 users in it. You want to see if any of them used "Passw0rd$". Without salt, you compute the hash once and check it against <i>all</i> the users (perhaps with a bloom filter). With per-user salts, you have to compute the hash for <i>each user</i>.<p>I think salting offers pretty clear benefits against other attacks if you have more than one user.<p>Edit: The point I'm trying to make here is that it is N_USERS times better to have a unique salt per user, regardless of the hash. One should use bcrypt/scrypt/pbkdf2 with unique per-user salts.
> I see the mantra ‘salt your password hashes!’
> repeated over and over, when its only real
> value is against rainbow tables<p>This is dangerously incomplete reasoning. Salts
real value is that if multiple password hashes are
Leaked simultaneously then each must be cracked individually. In the Adobe leak password hints were included, which allowed for very easy guessing of passwords, and because there were no salts even if you had no hint if someone else had the same password and an obvious hint you were cracked.
Salt has one other important property: Salt makes grouping users by password more difficult.<p>Some subset of your users will inevitably use the same terrible password as another user. Or one user will create multiple accounts using the same strong password. These passwords should appear unique in storage.<p>You still need salt, and that salt must be unique for each password. That's the peril of PBKDF2 password storage: I've seen applications completely botch salting by using one for all users. Bcrypt and scrypt avoid this common error by salting internally.
I'd be interested to hear more about the approaches a hacker would take in each case if they came across the hashed passwords and have no knowledge of the salts, etc.<p>For instance in the first case where hash = md5('deliciously-salty-' + password)<p>I'm not sure how easy it is for an attacker to reverse the hash if they don't know the salt. (I understand you need to assume the attacker has the salt, but just posing a constrained hypothetical here)
"The value of salts is limited to thwarting attacks leveraged pre calculated lookup tables such as rainbow tables."<p>This is absolute drivel.<p>Salts prevent checking an attempt against all the hashes in parallel.<p>That is to say if the attacker has a dump of 1 million salted hashes, they have 1 million times the work to do compared to 1 million unsalted hashes.
Found the <i>"unnamed blog"</i> post giving the <i>"terrible"</i> salting advice: <a href="http://blog.codinghorror.com/rainbow-hash-cracking/" rel="nofollow">http://blog.codinghorror.com/rainbow-hash-cracking/</a>
The need for unique passwords brings me to a stupid idea that I've had for a while.<p>Imagine a service which just stores hashes of every password that it can find from everywhere. Any site that wants can check whether a given password is in use..somewhere..and reject it if it is. Any site that wants can add more passwords to the list.<p>Internally the service would work from a bloom table designed for a fixed false positive rate. (You can actually layer bloom tables in front of bloom tables with parameters to make this possible.) So even if someone compromises that site, there is no direct record of the actual hashes for passwords.<p>Basically let sites say, "You have to choose a unique password, and do not reuse a password that anyone has used elsewhere!"
I've been saying "scrypt, bcrypt, PBKDF2, or bust" for years.<p>Also, there's a large industry trend of, "let's 'pepper' our hashes too!" whereby they have a sitewide salt. This is a mistake. If you want to add a site-specific layer of security to your passwords, encrypting them makes far better sense than adding to the salt.<p><a href="https://github.com/lizardhq/php_bcrypt_aes" rel="nofollow">https://github.com/lizardhq/php_bcrypt_aes</a><p><a href="http://blog.ircmaxell.com/2015/03/security-issue-combining-bcrypt-with.html" rel="nofollow">http://blog.ircmaxell.com/2015/03/security-issue-combining-b...</a>
It's not just the scheme that's important, it's also the implementation of it that's important. If I'm doing the smart thing and not rolling my own crypto, can I trust the existing implementation that I've chosen? It's hard to say. Does it have secure defaults or do I need to choose and why do I need to choose, why aren't the defaults secure? I'm not a crypto expert, I'm not qualified to judge and therefore I don't even care (as such) - why aren't the defaults secure?<p>For example, I'm writing an app that requires a password setup in Python so I was investigating this issue:<p>1. Passlib - <a href="https://pythonhosted.org/passlib/" rel="nofollow">https://pythonhosted.org/passlib/</a> - "implementations of over 30 password hashing algorithms" - What? I'm not qualified to judge what's secure so I don't even care, I just want something secure!<p>2. python bcrypt - <a href="https://pypi.python.org/pypi/bcrypt/1.0.1" rel="nofollow">https://pypi.python.org/pypi/bcrypt/1.0.1</a> - OK standard bcrypt, supposedly that's secure - "Author: Donald Stufft" - who is Donald Stufft? Is the code good? I don't know C and I'm not qualified to judge!<p>3. python scrypt - <a href="https://pypi.python.org/pypi/scrypt/" rel="nofollow">https://pypi.python.org/pypi/scrypt/</a> - OK it's Colin Percival's code, it's probably good, "Author: Magnus Hallin" - did Magnus Hallin screw it up though? "Burstaholic on Bitbucket provided the necessary changes to make the library build on Windows." Eh. Did "Burstaholic" ruin the crypto? Who knows.<p>Also, in my case I needed something cross-platform, primarily for Windows. bcrypt worked out of the box. The scrypt library required building on Windows with OpenSSL development headers or whatever and all that - I just said "pass".<p>Nacl is fantastic and simple to use, it can't get much easier than this: <a href="https://libnacl.readthedocs.org/en/latest/topics/public.html" rel="nofollow">https://libnacl.readthedocs.org/en/latest/topics/public.html</a><p>Something similar should exist for passwords - I just want to call compare(password, storedhash) or whatever and be done with it, I'm not qualified to judge the crypto. And it should be cross-platform.
This is missing something pretty important about salts. They hide the fact that two users have the same password. That's a huge security risk if that correlation is leaked.<p>Correct me if this is mentioned in the article, but based on several mentions of how salts were effectively useless, I think this was overlooked.
I fail to understand why salting is bad. Seems like he's saying it's not a cureall. We knew that. But it's at least marginally better than not salting and it's easy, so why the hell not?
I've recently found out about Diceware and the importance of a strong password [1][2]. Often users choose a really weak password to begin with. I've read [3] that if you have a strong password (like a 7 word Diceware password) even MD4 or MD5 would suffice :O. I'm really curious if this is true.<p>[1] <a href="http://world.std.com/~reinhold/diceware.html" rel="nofollow">http://world.std.com/~reinhold/diceware.html</a><p>[2] <a href="https://firstlook.org/theintercept/2015/03/26/passphrases-can-memorize-attackers-cant-guess/" rel="nofollow">https://firstlook.org/theintercept/2015/03/26/passphrases-ca...</a><p>[3] <a href="https://github.com/freedomofpress/securedrop/issues/180#issuecomment-29760395" rel="nofollow">https://github.com/freedomofpress/securedrop/issues/180#issu...</a><p>ps. for those that use bcrypt and want to ensure a constant user experience on their server see <a href="https://www.npmjs.com/package/bcrypt-speed" rel="nofollow">https://www.npmjs.com/package/bcrypt-speed</a>
while we're at it and throwing stuff around as if its an easy fix: lets stop using passwords. Use keys. Use a trust model on these keys.
So many advantages.. you don't receive the cleartext password no more (because really I DONT CARE if you use triplezscrypt.. SINCE YOU GET MY PASSWORD IN CLEAR TEXT during authentication.. its not like if compromises were "on the database". Its always at the application level.)<p>Beside it makes rotation easier, and not having to remember multiple passwords, or having a password manager, etc. a thing.<p>Oh wait ;)
Google and others are actually attempting to make this work with U2F:<p><a href="https://support.google.com/accounts/answer/6103523?hl=en" rel="nofollow">https://support.google.com/accounts/answer/6103523?hl=en</a> (yes it works with gmail. Right. Now.)<p><a href="https://www.yubico.com/applications/fido/" rel="nofollow">https://www.yubico.com/applications/fido/</a>
The points made here are covered in Coda Hale's post: <a href="http://codahale.com/how-to-safely-store-a-password/" rel="nofollow">http://codahale.com/how-to-safely-store-a-password/</a><p>While it recommends using bcrypt, if you augment that with "or scrypt or PBKDF2" the same principles apply.
There is one thing that I think is often omitted. A <i>lot</i> of user use trivial passwords and they reuse them. These users' passwords will fall essentially no matter what you do because making the check so slow that a dictionary attack with a couple thousand very common passwords becomes impractical is itself borderline impractical. On the other hand strong passwords will withstand an attack even if they are hashed with plain MD5 or SHA1 - at least right now, there are already some serious collision attacks.<p>The user group really benefiting from strong password hashing schemes is the one between the two mentioned extremes. So if you really want to protect all your users and use simple password authentication you have to enforce strong passwords policies which is itself not trivial and will definitely badly annoy some users.
Since the author didn't bother to mention any threat models, we can assume that the threat is the most common one, SQL Injection.<p>You don't need SQL Injection if you can directly read the database file, or can operate as the web server user, therefore if you're doing SQL Injection you don't have those privileges.<p>If you can HMAC or encrypt passwords (prior to hashing them) in the database with a key only on the web server, then that's an extra level of protection. You can't get that key with SQL Injection alone.<p><a href="https://blog.mozilla.org/webdev/2012/06/08/lets-talk-about-password-storage/" rel="nofollow">https://blog.mozilla.org/webdev/2012/06/08/lets-talk-about-p...</a><p>password_hash(base64_encode(hash_hmac("sha512", $password, $key, true)), PASSWORD_BCRYPT)
How about not reusing passwords and always using a strong password? SHA256 alone is enough, when you just do that. And so what if someone got my password. If they had already access to the system, they could have also stolen the data they were after anyway. Today's password: .P`éA@O?/^2HNVSé%@ÖY it contains more than 256 bits of entropy. Based on this SHA256 collision attacks and cracking AES128 should be trivial. I personally consider passwords to be unique shared secret blobs / service.
Jeff's and Thomas' posts are totally on the money. We wrote a piece as well, specifically to talk about how encryption and hashing are not the same thing. You'd be surprised how often people screw that up.<p><a href="https://www.tinfoilsecurity.com/blog/store-data-securely-encryption-hashing-how-to-guide" rel="nofollow">https://www.tinfoilsecurity.com/blog/store-data-securely-enc...</a>
If you are using .NET, you will be glad to know that .NET framework has a standard implementation of PBKDF2, one of the recommended choices in the article.<p><pre><code> var hash = new System.Security.Cryptography.Rfc2898DeriveBytes(password,
salt, workfactor).GetBytes(32);
</code></pre>
Using a NIST-approved function that's continuously supported by a large player seems like a good choice.
And, as always - these discussions about Salts/bcrypt/scrypt are only relevant to people where passwords/security are important, but not critical.<p>For anybody who has critical security needs, just use an HSM already. Sophos/Utimaco makes a nice one, and it is a nice foundation for password security.
How about using a tested login library instead and consider using OAuth as well (e.g. Google account to login)?<p>Rolling your own login system, dealing with hash functions and checking passwords yourself is far too low level and dangerous for most apps (as this thread demonstrates).
Urghh... I hate these articles that list bad examples of salt use and then doesn't explain the reasoning why exactly these are bad. Just trying to prove to the world how smart the author is. Maybe he doesn't really know how to explain it?
Does this mean we should drop the salts, simply scrypt and be done with it?<p>Or should we still include salts in addition to scrypt?<p>If yes, only one global or many user specific or both?