1

I am running into some issues with my log in system. If I set my user password to 'TestPassword1234', 'TestPassword' will be accepted as the password.

After testing some more I found out that the following code will result in two identical hashes being created even though the string passed is not the same.

It is important to know that all salts used are generated by this function. One is generated per test and the same one is used to hash both strings (just like it would be when logging a user in).

function GUID() {
    if (function_exists('com_create_guid') === true) { return trim(com_create_guid(), '{}'); }

    return sprintf('%04X%04X-%04X-%04X-%04X-%04X%04X%04X', mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(16384, 20479), mt_rand(32768, 49151), mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535));
}

The above function was sourced from a stack overflow question, I am not sure which.

This is not the case if the password is fundamentally changed, see below for tests.

The following snippet shows two different passwords resulting in the same hash.

$guid = GUID();

echo( crypt("TestPassword1234", $guid ) ); //455nKS7NToPuY
echo("<br />");
echo( crypt("TestPassword", $guid ) ); //455nKS7NToPuY (the same!)

This snippet shows two different passwords not resulting in the same result even though they follow a similar pattern to the above snippet

$guid = GUID();

echo( crypt("Test1234", $guid ) ); //BBWxwWzIXAOQI
echo("<br />");
echo( crypt("Test", $guid ) ); //BBhe4TjDcO5XA (different...)

I assume the problem originates from the use of the GUID function. Perhaps it is faulty or only supports a password with a max length of x. I have no idea and cannot track down the SO question I found it on.

Help is much appreciated.

5
  • 2
    Use password_hash instead. You should not generate a salt yourself as password_hash automatically generates a safe salt for you. Commented May 14, 2016 at 5:22
  • You found that function here - php.net/manual/en/function.com-create-guid.php#99425 Commented May 14, 2016 at 5:26
  • I can't use password_hash, my webhost uses a version of PHP which doesn't have that function. Commented May 14, 2016 at 5:34
  • 1
    Use the compatibility pack if you have >= 5.3.7 github.com/ircmaxell/password_compat If not, you should probably consider changing the webhost since even 5.3 is just too old. Ask your webhost to upgrade PHP anyway. I don't know how some webhost provider can just accept the responsibility for serving old, outdated since 5+ years, PHP versions. That's just ununderstandable. Commented May 14, 2016 at 5:57
  • I am using 000webhost which is providing PHP version 5.2.* Commented May 14, 2016 at 5:58

1 Answer 1

3

To use crypt() you must comply to one of the algorithm salt formats listed in the manual. You are not following one of the formats and as such PHP is reducing your salt down to the first two characters, and calculating it using the DES algorithm. DES only uses the first 8 characters and as such you are only hashing "TestPass" with the same salt twice.

The better thing to do is use password_hash() instead. However, as you mentioned your host does not support password_hash().

If crypt() is the final choice then you will require to format a salt correctly. However, the best of algorithms to chose from with crypt() only allows a max of 16 characters for the salt. As such using a GUID is not the best choice due to most of the data going un-used.

Here is an example using a secure random byte generator, This will only work on PHP 5.3.2 and beyond:

function newSalt() {
    $salt = bin2hex(openssl_random_pseudo_bytes (8));
    return '$5$'.$salt;
}


$salt1 = newSalt();
$salt2 = newSalt();

echo( crypt("TestPassword1234", $salt1 ) );
echo("<br />");
echo( crypt("TestPassword", $salt2 ) );

You can store the salt for later using by storing the values generated from newSalt()

Edit: OP's PHP installation is too old for any decent implementations. I highly suggest finding a server that supports a higher version. I hope that my example helped you or someone else, as well as the reasoning due to the original password similarities.

Sign up to request clarification or add additional context in comments.

7 Comments

When trying to use this code I get an error: Call to undefined function random_bytes()
@Harry I failed to notice that 5.2 supports neither random_bytes, or the SHA algorithm for crypt() Your best bet is to choose a new host that has a more up to date version or host locally if you are just messing around. There are a few different random things you could do for such an old version, but none of which I am willing to post due to their insecurities and poor practices.
Well, it appears I am screwed... Thanks anyway.
Random_byte is a PHP7 function, so instead use OpenSSL random pseudo bytes . @Harry
Tested and I am running PHP version 7.0.4. I have switched to password_hash and password_verify and am using BCRYPT to hash user passwords. Thanks all
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.