If you’re writing a direct HTTP/HTTPS GET request for accessing any of the Amazon Web Services -AWS- via the REST API you probably have dealt with this error message. For the general audience: why would you like to access AWS directly? (I mean, without using any of their frameworks). There are situations when you don’t want (or you can not) have the burden of a framework. For example: you’re using a programming language which is not provided with an Amazon framework or you’re coding from an embedded device (and again, there is not framework for your specific micro controller).

There are two steps: the first one it’s creating a canonical string of your request. The following example is a HTTP GET request to write into the Amazon SQS:

“GET\n” +
“END-POINT\n” +
“/ACCOUNT#/QUEUE-NAME\n” +
“AWSAccessKeyId=ACCESS-KEY” +
“&Action=SendMessage” +
“&MessageBody=MESSAGE” +
“&SignatureMethod=HmacSHA1” +
“&SignatureVersion=2” +
“&Timestamp=TIME-STAMP” +
“&Version=2012-11-05″;

You have to replace the following place holders with your own values: END-POINT, ACCOUNT#, QUEUE-NAME, ACCESS-KEY, MESSAGE and TIME-STAMP. I think all values are self explanatory except these ones:

-END-POINT: it’s the server name of the AWS (without the protocol). For example: sqs.eu-west-1.amazonaws.com

-MESSAGE: must be URL encoded. For example: you will have to replace ” ” for “%20” or “=” f0r “%3d”. If you’re using C# you can use HttpUtility.UrlEncode.

-TIME-STAMP: must be in the ISO format described by Amazon here. If you’re using C# try DateTime.Now.ToString(“s”). It should be url-encoded as well (replace “:” for “%3A”).

After creating your canonical string sign it using the HMACSHA1 (or HMACSHA256) C# class. Then after getting your calculated value url-encode it again to create the following URL:

http://END-POINT/ACCOUNT#/QUEUE-NAME?AWSAccessKeyId=ACCESS-KEY&Action=SendMessage&MessageBody=hello%20world&SignatureMethod=HmacSHA1&SignatureVersion=2&Timestamp=2012-12-11T13%3A14%3A02&Version=2012-11-05&Signature=YOUR-CALCULATED-SIGNATURE

Bear in mind that there are multiple API version dates. In this case I’m using the “2012-11-05”. Another one would require different parameters. By other hand pay special attention to the lexicographical order of the query name/values.

This blog was the result of finding by myself the solution to the following question posted in this Amazon forum.

[Update 12/Dec/2012 how did I find the solution: Combinatorial Testing for taking real world desitions]

Cheers,

Javier Andrés Cáceres Alvis

Microsoft Most Valuable Professional – MVP
Intel Black Belt Software Developer