I'm attempting to write an Amazon Product Advertising API client in Elixir. The developer guide describes the process for signing an API request in which the an HMAC-SHA26 hash must be created using the request and the "Secret Access Key." This is the function I wrote to handle signing the request:
defp sign_request(url) do
url_parts = URI.parse(url)
request = "GET\n" <> url_parts.host <> "\n" <> url_parts.path <> "\n" <> url_parts.query
url <> "&Signature=" <> :crypto.hmac(:sha256, 'ThisIsMySecretAccessKey', request)
end
The url passed into the function looks something like this: http://webservice.amazon.com/onca/xml?AssociateTag=ThisIsMyAssociateTag&AWSAccessKeyId=ThisIsMyAWSAccessKeyId&Keywords=stuff&Operation=ItemSearch&SearchIndex=Apparel&Service=AWSECommerceService&Timestamp=2014-11-22T12%3A00%3A00Z&Validate=True&Version=2013-08-01
The issue I'm having is that, while:crypto.hmac/3
returns a binary, that binary is not a string; passing the return value to String.valid?/1
returns false
. So, I am unable to concatenate the return value onto the end of the url string to sign the request.
Am I using :crypto.hmac/3
incorrectly? Is there something I'm missing? Is there an alternate way I should be going about this?
When you using :crypto.hmac/3
its return base 16 integer in binary format, your problem could be solved like this:
:crypto.hmac(:sha256, "key", "The quick brown fox jumps over the lazy dog")
|> Base.encode16
This is match example from https://en.wikipedia.org/wiki/Hash-based_message_authentication_code#Examples_of_HMAC_.28MD5.2C_SHA1.2C_SHA256.29