Asked  7 Months ago    Answers:  5   Viewed   55 times

I am trying out a new function from PHP 5.5 called password_hash().

No matter what i do the $hash and the $password wont match.

$password = "test";

$hash = "$2y$10$fXJEsC0zWAR2tDrmlJgSaecbKyiEOK9GDCRKDReYM8gH2bG2mbO4e";



if (password_verify($password, $hash)) {
    echo "Success";
}
else {
    echo "Error";
}

 Answers

66

The problem with your code is that you are using the double quotation marks " instead of the single quotation marks ' when dealing with your hash.

When assigning:

$hash = "$2y$10$fXJEsC0zWAR2tDrmlJgSaecbKyiEOK9GDCRKDReYM8gH2bG2mbO4e";

It's making php think you have a variable called $2y and another one called $10 and finally a third one called $fXJEsC0zWAR2tDrmlJgSaecbKyiEOK9GDCRKDReYM8gH2bG2mbO4e. Which obviously isn't the case.

I noticed when turning on error reporting that the error:

Notice: Undefined variable: fXJEsC0zWAR2tDrmlJgSaecbKyiEOK9GDCRKDReYM8gH2bG2mbO4e

Was being thrown by PHP.

Replace all your double quote marks with single quote marks to fix.

E.g

$hash = '$2y$10$fXJEsC0zWAR2tDrmlJgSaecbKyiEOK9GDCRKDReYM8gH2bG2mbO4e';

Treats the whole hash as a literal string instead of a string with embedded variables.

Wednesday, March 31, 2021
 
Sethunath
answered 7 Months ago
10

My best guess is that the filename itself isn't using UTF-8. Or at least scandir() isn't picking it up like that.

Maybe mb_detect_encoding() can shed some light?

var_dump(mb_detect_encoding($filename));

If not, try to guess the encoding (CP1252 or ISO-8859-1 would be my first guess) and convert it to UTF-8, see if the output is valid:

var_dump(mb_convert_encoding($filename, 'UTF-8', 'Windows-1252'));
var_dump(mb_convert_encoding($filename, 'UTF-8', 'ISO-8859-1'));
var_dump(mb_convert_encoding($filename, 'UTF-8', 'ISO-8859-15'));

Or using iconv():

var_dump(iconv('WINDOWS-1252', 'UTF-8', $filename));
var_dump(iconv('ISO-8859-1',   'UTF-8', $filename));
var_dump(iconv('ISO-8859-15',  'UTF-8', $filename));

Then when you've figured out which encoding is actually used, your code should look somewhat like this (assuming CP1252):

$filename = htmlentities(mb_convert_encoding($filename, 'UTF-8', 'Windows-1252'), ENT_QUOTES, 'UTF-8');
Wednesday, March 31, 2021
 
MDDY
answered 7 Months ago
71

From the HTML 4.01 specification, §17.2, "Controls":

A control's "control name" is given by its name attribute.

...

When a form is submitted for processing, some controls have their name paired with their current value and these pairs are submitted with the form.

"id" does not matter.

Wednesday, March 31, 2021
 
nomie
answered 7 Months ago
64

So let's take it one part at a time

but it returns a different hash every time

That's the idea. password_hash is designed to generate a random salt every time. This means you have to break each hash individually instead of guessing one salt used for everything and having a huge leg up.

There's no need to MD5 or do any other hashing. If you want to raise the security of password_hash you pass a higher cost (default cost is 10)

$password = password_hash($password4, PASSWORD_DEFAULT, ['cost' => 15]);

As to verify

if(password_verify($password4, $dbpassword))

So $password4 should be your unhashed password and $dbpassword should be the hash you've stored in your database

Friday, June 11, 2021
 
skrilled
answered 5 Months ago
62

Ok, Let's go through this one by one.

First, it's hashing, not encryption. Encryption is two-way, hashing is one way. We want to hash. We never want to encrypt. Yes, terminology matters. Please use the correct terminology.

Next, each call to password_hash is supposed to return a different hash. That's because it's generating a strong random salt. This is how it was designed, and how you really should be using it.

Further, DO NOT do the "pepper" thing of adding __STR before and after the password. You're doing nothing but potentially weakening the users password (which is not good). If you want more information around why that's a bad idea: Read This Answer.

Continuing, I would highly recommend that you do not use crypt directly. It is actually surprisingly easy to screw up and generate extremely weak hashes. This is why the password_* api was designed. crypt is a low level library, you want to use a high level library in your code. For more information on ways to screw up bcrypt, check out my blog: Seven Ways To Screw Up Bcrypt.

The Password API was designed to be a simple, one-stop shop. If it's not working for you check the following things:

  1. Are you using PHP >= 5.5.0? Or are you using PHP >= 5.3.7 with password_compat?

    1. Is your database column wide enough?

      It needs to be at least 60 characters long.

    2. Are you checking that the result of the function is a string, and not bool(false)?

      If there is an internal error, it will return a non-string from password_hash.

    3. Are you getting any errors?

      Have you turned on error_reporting to its maximum setting (I recommend -1 to catch everything) and checked that the code isn't throwing any errors?

    4. Are you sure you are using it correctly?

      function saveUser($username, $password) {
          $hash = password_hash($password, PASSWORD_BCRYPT);
          // save $username and $hash to db
      }
      function login($username, $password) {
          // fetch $hash from db
          return password_verify($password, $hash);
      }
      

      Note that each one should be called only once.

  2. Are you using PHP < 5.3.7 with password_compat? If so, this is your problem. You are using the compatability library on an unsupported version of PHP. You may get it to work (certain RedHat distributions have backported the necessary fixes), but you are using an unsupported version. Please upgrade to a reasonable release.

If all else fails, please try running this code and reporting back the output:

$hash = '$2y$04$usesomesillystringfore7hnbRJHxXVLeakoG8K30oukPsA.ztMG';
$test = crypt("password", $hash);
$pass = $test == $hash;

echo "Test for functionality of compat library: " . ($pass ? "Pass" : "Fail");
echo "n";

If that returns Fail, you are running an unsupported version of PHP and should upgrade. If it returns pass, than the error is somewhere in your logic (the library is functioning fine).

Sunday, August 1, 2021
 
Semirix
answered 3 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :