Jump to content

Password_Hash And Salt Uniquess


phdphd

Recommended Posts

Hi All,
I guess that people who developed password_hash did it with salt uniqueness in mind. However is it possible that two users defining the same password get the same "hash-salted" version of it ? If so, how to prevent this situation?
Thanks.

Link to comment
Share on other sites

Possible? probably, and I mean that in the "anything's possible" kind of way.

Likely to happen in the real world? No, unless for some crazy crazy reason you use a static salt for all passwords)

How to prevent it? Why would you bother? Even if it were to happen, what harm do you envisage? Technically you could put a unique index on the DB column and then request the user try a different password if it throws a duplicate entry error (just don't tell the user why their password doesn't work!). But the chances of the same random salt being generated for the same password the one time another user registers it is infinitesimal (like one times ten to the minus several billion). Of course enforcing a good password requirement will reduce the chance of raw password collisions as well.

Link to comment
Share on other sites

If so, how to prevent this situation?

Don't do anything. The only thing you should ever do with a password is make sure it is "secure enough": letters, numbers, symbols, minimum length, not a common password, doesn't contain their username, that stuff. The odds of two users picking the same password and getting the same salt are astronomical and, most importantly, it doesn't matter if it happens. (Would be cool to see, though.)

 

in b4 jacques

  • Like 1
Link to comment
Share on other sites

@requinix I'd like to see the numbers on how many users it would take to guarantee a duplicate hash assuming every one used the same password. Also I like using phrases for passwords over actual words eg. "I used to live at 221b Bakers Street, but got fed up with Danger Mouse ruining all the letters I put in the post box" would be a good one  :happy-04:

Link to comment
Share on other sites

Not so much related with the above subject/comments, but might be interesting to know; I have been playing with an online php editor (http://sandbox.onlinephpfunctions.com/).

$string='hel$lo';
echo 'string is '.$string."\n";//displays "string is hel$lo"
echo password_hash($string, PASSWORD_DEFAULT)."\n";

is ok, while

$string="hel$lo";
echo 'string is '.$string."\n";//displays "string is hel"
echo password_hash($string, PASSWORD_DEFAULT)."\n";

would still generate a hash, but also an "Undefined variable: lo" warning, apparently due to double quotes. Actually only "hel" is taken into account.

Link to comment
Share on other sites

@Jacques1 : thanks for the link, though I'd be lying if I said I understood half of the formula on that page.  It doesn't look like the answer to what I was asking though.  Assuming URANDOM is being used to create the salt, how many times would the same password have to be put trough the same algorithm in order to guarantee a collision?

 

Is that what you answered?

Link to comment
Share on other sites

Is that what you answered?

 

A random number generator doesn't guarentee anything – except the trivial fact that you're guaranteed to get duplicates when you've run out of salts. If that's what you wanted to know, the answer is 2^128 + 1 (the number of possible 128-bit salts and one more).

 

A much more practical problem is to actually take the randomness into account and calculate the number of required users to reach a certain duplicate probability. That's what I was referring to in my reply: To get a 50% chance of identical hashes when the salts are random and the passwords are idential, you need around 2.2E19 users.

 

The latter number is a lot smaller and can actually be alarming for shorter salts. For example, a 64-bit salt seems astronomical as well when you look at the number of possible values (~10^19). But it only takes a few billion users to end up with a 50% chance of a collision. This may not happen in a single application, but it will certainly happen accross multiple applications.

  • Like 1
Link to comment
Share on other sites

As to the original question: While the salt isn't a problem, there are problems with the code.

 

Do not rely on PASSWORD_DEFAULT. The whole point of modern password hash algorithms is to make the hashing as expensive as possible within the limits of your hardware. If you just go with the (low) default parameters, your hashes will be weaker than necessary. A better stratety is to choose a specific algorithm (PASSWORD_BCRYPT is the only one right now) and then increase the cost parameter until the duration is no longer acceptable. The previous value is the optimimum.

 

Also don't hash passwords directly. The current bcrypt algorithm in particular cannot handle arbitrary input. Long passphrases (like the one by Muddy_Funster) and null bytes will lead to truncation, meaning the hash is again a lot weaker than expected. A common workaround is to pre-hash the password with another hash algorithm like SHA-256:

<?php

function bcrypt_hash($password, $cost)
{
    /*
     * Pre-Hash the password with SHA-256 to obtain a 256-bit binary hash. Then encode the binary hash with Base64 to get a
     * string of 43 ASCII characters. This makes sure the string is within the length limit of bcrypt (56 bytes) and doesn't
     * contain any null bytes.
     */
    $binary_prehash = hash('sha256', $password, true);
    $encoded_prehash = rtrim(base64_encode($binary_prehash), '=');

    return password_hash($encoded_prehash, PASSWORD_BCRYPT, ['cost' => $cost]);
}



$raw_password = 'I used to live at 221b Bakers Street, but got fed up with Danger Mouse ruining all the letters I put in the post box';
$cost = 12; // adjust this to your current hardware

var_dump( bcrypt_hash($raw_password, $cost) );

---

 

 

Yeah, the first bit was what I was asking about.  I wasn't sure what the word length of URANDOM was, so didn't know.

 

128 is the bit length of bcrypt salts. It has nothing to do with randomness. You'd have the same limit if you used sequential salts.

Edited by Jacques1
Link to comment
Share on other sites

Thanks Jacques.

 

What would be the right password_verify() syntax ?

 

I applied your function to "hello" as password, and obtained string(60) "$2y$12$4HJ4ttxHjrmhnNamYZPftehUIlZ.IkQndxDca50kid.lmSXLjhTqy".

 

Then I ran :

$hash = '$2y$12$4HJ4ttxHjrmhnNamYZPftehUIlZ.IkQndxDca50kid.lmSXLjhTqy';

if (password_verify('hello', $hash)) {
    echo 'Password is valid!';
} else {
    echo 'Invalid password.';
}

And got "Invalid password."

Link to comment
Share on other sites

You have to go through the exact same prehashing procedure as above.

function bcrypt_verify($password, $hash)
{
    $binary_prehash = hash('sha256', $password, true);
    $encoded_prehash = rtrim(base64_encode($binary_prehash), '=');

    return password_verify($encoded_prehash, $hash);
}
Link to comment
Share on other sites

As explained in the second answer, the mysql_* functions are ancient and have been removed from PHP. Manual SQL-escaping in general is deprecated, because it's far too error-prone (as you can see).

 

Nowadays, we use PDO (or mysqli) together with prepared statements. The query string is supposed to be entirely static with no variable insertion of any kind. If you need dynamic input, you use query parameters and then bind the input to those parameters.

 

This not only solves your current problem. It eliminates the risk of SQL injections altogether (as long as the query strings are in fact static).

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.