如何在Elixir中生成HMAC字符串?

21

我正在尝试使用Elixir编写亚马逊产品广告API客户端。开发者指南描述了签署API请求的过程,其中必须使用请求和“秘密访问密钥”创建HMAC-SHA26哈希。这是我编写的处理签署请求的函数:

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

传入该函数的URL看起来像这样: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

我的问题是,虽然:crypto.hmac/3返回一个二进制值,但该二进制值不是一个字符串。将返回值传递给String.valid?/1将返回false。因此,我无法将返回值连接到url字符串的末尾以对请求进行签名。

我是否错误地使用了:crypto.hmac/3?我是否遗漏了什么?我应该用另一种方式进行吗?


1
你可能还想了解在Elixir中使用字符串插值。http://elixir-lang.org/getting_started/2.html#2.4-strings 这可能会简化你的代码。 - Onorio Catenacci
1个回答

45

6
也许可以使用 Base.encode16 (:crypto.hmac(:sha256, "key", "The quick brown fox jumps over the lazy dog") |> Base.encode16) 。 - sasajuric
我使用了@sasajuric在评论中提出的解决方案,因为它少了一行代码并且更易于阅读。 - Zach Garwood
7
与答案中的内容不同。差异类似于hmac_bytes |> Base.encode16hmac_bytes |> Base.encode16 |> Base.encode16之间的区别。进行两次编码似乎有些多余。 - pkoch
9
根据 https://erlang.org/doc/apps/crypto/new_api.html#the-new-api,未来将会是这样的:`crypto.mac(:hmac, :sha256, priv_key, content) |> Base.encode16`。 - Joe Eifert

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接