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...

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
Luke
  • 2,038
  • 3
  • 22
  • 46
  • `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. – sberry Feb 26 '16 at 07:43
  • @sberry, should the salt be different even? – Luke Feb 26 '16 at 07:45
  • @1615903, sadly, I don't have 5.3.7. – Luke Feb 26 '16 at 09:06

1 Answers1

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.

1615903
  • 32,635
  • 12
  • 70
  • 99
  • Your question was "Why is this happening" so I answered that - I have now modified my answer to include suggestions to improve the situation. – 1615903 Feb 26 '16 at 09:25
  • Yes! That's good :). But is this also good? `$password = crypt($password,'$6$rounds=5000'.$salt.'$');` – Luke Feb 26 '16 at 10:19
  • 2
    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? – 1615903 Feb 26 '16 at 10:32
  • @Mirabilis - It really depends on your PHP version, for 5.3.7 you can use the [compatibility pack](https://github.com/ircmaxell/password_compat/blob/master/lib/password.php), 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](http://www.openwall.com/phpass/). – martinstoeckli Feb 26 '16 at 15:35
  • @1615903, I have PHP Version 5.2.17-MIT-BACKPORT-GnuTLS. – Luke Feb 26 '16 at 20:29