Search code examples
hmacsha256erlang-otpelixiramazon-product-api

How does one generate an HMAC string in Elixir?


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?


Solution

  • When you using :crypto.hmac/3 its return base 16 integer in binary format, your problem could be solved like this:

    :crypto.mac(: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