2

I'm trying to find the best way to secure user passwords in a mysql database (hashing/encryption wise). I was which method was the most secure and hardest to crack. I am not very experience in the realm of encryption/hashing etc. Currently I am using a very unsecure method of doing this sort of encryption:

$encrypted_password = strrev(base64_encode($password));

I know that isn't the best way to do it, but like I said, I'm new. Could anyone point my in the right direction?

Thanks.

jww
  • 97,681
  • 90
  • 411
  • 885
Duncan Palmer
  • 2,865
  • 11
  • 63
  • 91
  • possible duplicate of [Secure hash and salt for PHP passwords](http://stackoverflow.com/questions/401656/secure-hash-and-salt-for-php-passwords) – Peter O. Feb 02 '12 at 14:15
  • Also see Openwall's [Portable PHP password hashing framework](http://www.openwall.com/phpass/) (PHPass). Its hardened against a number of common attacks on user passwords. – jww Oct 11 '14 at 23:27

10 Answers10

5

Use bcrypt:

Bcrypt is an adaptive password hashing algorithm which uses the Blowfish keying schedule, not a symmetric encryption algorithm.

Community
  • 1
  • 1
ThinkingMonkey
  • 12,539
  • 13
  • 57
  • 81
2

Edit: You should take a look at hash_hmac(). I think it's a better approach than just salting.

You can use sha1 and a salt:

$salt = "some random string";
$encrypted_password = sha1($salt.$password);

You add the salt to make it harder to use rainbow tables in case somebody manages to get the encrypted password list.

You could use any one-way hashing method (I just like sha1), but it's always better to salt it before hashing.

Daniel Dinu
  • 1,783
  • 12
  • 16
  • Thanks. would it help security if I then encoded the salted sha1 password with base64 or some other encoding? or would that be pointless? – Duncan Palmer Feb 02 '12 at 07:18
  • I think salting a password and encrypting it using sha1 is more than enough. – Naveen Kumar Feb 02 '12 at 07:30
  • Ok sweet here is my final code (I put it into a function so it's cleaner to use) http://pastebin.com/zDT3FmSS – Duncan Palmer Feb 02 '12 at 07:35
  • @Duncan using global salt is somewhat vulnerable to rainbow tables attack. it's considered good thing to add some user-specific salt, a username or email would be enough. just don't forget to regenerate the hash in case of these credential changed. And don't forget the password strength – Your Common Sense Feb 02 '12 at 07:46
  • @Col. Shrapnel I changed it to make the salt the inputted username, it is working great! Thanks for the help. – Duncan Palmer Feb 02 '12 at 07:52
  • The salt is there to protect against cases of compromised databases. It would be reasonable to assume that if an attacker has the passwords he will have access to the usernames and emails too and, if they are used as salts, to the salts. I would keep the salt separate, in code, because the chances of an attacker getting access to both the code and the database are lower, and if somebody has access to the code, he can do whatever he wants anyway. – Daniel Dinu Feb 02 '12 at 08:00
  • @Duncan though I didn't say to change the salt, but *to add* a username to the global salt. – Your Common Sense Feb 02 '12 at 09:17
  • @Col. Shrapnel Oh, will it matter which way I do it though? – Duncan Palmer Feb 02 '12 at 11:34
0

use hash_hmac to store encrypted passwords

If you need clear text password, use des/aes/3des

suchasplus
  • 50
  • 7
0

Here is an article from Php.net that talks about "Safe Password Hashing".

From the article:

When hashing passwords, the two most important considerations are the computational expense, and the salt. The more computationally expensive the hashing algorithm, the longer it will take to brute force its output.

There are two functions that are bundled with PHP that can perform hashing using a specified algorithm.

The first hashing function is crypt(), which natively supports several hashing algorithms. When using this function, you are guaranteed that the algorithm you select is available, as PHP contains native implementations of each supported algorithm, in case one or more are not supported by your system.

The second hashing function is hash(), which supports many more algorithms and variants than crypt(), but does not support some algorithms that crypt() does. The Hash extension is bundled with PHP, but can be disabled during compile-time, so it is not guaranteed to be available, while crypt() is, being in the PHP core.

The suggested algorithm to use when hashing passwords is Blowfish, as it is significantly more computationally expensive than MD5 or SHA1, while still being scalable.

Roman
  • 10,309
  • 17
  • 66
  • 101
0

You should look at php's hash() function: http://se2.php.net/manual/en/function.hash.php

With this you can use lots of different hash algorithms, I usually go with sha256, and add a salt to it before hashing it.

fredrik
  • 13,282
  • 4
  • 35
  • 52
0

Passwords should be hashed, not encrypted. That is, you should not be able to decrpyt the password. Instead, you should compare hashes.

  1. User sets password $password = 'hX4)1z'
  2. You get hash of password and store to DB:

    $pw = hash_hmac('sha512', 'salt' . $password, $_SERVER['site_key']); mysql_query('INSERT INTO passwords (pw) VALUES ('$pw');

  3. Customer comes back later. They put in their password, and you compare it:

    mysql_query('SELECT pw FROM passwords WHERE user_id = ?'); //$pw = fetch

    if ($pw == hash_hmac('sha512', 'salt' . $_REQUEST['password'], $_SERVER['site_key']) {

    echo "Logged in";

    }

I suggest using SHA2 with a salt to store your password.

To create a SHA2 hash, use this:

$hash = hash("sha512", $password.$salt);

A salt contains some extra characters to add to your password before hashing to prevent rainbow tables (databases of passwords and it's hashes). You can create one using a unique user info (like a user_id) or just create a random one and store it somewhere. Just make sure the salt is long enough.

Frankline
  • 40,277
  • 8
  • 44
  • 75
0

normally it is better not to encrypt a password, but to hash it.

the difference is that encryption is encoding a string, leaving the possibility to decode it. hashing is "one-way" - once you "hash" something, you cannot de-hash it. some strings can be hashed into the same result, but good hashing reduces the chance of a collision.

It is best to avoid storing actual passwords, since people tend to use a single common password to multiple websites. this means that you can access their accounts on other websites (or if you are leaked, the hacker can).

it's common to hash the password string together with "salt". This is some random string that it difficult to guess, like &%P)#@M@#)+!@~!@4320`2#@!$0 or something of that sort. Common hash methods are md5/sha1 (or other sha method).

so you would have:

$password = '....';
$enc_pass = sha1( '%^$sd%MDdF)@I#)3asd3223#@4*^&(*&@#' . $password );

$enc_pass will be stored in the database, and after a login form, the result will be hashed (as above) and compared to the value in the database.

PS: don't forget to have your database column of a size that would contain the entire password ;)

galchen
  • 5,252
  • 3
  • 29
  • 43
0

I'd just like to add that storing a hash of the passwords does not automatically make the authentication process secure. What you also should employ is a decent password policy. The reason is, even if you have the most sophisticated hash algorithm of all time, and a user uses the password "password" or "1234", then the algorithm is useless, because the password can be simply guessed.

ralfe
  • 1,412
  • 2
  • 15
  • 25
0

Don't forget to make a restriction on password strength.
Because password strength is a weakest part of the whole thing.

As long as your users do use weak passwords, no salt nor extra-secure hashing routine would be of any help.

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
-2

The best hashing algorithm you can use is salted MD5 hashing where you insert some random characters inside the MD5 hashed string for that particular object. But you must remember the positions where you had inserted the random characters. This is required so that you can decrypt the hashing to obtain the original object or string.

      $random="abcd";
      $hashed=md5(your_string);
      $salted_hash=$hashed.$random;

This is the simplest example where I have just concatenated the hashed and salt. but you can insert the salt string somewhere in the middle.

bluechill
  • 437
  • 1
  • 7
  • 24
  • 3
    This is bad advice for multiple reasons: 1. It's easy to find collisions in MD5 nowadays. Better algorithms include `bcrypt` and `PBKDF2`. 2. The salt is appended to the *hash*, not the password, making dictionary attacks viable again as long as an attacker knows two or more hashes. 3. Hashes are designed to be one way; it is not the same as encryption which is two-way. – Peter O. Feb 02 '12 at 14:24