AWS S3直接上传返回无效签名(版本4签名)



我厌倦了看到此响应:

我们计算的请求签名与您提供的签名不匹配。检查您的钥匙和签名方法。

我知道这个问题在这里回答:

so -AWS S3浏览器使用HTTP帖子上传无效签名

我遵循了它的每个细节,没有运气,我可能缺少简单的东西。我正在使用C#生成策略和V4 AWS签名。这是策略代码:

var policyBuilder = new StringBuilder();
policyBuilder.AppendFormat("{{ "expiration": "{0}",rn", "2017-12-30T12:00:00.000Z");
policyBuilder.Append("  "conditions": [rn");
policyBuilder.Append("    ["starts-with", "$key", ""],rn");
policyBuilder.AppendFormat("    {{"x-amz-credential": "{1}"}},rn",  <MyAccessKey>/20170214/us-east-2/s3/aws4_request));
policyBuilder.Append("    {"x-amz-algorithm": "AWS4-HMAC-SHA256"},rn");
policyBuilder.Append("    {"x-amz-date": "20170214T000000Z" }rn");
policyBuilder.Append("  ]rn}");
var policyString = policyBuilder.ToString();
var policyStringBytes = Encoding.UTF8.GetBytes(policyString);
return Convert.ToBase64String(policyStringBytes);

这是用于生成签名的代码:

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;
}
public static string ToHexString(byte[] data, bool lowercase)
{
    var sb = new StringBuilder();
    for (var i = 0; i < data.Length; i++)
    {
        sb.Append(data[i].ToString(lowercase ? "x2" : "X2"));
    }
    return sb.ToString();
}

将所有内容融合在一起的方法:

public string GetS3PolicySignatureV4(string policy)
{
    byte[] signingKey = GetSignatureKey(<MySecretKey>, "20170214T000000Z", "us-east-2", "s3");
    byte[] signature = HmacSHA256(policy, signingKey);
    return AWS4SignerBase.ToHexString(signature, true);
}

这是HTML形式:

<form action="http://<BucketName>.s3.amazonaws.com/" method="post" enctype="multipart/form-data">
    <input type="hidden" name="key" value="<FileKey>" />
    <input type="hidden" name="x-amz-credential" value="<MyAccessKey>/20170214/us-east-2/s3/aws4_request"/>
    <input type="hidden" name="x-amz-algorithm" value="AWS4-HMAC-SHA256" />
    <input type="hidden" name="x-amz-date" value="20170214T000000Z" />
    <input type="hidden" name="policy" value='<Base64PolicyResult>' />
    <input type="hidden" name="x-amz-signature" value="<GenerateSignature>" />
    File:
    <input type="file" name="file" /> <br />
    <input type="submit" name="submit" value="Upload to Amazon S3" />
</form>

我已经验证了示例策略在此示例中结果:

aws-示例:使用HTTP Post的基于浏览器的上传(使用AWS签名版本4)

以及所得的签名使用提供的参数和键匹配示例。但是,当我尝试发布到S3时,我总是会得到可怕的回应。

问题是将日期传递到getsignaturekey方法中的格式错误。应该只是" 20170214",隐藏的表单X-AMZ-DATE是" 20170214T000000Z"的ISO8601格式。我正在将相同的值传递到getsignaturekey方法中。

最新更新