Securely storing passwords

I’ve been doing a bit of reading lately about the correct way to store passwords, normally in a database. Obviously keeping passwords in plain text (i.e. no encryption) is A Bad Thing for obvious reasons. We’ve all done it at some point, but now is the time to stop.

The secret to getting over the “dunce” level of securing passwords is to use more than just a hash of a password, and instead throw a little salt into the recipe. A salt is basically an extra ingredient that mixes up your hashes and makes them bitter to crackers. Am I taking the analogy too far? Yes, yes I am.

So, I suggest the following (this is in PHP):

md5(md5("password") . "password");

Why? Well, it’s really easy to understand and implement. It means you don’t have to store the salt for your hashes anywhere – the password generates it’s own. Plus every salt is different. Plus it’s a constant length.

I’m not pretending it’s the most secure way in the world to store passwords, but for a better-than-average method it’s pretty good. Or I think so, at least. Any comments?

6 thoughts on “Securely storing passwords

  1. Since you asked for comments, here are two.

    First, the point of hashing is to make the use of precomputed attack dictionaries impractical. If the salt is determined by the password, however, the ultimate hashed password depends on only one variable: the password itself. So it’s easy for an attacker to take a dictionary of common passwords and run them through your hash function to create a hash-to-password attack dictionary. This dictionary, in turn, can be used to “reverse” the passwords in your database in a single pass.

    So I hope you can see why your salts must not be a function of your passwords. You get the benefit of salting only when salts and passwords are independent of one another. That’s why it’s common to use a random salt for each password. If you follow this convention, you will eliminate the possibility of precomputed-dictionary attacks and force attackers to use much-more-expensive guessing attacks.

    Which brings me to the second comment. Instead of using MD5, use a hashing function designed for password applications, e.g., bcrypt. MD5 was designed to be fast. That means attackers who are forced to guess passwords from your database will have the benefit of being able to make inexpensive guesses. If you use bcrypt, however, each guess becomes very expensive, making large-scale guessing attacks impractical.

    Cheers,
    Tom

  2. Hi Tom,

    Yes, you’re right about md5. In fact I did think before I posted that I should add a note saying the md5 isn’t necessarily the best way to encrypt passwords but was too lazy. My sins have found me out.

    However I don’t agree with your comment about dictionary attacks being powerful against this method. If the attacker knew that this method was being used to create the salt then they could factor this into their dictionary attack. However that would require them to get the database of passwords *and* source code for the application.

    Using a random salt is fine when storing passwords once, but when you come to authenticate the user you need to know what salt was used so you can recreate the encrypted password and therefore authenticate the users entered password. That means the salt needs to be stored somewhere, and in plain text. If this is in the database with the password then that’s a big security risk.

    This method gives you a psuedo-random salt (well, it’s a non-simple string of characters) which is easily retrievable – IF you know how you are generating it. To make it even more secure you could reverse the salt, replace charaters, change the order of characters etc.

    I would argue that this method still makes the use of precomputed attack dictionaries impractical, as long as your source – and therefore the method you use to generate the salt – is kept secure. If your source code is compromised then you’ve got bigger problems than an encryption mechanism will solve.

    Any further comments? Maybe I’ve missed something really obvious, in which case please enlighten me!

  3. Hi Chris,

    your suggestion is one extra step of security yes, but Tom is right – you should use a separate salt.
    The salts don’t need to be secret – you just put them in plaintext alongside the hash in the database. The salt is there to slow attackers down.

    Say an attacker steals your database of one million passwords. Your salting method does prevent an attacker from matching all those passwords against an off-the-shelf precomputed database of hashes (or, better still for the hacker, a rainbow table). But once they know of your salting method, they can generate a new table and check all million hashes against each.

    If your salting method used a random salt for each hash, the attacker couldn’t do this. They’d essentially have to build a new table for every one of your million hashes.

    So a crack of your hashes would be in constant time O(1) – it’d (pretty much) take the same amount of time to crack a million hashes as it would to crack just one (since the work to do a compare is tiny in comparison to generating a hash table)

    With a uniquely salted hashes, it’s linear time – O(n).

    It’s hard typing all this in this little box btw.

  4. Thanks for the comment, John. I see where you’re coming from, and you’re right. However in my defence I did say:

    I would argue that this method still makes the use of precomputed attack dictionaries impractical, as long as your source – and therefore the method you use to generate the salt – is kept secure. If your source code is compromised then you’ve got bigger problems than an encryption mechanism will solve.

    The ironic thing would be if someone made a hash table using this method. What a fool I would be then, eh?

    So I admit that a different salt per hash is the best way to go.

    I’ve also made the comment box bigger. I found it annoying sometimes as well but obviously needed a kick to do something about it.

Comments are closed.