1

I have the following password:

123

Now i hash that and it returns the following key:

$2y$10$rSq.2M7Ikc.QPhVtYlp1Nu8HI.Eq5fUgVWn25J

Now i try to verify the same key using:

return password_verify(123, $2y$10$rSq.2M7Ikc.QPhVtYlp1Nu8HI.Eq5fUgVWn25J);

however this returns false.

Can anyone tell me why?

Update

this is my full code:

<?php
/**
 * Created by JetBrains PhpStorm.
 * User: Marc
 * Date: 14-12-13
 * Time: 13:56
 * To change this template use File | Settings | File Templates.
 */
class Security {
    /**
     * @param $string
     * @return mixed
     */
    public function encrypt($string) {
        return password_hash($string, PASSWORD_DEFAULT);
    }

    /**
     * @param $string
     * @param $hash
     * @return mixed
     */
    public function validate($string, $hash) {
        return password_verify($string, $hash);
    }
}

    $hash = $this->db->template("SELECT password FROM User WHERE username = '".$username."'", READ_FROM_QUERY)['password'];
$validate =  $this->getSecurity()->validate($password, $hash);

I try to insert the following string:

Helloworld

However $validate = false;

The password has returns to $2y$10$VbicsFaGN9d3ggQTNYIto.Bp6x/rbjpsBe2kneEhJ9oP2KdPsZ7hy

If i try and rehash it, it returns the same value soo they must be equal to each other so why does it return false?!??!

Returns false as well

$validate =  $this->getSecurity()->validate((string)$password, (string)$hash);
Funk Forty Niner
  • 74,450
  • 15
  • 68
  • 141
Marc Rasmussen
  • 19,771
  • 79
  • 203
  • 364

1 Answers1

8

For your first example, with a password of 123, the problem is that you are truncating the hash.

$settings = array('cost' => 10, 'salt' => 'rSq.2M7Ikc.QPhVtYlp1Nu');                                        
echo password_hash('123', PASSWORD_BCRYPT, $settings);
// $2y$10$rSq.2M7Ikc.QPhVtYlp1Nu8HI.Eq5fUgVWn25J/WWUma/RrNWKFay // What is echoed
// $2y$10$rSq.2M7Ikc.QPhVtYlp1Nu8HI.Eq5fUgVWn25J                // Your hash

I would assume that your database colum has a maximum length of 45 characters and that's why it is truncating it.

For the second string, the problem is that somewhere along the line you are converting the password to a lower case.

// Uppercase 'H'
$settings = array('cost' => 10, 'salt' => 'VbicsFaGN9d3ggQTNYIto.');
echo password_hash('Helloworld', PASSWORD_BCRYPT, $settings);
// $2y$10$VbicsFaGN9d3ggQTNYIto.qFAer7kUmKmcy6y9RCNzaaKD7fJraba

// Lowercase 'h'
$settings = array('cost' => 10, 'salt' => 'VbicsFaGN9d3ggQTNYIto.');
echo password_hash('helloworld', PASSWORD_BCRYPT, $settings);
// $2y$10$VbicsFaGN9d3ggQTNYIto.Bp6x/rbjpsBe2kneEhJ9oP2KdPsZ7hy

So when you try to validate using Helloworld it will return false because the hash is for helloworld.

You really need to be more careful because both of these are really careless errors. And note, you should NEVER convert passwords to a certain case (upper or lower) because this weakens them significantly.

Mike
  • 23,542
  • 14
  • 76
  • 87
  • This could be relevant, from http://php.net/crypt --- *"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)."* – Funk Forty Niner Jan 10 '14 at 05:01
  • 1
    @Fred-ii- Interesting... however password_hash uses only bcrypt right now (notice the string starts with `$2y$`). – Mike Jan 10 '14 at 05:20
  • I thought it might have been the same or similar situation. – Funk Forty Niner Jan 10 '14 at 05:24
  • @Fred-ii- Well, that is talking about the string being hashed, not the hash itself. So either way it wouldn't truncate the hash. For example Microsoft has been truncating passwords silently for years with Hotmail at 16 characters. If you had a longer password, they would only use the first 16 characters of it so you could enter random characters for everything above 16 and get in. Now they actually **force** you to use a password of 16 characters or less. What lunatics decided that was the best way to handle security? I think it's the same for their OSes. – Mike Jan 10 '14 at 05:31
  • I've heard say that Hotmail stores passwords in plain text. I don't remember where I read that, but I'm almost tempted to believe it. – Funk Forty Niner Jan 10 '14 at 05:35
  • @Fred-ii- I **suuuuure** hope not... I wouldn't be suprised if they *used* to, but there have been so many companies over the years that have stored their passwords in unsalted `md5` or `sha1` (or even plain text) and have had them stolen that I honestly can't see that Microsoft would *still* be storing them in plain text. If that ever got leaked just imagine the lawsuits. However with that said, limiting the length, especially to something so short, just screams plain text. – Mike Jan 10 '14 at 05:40
  • All in the name of saving a few precious bytes of storage, which was the original intent way back when. I almost lost a Hotmail account a few years ago, and that scared the sh*t outta me. I was lucky and quick on the draw; it's rather a long story but in a nutshell, I waited for the right time to get a reset password email sent to my linked account and changed it right away. And yeah, if that were the case and it ever leaked out, we'd be swimming in a lot of dough ;-) – Funk Forty Niner Jan 10 '14 at 05:46
  • @Fred-ii- Only DES truncates the string after 8 characters, BCrypt uses up to 72 characters of the password, though it doesn't complain if you pass more characters. – martinstoeckli Jan 10 '14 at 12:07
  • "I would assume that your database colum has a maximum length of 45 characters and that's why it is truncating it." This was exactly what was happening!! Thanks – Marc Rasmussen Jan 10 '14 at 14:21