Is there anything available that isn't trivially breakable?
MD5 / SHA1 hashes are both good choices. MD5 is slightly weaker than SHA1.
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
MD5 or SHA in combination with a randomly generated salt value for every entry
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.
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.
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.
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.
Security is a tough field, do not think you can invent your own algorithms and protocols.
Don't write logs like "[AddUser] Hash of GeorgeBush:Rep4Lyfe:ASOIJNTY is xyz"
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).
MD5+salt or SHA1+salt is not 'trivially breakable' - most hacks depend on huge rainbow tables and these become less useful with a salt.
MD5+salt is a relatively weak option, but it isn't going to be easily broken.
SHA2 goes all the way up to 512 - that's going to be pretty impossible to crack with readily available kit - though I'm sure there's a Cray in some military bunker somewhere that can do it.
There's relatively available open source implementations of all the SHA variants, and .Net has built in support, so I'd go with SHA 512 +salt.
That's not so good if you need to do your encryption really fast though.
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.
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:
- Never store a plain text password (which means you can never display or transmit it either.)
- Never transmit the stored representation of a password over an unsecured line (either plain text, encoded or hashed).
- Speed is your enemy.
- Regularly reanalyze and improve your process as hardware and cryptanalysis improves.
- Cryptography and process is a very small part of the solution.
- Points of failure include: storage, client, transmission, processing, user, legal warrants, intrusion, and administrators.
Steps:
- Enforce some reasonable minimum password requirements.
- Change passwords frequently.
- Use the strongest hash you can get - SHA-256 was suggested here.
- Combine the password with a fixed salt (same for your whole database).
- 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.
- 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.