Coldfusion pack(H* equivalent

Question

I am trying to emulate a php function in coldfusion. The Php output for the following;

<?php echo (strtoupper(hash_hmac('SHA256', 'a cow jumps over the moom', pack('H*','specialkey')))); ?>

Results in E9C9E66592306F1BD27A3B1991C7650D4A8920D10E5FFDA955DA692225793F35

When try in CF

<cfset z=hmac("a cow jumps over the moom", "specialkey","HMACSHA256")>

Result is 1A905E37DC5F7544E170FB2D47743417AFC7CC0CE53188F30E78BC09D3A61ADF

It is obviously to do with the pack(H* part, as if I run

<?php echo (strtoupper(hash_hmac('SHA256', 'a cow jumps over the moom', 'specialkey'))); ?>

The result is 1A905E37DC5F7544E170FB2D47743417AFC7CC0CE53188F30E78BC09D3A61ADF

How do I emulate the pack(H* in php? I nee to return the result E9C9E66592306F1BD27A3B1991C7650D4A8920D10E5FFDA955DA692225793F35 in CF?


Show source
| php   | coldfusion   2017-01-03 21:01 1 Answers

Answers ( 1 )

  1. 2017-01-04 02:01

    Although it may seem like both sides are using the same key - they are not.

    In order to generate the HMAC, both PHP and CF must first decode the value into binary, and that value is what is actually used as the "key". The reason you are getting a different result is that the two sides are decoding the key value differently: PHP decodes it from hexadecimal and CF as a plain string using the JVM default ie UTF-8, ASCII, etcetera. As a result, PHP and CF are generating totally different keys and that is why the HMAC codes do not match.

    Having said that, I noticed your key value "specialkey" is not actually a valid hexadecimal string. So before you spend a lot of time on this, my question would be is the PHP code really using arbitrary strings like "specialkey" or is that just for testing purposes? If the real code is using valid hexadecimal strings, then just pass in a binary key to CF's HMAC function and the results should be the same:

    ColdFusion:

    writeOutput( hmac("a cow jumps over the moom"
                , binaryDecode("7370656369616c6b6579", "hex")
                , "HMACSHA256"));
    

    PHP:

    echo (strtoupper(hash_hmac('SHA256', 'a cow jumps over the moom', pack('H*','7370656369616c6b6579'))));
    

    Result:

    1A905E37DC5F7544E170FB2D47743417AFC7CC0CE53188F30E78BC09D3A61ADF
    

    Update: If for some reason you really did need to use arbitrary strings as keys, take a look the Perl docs for pack (on which the PHP function is based).

    Disclaimer: I am not really a PHP guy, so there is a little more to it, but ... essentially pack(H*) breaks your key string into pairs of characters and interprets them as hex. The invalid characters like "s", "p", "i", etcetera are converted to null or 0:

      sp   --> 00  ("s" and "p" are invalid)
      ec   --> EC  ("e" and "c" are valid hex)
      ia   --> 0A  ("i" is invalid, "a" is valid)
      lk   --> 00  ("l" and "k" are both invalid)
      ey   --> E0  ("e" is valid, "y" is invalid)
    

    The resulting binary is this (in hexadecimal):

    00 EC 0A 00 E0
    

    If you decode that hex string back into binary and use it as the key:

    hmac("a cow jumps over the moom", binaryDecode("00EC0A00E0", "hex"), "HMACSHA256")
    

    CF returns the same result as PHP:

    E9C9E66592306F1BD27A3B1991C7650D4A8920D10E5FFDA955DA692225793F35
    
◀ Go back