Bug or wrong docs for Bcrypt?

classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

Bug or wrong docs for Bcrypt?

Ralf Eggert
Hi,

in the docs I found the following text:

http://zf2.readthedocs.org/en/latest/modules/zend.crypt.password.html#bcrypt

> If you want to change the cost parameter of the bcrypt algorithm you
> can use the setCost() method. Please note that if you change the cost
> parameter, the resulting hash will be different. That means if you
> change the cost for existing user passwords you need to regenerate
> all the passwords.

I understand that I cannot change the cost value for a running
application without regenerating all passwords.

Please check this script:

---------------------------------------------------------------------
    use Zend\Crypt\Password\Bcrypt;
    use Zend\Debug\Debug;

    $bcrypt04 = new Bcrypt(array('cost' => 4));
    $bcrypt14 = new Bcrypt(array('cost' => 14));

    $password = "test123";

    $hash04 = $bcrypt04->create($password);
    $hash14 = $bcrypt14->create($password);

    $verify0404 = $bcrypt04->verify($password, $hash04);
    $verify0414 = $bcrypt04->verify($password, $hash14);
    $verify1414 = $bcrypt14->verify($password, $hash14);
    $verify1404 = $bcrypt14->verify($password, $hash04);

    Debug::dump($password);
    Debug::dump($hash04);
    Debug::dump($hash14);
    Debug::dump($verify0404);
    Debug::dump($verify0414);
    Debug::dump($verify1414);
    Debug::dump($verify1404);
---------------------------------------------------------------------

You will see that it does not matter which cost is used to generated a
hash. It will always be verified correctly.

Is this a bug in the Bcrypt implementation or is the documentation wrong?

Any thoughts?

Regards,

Ralf
Reply | Threaded
Open this post in threaded view
|

Re: Bug or wrong docs for Bcrypt?

Bittarman
Hi Ralf,

For verifying the password, the cost would actually be taken from the stored hash, and not from the initial setup.

This is because typically as time progresses, you might wish to increase the cost, and this allows you to do so without breaking all the password hashes you already have stored.

In Bcrypt, all of the parts needed to verify the hash are all together, separated with $'s, first the algorithm, then the cost, the salt, and then finally the hash.

So this is simply how BCrypt works rather than a bug.

Ryan


On 19 Feb 2013, at 09:20, Ralf Eggert <[hidden email]> wrote:

> Hi,
>
> in the docs I found the following text:
>
> http://zf2.readthedocs.org/en/latest/modules/zend.crypt.password.html#bcrypt
>
>> If you want to change the cost parameter of the bcrypt algorithm you
>> can use the setCost() method. Please note that if you change the cost
>> parameter, the resulting hash will be different. That means if you
>> change the cost for existing user passwords you need to regenerate
>> all the passwords.
>
> I understand that I cannot change the cost value for a running
> application without regenerating all passwords.
>
> Please check this script:
>
> ---------------------------------------------------------------------
>    use Zend\Crypt\Password\Bcrypt;
>    use Zend\Debug\Debug;
>
>    $bcrypt04 = new Bcrypt(array('cost' => 4));
>    $bcrypt14 = new Bcrypt(array('cost' => 14));
>
>    $password = "test123";
>
>    $hash04 = $bcrypt04->create($password);
>    $hash14 = $bcrypt14->create($password);
>
>    $verify0404 = $bcrypt04->verify($password, $hash04);
>    $verify0414 = $bcrypt04->verify($password, $hash14);
>    $verify1414 = $bcrypt14->verify($password, $hash14);
>    $verify1404 = $bcrypt14->verify($password, $hash04);
>
>    Debug::dump($password);
>    Debug::dump($hash04);
>    Debug::dump($hash14);
>    Debug::dump($verify0404);
>    Debug::dump($verify0414);
>    Debug::dump($verify1414);
>    Debug::dump($verify1404);
> ---------------------------------------------------------------------
>
> You will see that it does not matter which cost is used to generated a
> hash. It will always be verified correctly.
>
> Is this a bug in the Bcrypt implementation or is the documentation wrong?
>
> Any thoughts?
>
> Regards,
>
> Ralf

Reply | Threaded
Open this post in threaded view
|

Re: Bug or wrong docs for Bcrypt?

Enrico Zimuel-2
Hi Ralf,

Ryan has already explained how Bcrypt works, maybe the documentation
is not so clear, I will send a PR to change that.
Thanks for your feedback.

Enrico

On Tue, Feb 19, 2013 at 10:48 AM, Ryan Mauger <[hidden email]> wrote:

> Hi Ralf,
>
> For verifying the password, the cost would actually be taken from the stored hash, and not from the initial setup.
>
> This is because typically as time progresses, you might wish to increase the cost, and this allows you to do so without breaking all the password hashes you already have stored.
>
> In Bcrypt, all of the parts needed to verify the hash are all together, separated with $'s, first the algorithm, then the cost, the salt, and then finally the hash.
>
> So this is simply how BCrypt works rather than a bug.
>
> Ryan
>
>
> On 19 Feb 2013, at 09:20, Ralf Eggert <[hidden email]> wrote:
>
>> Hi,
>>
>> in the docs I found the following text:
>>
>> http://zf2.readthedocs.org/en/latest/modules/zend.crypt.password.html#bcrypt
>>
>>> If you want to change the cost parameter of the bcrypt algorithm you
>>> can use the setCost() method. Please note that if you change the cost
>>> parameter, the resulting hash will be different. That means if you
>>> change the cost for existing user passwords you need to regenerate
>>> all the passwords.
>>
>> I understand that I cannot change the cost value for a running
>> application without regenerating all passwords.
>>
>> Please check this script:
>>
>> ---------------------------------------------------------------------
>>    use Zend\Crypt\Password\Bcrypt;
>>    use Zend\Debug\Debug;
>>
>>    $bcrypt04 = new Bcrypt(array('cost' => 4));
>>    $bcrypt14 = new Bcrypt(array('cost' => 14));
>>
>>    $password = "test123";
>>
>>    $hash04 = $bcrypt04->create($password);
>>    $hash14 = $bcrypt14->create($password);
>>
>>    $verify0404 = $bcrypt04->verify($password, $hash04);
>>    $verify0414 = $bcrypt04->verify($password, $hash14);
>>    $verify1414 = $bcrypt14->verify($password, $hash14);
>>    $verify1404 = $bcrypt14->verify($password, $hash04);
>>
>>    Debug::dump($password);
>>    Debug::dump($hash04);
>>    Debug::dump($hash14);
>>    Debug::dump($verify0404);
>>    Debug::dump($verify0414);
>>    Debug::dump($verify1414);
>>    Debug::dump($verify1404);
>> ---------------------------------------------------------------------
>>
>> You will see that it does not matter which cost is used to generated a
>> hash. It will always be verified correctly.
>>
>> Is this a bug in the Bcrypt implementation or is the documentation wrong?
>>
>> Any thoughts?
>>
>> Regards,
>>
>> Ralf
>



--
Enrico Zimuel
Senior PHP Engineer     | [hidden email]
Zend Framework Team     | http://framework.zend.com
Zend Technologies Ltd.
http://www.zend.com
Reply | Threaded
Open this post in threaded view
|

Re: Bug or wrong docs for Bcrypt?

Ralf Eggert
In reply to this post by Bittarman
Hi Ryan,

Ryan Mauger schrieb am 19.02.2013 10:48:
> This is because typically as time progresses, you might wish to increase the cost, and this allows you to do so without breaking all the password hashes you already have stored.

So, then the manual is wrong as it says:

  That means if you change the cost for existing user passwords you need
  to regenerate all the passwords

Isn't it? Or am I misunderstanding the "regenerate" part?

Regards,

Ralf
Reply | Threaded
Open this post in threaded view
|

Re: Bug or wrong docs for Bcrypt?

Bittarman
I would say its not entirely incorrect, but definitely unclear hear,

You would need to regenerate the older passwords in order to have them use the new cost, but they would still be verifiable.

Regards

Ryan


On 19 Feb 2013, at 10:38, Ralf Eggert <[hidden email]> wrote:

> Hi Ryan,
>
> Ryan Mauger schrieb am 19.02.2013 10:48:
>> This is because typically as time progresses, you might wish to increase the cost, and this allows you to do so without breaking all the password hashes you already have stored.
>
> So, then the manual is wrong as it says:
>
>  That means if you change the cost for existing user passwords you need
>  to regenerate all the passwords
>
> Isn't it? Or am I misunderstanding the "regenerate" part?
>
> Regards,
>
> Ralf

Reply | Threaded
Open this post in threaded view
|

Re: Bug or wrong docs for Bcrypt?

Ralf Eggert
Hi Ryan,

Ryan Mauger schrieb am 19.02.2013 11:44:
> I would say its not entirely incorrect, but definitely unclear hear,
>
> You would need to regenerate the older passwords in order to have them use the new cost, but they would still be verifiable.

I am currently porting an ZF1 application to ZF2 with about 25.000
registered users. The passwords were saved as MD5 hashes in the ZF1
application. In the ZF2 application I will use Bcrypt on these md5
password hashes to encrypt the passwords. New passwords will first MD5ed
before Bcrypting them to be in a line.

Converting 25.000 passwords with a cost of 14 for Bcrypt will last much
longer than converting 25.000 passwords with a cost of 4.

Do you see any problems when encrypting passwords with a cost of 4 for
conversion and use a cost of 14 for all new passwords?

Regards,

Ralf
Reply | Threaded
Open this post in threaded view
|

Re: Bug or wrong docs for Bcrypt?

Enrico Zimuel-2
Hi Ralf,

I don't see any problem using this approach. Of course, the cost value
of 4 is less secure than 14 for bcrypt but definitely more secure than
MD5.
Maybe you can regenerate the bcrypt hash using a greater value of cost
the first time the user will login. In this way you don't have to
regenerate all the password.

Regards,
Enrico Zimuel

On Tue, Feb 19, 2013 at 11:50 AM, Ralf Eggert <[hidden email]> wrote:

> Hi Ryan,
>
> Ryan Mauger schrieb am 19.02.2013 11:44:
>> I would say its not entirely incorrect, but definitely unclear hear,
>>
>> You would need to regenerate the older passwords in order to have them use the new cost, but they would still be verifiable.
>
> I am currently porting an ZF1 application to ZF2 with about 25.000
> registered users. The passwords were saved as MD5 hashes in the ZF1
> application. In the ZF2 application I will use Bcrypt on these md5
> password hashes to encrypt the passwords. New passwords will first MD5ed
> before Bcrypting them to be in a line.
>
> Converting 25.000 passwords with a cost of 14 for Bcrypt will last much
> longer than converting 25.000 passwords with a cost of 4.
>
> Do you see any problems when encrypting passwords with a cost of 4 for
> conversion and use a cost of 14 for all new passwords?
>
> Regards,
>
> Ralf



--
Enrico Zimuel
Senior PHP Engineer     | [hidden email]
Zend Framework Team     | http://framework.zend.com
Zend Technologies Ltd.
http://www.zend.com
Reply | Threaded
Open this post in threaded view
|

Re: Bug or wrong docs for Bcrypt?

Bittarman
I would second Enrico here, migrate users upon login to the new password hashing scheme.

Regards
Ryan
On 19 Feb 2013, at 10:57, Enrico Zimuel <[hidden email]> wrote:

> Hi Ralf,
>
> I don't see any problem using this approach. Of course, the cost value
> of 4 is less secure than 14 for bcrypt but definitely more secure than
> MD5.
> Maybe you can regenerate the bcrypt hash using a greater value of cost
> the first time the user will login. In this way you don't have to
> regenerate all the password.
>
> Regards,
> Enrico Zimuel
>
> On Tue, Feb 19, 2013 at 11:50 AM, Ralf Eggert <[hidden email]> wrote:
>> Hi Ryan,
>>
>> Ryan Mauger schrieb am 19.02.2013 11:44:
>>> I would say its not entirely incorrect, but definitely unclear hear,
>>>
>>> You would need to regenerate the older passwords in order to have them use the new cost, but they would still be verifiable.
>>
>> I am currently porting an ZF1 application to ZF2 with about 25.000
>> registered users. The passwords were saved as MD5 hashes in the ZF1
>> application. In the ZF2 application I will use Bcrypt on these md5
>> password hashes to encrypt the passwords. New passwords will first MD5ed
>> before Bcrypting them to be in a line.
>>
>> Converting 25.000 passwords with a cost of 14 for Bcrypt will last much
>> longer than converting 25.000 passwords with a cost of 4.
>>
>> Do you see any problems when encrypting passwords with a cost of 4 for
>> conversion and use a cost of 14 for all new passwords?
>>
>> Regards,
>>
>> Ralf
>
>
>
> --
> Enrico Zimuel
> Senior PHP Engineer     | [hidden email]
> Zend Framework Team     | http://framework.zend.com
> Zend Technologies Ltd.
> http://www.zend.com

Reply | Threaded
Open this post in threaded view
|

Re: Bug or wrong docs for Bcrypt?

Ralf Eggert
In reply to this post by Enrico Zimuel-2
Hi Enrico,

thanks for your suggestion.

Enrico Zimuel schrieb am 19.02.2013 11:57:
> I don't see any problem using this approach. Of course, the cost value
> of 4 is less secure than 14 for bcrypt but definitely more secure than
> MD5.
> Maybe you can regenerate the bcrypt hash using a greater value of cost
> the first time the user will login. In this way you don't have to
> regenerate all the password.

With this approach I need to save a flag somewhere to check if a
password has been regenerated the first time, won't I? Or should I use
the beginning of the bcrypt hash to identify the cost value? When the
password starts with "$2a$04" I regenerate the hash with a higher cost
value.

Anyway what do you think about the approach of bcrypting the old MD5
hashes and using MD5 for the new passwords as well before bcrypting them?

Regards,

Ralf
Reply | Threaded
Open this post in threaded view
|

Re: Bug or wrong docs for Bcrypt?

Ralf Eggert
Anyway, I will use a cost of 7 for conversion since I don't see much
time impact in comparison to 4. With 8 it slowly starts getting slower.

Ralf
Reply | Threaded
Open this post in threaded view
|

Re: Bug or wrong docs for Bcrypt?

Enrico Zimuel-2
In reply to this post by Ralf Eggert
Hi Ralf,

you can use the MD5($password) as a user password but you don't need it.
i think the best approach is to change the authentication part of your
code with something like that:

use Zend\Crypt\Password\Bcrypt;

$bcrypt = new Bcrypt();
$bcrypt->setCost(x); // where x is the cost that you want to use (I
suggest at least 10)

// $password is the user password and $hash is the hash value to check
if (md5($password) === $hash) {
    // the user is authenticated with MD5 but we want to upgrade it using bcrypt
    $newhash = $bcrypt->create($password);
    // update the old hash password with $newhash
    ...
} else if ($bcrypt->verify($password, $hash) {
    // the user is authenticated with bcrypt
} else {
    // wrong password, the user is not authenticated
}

Basically, for the old hash values you authenticate using MD5 for the
first time and create the bcrypt hash starting form the user password
($password) and not the MD5 value. The second time that the user will
login it will use the bcrypt value instead of MD5.
Using this approach you don't have to regenerate all the passwords. If
you store the bcrypt value in a database be sure that the field is
able to store a string of 60 bytes for bcrypt, compared with 32
characters of the MD5.

Regards,
Enrico Zimuel

On Tue, Feb 19, 2013 at 12:33 PM, Ralf Eggert <[hidden email]> wrote:

> Hi Enrico,
>
> thanks for your suggestion.
>
> Enrico Zimuel schrieb am 19.02.2013 11:57:
>> I don't see any problem using this approach. Of course, the cost value
>> of 4 is less secure than 14 for bcrypt but definitely more secure than
>> MD5.
>> Maybe you can regenerate the bcrypt hash using a greater value of cost
>> the first time the user will login. In this way you don't have to
>> regenerate all the password.
>
> With this approach I need to save a flag somewhere to check if a
> password has been regenerated the first time, won't I? Or should I use
> the beginning of the bcrypt hash to identify the cost value? When the
> password starts with "$2a$04" I regenerate the hash with a higher cost
> value.
>
> Anyway what do you think about the approach of bcrypting the old MD5
> hashes and using MD5 for the new passwords as well before bcrypting them?
>
> Regards,
>
> Ralf



--
Enrico Zimuel
Senior PHP Engineer     | [hidden email]
Zend Framework Team     | http://framework.zend.com
Zend Technologies Ltd.
http://www.zend.com
Reply | Threaded
Open this post in threaded view
|

Re: Bug or wrong docs for Bcrypt?

Pádraic Brady
In reply to this post by Ralf Eggert
Hi Ralf,

I'd bump it up if possible. Updating the passwords carefully as users login may allow you to creep up to 10+ with little downside. You can look at what's left on MD5 (i.e. irregular or dormant users).

You sort of indicated yourself why a higher number is generally preferred. The extra slowness you're observing at cost 8+ translates into making a password crackers life a living nightmare ;).

I won't say that a cost of 7 is bad - it likely is reasonably secure subject to the passwords used and whatever you do use needs to fit within your hardware's capabilities regardless.

Paddy


On Tue, Feb 19, 2013 at 11:42 AM, Ralf Eggert <[hidden email]> wrote:
Anyway, I will use a cost of 7 for conversion since I don't see much
time impact in comparison to 4. With 8 it slowly starts getting slower.

Ralf



--
Pádraic Brady

http://blog.astrumfutura.com
http://www.survivethedeepend.com
Zend Framework Community Review Team
Reply | Threaded
Open this post in threaded view
|

Re: Bug or wrong docs for Bcrypt?

Enrico Zimuel-2
In reply to this post by Bittarman
Hi Ralf,

we just changed the doc of bcrypt, you can see the new sentence
regarding the cost parameter here:
http://zf2.readthedocs.org/en/latest/modules/zend.crypt.password.html

Regards,
Enrico Zimuel

On Tue, Feb 19, 2013 at 11:44 AM, Ryan Mauger <[hidden email]> wrote:

> I would say its not entirely incorrect, but definitely unclear hear,
>
> You would need to regenerate the older passwords in order to have them use the new cost, but they would still be verifiable.
>
> Regards
>
> Ryan
>
>
> On 19 Feb 2013, at 10:38, Ralf Eggert <[hidden email]> wrote:
>
>> Hi Ryan,
>>
>> Ryan Mauger schrieb am 19.02.2013 10:48:
>>> This is because typically as time progresses, you might wish to increase the cost, and this allows you to do so without breaking all the password hashes you already have stored.
>>
>> So, then the manual is wrong as it says:
>>
>>  That means if you change the cost for existing user passwords you need
>>  to regenerate all the passwords
>>
>> Isn't it? Or am I misunderstanding the "regenerate" part?
>>
>> Regards,
>>
>> Ralf
>



--
Enrico Zimuel
Senior PHP Engineer     | [hidden email]
Zend Framework Team     | http://framework.zend.com
Zend Technologies Ltd.
http://www.zend.com
Reply | Threaded
Open this post in threaded view
|

Re: Bug or wrong docs for Bcrypt?

Ralf Eggert
Hi Enrico,

> we just changed the doc of bcrypt, you can see the new sentence
> regarding the cost parameter here:
> http://zf2.readthedocs.org/en/latest/modules/zend.crypt.password.html

This is much more clear now. Thanks a lot!

Regards,

Ralf