Alex Grin Alex Grin - 3 months ago 7
PHP Question

What's wrong with my implementation of HMAC in PHP?

I'm trying to implement a generic HMAC function in PHP. I'm following the RFC and the wikipedia page, but I cannot get my function to match the sample outputs. What am I doing wrong?

function myHmac(string $data, string $key, callable $algoFn, int $algoBlockSizeInBytes): string
{
if (strlen($key) > $algoBlockSizeInBytes)
{
$key = $algoFn($key); // keys longer than blocksize are shortened
}

if (strlen($key) < $algoBlockSizeInBytes)
{
$key = $key . str_repeat(0x00, $algoBlockSizeInBytes - strlen($key)); // keys shorter than blocksize are zero-padded
}

$outerKeyPad = str_repeat(0x5c, $algoBlockSizeInBytes) ^ $key;
$innerKeyPad = str_repeat(0x36, $algoBlockSizeInBytes) ^ $key;

return bin2hex($algoFn($outerKeyPad . $algoFn($innerKeyPad . $data)));
}

$md5Fn = function ($str) { return md5($str, true); };

echo 'my output: ' . myHmac("", "", $md5Fn, 64) . "\n";
echo 'correct output: ' . hash_hmac('md5', "", "") . "\n";

Answer

You invoke string_repeat() with an integer instead of the string to be repeated. So integer to string conversion applies. This means that currently you get something like 0x36 -> '54' -> '54545454...5454' ('54' repeated 64 times) and so on. Use chr(0x36) to get the actual byte.

Comments