Link to home
Start Free TrialLog in
Avatar of drgdrg
drgdrg

asked on

Problem Generating Keys for Amazon / Alexa with HMAC / SHA-1

I've been trying to generate keys for accessing the Amazon / Alexa API.  It uses HMAC / SHA-1 to encode a key for authentication.  I've tried the CF_HMAC custom tag but it generates a 56 character signature... the "valid" signature is 28 characters.  Obviously I'm off by double... not sure how to interpret or handle that.

The code "in" is 40 characters (the secret key).

There is a test page where I've tested the key and parameters (SecretKey, ServiceName, operationName, TimeStamp) and it outputs the "acceptible" key that would be used by Amazon.  They give you the page to download locally and run locally.  It uses Javascript to generate the key.  I've done it, tested the key and it did work on Amazon correctly, and was a 28 character key.

The key is driven, in part, by a time stamp, so it is constantly changing.  I can't do a CFHTTP (AFAIK) to my copy of that page because the javascript would be run by the browser, not by the server, so all I get back is the page with the unexecuted javascript on it.

The new encrypt() function does not work - it does not support SHA-1.

Any suggestions?  Is there any easy way to convert javascript to, say, CFScript?  Or is there a tag out there that does all of this already?

Here's a link to the test javascript: http://www.drg1.com/alexakeygen.cfm

Any suggestions?  I"m really stuck !

Here's my code:

<CFSET accessKey="12345678901234567890">
<CFSET secretKey="1234567890123456789012345678901234567890">

<CFSET TimeStamp=dateConvert("local2Utc",now())>
<CFSET TimeStamp=trim(urlencodedformat("#LSDateFormat(TimeStamp,"YYYY-MM-DD")#T#LSTimeFormat(TimeStamp,"HH:mm:ss.000Z")#"))>

<!--- Note: the one below was added so on all tests I would produce the same result... it is in the right format --->
<CFSET TimeStamp="2006-03-07T13:43:45.000Z">

<CFSET service="AlexaWebInfoService">
<CFSET operation="UrlInfo">

<!--- Amazon indicates that the key must be converted to base64... it isn't clear at what step, so I've tested all ways --->

<!--- Here's testing, first converting the secret key to base64 --->
<CF_HMAC data="#Service##Operation##TimeStamp#" key="#tobase64(secretKey)#" hash_function="sha1">
digest=#digest# (len #len(digest)#)<BR>

<!--- Here's testing, converting the result to base64 --->
<CF_HMAC data="#Service##Operation##TimeStamp#" key="#secretKey#" hash_function="sha1">
digest=#tobase64(digest)# (len #len(tobase64(digest))#)<BR>

I keep getting 56 character - and invalid - responses.

Help!  Thanks

Chris
ASKER CERTIFIED SOLUTION
Avatar of RCorfman
RCorfman

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of drgdrg
drgdrg

ASKER

I found the answer myself on another forum (thanks for the try RCorfman).  Let me share it if anyone else needs it:

This last line was the tricky part.  it needed three levels of "decoding" to get it into the right format - first BinaryDecode, then toBase64 and then finally urlencodedformat - all in that order.  It also uses a custom tag (found in the macromedia gallery).  Just search for "HMAC".  The tag is several years old but still works 100%

<CFSET accessKey="1111111111111111">
<CFSET secretKey="222222222222222222222222222222222222">

<CFSET thenow=dateConvert("local2Utc",now())>
<cfset time_stamp = "#DateFormat(thenow,'yyyy-mm-dd')#T#TimeFormat(thenow,'HH:mm:ss')#.000Z">
<cfset service_name = "AlexaWebInfoService">
<cfset operation_name = "UrlInfo">
<cfmodule      template="/CustomTags/hmac/hmac.cfm"
            key="#secretkey#"
            data="#service_name##operation_name##time_stamp#"
            hash_function="sha1">
<cfset signature = urlencodedformat(toBase64(BinaryDecode(digest, "hex")))>