18

Possible Duplicate:
Secure hash and salt for PHP passwords

I am making a system that has stores user credentials (email, username and password) in a MySQL database and have seen conflicting views on using encryption, salting and encryption types.

What are the best methods you would recommend? Encoding in MD5 or SHA1? Salting or not salting? Encrypting just the password or all 3 elements?

Community
  • 1
  • 1
Phil Young
  • 1,334
  • 3
  • 21
  • 43

5 Answers5

12

For the password hash use PBKDF2 it's NIST approved. You should use a random non-secret salt for each password and nontrivial (over 1000) iteration count.

For the username and email, probably not worth encrypting.

jbtule
  • 31,383
  • 12
  • 95
  • 128
  • 1
    +1 for PBKDF2 is much better, although I generally use 10,000 iterations when performance is not an issue ;) For an example: http://csharptest.net/470/another-example-of-how-to-store-a-salted-password-hash/ – csharptest.net May 01 '12 at 17:39
  • @csharptest.net I agree on your iteration count, nice example. – jbtule May 01 '12 at 17:42
7

The best practices IMO are:

  • Use a hashing algorithm such as SHA256 or SHA512. MD5 is insecure now as you can reverse the hash/perform a rainbow attack.

  • Use a strong salt to ensure an attacker cannot guess commonly hashed passwords if they ever gained entry to your database.

  • Do not use encryption.

  • Only hash the passwords, usernames and e-mails are fine as plain text.

Darren
  • 68,902
  • 24
  • 138
  • 144
  • +1 Hashing emails and usernames would be tough because they're generally not case sensitive either. – Marcus Adams May 01 '12 at 13:05
  • 1
    This is not the correct answer. You want to use a proper password hashing function such as PBKDF2 or bcrypt. – imichaelmiers May 01 '12 at 21:03
  • @imichaelmiers - this does not mean my answer is not correct. You recommended a stronger hashing function, however SHA256 and 512 are still valid because no hash collisions have been found. – Darren May 02 '12 at 07:58
  • @DarrenDavies The issue isn't collisions, It's the time to try a guess at the password.Yi u can do at least 2300 million sha1 hashes a second on a gpu. Then means you can guess roughly that many passwords. Given how short most passwords are, this makes sha1 pretty worthless. The logic for this is outlined here. It recommends using a different function, bcrypt, but the logic and point is the same: password hashing functions should be slow to limmit guessing and sha1/256 is fast by design. http://codahale.com/how-to-safely-store-a-password/ – imichaelmiers May 02 '12 at 14:08
  • @imichaelmiers - what are you talking about? I did not recommend SHA1.... – Darren May 02 '12 at 14:21
  • 1
    And I am not talking specifically about sha1, though that happens to be what I could find data for quickly. You can do at least 65 million sha256 hashes a second, and the site I am getting that from looks old and dated. http://www.insidepro.com/eng/egb.shtml The logic applies to any of the general purpose hash functions. SHA 256/ 512 are harder to get a collision on and harder to invert ( in the since of given the output on a random input, recover the input, not verify a guess of the input). They are designed to be fast to compute. If they are fast, you can quickly guess passwords – imichaelmiers May 02 '12 at 14:30
3

It's only really the password that you need encrypting. Realistically, you should be both Hashing (that's what you mean when you say encoding) in an algorithm at least SHA-256 really (I'm pretty sure MD5 and SHA1 are crackable?) AND Salting your passwords to be extra safe.

Here's an answer on the preferred method of storing them: Preferred Method of Storing Passwords In Database

Community
  • 1
  • 1
Mathew Thompson
  • 55,877
  • 15
  • 127
  • 148
2

Usernames and emails should not be encrypted, you need them to be in plaintext, they will be more useful that way.

As for the passwords: they should ABSOLUTELY be encrypted or hashed, preferably with salt too. Up until now I used a somewhat interesting technique to do this: AES, the key for which is the password itself. So if the user makes his password to be "blabla123", then I would store it in MySQL by calling AES_ENCRYPT('blabla123', 'blabla123'). There are 2 advantages for this:

  • you don't store the encryption key anywhere
  • each password is encrypted using a different key. So even if you figure a key out, it will have a limit on its usefulness.

The validity is then done by encrypting what the user types and comparing the 2 values.

Radu Murzea
  • 10,724
  • 10
  • 47
  • 69
  • I love this method too! Is it worth salting as well if you do this method? – Phil Young May 01 '12 at 12:50
  • 1
    @PhilFaceplantYoung, I think you'd want to salt this one. This is open to rainbow attacks without a salt. – Marcus Adams May 01 '12 at 13:02
  • 1
    This [answer](http://stackoverflow.com/a/4941870/950055) makes some good arguments for the use of hashing rather than encryption. – Morgan Bruce May 01 '12 at 13:09
  • So looking into MYSQL AES_ENCRYPT function, it doesn't use an IV, so for 8 character passwords they will only take about 16 bytes so in a rainbow table is going to be half the size of a sha256 table. Looking into the implementation it doesn't use a key derivation function and basically pads short keys with zeros, so it's going to be fast to brute force all weak passwords to make a rainbow table. Not to mention there is nothing making it unlikely that more then one password will encrypt to the same thing. Better to use a something more standard based on a secure hash. – jbtule May 01 '12 at 14:25
  • 1
    [How strong is this hashing technique?](http://stackoverflow.com/questions/4456460/how-strong-is-this-hashing-technique), [Is AES encrypting a password with itself more secure than SHA1?](http://security.stackexchange.com/questions/10476/is-aes-encrypting-a-password-with-itself-more-secure-than-sha1),[Is it safe to encrypt a string using same string as key?](http://stackoverflow.com/questions/3638281/is-it-safe-to-encrypt-a-string-using-same-string-as-key), - I think consensus is that this is not a proven way to hash passwords. – jbtule May 01 '12 at 15:01
  • @jbtule thanks for the links. But I think that, if the hacker is sooo good as to crack this way of storing passwords, then the way you store them won't make much difference. Why ? Because instead of finding out some passwords, he'll delete all the data in your tables and then crash everything on that server... – Radu Murzea May 01 '12 at 15:51
  • 2
    -1 for suggesting that encryption be used on passwords, -1 for saying 'preferably with salt', -1 for suggesting a REALLY bad idea of AES encrypting password with the password, -1 for NOT suggesting PBKDF2. --Nutshell: DO NOT USE THIS ANSWER-- – csharptest.net May 01 '12 at 17:25
  • SoboLAN There are many avenues to gain a password table that don't mean you have access to the live database. And even if the avenue did like an sql injection attack, why would taking down the server be more valuable than stolen username,email,passwords that very well could be used to gain access to other sites as well. Further more the whole point of a rainbowtable is that it makes brute forcing worth it because it can be used over and over again, so the hacker doesn't need to be skilled, they just download what someone else has done, which is easier in this case with your hash being short. – jbtule May 01 '12 at 17:38
  • 2
    -1Do not do this. As others have said, you want to use purpose designed password hashing functions that are slow. That way an attacker cannot simply iterate through all possible passwords. You can do at least 2300 Million sha1 hashes a second on a GPU. Use something like PBKDF2 with a large iteration count,bcrypt, or scrypt, to actually do this securely. They are designed to substantially slow down an attacker – imichaelmiers May 01 '12 at 19:59
  • 2
    I actually want to delete this, but I can't... since it's an accepted answer... – Radu Murzea May 01 '12 at 20:03
1

The password should be protected by hashing with a strong salt (either MD5 or SHA1 are fine), to prevent attack using rainbow tables.

You shouldn't hash the email address - as soon as you hash it, you're unable to use it for anything other than checking against what the user types in, so having it hashed would prevent you emailing that person. Equally the username would be best stored in plain text to let you identify that person.

Ben Emmett
  • 450
  • 1
  • 3
  • 9