Hacker News new | past | comments | ask | show | jobs | submit login
Securely store passwords with bcrypt (phusion.nl)
23 points by acangiano on Aug 14, 2009 | hide | past | favorite | 19 comments

Very interesting stuff here-I've never heard of anyone using bcrypt for encrypting passwords, but it seems like a good solution. The only problem that I see for large implementations is that even with the lowest time setting on bcrypt you're introducing at LEAST a second delay every time someone logs in while you generate the hash. And even on his MacBook Pro he was only able to generate a few hashs per second-if you ever have a rush of signups your potential users could see quite the delay while submitting their passwords.

If you're introducing a 1-second delay for login, and that's not what you wanted, you're doing it wrong. The point of bcrypt is that it's tunable, and its defaults are nowhere near that slow. You do not need to slow hashing down to user-perceptable time to make dictionary attacks infeasible.

Also, bcrypt is pretty much the de facto industry standard adaptive password hash. It's not Phusion's crazy idea. There's a PKCS function that works on similar principles (PBKDF), but it isn't as resilient as bcrypt is.

I don't think this is necessary. SHA1 was designed to be fast, yes - and fast is exactly what you want when you're logging thousands of users into a web site. But that's not even the problem.

Security is all about the weakest link. There is no point dialing one of the links up to absolutely insane heights without taking commensurate measures with the rest of your links - and a salted, hashed, SHA1 password is already pretty freaking secure.

Let me give an example. If your opponent possesses the incredible resources necessary to brute force SHA1 in a useful timeframe - and there are probably only a handful of such organisations on earth, all governmental - then they will not even bother with that. They will simply bug your server and collect the passwords plaintext somehow there. Or they'll subpoena you and force you to start collecting the plaintext. Hell, what do they need the passwords for anyway?

See what I mean? It's solving the wrong problem. Anyone who could actually brute force SHA1 is such a formiddable opponent that they could not care less if you changed to bcrypt or whatever. You have already lost if they even decide to mess with you.

Plus, it's yet another dependency. And then the speed penalty. Forget it. Put the time into setting up SSH keys or turning off root login or something; you're a million times more likely to be compromised by those kinds of everyday flaws than NSA-level shit like this.

I strongly disagree. What web site has ever been without scaling problems if it weren't for that darn password hash complexity issue? IMO this is really _NOT_ something to optimize for.

Consider, most users of web sites have pretty simplistic passwords. The salt needs to be known in order to validate the password, probably stored in the row with the password. If the password database is ever compromised, it's then trivial for an interested party to start pounding salts and hashes through something like http://nsa.unaligned.org/ or a botnet of compromised machines.*

Sure security might be about the weakest link, but you also have to look at the value of each loss. You're opening yourself up to a firestorm of embarrassment if your user table is leaked (so your argument about securing everything else is important) but that's so much worse when decrypted passwords are going around with the table.

[*] The winners of the Engine Yard SHA1 challenge http://www.win.tue.nl/cccc/sha-1-challenge.html did almost 700 MILLION SHA1 hashes per second on two beefcake video cards.

"The salt needs to be known in order to validate the password, probably stored in the row with the password."

But it is not enough to know the salt. A correct implementation also includes a (lengthy) pepper, stored in the application code. If you've got that as well, and also details of how the particular hashing setup works, then it is indeed probable you would be able to brute force the hashes.

But my point is, if someone has enough access to get all that, then they can probably just silently suck off the passwords in some way anyway. They are obviously in the machines and are probably root. They could probably insert code right into your app to email them every new password coming in, pre-hashing, and you wouldn't learn about it for months.

And if they only have the user table - well, 700m hashes a second is very impressive indeed but that's still 2.7 × 10^36 seconds to brute force a 32-character pepper.

You might still think it's worth it - defence in depth and all that. But considering the price you pay, like its slowness - 0.1 seconds might sound fast but if the server's running at load then it will be more - and the hassle of having another gem, especially one with a C dependency, I do not agree.

update: actually, upon further consideration and research, fine. I'll switch to bcrypt too from now on. That's a huge gain and the cost is not that high. I guess it hadn't sunk in just how fast SHA1 implementations were getting.

I still maintain it's not the weakest link - the weakest links numbers 1 through 50 are staff - but it's a definite improvement with little cost.

No secure system depends on attackers not having access to your source code. This "pepper" idea is silly; if you believe it adds security, then you don't even have to bother with password hashing. Just XOR your passwords against a string in your code.

It does add security, because now your attacker needs the source code as well, which is probably on a different machine, requiring different login credentials, etc. Every little bit helps and it's a trivial addition to the authentication code.

Of course you would not depend upon it solely but it's called defence in depth.

You can say "defense in depth" about any idea, whether it works or it doesn't. My XOR idea --- which I am going to name "hippo", as in "your passwords should be salted, peppered, and hippoed", is also "defense in depth".

To evaluate the efficacy of a "defense in depth" measurement, insert it into an incident disclosure. For instance:

"We're sorry to inform our users that owing to an SQL Injection vulnerability, we may have disclosed the password hashes of all of our users. We believe these passwords remain safe, because an attacker would also need to have access to our source code in order to learn the secret key needed to mount a dictionary attack against them."

Compare to:

"We're sorry to inform our users that owing to an SQL Injection vulnerability, we may have disclosed the password hashes of all of our users. We believe these passwords remain safe, because the cryptographic algorithm used to create the hashes ensures that it would take over 100 years to complete a dictionary attack against a single password."

Right, this will be my last response on this, especially as I have already conceded defeat. You just like arguing, apparently.

Firstly, even in the first "disclosure" message - the passwords are indeed safe. Because of that "useless" peppering, there is no way the attackers will be able to unmask the hashes.

Secondly, if you have configured your database such that it is even possible to perform a select all on Users from the app server account, you are Doing It Wrong.

However, you are broadly right.

That said - my whole thesis here is that there are no magic bullets. Yes bcrypt is (much) better against this particular attack. But the DB server is not even web-facing and is unlikely to be compromised; the app servers are far more risky. They have access to the plaintext passwords flowing through them. When they are rooted, you're fucked no matter what hashing strategy you chose. And if you have a crooked insider - which as a security professional, you will know is by far the more likely risk - that's where they will strike as well, of course. Your precious passwords will be bcrypt hashed to the DB all right, but Mallory keeps his own plaintext backup, written by the comped bcrypt gem he snuck onto the system looking for a payday. Or whatever. There's a million ways to do it, all of them easier than brute forcing anything. You're focusing on this single scenario to the exclusion of any number of more likely attacks. Despite the hype, "steal-the-user-table" breaks are not common.

Anyway. I was wrong, and I admitted it. Use bcrypt, everyone. EOF

Most web applications will never be "rooted". Many web applications will have SQL Injection vulnerabilities, even in modern frameworks.

You only have to generate the hash during login, not during every page request. I don't think the majority of the time on most websites are spent on logging in.

You're right, but (I know I'm repeating myself) you don't even have to concede that for bcrypt to be a win. You can make hashes take sub-user-visible time and still make dictionary attacks totally infeasible. SHA1 is extremely fast. Even "just not extremely fast" is a win.

This isn't even an argument; it's just an attempt to troll this conversation. You've written enough stuff elsewhere on HN that I know you're not this dumb, and I know you don't actually think people are talking about brute-forcing the SHA function itself, despite Phusion's poor choice of words.

You and I both know this attack is about running a dictionary of possible passwords against a stolen password database, and, because you seem smart (if annoying), I'm pretty sure you also know that attack is lightning fast. You also seem young, so you might not realize that this attack was the "industry standard" password cracking mechanism throughout the entire 1990s; it's the attack that Crack and John The Ripper are based off of. Before the crappy LANMAN hash, it was the only password attack Unix hackers had available to them, and it was so effective that every Unix system had to implement "shadow" passwords.

Please stop trolling, sho.

tptacek, I am not trolling. If you can show me an instance where anyone, ever, has successfully brute forced a properly set up (salted AND peppered) hashed password from ONLY the hash and the salt then I will quite literally eat my hat. It simply cannot be done with current technology and no amount of rank-pulling will change that.

However, I've actually changed my mind and conceded defeat on this one. If the attacker could grab a copy of the app code as well and get the pepper & hashing setup, bcrypt would indeed slow down the ensuing attack on the passwords. You're basically screwed by then, of course, but it would be nice for the users if they had a little while longer to change their passwords on other sites.

I'll be using bcrypt from now on.

You're not even reading my comment before responding to it. Focus your attention on the part about how the attack bcrypt defeats was the sole attack used against Unix passwords for an entire decade, the basis for two of the most popular security tools of all time, and the reason we have shadow passwords.

Also, there's no such thing as "pepper", despite what the PHP forums may say.

If you weren't deliberately misleading developers into using insecure code patterns, I'd just ignore you, sho.

There's a small Ruby binding for Scrypt available on GitHub. All it needs is for someone put the time into making it a gem, and maybe bundling it with Scrypt as a Ruby extension.


That's a binding alright. But it's not easily installable: one has to install the scrypt library manually. I'm not sure how to do that because last time I checked scrypt is a program. Scrypt is also not packaged by Debian at this time. All in all, I think it's not the right time to use scrypt yet - at least not until there are easily installable libraries.

Ok so what happens if my site gets popular - and I can dream, can't I? - and I get hundreds of people logging on per second?

Applications are open for YC Winter 2022

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact