0

Say I have a linear hashing algorithm:

<?php
    $input = "password1";

    $round1 = hash('sha512', $input, true);
    $round2 = hash('sha512', $round1, true);

    echo(base64_encode($round2) . "<br>\n");
?>

How would I convert this to a for loop using hash_init, hash_update, and hash_final? I have a algorithm using these in a for loop right now, but I am unable to post it.

NobleUplift
  • 5,631
  • 8
  • 45
  • 87
  • i have an answer, but i'm unable to post it :P – r3wt Feb 04 '14 at 19:09
  • There's an example [in the documentation](http://ca2.php.net/manual/en/function.hash-init.php), just add a `for` loop. – Sammitch Feb 04 '14 at 19:11
  • @r3wt Hardy har har. But seriously, the loop is already part of a closed-source system so I can't post it. – NobleUplift Feb 04 '14 at 19:13
  • @Sammitch It isn't that simple. hash_update is basically the same as concatenating strings together for the first parameter of hash. You have to account for how to handle the return value. – NobleUplift Feb 04 '14 at 19:16
  • 1. I didn't ask you to post your super-secret `for` loop, I said you should refer to the example and then *add the loop yourself* to get the desired effect. 2. You also can't include the result of an incremental hash in a subsequent hash because that will close the handle to the hash resource. So, short answer: what you're asking is not possible. – Sammitch Feb 04 '14 at 19:17
  • @Sammitch 1. I was replying to r3wt, not you. 2. That's my point. – NobleUplift Feb 04 '14 at 19:19
  • 1
    For hashing passwords, it is _not_ a good idea to just repeate hashing in a for loop. Have a look at the PBKDF2 specification using a salt, or even better switch to the PHP function [password_hash()](http://www.php.net/manual/en/function.password-hash.php) to generate a BCrypt hash. – martinstoeckli Feb 05 '14 at 09:04
  • Would it be compatible with Java? – NobleUplift Feb 05 '14 at 14:31
  • According to this [answer](http://stackoverflow.com/a/21140482/575765), it seems to be compatible. – martinstoeckli Feb 05 '14 at 15:59
  • 1
    The real question is not if it is compatible with Java, but if the Java dev that wrote what you're trying to match implemented a standard hashing method [good/easy] or tried to devise his own. [bad/complicated] – Sammitch Feb 05 '14 at 19:35
  • The real point is that if I wanted to use bcrypt, I would have to use jBCrypt or Spring, which are both outside libraries and more upkeep for our build process. – NobleUplift Feb 06 '14 at 17:06

1 Answers1

3

Scratch what I said about closing the handle, that's what hash_copy() function is for. You're probably looking for something like:

$algo = 'sha512';
$input = 'password';
$rounds = 1000;

function extend($algo, $rounds, $input) {
    $ctx = hash_init($algo);
    hash_update($ctx, $input);
    for($i=1; $i<$rounds; $i++) {
        hash_update($ctx, hash_final(hash_copy($ctx), TRUE));
    }
    return hash_final($ctx, TRUE);
}
echo base64_encode(extend($algo, $rounds, $input));

But this essentially appends the hashes together, whereas your existing code re-hashes the hashes. You will not be able to get the same result as the code you posted using this method.

If you want to replicate the code you have, then something like:

$algo = 'sha512';
$input = 'password';
$rounds = 1000;

function cycle($algo, $rounds, $input) {
    $curhash = reinvent_the_wheel($algo, $input);
    for($i=1; $i<$rounds; $i++) {
        $curhash = reinvent_the_wheel($algo, $curhash);
    }
    return $curhash;
}

//equivalent to hash($algo, $input, $true);
function reinvent_the_wheel($algo, $input) {
    $ctx = hash_init($algo);
    hash_update($ctx, $input);
    return hash_final($ctx, TRUE);
}

echo base64_encode(cycle($algo, $rounds, $input)) . "\n";

Which is basically the same code as you posted, just with a for loop added.

Sammitch
  • 30,782
  • 7
  • 50
  • 77