Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

coldfusion calculating HMAC256 of a getHTTPRequestData

I'm working with Shopify at the moment and using their webhook notifications so I can save stuff to our database.

Within their webhook headers, they provide a header of: X-Shopify-Hmac-Sha256

which is:

Each Webhook request includes a X-Shopify-Hmac-SHA256 header which is generated using the app's shared secret (looks like: '267bb1719a8e6ff75c4f2d709be0ca11'), along with the data sent in the request.

This is jolly wonderful; However, I'm really struggling to calculate the value of the X-Shopify-Hmac-Sha256.

I have a .cfm page which the webhook hits and I pass through the getHTTPRequestData to a function like thus:

<cfscript>
variables.stArgs                        = {};
variables.stArgs.stWebHookData          = getHTTPRequestData();
application.stObj.stShopify.oShopifyWebHookBusiness.receiveWebHook(argumentCollection=variables.stArgs);
</cfscript>

I then stole some code from StackOverflow and Ben Nadel, but neither seem to end up giving me the value that I want. Currently I'm using Ben Nadels code like thus:

local.data = arguments.stWebHookData.toString();
local.macClass = createObject( "java", "javax.crypto.Mac" );
local.secretkeySpec = createObject( "java", "javax.crypto.spec.SecretKeySpec" ).init(toBinary(toBase64(arguments.key)),'HmacSHA256');
local.mac = local.macClass.getInstance('HmacSHA256');
local.mac.init(local.secretkeySpec );

local.hashedBytes = local.mac.doFinal(toBinary(toBase64(local.data)));
return lcase( binaryEncode( local.hashedBytes, "base64" ) );

(arguments.key is the shared secret)

Somewhere along the way, I am going wrong. Have I completely misunderstood what I am meant to be doing. This looks so easy in PHP.

like image 382
Jarede Avatar asked Oct 20 '22 16:10

Jarede


1 Answers

So, getHTTPRequestData() returns a struct with a number of members. The one we're interested is content, which will be a byte array.

The MAC classes' doFinal() method expects an array of bytes (in our case the HTTP request's content) and returns an array of bytes (the HMac of the content)

The returned byte array needs to be base-64 encoded in order to compare it to the one Shopify puts in the webhook's headers. toBase64() will do that for us.

Putting it all together, you get this: toBase64(local.mac.doFinal(getHTTPRequestData().content))

like image 157
barnyr Avatar answered Oct 27 '22 09:10

barnyr