1

I have this code

<?php
error_reporting(E_ALL);
    $caratteri_disponibili ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
    $lunghezza= 50;
    $code = "";
    for($i = 0; $i<$lunghezza; $i++){
        $code = $code.substr($caratteri_disponibili,rand(0,strlen($caratteri_disponibili)-1),1);
    }
$hashed_password = crypt('mypassword',$code); 
?>

To crypt a password with a random salt. Error_reporting does not notify me about any mistakes, but when I try to check if the hashed password matches with an other input using this code (put in the same page of the previous one)

<?php
$input = "Hey";
if (crypt($input, $hashed_password) == $hashed_password) {
   echo "Password verified!";
}
?>

I'm told 'Password verified!' even if I should not. What am I doing wrong?

  • 2
    Closers, the question has the problem well described, the desired behavior and actual behavior explained, and a short piece of code that reproduces the problem. I don't see a reason to close or to vote this question down. – Madara's Ghost Jun 29 '14 at 13:23
  • You should be setting up your `$code` variable according to the specific formats explained in the documentation. That's the way to choose which algorithm is used. – deceze Jun 29 '14 at 13:29
  • [I cannot reproduce it](http://3v4l.org/BVm6Q). What exact output are you getting? – Álvaro González Jun 29 '14 at 13:31
  • @deceze in the documentation rules about how to choose the salt depend on the type of hashing used. How can I know which is the one I'm using? –  Jun 29 '14 at 13:36
  • @ÁlvaroG.Vicario I'm getting 'Password verified!' –  Jun 29 '14 at 13:37
  • Yeah, I know, but that's because the condition on previous `if()` is `true`. Why is it true? What does `crypt()` return that's always the same thing? – Álvaro González Jun 29 '14 at 13:38
  • That's the point. You're supposed to choose your algorithm with the way you set up the salt. A salt starting with `$2a$` and following the rest of the format specification means you're using blowfish (which is a good choice). – deceze Jun 29 '14 at 13:40
  • Applying 'var_dump($hashed_password, crypt($input, $hashed_password));' I get string(13) "hUV7r6EFejQoY" string(13) "hUV7r6EFejQoY" –  Jun 29 '14 at 13:40
  • @deceze thanks! I'm editing the code right now –  Jun 29 '14 at 13:42
  • Because you're not choosing a strong algorithm, you're probably falling back to some weak hash which isn't actually considering enough characters of the input. We'd need to see exact input and output here... – deceze Jun 29 '14 at 13:43
  • I edited my code using blowfish and now it seems to work. Thank you all for your help –  Jun 29 '14 at 13:48
  • You're missing `$hashed_password = crypt('Hey');` on top of `$input = "Hey";` – Funk Forty Niner Jun 29 '14 at 13:51
  • Thanks for your comment, but the two pieces of code were in the same file, so I didn't need to re-define the variable again –  Jun 29 '14 at 13:53
  • A 13-byte string technically means that nothing failed, so you're possibly obtaining bad default values. I've written an answer. – Álvaro González Jun 29 '14 at 14:00
  • To `crypt()` a password with a random salt already has a solution; it's called [`password_hash()`](http://php.net/password_hash). – Ja͢ck Jun 29 '14 at 14:01
  • @deceze It should be `$2y$`, not `$2a$`. – Ja͢ck Jun 29 '14 at 14:04

1 Answers1

2

The mechanism to select an algorithm is to provide a $salt with a given syntax. For instance, to select Blowfish you have to follow these rules:

Blowfish hashing with a salt as follows: "$2a$", "$2x$" or "$2y$", a two digit cost parameter, "$", and 22 characters from the alphabet "./0-9A-Za-z". [...] The two digit cost parameter is the base-2 logarithm of the iteration count for the underlying Blowfish-based hashing algorithmeter and must be in range 04-31, values outside this range will cause crypt() to fail.

Your salt (what you call $code) is a random 50-byte alphanumeric string does not seem to match any of the rules defined in the manual so what's happening is possibly this:

  • The function defaults to a given algorithm
  • Such algorithm ignores extra chars

To make it worse, some old hashing algorithms have a maximum string size.

The fallback algorithm is probably CRYPT_STD_DES:

Standard DES-based hash with a two character salt from the alphabet "./0-9A-Za-z".

In my system, only the 8 first bytes of passwords are considered:

var_dump( crypt('00000000 does not matter', 'aa does not matter') );
var_dump( crypt('00000000 how long passwords are', 'aa what I write here') );
var_dump( crypt('00000000 only 8 bytes count', 'aa because only first two bytes are used') );
string(13) "aaJfK9SF.cm2o"
string(13) "aaJfK9SF.cm2o"
string(13) "aaJfK9SF.cm2o"

Solution: don't let the system select default values for you.

Álvaro González
  • 142,137
  • 41
  • 261
  • 360