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. :)