views:

1679

answers:

11

Is there anything available that isn't trivially breakable?

+1  A: 

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

JeffFoster
+10  A: 

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

Lou Franco
That's a great article.
Nick Gerakines
Here is an implementation in .net: http://derekslager.com/blog/posts/2007/10/bcrypt-dotnet-strong-password-hashing-for-dotnet-and-mono.ashx
Yaakov Ellis
+2  A: 

SHA-256 or SHA-512

raven
+2  A: 

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

Vasil
+6  A: 

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.

Adam Rosenfield
Note: Good salt == different for every time you use a salt.If you choose one salt for all passwords, it may be random the first time you generate it, but essentially attackers guessing your birthday as your password add in the salt just like the software does, guessing "(super good salt)(your birthday)".
maxwellb
A: 

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.

sanity
If you use <a href="http://en.wikipedia.org/wiki/Salt_(cryptography)">salt</a> you will make dictionary attacks much more difficult.
Kip
"much more difficult"? Proper salt makes a dictionary attack impossible because there's not enough storage on the planet.
erickson
Salt isn't against dictionary attack, but to defeat rainbow tables. The two concept are very different.
KovBal
+1 to KovBal. Also, using a k-bit hash function, a "dictionary attack" against all possible passwords is 2^k many "words". Using a non-alphanumeric (essentially) alphabet already increases the search space exponentially. Compare "provide alphanumeric password up to 8 characters" with "160-bit integer". Which one has a larger dictionary?
maxwellb
Salt is to defeat dictionary attacks. A rainbow table is a specific form of dictionary attack. It's not a different concept.
erickson
+19  A: 
  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"

JeeBee
+7  A: 

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).

Wedge
+1  A: 

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.

Keith
SHA2 is surprisingly fast. Definitly much faster even than AES... Even hashing large amounts of data many times, I find it highly unlikely that performance will be degraded any significant amount.
AviD
+4  A: 

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.

KovBal
I think there are good uses for PBKDF's, but if you are implementing a server application with password-protection, the password needs to be transformed before it goes over the wire. Often PBKDF's will be used to *generate a key* for use in, e.g. symmetric encryption. A password-protected forum usually needs to use cheap algorithms with pretty good collision-resistance, as the result of the transformation is essentially the "password" to check against the database. Increasing randomness and decreasing likelihood of collisions are how to increase security here. Random salt+good hash should work
maxwellb
@mpbloch : You can't transform the password before it goes over the wire. You can use SSL to protect it. You need to hash the passwords because of the rainbow table attacks. And it's only possible if you hash it on the server.
KovBal
+14  A: 

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.

Jim McKeeth
Why use a site wide salt and also a user unique salt? Wouldn't a single large random salt value be sufficient?
jkf
A single salt (of any size) means that if they generate a rainbow table (hash dictionary) once, it is good for every user in the database, so they are much more likely to find a hit quicker. If each user has a different salt then it means a new lookup table needs to be generated for each user.
Jim McKeeth
I understand why its bad to use just a single salt for all users. I wanted to find out what the idea is behind using a single site wide salt plus a user unique salt when, at least to me, just a user unique salt appears to be sufficient.
jkf
The additional site wide salt is more important if you are using the username or some other weak salt as your user specific salt. For example, if a user has the same username and password on another site then you will have the same hash on both sites. Beyond that it is just an incremental improvement.
Jim McKeeth
Random salts are best. Change them every time the user changes/creates a password. You can store the extra 3-4 characters in the same field as the password hash, separating them with, e.g. `:`. So your field goes from `aabbccddeeaabbccddeeaabbccddeeaabbccddee` to `sLt:fb1337ce1afb1337ce1afb1337ce1afb1337ce1a`. Swap the order of the two subfields if you want, but the point is, it's cheap to parse later, and increases the security dramatically.
maxwellb