-
-
Save paragonie-scott/0fe50b71d902f2cdaf88a565888e5801 to your computer and use it in GitHub Desktop.
Symfony's PBKDF2 polyfill benchmark (TL;DR it's slow) for the thread here https://twitter.com/spazef0rze/status/1050436425559302147
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
function hashPbkdf2($algorithm, $password, $salt, $iterations, $length = 0) | |
{ | |
// Number of blocks needed to create the derived key | |
$blocks = ceil($length / strlen(hash($algorithm, null, true))); | |
$digest = ''; | |
$length = strlen(hash($algorithm, '', true)); | |
if (strlen($password) > $length) { | |
$password = hash($algorithm, $password, true); | |
} | |
for ($i = 1; $i <= $blocks; $i++) { | |
$ib = $block = hash_hmac($algorithm, $salt . pack('N', $i), $password, true); | |
// Iterations | |
for ($j = 1; $j < $iterations; $j++) { | |
$ib ^= ($block = hash_hmac($algorithm, $block, $password, true)); | |
} | |
$digest .= $ib; | |
} | |
return substr($digest, 0, 40); | |
} | |
function hashPbkdf2Original($algorithm, $password, $salt, $iterations, $length = 0) | |
{ | |
// Number of blocks needed to create the derived key | |
$blocks = ceil($length / strlen(hash($algorithm, null, true))); | |
$digest = ''; | |
for ($i = 1; $i <= $blocks; $i++) { | |
$ib = $block = hash_hmac($algorithm, $salt . pack('N', $i), $password, true); | |
// Iterations | |
for ($j = 1; $j < $iterations; $j++) { | |
$ib ^= ($block = hash_hmac($algorithm, $block, $password, true)); | |
} | |
$digest .= $ib; | |
} | |
return substr($digest, 0, 40); | |
} | |
function bench($p, $s, $i) | |
{ | |
echo 'pw length: ' . strlen($p) . "\n"; | |
echo 'iterations: ' . $i . "\n"; | |
$start = microtime(true); | |
$h1 = bin2hex(hashPbkdf2('sha256', $p, $s, $i, 32)); | |
echo 'polyfill: ' . (microtime(true) - $start) . "s\n"; | |
$start = microtime(true); | |
$h2 = hash_pbkdf2('sha256', $p, $s, $i); | |
echo 'native: ' . (microtime(true) - $start) . "s\n"; | |
echo 'h1 === h2: ' . ($h1 === $h2 ? 'true' : 'false') . "\n\n"; | |
} | |
$iter = 1e4; | |
bench(str_repeat('*', 1e2), 'somerandombytes', $iter); | |
bench(str_repeat('*', 1e3), 'somerandombytes', $iter); | |
bench(str_repeat('*', 1e4), 'somerandombytes', $iter); | |
bench(str_repeat('*', 1e5), 'somerandombytes', $iter); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pw length: 100 | |
iterations: 10000 | |
polyfill: 0.039463996887207s | |
native: 0.032675981521606s | |
h1 === h2: true | |
pw length: 1000 | |
iterations: 10000 | |
polyfill: 0.044183969497681s | |
native: 0.030115127563477s | |
h1 === h2: true | |
pw length: 10000 | |
iterations: 10000 | |
polyfill: 0.037073850631714s | |
native: 0.032072067260742s | |
h1 === h2: true | |
pw length: 100000 | |
iterations: 10000 | |
polyfill: 0.044167041778564s | |
native: 0.047009944915771s | |
h1 === h2: true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is broken. Test:
Note length for hashPbkdf2 and hashPbkdf2Original:
Fixes:
Umm yeah so it uses mcrypt which you got removed :P... so I guess you need to do it the hard way:
One more thing:
The
$length = 0
suggests this does something better than returning an empty string.But really you should add this if
hash_copy()
is available:And change these: