'Unable to match results of php hash_hmac() and coldfusion hmac()

I am working on encrypting a URL and converting a working script from PHP to ColdFusion. I have completed 95% of the work but I am stuck at this point after trying many solutions available on StackOverflow. My results are still not matching. I confirmed the saltBin and keyBin values are the same on both scripts. Please have a look.

PHP version

$saltBin = R�k��E�x^ �O<�-�7J=S�z��� �;
$keyBin = �;B��|� �0U,��h�NS+��.��G���

res = hash_hmac('sha256', $saltBin, $keyBin);
result
39ddcd6156a30fdcebc9fbf5dd59a0ef4f47e27841bbc12ce72b64a0a63c0324

Coldfusion version

<cfset res = hmac(saltBin,keyBin,"HMACSHA256")>
result
30A658BEB3965C2D7D27A3F717FB6C13B05ED44E8B2A5A7FEBB9B57887CF57A0

I have tried the following solutions

ColdFusion equivalent to PHP hash_hmac

coldfusion hashing and difference between hmacSHA256 and SHA256

Update:

Below is an abbreviated version of the PHP version

$key = '943b421c9eb07c830af81030552c86009268de4e532ba2ee2eab8247c6da0881';
$salt = '520f986b998545b4785e0defbc4f3c1203f22de2374a3d53cb7a7fe9fea309c5';
$keyBin = pack("H*" , $key);
$saltBin = pack("H*" , $salt);
$path = "/rs:fill:300:300:1/g:no/aHR0cDovL2ltZy5leGFtcGxlLmNvbS9wcmV0dHkvaW1hZ2UuanBn.png";
echo hash_hmac('sha256', $saltBin.$path, $keyBin);

Result: 7062c2b5786c82de963767de4b0cdbc4e7ed7db2ce7466708bf8a28d8572888b

ColdFusion version

<cfset key = '943b421c9eb07c830af81030552c86009268de4e532ba2ee2eab8247c6da0881'>
<cfset salt = '520f986b998545b4785e0defbc4f3c1203f22de2374a3d53cb7a7fe9fea309c5'>
<cfset keyBin = binaryDecode(key, 'hex')>  
<cfset keyBin =  toString(keyBin)>
<cfset saltBin = binaryDecode(salt, 'hex')>  
<cfset saltBin =  toString(saltBin)>
<cfset path =  "/rs:fill:300:300:1/g:no/aHR0cDovL2ltZy5leGFtcGxlLmNvbS9wcmV0dHkvaW1hZ2UuanBn.png">
<cfset result = hmac(saltBin&path,keyBin,"HMACSHA256")>
<cfoutput>#result#</cfoutput>

Result: FFA7A526BB464CA1470F309605F1ED63832342B704F8475BFAF26CCD1092603B

Can anyone please help me in this regard?

Thanks.



Solution 1:[1]

saltBin and keyBin values are the same on both scripts

Yes, those values are the same, but the data being hashed isn't. That's why the results don't match.

The php code hashes the concatenated binary of the salt and path variables. To illustrate using a simple values:

Data Value Binary Base64
Salt ab [-85] qw==
Path 123 [49,50,51] MTIz
Salt + Path n/a [-85,49,50,51] qzEyMw==

Whereas the CF code uses the binary of the concatenated strings salt and path, after some very ... dubious re-encoding with ToString(). As you can see, the resulting binary is very different than what's used by php:

Data Value Binary Base64
Salt ? [-17,-65,-67] 77+9
Path 123 [49,50,51] MTIz
Salt + Path ?123 [-17,-65,-67,49,50,51] 77+9MTIz

The CF code needs to concatenate the binary of the two variables. Then pass that binary to the hmac() function:

CF (see runnable example)

<cfscript>
   key = '943b421c9eb07c830af81030552c86009268de4e532ba2ee2eab8247c6da0881';
   salt = '520f986b998545b4785e0defbc4f3c1203f22de2374a3d53cb7a7fe9fea309c5';
   keyBin =  binaryDecode(key, "hex");
   saltBin = binaryDecode(salt, "hex");
   path = "/rs:fill:300:300:1/g:no/aHR0cDovL2ltZy5leGFtcGxlLmNvbS9wcmV0dHkvaW1hZ2UuanBn.png";
   pathBin = charsetDecode(path, "utf-8");

   // merge binary of salt and path
   combined = [];
   combined.append(saltBin, true);
   combined.append(pathBin, true);
   result = lcase(hmac( javacast("byte[]", combined),keyBin,"HMACSHA256"));
   writeDump(result);
</cfscript>

Result: 7062c2b5786c82de963767de4b0cdbc4e7ed7db2ce7466708bf8a28d8572888b

PHP (see runnable example)

<?php
$key = '943b421c9eb07c830af81030552c86009268de4e532ba2ee2eab8247c6da0881';
$salt = '520f986b998545b4785e0defbc4f3c1203f22de2374a3d53cb7a7fe9fea309c5';
$keyBin = pack("H*" , $key);
$saltBin = pack("H*" , $salt);
$path = "/rs:fill:300:300:1/g:no/aHR0cDovL2ltZy5leGFtcGxlLmNvbS9wcmV0dHkvaW1hZ2UuanBn.png";
echo hash_hmac('sha256', $saltBin.$path, $keyBin);

Result: 7062c2b5786c82de963767de4b0cdbc4e7ed7db2ce7466708bf8a28d8572888b

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1