We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Confusion over security-> hash() & security->checkHash()

I have been doing some testing while coding a secure auth system, and I'm left slightly confused and have some questions!

Here's how I have security setup in DI

protected function security()
{
    $config = $this->_config;
    $this->_di->set('security', function() use ($config) {
        $security = new \Phalcon\Security();
        $security->setWorkFactor($config->auth->hash_workload);
        $security->setDefaultHash(\Phalcon\Security::CRYPT_BLOWFISH_Y);
        return $security;
    });
}

Now in my Auth library I use return $this->_security->checkHash($str, $hash); and providing my user provides the correct password, they are authenticated. However, in PHP5.5 bcrypt functionality has been builtin as standard and in my Auth library I can also use return password_verify($str, $hash); and this will also authenticate my user. So what exactly is the difference between using PHP5.5 password_hash() and password_verify() and Phalcon's hash() and checkHash()? And given that the native php functions and the phalcon functions are both compiled in C, is there any advantage to using the phalcon methods?

Also another thing I find weired is that if I change setWorkFactor and setDefaultHash settings, my user still gets authenticated, but surelly these settings should have completely changed the hashing algorithm, so my user shoulkd nolonger be authenticated. What am I missing here?



20.4k
edited Aug '15

I think I may have answered the second part of my question;

Also another thing I find weired is that if I change setWorkFactor and setDefaultHash settings, my user still gets authenticated, but surelly these settings should have completely changed the hashing algorithm, so my user shoulkd nolonger be authenticated. What am I missing here?

It seems that checkHash() or password_verify() can determine the hashing algorithm used by the prefix at the beginning of the hash. However I am still not sure how it determines how many rounds/workload was performed to generate the hash. This is some kind of voodoo magick!

edited Aug '15

Number of rounds is stored in the hash itself, to validate the hash it doesn't take the value in \Phalcon\Security, this option is only used to generate the hashes.

$2a$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi
     ^-- rounds


20.4k
edited Aug '15

Andres, thanks for explaining that. It makes sense now.

Also number of rounds = workload/cost? I did a test to see what I should set this to according to the server (based on the test in PHP password_hash manual). I set this up as setWorkfactor(13) but my hashes come out showing only 8 rounds e.g. $2a$08$

Also as you can see in my DI setup above, I have $security->setDefaultHash(\Phalcon\Security::CRYPT_BLOWFISH_Y); but I am getting $2a$ and not $2y$ as expected. Why would this be? If I use php's password_hash() I get $2y$ and the correct number of rounds.

edited Aug '15

It works as expected:

<?php

$security = new \Phalcon\Security;
$security->setWorkFactor(13);
$security->setDefaultHash(\Phalcon\Security::CRYPT_BLOWFISH_Y);

echo $security->hash("hello");

Outputs:

$2y$13$bvQCYdQlCn9i5Vxwv80GF.cL8laS0sQHlZ48A7JOZ/3eXNM7hGsSW