Question

This question already has an answer here:

Is there anything available that isn't trivially breakable?

Was it helpful?

Solution

This 2008 answer is now dangerously out of date. SHA (all variants) is now trivially breakable, and best practice is now (as of Jan 2013) to use a key-stretching hash (like PBKDF2) or ideally a RAM intensive one (like Bcrypt) and to add a per-user salt too.

Points 2, 3 and 4 are still worth paying attention to.

See the IT Security SE site for more.


Original 2008 answer:

  1. Use a proven algorithm. SHA-256 uses 64 characters in the database, but with an index on the column that isn't a problem, and it is a proven hash and more reliable than MD5 and SHA-1. It's also implemented in most languages as part of the standard security suite. However don't feel bad if you use SHA-1.

  2. Don't just hash the password, but put other information in it as well. You often use the hash of "username:password:salt" or similar, rather than just the password, but if you play with this then you make it even harder to run a dictionary attack.

  3. Security is a tough field, do not think you can invent your own algorithms and protocols.

  4. Don't write logs like "[AddUser] Hash of GeorgeBush:Rep4Lyfe:ASOIJNTY is xyz"

OTHER TIPS

First rule of cryptography and password storage is "don't invent it yourself," but if you must here is the absolute minimum you must do to have any semblance of security:

Cardinal rules:

  1. Never store a plain text password (which means you can never display or transmit it either.)
  2. Never transmit the stored representation of a password over an unsecured line (either plain text, encoded or hashed).
  3. Speed is your enemy.
  4. Regularly reanalyze and improve your process as hardware and cryptanalysis improves.
  5. Cryptography and process is a very small part of the solution.
  6. Points of failure include: storage, client, transmission, processing, user, legal warrants, intrusion, and administrators.

Steps:

  1. Enforce some reasonable minimum password requirements.
  2. Change passwords frequently.
  3. Use the strongest hash you can get - SHA-256 was suggested here.
  4. Combine the password with a fixed salt (same for your whole database).
  5. Combine the result of previous step with a unique salt (maybe the username, record id, a guid, a long random number, etc.) that is stored and attached to this record.
  6. Run the hash algorithm multiple times - like 1000+ times. Ideally include a different salt each time with the previous hash. Speed is your enemy and multiple iterations reduces the speed. Every so often double the iterations (this requires capturing a new hash - do it next time they change their password.)

Oh, and unless you are running SSL or some other line security then don't allow your password to be transmitted in plain text. And if you are only comparing the final hash from the client to your stored hash then don't allow that to be transmitted in plain text either. You need to send a nonce (number used once) to the client and have them hash that with their generated hash (using steps above) hash and then they send you that one. On the server side you run the same process and and see if the two one time hashes match. Then dispose of them. There is a better way, but that is the simplest one.

CodingHorror had a great article on this last year

http://www.codinghorror.com/blog/archives/000953.html

The recommendation at the end of the article is BCrypt

The aforementioned algorithms are cryptographically secure hashing algorithms (but MD5 isn't considered to be secure today).

However there are algorithms, that specifically created to derive keys from passwords. These are the key derivation functions. They are designed for use with symmetric ciphers, but they are good for storing password too. PBKDF2 for example uses salt, large number of iterations, and a good hash function. If you have a library, what implements it (e.g. .NET), I think you should consider it.

Add a unique salt to the hashed password value (store the salt value in the db). When a unique salt is used the benefit of using a more secure algorithm than SHA1 or MD5 is not really necessary (at that point it's an incremental improvement, whereas using a salt is a monumental improvement).

Use a strong crytographic hash function like MD5 or SHA1, but make sure you use a good salt, otherwise you'll be susceptible to rainbow table attacks.

Update Jan 2013

The original answer is from 2008, and things have moved a bit in the last 5 years. The ready availability of cloud computing and powerful parallel-processor graphics cards means that passwords up to 8 or 9 characters hashed as MD5 or SHA1 are now trivially breakable.

Now a long salt is a must, as is something tougher like SHA512.

However all SHA variant hashes are designed for communication encryption - messages back and forth where every message is encrypted, and for this reason they are designed to be fast.

In the password hashing world this design is a big disadvantage as the quicker the hash is the generate the less time it takes to generate large numbers of hashes.

A fast hash like SHA512 can be generated millions, even billions of times a second. Throw in cheap parallel processing and every possible permutation of a password becomes an absolute must.

Key-stretching is one way to combat this. A key-stretching algorithm (like PBKDF2) applies a quicker hash (like SHA512) thousands of times, typically causing the hash generation to take 1/5 of a second or so. Someone logging in won't notice, but if you can only generate 5 hashes per second brute force attacks are much tougher.

Secondly there should always be a per-user random salt. This can be randomly generated as the first n bytes of the hash (which are then stripped off and added to the password text to be checked before building the hashes to compare) or as an extra DB column.

So:

What algorithm should I use to hash passwords into my database?

  • Key-stretching to slow down hash generation. I'd probably go with PBKDF2.

  • Per-user salt means a new attack per user, and some work figuring out how to get the salt.

Computing power and availability are going up exponentially - chances are these rules will change again in another 4 years. If you need future-proof security I'd investigate bcrypt/scrypt style hashes - these take the slower key-stretching algorithms and add a step that uses a lot of RAM to generate the hash. Using so much RAM reduces the effectiveness of cheap parallel processors.

Original Sept 2008 (left in so comments make sense)

MD5+salt or SHA1+salt is not 'trivially breakable' - most hacks depend on huge rainbow tables and these become less useful with a salt [update, now they are].

MD5+salt is a relatively weak option, but it isn't going to be easily broken [update, now it is very easy to break].

SHA2 goes all the way up to 512 - that's going to be pretty impossible to crack with readily available kit [update, pretty easy up to 9 char passwords now] - though I'm sure there's a Cray in some military bunker somewhere that can do it [You can now rent this 'Cray' from Amazon]

MD5 or SHA in combination with a randomly generated salt value for every entry

as mentioned earlier simple hashing algorithms should not be used here is reason why :

http://arstechnica.com/security/2012/08/passwords-under-assault/

so use something else such as http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx

All hashing algorithms are vulnerable to a "dictionary attack". This is simply where the attacker has a very large dictionary of possible passwords, and they hash all of them. They then see if any of those hashes match the hash of the password they want to decrypt. This technique can easily test millions of passwords. This is why you need to avoid any password that might be remotely predictable.

But, if you are willing to accept the threat of a dictionary attack, MD5 and SHA1 would each be more than adequate. SHA1 is more secure, but for most applications this really isn't a significant improvement.

MD5 / SHA1 hashes are both good choices. MD5 is slightly weaker than SHA1.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top