Leszek,

On Thu, May 7, 2015 at 2:11 AM, Leszek Krupinski <leafn...@gmail.com> wrote:
> On Wed, May 6, 2015 at 4:00 PM, Nikita Popov <nikita....@gmail.com> wrote:
>
>> It should be further noted that there is no standardized crypt() format for
>> PBKDF2 and password_hash() is a crypt-compatible API. As such supporting
>> PBKDF2 there would be very problematic. We do already support it in the
>> form of hash_pbkdf2() and people who wish to use this method (e.g. due to
>> legal restrictions) can use it through this API - I don't see a reason to
>> have it in password_hash(), which should only support the recommended
>> default use case.
>> <http://csrc.nist.gov/publications/nistpubs/800-132/nist-sp800-132.pdf>
>>
>
> That's true that there's no support for pbkdf2 in crypt. On the other hand,
> the RFC for password_hash stated:
>
>> These hashing APIs will initially be thin wrappers around *crypt()* to
> allow for automatic salt generation and better error checking.
>
> It says "initially" - that's why I understood that in the future we can
> diverge from crypt in situations when there's a great new hash we would
> like to use, but it's not supported by crypt (yet or at all).

That was precisely the intention. For that exact reason.

*HOWEVER* (and this is a big however), I think we should avoid doing
that unless *absolutely* necessary. We should strive to build off
standardized crypto. This is good both from an interoperability
standpoint, and the standpoint of relying on cryptographers to set the
standard. We have few if any professional cryptographers on this
list/project, so we should avoid as much as possible inventing our own
(unless absolutely necessary, in which we can elicit the help of
professionals).

> Also, I'm pro-choice ;) We have an extensible API for password_hash(), and
> because people have different needs (like gpu strain in bcrypt or longer
> passwords in pbdkf2) we should provide an option for more experienced
> users, while having reasonable defaults. Yes, advanced users can use hash
> functions directly, but password_* are so nice :)

Well, I'm not sure I agree here. I think the point of password_hash()
is to raise the bottom barrier. I have said multiple times that it is
not a replacement for crypt(3) or other more complicated tools. It's
meant more as a way for non-experts to implement secure code.

If you need to make a different tradeoff, then you can always use a
different library or more advanced use case. I think that
password_hash() should remain simple, with as few choices as possible
(less for users to screw up).

As far as length protection, you can simply pre-hash with sha-512 and
base64_encode the result:

    $prehash = base64_encode(hash('sha512', $password, true));
    $hash = password_hash($prehash, PASSWORD_DEFAULT, []);

This is also "inventing" crypto, so I would be extremely wary of
recommending this as a project. If we can get the upstream providers
(specifically the OpenBSD project) to add a crypt(3) format for this
specific case, then we can integrate it into our crypt(3)
implementation, and hence password_hash(). But I would want the
upstream to do it first.

The only algorithm at present that I have seen that today could
replace bcrypt in password_hash is scrypt. However, there are 2
fundamental problems with it: 1) there's no crypt(3) binding or
format. 2) At similar cost settings to what most users use bcrypt at
(< 0.1 second runtime), it's been shown to be at best no stronger than
bcrypt, or at worst several times weaker.

There is currently a competition for a new password hashing algorithm:
https://password-hashing.net/ I've been watching it fairly closely,
but many of the algorithms suffer a similar "weaker than bcrypt at low
runtime" problem. The main reason for this is that they are mainly
targeting different use-cases than password_hash targets. Namely, they
are looking at key derivation and login where you can dedicate a login
server (and hence keep potentially GB of memory persistent for use in
hashing). While these techniques are far superior if you can dedicate
the hardware to them, they don't solve the same problem that we're
solving with password_hash.

We could use scrypt or yescrypt (or a few others) as a next-gen
algorithm, but we'd have to be careful with the settings parameters,
as there's more than just one. And it's really easy to screw up the
settings and make it easier for an attacker. Ideally, I wonder if it's
possible for us to simply "proxy" from a single setting (give users a
"cost" setting, and generate an pseudo-ideal set of settings given
that cost).

The bottom line is that I think password_hash needs to stay as simple
as possible. It's not designed to be a full fledged library or set of
primitives. It's designed to be an opinionated library that takes as
much decision away from the user as possible. If you need more
control, use a different library. But for the 98% use-case, that
additional complication simply makes it harder for users to get it
right: http://blog.ircmaxell.com/2015/03/thoughts-on-design-of-apis.html

Anthony

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to