Jump to content

PHP 7.0.8 password_verify not returning a value


cjburkey01

Recommended Posts

So, basically, I have a simple database where users are stored.  password_hash is used to insert the passwords, but for some reason, this code:

 

$sql = $conn -> prepare("SELECT `password` FROM `users` WHERE `email`=:email LIMIT 1");
$sql -> bindParam(":email", $email);
$sql -> execute();
$out = $sql -> fetch();
print_r(password_verify($password, trim($out['password'])) . " - " . $password . " - " . $out[0]);
die();

displays this:

 

- spice - $2y$10$YOVX2MCk8KSpUuii5fEQ5.OUmRh09lEfF.wZ65jh4.PUB5wSgdHim

 

Even if I was using the wrong password, shouldn't it at least return false?  Is this some part of a new feature in PHP 7?

Link to comment
Share on other sites

when you try to print/echo/print_r a false value, you will get nothing.

 

if you want to know what the password_verify() statement is returning, use var_dump() on just that part of the value (if you concatenate it with a string, you will get a string result, and var_dump will show the string result, which will show nothing again from the false value.)

Link to comment
Share on other sites

when you try to print/echo/print_r a false value, you will get nothing.

 

if you want to know what the password_verify() statement is returning, use var_dump() on just that part of the value (if you concatenate it with a string, you will get a string result, and var_dump will show the string result, which will show nothing again from the false value.)

I'll try that, thanks :)

Link to comment
Share on other sites

I have just discovered my error.  It was extreme stupidity:

$sql -> bindParam(":password", password_hash($email, PASSWORD_DEFAULT));

should be

$sql -> bindParam(":password", password_hash($password, PASSWORD_DEFAULT));

in the register form.  *sigh*

 

 

 

Note that the correct hash for that password+salt is

$2y$10$YOVX2MCk8KSpUuii5fEQ5.fchxgv0ZkbWxTGnOcHwgqfvspDNsYlmso you do, in fact, have the wrong password.

 

 

Yup :(

Edited by cjburkey01
Link to comment
Share on other sites

Don't use PASSWORD_DEFAULT. The whole point of modern password hash algorithms is that they're adaptable, allowing your to set the parameters specifically for your hardware and your security requirements. When you just go with the default parameters, you get the lowest common denominator, not the strongest possible settings.

 

The bcrypt algorithm (which is currently the only available algorithm) also cannot handle long input. So a more reasonable setup would be:

<?php

/*
 * Adjust the settings to your hardware and security requirements. A high cost factor increases the hash strength, but
 * it also increases the waiting time for users and the risk of denial-of-service attacks. Targeting a one second delay
 * should be an acceptable compromise for standard user accounts. Critical accounts like administrators should have
 * more aggressive settings.
 */
const PASSWORD_HASH_ALGORITHM = PASSWORD_BCRYPT;
const PASSWORD_HASH_PARAMETERS = ['cost' => 12];     // example
const PASSWORD_MIN_LENGTH = 8;
const PASSWORD_MAX_LENGTH = 56;    // bcrypt is limited to 56 bytes of input



$password = '3b4PSv1m';     // test

if (strlen($password) < PASSWORD_MIN_LENGTH)
{
    die('Password is too short, must have at least '.PASSWORD_MIN_LENGTH.' bytes.');
}

if (strlen($password) > PASSWORD_MAX_LENGTH)
{
    die('Password is too long, can have at most '.PASSWORD_MAX_LENGTH.' bytes.');
}

$hash = password_hash($password, PASSWORD_HASH_ALGORITHM, PASSWORD_HASH_PARAMETERS);

var_dump($hash);
Edited by Jacques1
  • Like 1
Link to comment
Share on other sites

Since the whole point of password_hash() is so that you don't have to think about what the defaults are, make sure you keep up to date with any changes made to the function. Case in point, PHP will likely switch the default to argon2 soon so a hardcoded bcrypt will be out of date.

Link to comment
Share on other sites

If you want to conduct a surprise beta test with all of your customers, feel free to try out Argon2. As somebody who knows a bit about the bug-ridden history of password hash algorithms, crypt() and the hash API, I wouldn't recommend that.

 

And if you mean “out of date” as in “ext/mysql is out of date since 12 years, guys, please update your code”, relying on PASSWORD_DEFAULT means that people will run around with a cost factor of 10 for the next decade.

Edited by Jacques1
Link to comment
Share on other sites

requinex:

This would refute Jacques1 position that one should specify the algorithm and not use PASSWORD_DEFAULT. Hmmm... Of course, the manual also says what you imply - use the default constant and let the authors supply the actual algorithm so that (as you say) don't have to worry about it.

 

I'mmm soooo confused....

Link to comment
Share on other sites

Of course, the manual also says what you imply - use the default constant and let the authors supply the actual algorithm so that (as you say) don't have to worry about it.

 

The manual says the exact opposite:

 

 

It is recommended that you test this function on your servers, and adjust the cost parameter so that execution of the function takes less than 100 milliseconds on interactive systems.

http://php.net/manual/en/function.password-hash.php#refsect1-function.password-hash-notes

 

 

 

Adjusting the cost is critical for security. If you skip this step, you give up a major advantage, namely the ability to dictate the effort required for an attack.

 

And what exactly is the problem, anyway? You certainly have a configuration file somewhere. Add the hash settings, choose reasonable defaults according to how critical your application is, optionally adjust the settings when the application is deployed in production, and that's it. The chance that you have to update the algorithm within the lifetime of the application is neglectable. bcrypt has been around for almost 20(!) years, and it's still perfectly fine. In fact, I would not switch to a new algorithm until it has proven itself for many years as well. There's always a chance that the algorithm itself has fatal flaws, and the implementations will definitely have tons of bugs during the initial phase.

Edited by Jacques1
  • Like 1
Link to comment
Share on other sites

You cannot leave the algorithm open and then start setting algorithm-specific parameters like a “cost”. For example, Argon2 has no “cost” at all, it has multiple parameters for the time, the memory and the parallelism.

 

So if you want to set the hash parameters (as the manual specifically recommends), you cannot use PASSWORD_DEFAULT. You must explicitly define the algorithm.

 

Or in other words: If you go with PASSWORD_DEFAULT, you have to accept any choice made by the PHP core developers. And the chosen parameters are necessarily weak, because they have to work on even the weakest servers.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.