Re: [VOTE] Hash_pbkdf2
| From: | Anthony Ferrara | Date: | Tue, 10 Jul 2012 14:14:16 +0000 |
| Subject: | Re: [VOTE] Hash_pbkdf2 | ||
| References: | 1 2 3 4 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-61119@lists.php.net to get a copy of this message | ||
Hey all,
The voting phase has ended for hash_pbkdf2, and it has passed with a vote
of 8:0. I've moved the RFC into Accepted state, and will merge the PR today
into master, then move the RFC into Implemented.
Thanks!
Anthony
On Mon, Jul 2, 2012 at 10:37 PM, Sara Golemon <pollita@php.net> wrote:
>
>
> On Mon, Jul 2, 2012 at 5:49 PM, Anthony Ferrara <ircmaxell@gmail.com>wrote:
>
>> Sara,
>>
>> On Mon, Jul 2, 2012 at 8:24 PM, Sara Golemon <pollita@php.net> wrote:
>> > I'd like to see hash_init() support this mode as well (for
>> completeness).
>> > Perhaps something like the following:
>> >
>> > $ctx = hash_init("sha512", HASH_PBKDF2, $salt, array('length'
>> > => 32,
>> > 'iterations' => 5000));
>> >
>> > The new fourth parameter being an overloadable options generic so that
>> we
>> > don't have an endless list of parameters for all the possible hashing
>> types.
>>
>> The only problem that I have with this sort of implementation is that
>> the only way it would work is to buffer the entire input (each
>> hash_update call), and run it all at the end. That's because the data
>> (password) is used in every iteration, so there's no pre-computation
>> that can be done. And at that point, what's the benefit to it?
>>
>> public function pbkdf2($algo, $password, $salt, $iterations, $length) {
>> $size = getHashBlockSize($hash);
>> $len = ceil($length / $size);
>> $result = '';
>> for ($i = 1; $i <= $len; $i++) {
>> $tmp = hash_hmac($hash, $salt . pack('N', $i), $password,
>> true);
>> $res = $tmp;
>> for ($j = 1; $j < $iterations; $j++) {
>> $tmp = hash_hmac($hash, $tmp, $password, true);
>> $res ^= $tmp;
>> }
>> $result .= $res;
>> }
>> return substr($result, 0, $length);
>> }
>>
>> Contrast that to a normal hash function (used by the current
>> hash_init) which iterates over blocks of input, and once it's done
>> with a block, it doesn't need it anymore (which is where using
>> something like hash_init/hash_update can make sense on large input).
>>
>> Additionally, hmac only uses the message in a single hash, so it can
>> be streamed in as well (pre-compute the earlier hashes/data, stream
>> the intermediate hash, then hash the final one).
>>
>> So while it could be added (just make hash_update buffer into a
>> context, then have hash_final actually run the derivation), I'm not
>> sure it makes sense to add it there.
>>
>> Thoughts?
>>
>> Anthony
>>
>
> Ah, wasn't clear on how pbkdf2 worked. Your argument makes total sense.
> Thanks for explaining it. :)
>