3

Let's say I have thousands of users and I want to make the passwords very secure. Now, I've learned that md5() is not the safest to use, however what I think can be done to be safe is salt it (I know this is nothing new). So for this I was thinking of creating two tables, one called accounts which will have all information associated with accounts and a table column called salt and the second table would be called something like auth and have the fields account_id, password

to start, I create a salt upon registration (generated randomly)

$salt = "#52/sBsO8";

then all the provided information goes to accounts salt being one of them

then after successfully putting the information in database, I create the password that is going to be stored in auth table, this way the password is not the md5 of the password the user enters, rather its the md5 of the salt and the password user enters

so the password in auth is

$password = md5($user_entered_password . $salt);

Test strings: PHP Code

$password = "123";
$salt = "#52/sBsO8";
echo md5($password) ." / ";
echo md5($password . $salt);

output: 202cb962ac59075b964b07152d234b70 / dfbf0b257c5182af0ae893c2680f4594

The question is: Is this a pretty safe way of dealing with passwords? Because of md5() decrypting websites, there are so many ways to guess the passwords. And the decrypting websites don't actually decrypt the md5() they just have the md5 hashes of millions of strings.

Whisperity
  • 3,012
  • 1
  • 19
  • 36
Grigor
  • 4,139
  • 10
  • 41
  • 79
  • use bcrypt: http://stackoverflow.com/questions/4795385/how-do-you-use-bcrypt-for-hashing-passwords-in-php – sehe Jun 08 '12 at 15:32
  • never heard of that one, but why isn't this way safe? – Grigor Jun 08 '12 at 15:33
  • This might help if not answer your question outright: Here's a great discussion on the benefits of multiple password hashing methods in php http://www.php.net/manual/en/faq.passwords.php#faq.passwords.fasthash – Hans Z Jun 08 '12 at 15:34
  • @Grigor Two reasons not to write the code yourself. 1. easy to make a coding mistake or overlook something as you are not a security expert. 2. Why reinvent the wheel? – Colin D Jun 08 '12 at 15:35
  • if you never try new things, you won't invent anything. Why not use two hashes at each end of the password, md5($salt_start . $password . $salt_end) and use that as password, and if ever your database was hacked, they won't find the password that was used to signup – Grigor Jun 08 '12 at 15:38
  • 3
    @Grigor: Use an expensive hash. You don't want a fast hash. You want to make it hard to generate lookup tables/brute force things. bcrypt has that; See the linked answer for other background – sehe Jun 08 '12 at 15:43

3 Answers3

1

md5 is likely to be the least safe among "popular" hashing algorithms.
Since you're using PHP, a better option would be crypt: http://php.net/manual/en/function.crypt.php

crypt($password, $salt)

For a good comparison of various hashing methods, see Jeff Atwood's post about password hashing

Excerpt about brute forcing benchmarks:

MD5 23070.7 M/s
SHA-1 7973.8 M/s
SHA-256 3110.2 M/s
SHA-512 267.1 M/s
NTLM 44035.3 M/s
DES 185.1 M/s
WPA/WPA2 348.0 k/s

the lower, the better, although DES is too short to be considered nowadays (56bit, thanks @thebod).

EDIT:

Although it isn't listed in the benchmarked methods above, the best hashing method that crypt supports is blowfish, here's an example to use it:

// $salt has to be built with exactly these components:
// '$2a$' . $2DigitsNumberAroundTen . '$' . $TwentyTwoLetters
$salt = '$2a$07$somesillystringforsalt';
crypt( $password, $salt );
Razor
  • 27,418
  • 8
  • 53
  • 76
  • @martinstoeckli indeed, I was just summing up the data above, not saying that DES is always the best: edited to clarify this – Razor Jun 08 '12 at 19:20
  • I'm sure you don't mean DES (data encryption standard) - DES is broken since 1998 (first theoretical attacks in '94)... Also WPA/WPA2 is obviously nothing you will choose for hashing a password... SHA-512 is nice, use it ;-) – thebod Jun 08 '12 at 23:26
1
  1. Hash functions for passwords should be slow (need some computing time). Most hash algorithms are designed to be fast, but this makes it easier to create rainbow tables for every salt.
  2. The salt should be random, and should be generated separately for every stored password. This salt has to be stored together with the hash, but is not secret (can be plain text). The salt makes dictionary attacks more difficult, and different salts make rainbow tables impracticable.
  3. Ideally, you can adjust the computing time later for new hardware, without breaking existing hashes.

That's why you should use bcrypt to hash your passwords, it was designed especially for hashing password. And don't be afraid to use bcrypt! It is not for high security sites only, and using it can be as easy, as using an md5 hash.

It's recommended to use a well established library like phpass, and if you want to understand how PHP can generate such hashes, you can read this article.

martinstoeckli
  • 23,430
  • 6
  • 56
  • 87
-1

Why do you think that this is more secure? The user types in a password. One assumes that the user is not an idiot and choses something that (s)he only knows. How is that different if that individual typed it in with the salt?

This actually makes it more insecure because if a person gets hold of the table that person has something to work on.

You are better off spending your engergies on ensuring that the computer is secure, your network is secure and teaching your users on sensible and secure passwords.

Ed Heal
  • 59,252
  • 17
  • 87
  • 127
  • I didn't downvote you, but I'd guess it's because your answer seems to suggest that adding a salt provides no benefit at all, which isn't true. It just doesn't provide *enough* benefit. A hashing algorithm with an expense factor is the best way to protect your users now. Unfortunately you'll always have users who set their password to something simple and you have to protect them from their own foolishness. – Gareth Jun 08 '12 at 15:51
  • @Gareth - It provides no benefit at all. Adding a machine generated string of characters to a (supposdly) human generated random string of chacters just gives you a random string of characters. AKA a password. Some systems initial password is just the `salt` (a random string of characters) generated by a machine. As to protecting them from their foolishness you cannot - A password is just a collection of key presses. Anybody with that knowledge can do it. Biometrics anybody? – Ed Heal Jun 08 '12 at 16:06
  • 1
    The salt does add benefit. First it makes the use of a rainbow table essentially useless. Second if you don't salt, an attacker running a brute force attack can compare the results to all of your users passwords (They are essentially creating their own rainbow table). With the salt you have to attack each password individually. – Philip Tinney Jun 08 '12 at 16:18
  • 1
    I bet LinkedIn wishes it used a salt, which I think it now does since the leak! – John Warlow Jun 08 '12 at 16:23
  • @PhilipT. - The OP definition of a salt is just a string of characters to append to the password. i.e. a password that is longer by adding random characters created by a machine. So to guess a password you do not know the length and also the contents. Lets assume without the `salt` (BTW the OP definition is incorrect) you are just trying a variety of strings of characters of various lengths until you can open pandoras box. With the OP version of a `salt` you still do not know the length or contents of a string (AKA password concatinated with a `salt`). You are still in the same position. – Ed Heal Jun 08 '12 at 16:28
  • @Ed Heal - A small example why a salt is important. Hash the password "world" with MD5(), this will result in "7d793037a0760186574b0282f2f435e7". Now put this value into google and the first entry will surely contain the original password "world"... That is the problem with rainbow tables. – martinstoeckli Jun 08 '12 at 16:37
  • @martinstoeckli - You are assuming that somebody can get hold of those MD5 hashes - i.e. breaking into the computer system and grabbing the auth table. – Ed Heal Jun 08 '12 at 16:51
  • @Ed Heal - That's one possibility, SQL-injection is another one and can be done without having control over the system. There are many possible attacks, and the whole purpose of hashing is, that the password is not lost when somebody gains access to the hashes. – martinstoeckli Jun 08 '12 at 16:57
  • You aren't thinking of the big picture. When you compromise a websites password file, you want to compare all the passwords at the same time. If you have 10,000 passwords, you have to hash each iteration and the salt. No salt you just run the hash and can match any of the existing passwords. – Philip Tinney Jun 08 '12 at 17:02
  • @PhilipT. If you have compromised the web site - surely you have the salt along with the vinegar. If you have SQL inject - let the party begin! – Ed Heal Jun 08 '12 at 17:17
  • @EdHeal by the same reasoning, you should just store passwords as plain text without any sort of hashing - I mean, your DB is secure, *right*? Just like linkedin was... – Razor Jun 08 '12 at 18:46