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

问题描述:

我正在尝试在Elixir中编写亚马逊产品广告API客户端。开发者指南描述了the process for signing an API request,其中必须使用请求和“秘密访问密钥”来创建HMAC-SHA26哈希。这是我写的处理请求签名的功能:如何在Elixir中生成HMAC字符串?

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可能会简化您的代码。 – 2014-11-24 16:27:31

当您使用:crypto.hmac/3其返回基地以二进制格式16位整数,你的问题就可以解决这样的:

:crypto.hmac(:sha256, "key", "The quick brown fox jumps over the lazy dog") 
|> Base.encode16 

这是比赛例如从https://en.wikipedia.org/wiki/Hash-based_message_authentication_code#Examples_of_HMAC_.28MD5.2C_SHA1.2C_SHA256.29

+5

或者可能使用Base.encode16(:crypto.hmac(:sha256,“key”,“快速棕色狐狸跳过懒狗”)|> Base.encode16) – sasajuric 2014-11-23 12:15:13

+0

我使用了@sasajuric在他的评论中提出的解决方案因为它少了一行,阅读起来更容易。 – 2015-01-22 20:53:04

+3

这与答案中的内容不一样。与'hmac_bytes |> Base.encode16'和'hmac_bytes |> Base.encode16 |> Base.encode16'之间的区别是相同的。两次编码看起来不合适。 – pkoch 2017-08-31 16:18:36