What's Your Prefered Hashing Method

After getting the hang of the crypt() function it got me wondering what other hashing functions there were so I had a look and dug up two:

  • hash()
  • mcrypt()

I put together this to see what sort of hash they would give out using password as the password (I would hope that no-one would ever use that as a password for a real site):

<?php

/*
Hashing Functions Testing
*/

$password = 'password';
$salt=str_shuffle('AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz012345678987654321');

// hash (Using sha512)
echo '<p>hash() using sha512</p>';
$password1 = hash_function($password,$salt);
echo "<p>Password: $password1</p>";

// mcrypt (Using rijndael-256)
echo '<p>mcrypt using rijndael-256</p>';
$password1 = mcrypt_function($password,$salt);
echo "<p>Password: $password1</p>";

// crypt (Using sha512)
echo '<p>crypt using sha512</p>';
$password1 = crypt_function($password,$salt);
echo "<p>Password: $password1</p>";

function hash_function($password,$salt) {
    $count=0;
    while ($count < 5000 ) {
        $count=$count+1;
        $password = hash('sha512',"$password.$salt");
    }
    $final_password = $password;
    return $final_password;
}

function crypt_function($password,$salt) {
    $salt=substr($salt,0,16);
    $crypt_salt='$6$rounds=5000$'.$salt.'$';
    $password=crypt($password,$crypt_salt);
    $final_password = $password;
    return $final_password;
}

function mcrypt_function($password,$salt) {
    $salt=substr($salt,0,32);
    $td = mcrypt_module_open('rijndael-256', '', 'ecb', '');
    $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
    mcrypt_generic_init($td, $salt, $iv);
    $password = mcrypt_generic($td, $password);
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);
    $final_password = $password;
    return $final_password;
}
?>

Output:

hash() using sha512
Password: 2730720b94c219014ed3e45e0d675d3ab86a7a4aad3a2f654e205af1ca5ea0f7c416b735a65e0d5b186ebadaf2ef06bf68f707a1efd24ea394eea74f8a92c34b
mcrypt using rijndael-256

Password: m vÈ‚Õ«äµÞ•/³h…$ÁÀHyîÁŠ˜"~Ð

crypt using sha512
Password: $6$rounds=5000$K5NFMuw1koxQmA7G$8WuiGFmH7AxI5BmULbAhplz4nxMcz.1eHf6WfQKW4RfLDM2dO8VMOGCkaI1h97HIoYwvOvBYPRJfshHcaO479/

At the moment I’m leaning towards using mcrypt with rijndael-256, reading up on rijndael-256 it appears that realistically it’s uncrackable (well it looks like any hacker would need some ridiculously expensive and powerful hardware). Also the has string is shorter so won’t take up so much disk space (assuming a site ever gets more then 1,000 members).

What is you’re preferred function (and algorithm) and why?

spl_object_hash()?

Some quick comments:

$salt=str_shuffle(‘AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz012345678987654321’);

This doesn’t allow characters to repeat. So, for example, “A” can appear once and only once. That behavior reduces its randomness.

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

There’s what’s called a length extension attack. Since the salt will be a known value, an attacker could “rewind” the hash function to its state before the salt was applied. That’s why established algorithms such as PBKDF2 will use HMAC to combine the salt with the password.

$td = mcrypt_module_open(‘rijndael-256’, ‘’, ‘ecb’, ‘’);
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $salt, $iv);
$password = mcrypt_generic($td, $password);

The problem here is that both the salt and the IV will be known values (otherwise you could never repeat the process, for example, to check if a user entered the correct password). And if both the salt and IV are known, then an attacker could – rather simply – decrypt the result and recover the password. The fatal flaw is that you used the salt to encrypt the password. You should have used the password to encrypt the salt. You’re correct that AES/Rijndael is currently uncrackable, but how you use the algorithm is just as important as the algorithm itself. You need to be very, very careful. That’s why it’s best to use known-good algorithms (such as PBKDF2/bcrypt/scrypt) rather than to roll your own solution.

Your best bet is to use the password hashing functions (new to PHP 5.5). This way, you won’t have to specify an algorithm, a cost, or even a salt. It does it all for you, and it does it right. If you need to support versions of PHP earlier tha 5.5, then you can use this [URL=“https://github.com/ircmaxell/password_compat”]forward compatibility library.

Are the new hashing passwords in PHP 5.5 basically identical (currently) to using crypt with blowfish, except easier to use?

Correct. Easier to use, plus it will deal with the salt for you, because even trying to make your own salt can introduce mistakes. Now you don’t need to know or do anything except to invoke hash and verify.

Just trying the forward compatibility library, it looks like it has one or more bugs in it. On a single run the password_hash function gives as the hash for the password ‘password’:

$2y$10$I4MNxYpsAEPxt5S/fy0csOw258RYIDcOSI8yBAKeQM.B0R9ua38hG

In the password_verify function, using var_dump to get the has it has generated I get:

$2y$10$I4MNxYpsAEPxt5S/fy0csO60fFYiJx4N6K0hgWNK.emI4cm57l7W.

so the password will always be rejected.

<?php

// Pasword Functions test

require_once 'password.php';

$password = 'password';
$hash = password_hash('$password',PASSWORD_BCRYPT);
echo "The password hash for the password '$password' is $hash";

$password_info = password_get_info($hash);
var_dump($password_info);

$match = password_verify($password, $hash);
var_dump($match); 
?>

That’s the test code, the output from all that is:

The password hash for the password ‘password’ is $2y$10$I4MNxYpsAEPxt5S/fy0csOw258RYIDcOSI8yBAKeQM.B0R9ua38hGarray I[/I]
‘algo’ => int 1
‘algoName’ => string ‘bcrypt’ I[/I]
‘options’ =>
array I[/I]
‘cost’ => int 10
string ‘$2y$10$I4MNxYpsAEPxt5S/fy0csO60fFYiJx4N6K0hgWNK.emI4cm57l7W.’ I[/I]
boolean false

I don’t have any plans to upgrade to php 5.5 for the time being

You may slap yourself over this one. :wink:

$hash = password_hash('$password,PASSWORD_BCRYPT);

Should be…

$hash = password_hash($password,PASSWORD_BCRYPT);

interesting and slightly on-topic: http://www.unlimitednovelty.com/2012/03/dont-use-bcrypt.html

what sucks about security is it must be performed by those who know little about it. Not all or even most car drivers can be mechanics, and most web sites are not built by sec guys and cypherpunks. Libraries built by these people for use by the rest of us === jawsome.

We use Python so we use passlib.

Interesting article, however while the author clearly states “don’t use bcrypt” his arguments for doing so sound weak to me. The only one seem to be that bcrypt has been less studied than PBKDF2, which is not clear to me either from reading this article since he doesn’t back up this claim with any sources. The comment by perseids who disagrees with the author doesn’t sound wrong, either.

Having said that - I still don’t know. You are right that most people don’t know a lot about cryptography and so use the tools provided by available libraries. This is a very broad subject and would certainly require a LOT of time to study and we normal ‘car drivers’ don’t have the time to do so. I have spent many, many hours reading about various password hashing methods and what I use is based on the opinion of experts I found most trustworthy - so I use bcrypt but how do I know if it’s the best choice? I have no capability of checking this on my own. From time to time an article like this pops up somewhere, I think I have learned something new only to find out a counter argument by someone else and I’m back to square one.

At least people are moving from using plain hashes, plain salted hashes and other self-invented algorithms to bcrypt - I think it’s still much better than any of the former methods.

Interesting article, however while the author clearly states “don’t use bcrypt” his arguments for doing so sound weak to me.

It starts out with “don’t use bcrypt” and then goes on to say “if you’re using it already, fine”… because I think his point really wasn’t any real issues with bcrypt itself, but with the mantra of “use bcrypt”, and then tried to come up with some possible problems with bcrypt that certainly anyone simply told to use bcrypt or whatever wouldn’t know about. Since they’re somewhat theoretical, I wouldn’t use this article as any actual reason NOT to use bcrypt.

I suppose his real point is not to be too thoughtless with choosing something, or not to simply repeat to others “use x”. <– something I practically make my living doing :stuck_out_tongue:

I have no capability of checking this on my own.

Yeah, this is our problem and I think libraries are for now the best answer for it. That said, since we are ultimately the ones responsible, we are probably required to do some homework when we can, at least so that if we hear “use bcrypt” we have some ideas why. Or, if we know where we could check if our libraries are indeed good enough, since we can’t tell ourselves.

At least people are moving from using plain hashes, plain salted hashes and other self-invented algorithms to bcrypt - I think it’s still much better than any of the former methods.

Agreed.

I tried to have this conversation on here before and it degraded into *****iness. Personally I think that the average developer doesn’t understand how these work or why one is better than another. What I do believe is that people who know a lot more about these things than most of us recommend bcrypt. I use bcrypt mostly because of this. I know quite a bit about the subject, but not enough to argue for or against bcrypt. I just go with the experts.

One thing I do agree on though is that if it can be decrypted, it’s unsuitable. Hash, don’t encrypt

md5() works fine with me. :slight_smile:

Troll :slight_smile:

I don’t get how overlapping crypts are supposed to be hackable, especially with random salt… md5(md5($password).$salt) Without access to the algorythm, how do you unwork that? Aren’t hashes supposed to be destructive, in that there is no way to retrieve the input data for certain once the algorythm runs?

I’ve been using PHP 5.5’s password methods because I know I’m no expert. Still, I used the algorythm above, which I first saw in vbulletin 3, for many years and never had a server compromised. What gives?

The point is that with brute-forcing it still doesn’t take long to calculate an md5() value, compared to, say, a bcrypt value. Plus collisions are more probable in md5()

How do you brute force a 3 strikes system that blocks further tries for 15 minutes? And who doesn’t use a striking system specifically to halt bruting?

If I have your data, why would I be entering it into your application to work it out though? Presumably you store your random salts alongside the hash value, yes? Oh, and does your application specify a password policy? Such as 7 characters, contains one number, one symbol and at least one character of both upper and lower case? Makes it much simpler to know what is a genuine password and what’s not pretty quickly. I have all of your passwords, remember, not just one. Makes it MUCH easier to work out your relatively simple algorithm, even without your source

This is irrelevant here, the purpose of strong hashing techniques is not to stop brute forcing over the network through a system protected with a striking system. From this perspective you can store all passwords in plain text and it will be just as secure. The point is what an hacker can do once he gets hold of your database.

Wasn’t md5 created more for checksumming rather than protection?

A recent-ish real-life example for everyone:

http://www.telegraph.co.uk/technology/news/8475728/Millions-of-internet-users-hit-by-massive-Sony-PlayStation-data-theft.html

and