Monday, September 17, 2007

Quick: Read this if you ever store password data

Thomas Ptacek has a good post explaining why your password storage scheme is probably bad.

His post has a lot of words, so I'll summarize:
  • Storing passwords in plaintext is obviously bad (most developers already know this)
  • Using a salted-hash such as MD5 or SHA-1 isn't much better. (too easy to brute force)
  • Your other clever password storage ideas are probably bad too.
  • Use bcrypt instead. It was created by real cryptographers for just this kind of thing.

Here's bcrypt for Java. It has a nice simple API:

// Hash a password for the first time
String hashed = BCrypt.hashpw(password, BCrypt.gensalt());

// Check that an unencrypted password matches one that has
// previously been hashed
if (BCrypt.checkpw(candidate, hashed))
System.out.println("It matches");
else
System.out.println("It does not match");

I'm sure other popular languages have similar libraries.

13 comments:

kappa said...

Secure authentication is much more important than secure password storage. That leads us to challenge-response methods and those usually make us store passwords in clear text anyway.

Btw, as far as I understand, linked article did it work wonderfully and became obsolete :) Nobody uses plain old DES crypt(3) in password hashes for a long time, in part due to the work authors of the paper did in OpenBSD.

Thomas Ptacek said...

The (patented) state of the art in challenge-response auth, SRP, doesn't require passwords stored reversably. It's a neat trick. But you have a good point; cleartext password storage is what was wrong with APOP, too.

Anonymous said...

Is SHA-1 really that easy to brute-force,
currently (circa late 2007)?

Unknown said...

hum... salted + SHA2 then.

Ron Forrester said...

To say that a properly salted SHA-1 password digest is "not much better" than a plain-text password is really, really misleading. I can appreciate the gist of your post, which is don't take password storage lightly, and think you can come up with your own scheme.

I haven't looked at the code for bcrypt, but I would be very surprised, even based on the api snippet you show, if they are not simply salting and and digesting the password.

Rainbow tables are making this type of password storage less secure, but it's still many orders of magnitude stronger than plain-text.

Cheers,
rjf&

Anonymous said...

I already use sha256, but the problem is that in my web application, I send a fully random binary salt to the client (using a base64) with the length equal to a block in the used hash function (so for sha256 thats 64 bytes iirc). Then a javascript uses that salt and the hash of the password to create another hash. Then the server does this too, yadda yadda you get the idea.

If the database has a salt on it, then I'd need to send 2 salt values to the client. There's not much point to it other then to secure the database after it has been compromised. Which sounds like a weird idea to me anyway. In fact, why shouldn't they be stored in plain text? After all, if they've got acces to the database, they don't really need a password anyway. The only reason I can think of is that perhaps some users use a single password everywhere. But that's not my fault.

Ron Forrester said...

They don't necessarily have full access to the database though -- it may be that a sql injection vulnerability exists such that they can only read the user table, in which case they now have names and passwords to login to the web site and wreak havoc.

Security is best applied in layers.

Cheers,
Ron

Anonymous said...

They can wreak havoc with the hashes too, only difference is that they don't know the original plaintext password.

Jay Bose said...

You may want to consider Acegi, now a subproject of the Spring framework. They have a pretty mature auth' mechanisms, that allow for salts, password encoders, and various data sources (in memory, jdbc, hibernate, etc).

Ron Forrester said...

paulvg: if the hashes are the result of a properly salted-password digest, then it will be much more difficult to do anything with them. That's the point. Rainbow tables are not effective against proper use of salt when digesting passwords.

It's your system though, so your call.

Cheers,
Ron

Amit said...

I wish developers knew that storing passwords in plain text is bad. I've heard several stories of widely-used startup sites that store passwords unencrypted, and it makes me wonder how many other sites are doing the same thing. What if my bank does that? I have no way of knowing.

Anonymous said...

Ron: That doesn't work for me, if the passwords in the database are salted then the only difference it would make is that I then have to send 2 salts to the user agent.

Right now the server generates a random salt after it serves the login page (it's fetched through xmlhttp). The reason I did that is so that if someone intercepts the login on the network, then the hash is useless because the hash changes at every login attempt wether the password has changed or not.

I certainly recommend https over a scheme like this, using this method *and* https just makes no sense at all. Using https and another crypto challenge (beside login/pass) is best. I guess with these things it's a matter of what you can get away with though; When will you get complaints and how big a target are you?

jay: Thanks for the tip, I'll look into it when I'm doing something in Java :)
Hosters suck where I live though, they're still moving from PHP4 to PHP5 (ditto for FreeBSD). I wish there was a hoster in europe with, like, Lighttpd+php5 w/suhosin, apc and postgresql. (It's not that hard to configure a setup like that.) So the only chance for me to do a servlet is when I have to write an internal / business app.

FinancialMan said...

Hi Paul,

I'm Richie Hecker, serial entrepreneur, i run bootstrapper.com and you can see who i am at www.richhecker.com. Anyway, someone got access to my gmail account and i (stupidly) fwd a lot of my business email through it and a lot of business contacts have it and i'm trying to figure out how to get it back. My secondary email address is old and no longer valid so i don't think there's anything i can do, also i can't afford to wait 5 days to get my email back, i'm wondering if you can help, i'm sorry for reaching out like this but my philosophy is when there's a problem, go right to the source so i figured i'd reach out to you. My account is rhecker@gmail.com and can prove it and provide a zillion industry references. please help me

Richie Hecker
347 385 7865
rich at bootstrapper.com