Willing to pay immediately via PayPal for anyone who can solve ASAP, but only
if the problem is solved, no partial solutions.
******************************
Background:
Code that is about 3 years old, worked fine in older version of CF
engine (Blue Dragon Server JX 6). Code takes a stirng, encypts it to
HMAC_SHA256 and sends it to Amazon. I am 100% certain of the code working
now, with the exception of the signature, which is the problem.
******************************
Tools needed:
Amazon account - AWSAccessKeyId and Secret Access Key (Key pair);
Associate Tag
Railo 3 - (I am using 3.3.1)
Platform - OS X 10.6 or 10.7 or Ubuntu (using Ubuntu 11.04 Server) but
problem is seen on both OS X and Unix, so either one will work to test.
******************************
More info:
The code uses two custom functions and creates a signed request for
use with Amazon services. Even after updating the URL key pairs with latest
(minor) amazon changes, the signature simply is not matching what Amazon
expects. I can use Amazon's tool to check the URL I generate
(http://associates-amazon.s3.amazonaws.com/signed- requests/helper/index.html)
and then allow Amazon to add the signature based on my keys, and that works.
But whenever I try to generate the signed request in CF it fails. I can get
the signed request to work with a PHP script I downloaded. But I need it in
CF.
******************************
START ENTIRE CF CODE:
<!--- function to create your encoded signature --->
<cffunction name="HMAC_SHA256" returntype="binary" access="public"
output="false">
<cfargument name="signKey" type="string" required="true" />
<cfargument name="signMessage" type="string" required="true" />
<cfset var jMsg =
JavaCast("string",arguments.signMessage).getBytes("iso-8859-1") />
<cfset var jKey =
JavaCast("string",arguments.signKey).getBytes("iso-8859-1") />
<cfset var key = createObject("java","javax.crypto.spec.SecretKeySpec")
/>
<cfset var mac = createObject("java","javax.crypto.Mac") />
<cfset key = key.init(jKey,"HmacSHA256") />
<cfset mac = mac.getInstance(key.getAlgorithm()) />
<cfset mac.init(key) />
<cfset mac.update(jMsg) />
<cfreturn mac.doFinal() />
</cffunction>
<!--- function to create your url --->
<cffunction name="GenerateSignedAmazonURL" returnType="string" output="no">
<!--- parameters --->
<cfargument name="HTTPVerb" required="yes">
<cfargument name="HostHeader" type="string" required="yes">
<cfargument name="HTTPRequestURI" type="string" required="yes">
<cfargument name="SecretAccessKey" type="string" required="yes">
<cfargument name="RawQueryString" type="string" required="yes">
<!--- initialize local var --->
<cfset variables.signature = "">
<cfset variables.encodedQueryString = "">
<cfset variables.sortedQueryString = "">
<cfset variables.encodedSignature = "">
<!--- get your timestamp--->
<cfset thenow=dateConvert("local2Utc",now())>
<cfset time_stamp = "#DateFormat(thenow,'yyyy-mm-
dd')#T#TimeFormat(thenow,'HH:mm:ss')#.00Z">
<!--- append timestamp to query string --->
<cfset arguments.RawQueryString = arguments.RawQueryString &
"&Timestamp=#time_stamp#">
<!--- start building signature --->
<cfset variables.signature = arguments.HTTPVerb & chr(10)>
<cfset variables.signature = variables.signature
&lcase(arguments.HostHeader) & chr(10)>
<cfset variables.signature = variables.signature
&arguments.HTTPRequestURI & chr(10)>
<!--- loop over the list and urlEncode each value --->
<cfloop list="#arguments.RawQuerySTring#" delimiters="&" index="i">
<cfset name = listGetAt(i, 1, "=")>
<cfset value = "">
<!--- if this item has a value encode it --->
<cfif listLen(i, "=") gt 1>
<cfset value = replace(replace(replace(listGetAt(i, 2,
"="), ",", "%2C", "ALL"), ":", "%3A", "ALL"), " ", "%20", "ALL")>
</cfif>
<!--- build the new query string with encoded values --->
<cfset variables.encodedQueryString =
listAppend(variables.encodedQueryString, "#name#=#value#", "&")>
</cfloop>
<!--- next we need to canonically order the queryString params --->
<cfset variables.sortedQueryString =
listSort(variables.encodedQueryString, "textnocase", "asc", "&")>
<!--- append to the signature --->
<cfset variables.signature = variables.signature &
variables.sortedQueryString>
<!--- encode the signature --->
<cfset variables.encodedSignature =
urlencodedformat(toBase64(HMAC_SHA256(arguments.SecretAccessKey,
variables.signature))) />
<cfreturn "http://#arguments.HostHeader##arguments.HTTPRequestURI#?
#variables.sortedQueryString#&Signature=#variables.encodedSignature#">
</cffunction>
<!--- generate signed request --->
<cfset theHTTPVerb = "GET">
<cfset theHostHeader = "ecs.amazonaws.com">
<cfset theHTTPRequestURI = "/onca/xml">
<cfset theSecretAccessKey = "YOUR-AMAZON-SECRET-ACCESS-KEY">
<!--- each param on a new line for readability. order is immaterial here, see
code source for more options --->
<cfset theQueryString = "AWSAccessKeyId=YOUR-AMAZON-ACCESS-KEY-ID"
& "&AssociateTag=YOUR-AMAZON-ASSOCIATE-ID"
& "&IdType=ASIN"
& "&ItemId=iPad2"
& "&MerchantID=Amazon"
& "&Operation=ItemLookup"
& "&ResponseGroup=Large"
& "&SearchIndex=Electronics"
& "&Service=AWSECommerceService"
& "&SignatureMethod=HmacSHA256"
& "&SignatureVersion=2"
& "&Version=2011-08-01">
<!--- debug --->
<cfoutput>
<a href="#GenerateSignedAmazonURL(theHTTPVerb, theHostHeader,
theHTTPRequestURI, theSecretAccessKey,
theQueryString)#">#GenerateSignedAmazonURL(theHTTPVerb, theHostHeader,
theHTTPRequestURI, theSecretAccessKey, theQueryString)#</a>
</cfoutput>
END ENTIRE CF CODE:
******************************
So, what happens when you run this? Well, you get an output like this which is
correct EXCEPT for the signature:
http://ecs.amazonaws.com/onca/xml?AssociateTag=YOUR-ASSOCIATE-ID&AWSAccessKeyId=YOUR-AWS-ACCESS-JEY&IdType=ASIN&ItemId=iPad2&MerchantID=Amazon&Operation=ItemLookup&ResponseGroup=Large&SearchIndex=Electronics&Service=AWSECommerceService&SignatureMethod=HmacSHA1&SignatureVersion=2&Timestamp=2011-11-10T16%3A32%3A40.00Z&Version=2011-08-01&Signature=Cbojm2j3XyG8i%2FweIT%2Fzkt4uff4wWjcqLHwwg8EkG0I%3D
HOW DO I KNOW THAT THE REQUEST IS CORRECT - - EXCEPT FOR THE SIGNATURE?
Test the code at
http://associates-amazon.s3.amazonaws.com/signed-requests/helper/index.html
...by entering the URL created by the CF code above - except for the time
stamp and the signature at the end:
http://ecs.amazonaws.com/onca/xml?AssociateTag=YOUR-ASSOCIATE-ID&AWSAccessKeyId=YOUR-AWS-ACCESS-JEY&IdType=ASIN&ItemId=iPad2&MerchantID=Amazon&Operation=ItemLookup&ResponseGroup=Large&SearchIndex=Electronics&Service=AWSECommerceService&SignatureMethod=HmacSHA1&SignatureVersion=2&Version=2011-08-01
remove this part ==> &Timestamp=2011-11-10T16%3A32%3A40.00Z
and
remove this part ==>
&Signature=Cbojm2j3XyG8i%2FweIT%2Fzkt4uff4wWjcqLHwwg8EkG0I%3D
The Amazon request helper will then generate the time stamp and signature for
you, then cut and paste the final Signed URL that Amazon generates into a
browser address bar and you will get the XML data back as you should.
However, if you test your output WITH the signature, you will get:
<?xml version="1.0"?>
<ItemLookupErrorResponse
xmlns="http://ecs.amazonaws.com/doc/2011-08-01/"><Error><Code>SignatureDoesNotMatch</Code><Message>The
request signature we calculated does not match the signature you provided.
Check your AWS Secret Access Key and signing method. Consult the service
documentation for
details.</Message></Error><RequestID>cdddeba5-953a-4315-8248-9bdc0101101e</RequestID></ItemLookupErrorResponse>
******************************
Encryption seems to be a major PITA in CF. But the function at the start of
this code is Java and so it woudl seem that the problem is with Java and
getting Java to generate the correct signature. But, I'm not a Java pro, so I
don't know. This could be as easy as installing the correct Java encryption
library, but I've not been successful in discovering what that is. So, if
that's the problem and you know, well you just made a little cash.
__________________
Derrick Peavy
[email protected]
404-786-5036
“Innovation distinguishes between a leader and a follower.” - Steve Jobs
"In economics, the majority is always wrong." - John Kenneth Galbraith
"Faced with the choice between changing one’s mind and proving there is no need
to do so, almost everyone gets busy on the proof." - John Kenneth Galbraith
_____________________
-------------------------------------------------------------
To unsubscribe from this list, manage your profile @
http://www.acfug.org?fa=login.edituserform
For more info, see http://www.acfug.org/mailinglists
Archive @ http://www.mail-archive.com/discussion%40acfug.org/
List hosted by http://www.fusionlink.com
-------------------------------------------------------------