Search code examples
c#phpsha1hmacsha1

C# HMACSHA1 vs PHP hash_hmac


I am trying to connect to an API to get an access token using PHP and the only hashing example code is written in C#. This is the C# version:

private static string GetHMACSignature(string privatekey, string message)
        {
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            byte[] keyByte = encoding.GetBytes(privatekey);
            Console.WriteLine("Key: "+ToReadableByteArray(keyByte));

            System.Security.Cryptography.HMACSHA1 hmacsha1 = new System.Security.Cryptography.HMACSHA1(keyByte);
            byte[] messageBytes = encoding.GetBytes(message);
            Console.WriteLine("Message: "+ToReadableByteArray(messageBytes));
            byte[] hashmessage = hmacsha1.ComputeHash(messageBytes);
            Console.WriteLine("Hash: "+ToReadableByteArray(hashmessage));
            return Convert.ToBase64String(hashmessage);
        }

With a privatekey of "a1" and message of "b1", you get the following:

Key: 97, 49
Message: 98, 49
Hash: 219, 205, 149, 90, 235, 40, 133, 252, 91, 27, 240, 61, 201, 173, 220, 76, 73, 248, 92, 212
282VWusohfxbG/A9ya3cTEn4XNQ=

When I try to run the equivalent in PHP, I get the same bytes, but the hash is different:

$key = 'a1';
$message = 'b1';
$hmac = hash_hmac('sha1', $key, $message, true);
$hmac_base64 = base64_encode($hmac);

echo 'KEY BYTES: '.implode(',',$this->getByteArray($key)).'<br>';
echo 'MESSAGE BYTES: '.implode(',',$this->getByteArray($message)).'<br>';
echo 'HMAC BYTES: '.implode(',',$this->getByteArray($hmac)).'<br>';
echo 'HMAC: '.$hmac_base64;

function getByteArray($text) {
     $secretBytes = array();
        for($i = 0; $i < strlen($text); $i++)
         {
           $secretBytes[] = ord($text[$i]);
         }

     return $secretBytes;
}

Result:

KEY BYTES: 97,49
MESSAGE BYTES: 98,49
HMAC BYTES: 3,162,147,8,198,26,126,189,195,122,228,215,10,18,187,216,22,151,202,237
HMAC: A6KTCMYafr3DeuTXChK72BaXyu0=

What am I doing wrong? A lot of the problems I've found on here say to set the binary output of hash_hmac to true in PHP, which I've done. Originally my message had return (\r) and newline chars (\n) in it so I thought it might have been an ASCII conversion issue, but running it with a1 and b1 as key and message still don't result in matching hashes, even though the byte arrays match. Any help is appreciated, thank you in advance!


Solution

  • I don't know much about PHP, but according to the documentation on hash_hmac it looks as if you might have the $key and $data parameters reversed.

    From the documentation:

    hash_hmac ( string $algo , string $data , string $key [, bool $raw_output = FALSE ] ) : string

    So, it looks like you're passing the $message as the key and $key as the message.