我遇到了为ec2 API的第2版签名编码哈希的问题。
注意我的版本1签名哈希工作正常,但这是折旧的,我需要转移到版本2.所以首先这里是有效的代码...
参数只是一个字典,我要做的只是按键对参数进行排序,并附加没有分隔符的每个值对,然后将该字符串与我的密钥进行散列。 (再次注意这很好用)
private string GetVersion1Sig()
{
string sig = string.Join(string.Empty, parameters.OrderBy(vp => vp.Key).Select(p => string.Format("{0}{1}", p.Key, p.Value)).ToArray());
UTF8Encoding encoding = new UTF8Encoding();
HMACSHA256 signature = new HMACSHA256(encoding.GetBytes(_secretAccessKey));
byte[] hash = signature.ComputeHash(encoding.GetBytes(sig));
string result = Convert.ToBase64String(hash);
return result;
}
现在,版本2有一些变化,这里是来自API开发人员指南的doco ......
一个。使用自然字节顺序按参数名称对UTF-8查询字符串组件进行排序。 参数可以来自GET URI或POST主体(当Content-Type时 是application / x-www-form-urlencoded)。
湾URL根据以下规则对参数名称和值进行编码:
•不要对RFC 3986定义的任何未保留字符进行URL编码。
这些未保留的字符是A-Z,a-z,0-9,连字符( - ),下划线(_),句点(。),
和波浪号(〜)。
•百分比用%XY编码所有其他字符,其中X和Y是十六进制字符0-9和
大写A-F。
•百分比编码扩展的UTF-8字符,格式为%XY%ZA ....
•百分比将空格字符编码为%20(而不是+,作为常见编码方案
做)。
请注意
目前,所有AWS服务参数名称都使用未保留的字符,因此您不需要
需要对它们进行编码。但是,您可能希望包含代码来处理参数
使用保留字符的名称,以备将来使用。
℃。使用等号(=)将编码的参数名称与其编码值分开 (ASCII字符61),即使参数值为空。
d。用符号(&)(ASCII码38)分隔名称 - 值对。
所以我拥有的是......
private string GetSignature()
{
StringBuilder sb = new StringBuilder();
sb.Append("GET\n");
sb.Append("ec2.amazonaws.com\n");
sb.Append("/\n");
sb.Append(string.Join("&", parameters.OrderBy(vp => vp.Key, new CanonicalizedDictCompare()).Select(p => string.Format("{0}={1}", HttpUtility.UrlEncode(p.Key), HttpUtility.UrlEncode(p.Value))).ToArray()));
UTF8Encoding encoding = new UTF8Encoding();
HMACSHA256 signature = new HMACSHA256(encoding.GetBytes(_secretAccessKey));
byte[] hash = signature.ComputeHash(encoding.GetBytes(sb.ToString()));
string result = Convert.ToBase64String(hash);
return result;
}
完整性这里是IComparer实现....
internal class CanonicalizedDictCompare : IComparer<string>
{
#region IComparer<string> Members
public int Compare(string x, string y)
{
return string.CompareOrdinal(x, y);
}
#endregion
}
据我所知,我已经完成了我需要为此哈希做的所有事情,但我不断从服务器收到错误,告诉我我的签名不正确。帮助...
答案 0 :(得分:7)
好吧,我想通了...... HttpUtility类中的UrlEncoding不符合亚马逊编码方案.... grrr(特别是.NET实用程序中的%之后的十六进制值是小写,而不是大写)
湾URL根据以下规则对参数名称和值进行编码:
百分比编码所有其他字符 %XY,其中X和Y是十六进制 字符0-9和大写字母A-F 。
百分比编码扩展的UTF-8 %XY%ZA ....
因此,在编写了一个编码为此方案的快速方法之后,它可以正常工作。