All,

Look at the issue, there's a line in there that is the crux of the issue:

> So problem isn't only in ROUNDS_MIN.

In fact, the overall algorithm changed.

Look at a quick example: http://3v4l.org/Eov3o

>From 5.3.2+ (when we pulled in our own implementation of crypt-sha256
and crypt-sha512, and crypt-blowfish):

using salt:
string(31) "$6$rounds=1000$abcdefghijklmnop"
gives hash:
string(118) 
"$6$rounds=1000$abcdefghijklmnop$SgL/Atu7DClkX0qBUuG6FS2bRf2XmLFWY9b8pRttPEj9ZSh4MKE5bKlz4WAKomLuWI.YQ5oIPLO2L.0OioAeW/"

great.
But in 4.3.0 - 5.2.17:
the same salt gives:
string(99) 
"$6$rounds=10$EdPD9pXG2vAIeeyG2E/9Mzey2mA/qZgIBAbccXWtrNiymhFYXNK4r2gphMi4KOksXRubHnBWGVh/p2pP2D3R.."

Which is shorter. Also note that the rounds went from the defined 1000, to 10.

Things get far weirder: http://3v4l.org/KZoIv

$h1='$6$rounds=1$abcdefghijklmnop';
$h2='$6$abcdefghijklmnop';
gives us (on 4.3.0 - 5.2.17):
string(102) 
"$6$rounds=1000$$6TFP.7u1vZP5A9fccvmUPteI8f29BLhgfqL1XEQqcrvqTSKKw5SBa2qw1sOwLEQ41Dhl1u/Jbi2hRHRYCdxuv0"
string(99) 
"$6$abcdefghi$4Dv/xQG4euniWsyrRHGUrNqM9CFl5Pg9EI88OgO4tIzuV952JnT09wVxrzUP9l/dr0wP3YSs1Ufz1qJpifLAA0"

Note that these are different all around from the other results from
the same version range.

Basically, the version of crypt being linked to is either buggy (not
likely) or our documentation of it is (likely). And our implementation
(since 5.3.2) conforms to our documentation instead of the old
behavior.

Considering 5.3.2 was released 4 years ago, and 5.2 has been EOL for
3.5 years, I don't think there's anything that can be done about this.
If it was a simple limit that needed changing, a polyfill would be
easy (took me 10 minutes:
https://gist.github.com/ircmaxell/ac0710ce044504f65cf0 ). But seeing
the entire algorithm is different, much harder.

I think this should be documented, and then called a day. I don't see
anything else that could reasonably be done (changing crypt() at this
point is out of the question IMHO).

>  - Add bool crypt_migration INI that is default to OFF for PHP 5.4 and up.
>  - master will not have this INI.

Please don't. As I showed above, it's already long past that point.
And we don't need new ini settings.

And what that ini setting would control is not the minimum iteration
flag (as that's not the only problem), but which version of libcrypt
we're binding to (our internal one, or an external one). Which means
that the overall behavior *will* change. And unless you do it
perfectly, it could effect all of crypts algorithms (potentially
impacting password_hash, etc).

We internalized the algorithms in 5.3.2 at least partially because the
system provided libraries were inconsistent at best (hence why many
but not all 5.2 systems don't support bcrypt, it depended on the build
of libcrypt you linked against).

Please don't make us re-live this inconsistency... Especially when it
won't really solve the problem.






Regarding password_verify() accepting crypt(), I consider it an
implementation detail that it works. I know the RFC specifies it, but
it specifies it not as a conceptual fact (that it will always be no
more than a reason to be there), but more as an explanation for what
it's currently doing. I would not rely on that fact. It may work
today. It may work tomorrow, but it shouldn't be documented as such
(as it's the complement of password_hash(), not the complement of
crypt()).

> As far as I'm aware, the only reason for not marking crypt()
> E_DEPRECATED right now is for compatibility with external systems, and
> as far as those go, changing a default won't effect anything.

I want to reinforce that point, because it's spot on the money:

I think crypt should live on. password_hash should be the way new
systems are built, sure. But as you mention external systems, crypt
should be a standard way of interacting with them (heck, that's what
the lib was designed for). It shouldn't be a "if you're not using
password_hash(), you're doing it wrong". It's "password_hash() should
solve the majority of use-cases, but if you have a different need,
there are other options".

My $0.02

Anthony

On Thu, Jul 17, 2014 at 1:50 PM, Adam Harvey <ahar...@php.net> wrote:
> On 16 July 2014 23:16, Tjerk Meesters <tjerk.meest...@gmail.com> wrote:
>> On Thu, Jul 17, 2014 at 10:25 AM, Yasuo Ohgaki <yohg...@ohgaki.net> wrote:
>>
>>> Hi Tjerk,
>>>
>>> On Thu, Jul 17, 2014 at 11:09 AM, Tjerk Meesters <tjerk.meest...@gmail.com
>>> > wrote:
>>>
>>>> Why should `password_verify()` work on a hash that wasn't generated with
>>>> `password_hash()`? The fact that it uses `crypt()` internally should not
>>>> leak outside of its API, imho.
>>>
>>>
>>> password_*() is designed as crypt() wrapper and this fact is documented
>>> since it was released.
>>>
>>> Obsolete password hash is easy to verify with password_needs_rehash().
>>> Developers can check password database easily with password_needs_rehash().
>>>
>>
>> The documentation states that the `hash` argument to both
>> `password_needs_rehash()` and `password_verify()` is:
>>
>>     hash - A hash created by password_hash().
>
> Whoa. Don't put too much stock in that — I think I made that up out of
> whole cloth while trying to get _something_ into the manual for one of
> the early alpha releases of 5.5, and it wasn't intended as a
> restrictive statement.
>
>> Passing a value from your own crypt() implementation may work, but that
>> shouldn't be relied upon. I certainly wouldn't classify it as a problem
>> that should be fixed in the password api.
>
> The original RFC specified that both crypt() and password_hash()
> hashes were accepted here, and that's probably what the documentation
> should say too.
>
> Adam
>
> --
> PHP Internals - PHP Runtime Development Mailing List
> To unsubscribe, visit: http://www.php.net/unsub.php
>

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

Reply via email to