Несоответствие подписи поиска продукта Amazon
Вот ответ, который я получаю: рассчитанная нами подпись запроса не соответствует предоставленной вами подписи.
Вот код, который я использую для генерации подписи:
static byte[] HmacSHA256(String data, byte[] key)
{
String algorithm = "HmacSHA256";
KeyedHashAlgorithm kha = KeyedHashAlgorithm.Create(algorithm);
kha.Key = key;
return kha.ComputeHash(Encoding.UTF8.GetBytes(data));
}
static byte[] getSignatureKey(String key, String dateStamp, String regionName, String serviceName)
{
byte[] kSecret = Encoding.UTF8.GetBytes(("AWS4" + key).ToCharArray());
byte[] kDate = HmacSHA256(dateStamp, kSecret);
byte[] kRegion = HmacSHA256(regionName, kDate);
byte[] kService = HmacSHA256(serviceName, kRegion);
byte[] kSigning = HmacSHA256("aws4_request", kService);
return kSigning;
}
Когда я использую настройки теста Amazon, я получаю правильную подпись
key = 'wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY'
dateStamp = '20120215'
regionName = 'us-east-1'
serviceName = 'iam'
Однако, когда я вставляю свои живые настройки, я получаю ошибку, которая не соответствует.
Вот что я использую, чтобы получить свою подпись:
var reqSig = getSignatureKey("[my secret key]", dateStamp, "us-west-2","AWSECommerceService");
Это то, что я отправляю (сейчас я просто проверяю это в браузере):
ecs.amazonaws.com/onca/xml?Service=AWSECommerceService&AWSAccessKeyId=[my
access key that corresponds with the secret
key]&Operation=ItemLookup&IdType=UPC&ItemId=635753490879&Timestamp=2019-01-24T19:14:55.2644840Z&Signature=32BA07ECE67F3177BF2EA02923E624D612A45FAA144ED0E43BDDC0DF6574EAC3
Я не уверен, имеет ли это отношение к региону - us-west-2 в моем случае - потому что в запросе на регион нет места. Я не уверен, как Amazon может проверить мою подпись по моим параметрам, если я не могу указать, какой это регион, и я использовал регион для вычисления подписи.
Что мне не хватает?
1 ответ
Хорошо. Потратив на это дни, вот что я должен был сделать:
/*
DOCUMENTATION: https://docs.aws.amazon.com/AWSECommerceService/latest/DG/rest-signature.html#rest_detailedexample
*/
var itemID = "0679722769";
var accessKeyID = "AKIAIOSFODNN7EXAMPLE";
var timeStamp = DateTime.UtcNow.ToString("o");
var req = $"Service=AWSECommerceService&AWSAccessKeyId={accessKeyID}&Operation=ItemLookup&IdType=UPC&ItemId={itemID}&Version=2013-08-01&Timestamp={timeStamp}";
req = req.Replace(":", "%3A").Replace(",", "%2C"); //UrlDecode certain characters
var reqlist = req.Split('&').ToArray(); //we need to sort our key/value pairs
Array.Sort(reqlist);
req = String.Join("&", reqlist); //join everything back
var reqToSign = $@"GET
webservices.amazon.com
/onca/xml
{req}".Replace("\r", ""); //create the request for signing. We need to replace microsofts's crlf with just a lf; Make sure there are no leading spaces after the linefeeds.
var signage = getSignatureKey("1234567890",reqToSign);
req = $"http://webservices.amazon.com/onca/xml?{req}&Signature={signage}"; //create our request with the signature appended.
return req;
}
private static byte[] HmacSHA256(String data, byte[] key)
{
String algorithm = "HmacSHA256";
KeyedHashAlgorithm kha = KeyedHashAlgorithm.Create(algorithm);
kha.Key = key;
return kha.ComputeHash(Encoding.UTF8.GetBytes(data));
}
private static string getSignatureKey(string key, string stringToSign)
{
byte[] kSecret = Encoding.UTF8.GetBytes(key.ToCharArray());
byte[] kSigning = HmacSHA256(stringToSign, kSecret);
return WebUtility.UrlEncode(Convert.ToBase64String(kSigning));
}
Вопреки большинству ответов, найденных здесь и в других местах, это единственный способ, который работает. Весь запрос должен быть хэширован, а не только конкретные параметры. Я не могу разговаривать с другими сервисами Amazon, но Commerce Service должен быть сделан следующим образом.
На некоторые ответы ссылались: https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html или вот что: Amazon API генерирует подпись запроса в C# .NET
Как я сказал в своем вопросе, это, безусловно, не правильно. Если вы не передаете параметр региона, как Amazon может создать такую же подпись, поскольку она не имеет всей информации.
Во всяком случае, это работает сейчас.