1

Because I am using an older version of PHP, I have to use .crypt(). I was testing some password validation, and the server was validating the wrong password as correct. I then decided to go to the most basic test possible, and I still have this issue:

<?php
echo crypt("cryptcryptcrypt","salt");
echo "<br>";
echo crypt("cryptcryptcrypta","salta");
?>

– and the result is:

saRyxun8Pn/K6
saRyxun8Pn/K6

Why is this hapening?


For testing purposes, I am using PhpFiddle, so you may find this useful when answering...

3
  • It also only uses the first eight characters of str, so longer strings that start with the same eight characters will generate the same result (when the same salt is used). explains part of the problem. Why they generate the same output for two different salts is another question entirely. Commented Feb 26, 2016 at 7:43
  • @sberry, should the salt be different even? Commented Feb 26, 2016 at 7:45
  • @1615903, sadly, I don't have 5.3.7. Commented Feb 26, 2016 at 9:06

1 Answer 1

8

Quoting the docs:

The standard DES-based crypt() returns the salt as the first two characters of the output. It also only uses the first eight characters of str, so longer strings that start with the same eight characters will generate the same result (when the same salt is used).

The salt you provide is only 4 or 5 characters long, which makes crypt use the standard DES-based algorithm. So, only the first 9 chars of password are used, and only the first two chars of salt are used. Therefore your hashes are equal. You really should update your PHP version so you can use the modern password_hash functions. If that's not possible, try using http://www.openwall.com/phpass/ which is compatible with PHP version 3 and above. If that's not possible read on...

You need to pass the salt in correct format to the crypt function. From the examples in the docs:

if (CRYPT_BLOWFISH == 1) {
    echo 'Blowfish:     ' . crypt('rasmuslerdorf', '$2a$07$usesomesillystringforsalt$') . "\n";
}

if (CRYPT_SHA256 == 1) {
    echo 'SHA-256:      ' . crypt('rasmuslerdorf', '$5$rounds=5000$usesomesillystringforsalt$') . "\n";
}

if (CRYPT_SHA512 == 1) {
    echo 'SHA-512:      ' . crypt('rasmuslerdorf', '$6$rounds=5000$usesomesillystringforsalt$') . "\n";
}

The beginning of the hash defines which algorithm to use. You also need to make sure that you use random unique salt for each user.

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

5 Comments

Your question was "Why is this happening" so I answered that - I have now modified my answer to include suggestions to improve the situation.
Yes! That's good :). But is this also good? $password = crypt($password,'$6$rounds=5000'.$salt.'$');
That would require support for SHA-512 which requires PHP 5.3.2, I had the impression that you were using an older version. Which PHP version do you have?
@Mirabilis - It really depends on your PHP version, for 5.3.7 you can use the compatibility pack, for 5.3 you can change the algorithm in the compatibility pack from 2y to 2a, and for even smaller versions you should use the mentioned phpass library.
@1615903, I have PHP Version 5.2.17-MIT-BACKPORT-GnuTLS.

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.