Подпись не соответствует ошибке-использование AWS Signature версии 4
Я использую плагин jquery-file-upload для прямой загрузки файла в S3. Я написал код для создания соответствующего документа политики, а также рассчитал подпись в меру моих знаний. Ниже приведены данные, отправляемые в S3
-----------------------------233832764916806 Content-Disposition: form-data; name="key" 50121d1ccb3f3f04400203ab/5365aa6fe104842054008a71.log
-----------------------------233832764916806 Content-Disposition: form-data; name="acl" private
-----------------------------233832764916806 Content-Disposition: form-data; name="Policy" eyAiZXhwaXJhdGlvbiIgOiAiMjAxNC0wNS0wNFQwMzo0ODoxNS4wMDBaIiwgImNvbmRpdGlvbnMiIDogW1siZXEiLCAiJGFjbCIsICJwcml2YXRlIl0sIFsiZXEiLCAiJGJ1Y2tldCIsICJmaXJtemVuLWRvY3VtZW50LXVwbG9hZHMiXSwgWyJzdGFydHMtd2l0aCIsICIka2V5IiwgIjUwMTIxZDFjY2IzZjNmMDQ0MDAyMDNhYi8iXSwgWyJjb250ZW50LWxlbmd0aC1yYW5nZSIsIDAsIE51bWJlckxvbmWFtei1kYXRlIiwgIjIwMTcoNTI0Mjg4MCldLCBbImVxIiwgIiR4LQwNTA0VDAwMDAwMFoiXSwgWyJlcSIsICIkeC1hbXotYWxnb3JpdGhtIiwgIkFXUzQtSE1BQy1TSEEyNTYiXSwgWyJlcSIsICIkeC1hbXotY3JlZGVudGlhbCIsICJBS0lBSUczSFZEUzZCRllaNE1NUS8yMDE0MDUwNC9hcC1zb3V0aGVhc3QtMS9zMy9hd3M0X3JlcXVlc3QiXV0gfQ==
-----------------------------233832764916806 Content-Disposition: form-data; name="X-Amz-Algorithm" AWS4-HMAC-SHA256
-----------------------------233832764916806 Content-Disposition: form-data; name="X-Amz-Credential" AKIHVDSAIG36BFYZ4MMQ/20140504/ap-southeast-1/s3/aws4_request
-----------------------------233832764916806 Content-Disposition: form-data; name="X-Amz-Date" 20140504T000000Z
-----------------------------233832764916806 Content-Disposition: form-data; name="X-Amz-Signature" 6d675b1a24ccd5e4299faaac4218fe27949fb3ac38bd7ccfb7b213195a014682
-----------------------------233832764916806 Content-Disposition: form-data; name="file"; filename="test.log" Content-Type: application/octet-stream
Получен ответ на ошибку
<error>
<code>SignatureDoesNotMatch</code>
<message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</message>
<stringtosignbytes>hex string</stringtosignbytes>
<requestid>C2CAD41FF4687E39</requestid>
<hostid>52UqNeMK28UEydmQx/I/jy/3fsMdKo0UtRAbZnXkfB2aEk35A2bjkciJvNzRktdt</hostid>
<signatureprovided>6d675b1a24ccd5e4299faaac4218fe27949fb3ac38bd7ccfb7b213195a014682</signatureprovided>
<stringtosign>eyAiZXhwaXJhdGlvbiIgOiAiMjAxNC0wNS0wNFQwMzo0ODoxNS4wMDBaIiwgImNvbmRpdGlvbnMiIDogW1siZXEiLCAiJGFjbCIsICJwcml2YXRlIl0sIFsiZXEiLCAiJGJ1Y2tldCIsICJmaXJtemVuLWRvY3VtZW50LXVwbG9hZHMiXSwgWyJzdGFydHMtd2l0aCIsICIka2V5IiwgIjUwMTIxZDFjY2IzZjNmMDQ0MDAyMDNhYi8iXSwgWyJjb250ZW50LWxlbmd0aC1yYW5nZSIsIDAsIE51bWJlckxvbmWFtei1kYXRlIiwgIjIwMTcoNTI0Mjg4MCldLCBbImVxIiwgIiR4LQwNTA0VDAwMDAwMFoiXSwgWyJlcSIsICIkeC1hbXotYWxnb3JpdGhtIiwgIkFXUzQtSE1BQy1TSEEyNTYiXSwgWyJlcSIsICIkeC1hbXotY3JlZGVudGlhbCIsICJBS0lBSUczSFZEUzZCRllaNE1NUS8yMDE0MDUwNC9hcC1zb3V0aGVhc3QtMS9zMy9hd3M0X3JlcXVlc3QiXV0gfQ==</stringtosign>
<awsaccesskeyid>AKIHVDSAIG36BFYZ4MMQ</awsaccesskeyid>
</error>
Я использую следующий код C#, чтобы сгенерировать политику и подписать ее
var extension = Path.GetExtension(fileName);
var fileId = ObjectId.GenerateNewId();
var key = string.Format("{0}/{1}{2}", _firm.Id, fileId, extension);
var keyMatchCondition = string.Format("{0}/", _firm.Id);
var utcNow = DateTime.UtcNow;
var dateString = utcNow.Date.ToString("yyyyMMdd"); // 20140504
var amzCredentialString = string.Format("{0}/{1}/{2}/s3/aws4_request",
<AWSAccessKey>,
dateString,
"ap-southeast-1");
const string awsAlgorithm = "AWS4-HMAC-SHA256";
var conditions =
new List<dynamic[]>
{
new dynamic[] {"eq", "$acl", "private"},
new dynamic[] {"eq", "$bucket", _commonConfig.S3Config.DocumentsBucket},
new dynamic[] {"starts-with", "$key", keyMatchCondition},
new dynamic[] {"content-length-range", 0, 1 * 1024 * 1024},
// utcNow.Date.ToAwsIS08601String() == 20140504T000000Z
new dynamic[] {"eq", "$x-amz-date", utcNow.Date.ToAwsIS08601String()},
new dynamic[] {"eq", "$x-amz-algorithm", awsAlgorithm},
new dynamic[] {"eq", "$x-amz-credential", amzCredentialString},
};
var expiration = utcNow.AddHours(1).ToString("yyyy-MM-ddTHH:mm:ss.000Z", CultureInfo.InvariantCulture);
var policyJson = new {expiration = expiration, conditions = conditions}.ToJson();
var policyBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(policyJson));
var dateKey = new HMACSHA256(Encoding.UTF8.GetBytes("AWS4" + "<secret-key>"))
.ComputeHash(Encoding.UTF8.GetBytes(dateString));
var dateRegionKey = new HMACSHA256(dateKey)
.ComputeHash(Encoding.UTF8.GetBytes("ap-southeast-1"));
var dateRegionServiceKey = new HMACSHA256(dateRegionKey)
.ComputeHash(Encoding.UTF8.GetBytes("s3"));
var signingKey = new HMACSHA256(dateRegionServiceKey)
.ComputeHash(Encoding.UTF8.GetBytes("aws4-request"));
var signedPolicyBytes = new HMACSHA256(signingKey)
.ComputeHash(Encoding.UTF8.GetBytes(policyBase64));
var signature = BitConverter.ToString(signedPolicyBytes).Replace("-", string.Empty).ToLowerInvariant();
Я был бы очень признателен за любые указания на то, что я делаю неправильно или как я должен быть делающий это...1 ответ:
Проблема заключалась в том, как вычислялся конечный результат
signingKey
.Предполагается, что хэшируемые данные должны бытьvar signingKey = new HMACSHA256(dateRegionServiceKey) .ComputeHash(Encoding.UTF8.GetBytes("aws4-request"));
aws4_request
, а неaws4-request
. На момент написания статьи AWS S3 docs ошибочно[1] упоминание[2] окончательные данные должны бытьaws4-request
.В заключение, окончательный ключ подписи должен быть вычислен следующим образом,
var signingKey = new HMACSHA256(dateRegionServiceKey) .ComputeHash(Encoding.UTF8.GetBytes("aws4_request"));