亚马逊AWS Signature V4 Java提供错误的编码

时间:2016-05-15 15:33:46

标签: java amazon-web-services amazon-s3

我正在尝试创建一个简单的表单,使用AWS Signature V4直接从我的浏览器将对象发布到S3中的存储桶。

我使用Java为预签名表单生成策略和签名值。目前,我只是想测试一下它是否有效,所以我不介意这是一个手动签名生成过程。

我的Java代码如下

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class Lala {    
    static String policy_document = "{ \"expiration\": \"2015-12-30T12:00:00.000Z\"," +
            "  \"conditions\": [" +
            "    {\"bucket\": \"sigv4examplebucket\"}," +
            "    [\"starts-with\", \"$key\", \"user/user1/\"]," +
            "    {\"acl\": \"public-read\"}," +
            "    {\"success_action_redirect\": \"http://sigv4examplebucket.s3.amazonaws.com/successful_upload.html\"}," +
            "    [\"starts-with\", \"$Content-Type\", \"image/\"]," +
            "    {\"x-amz-meta-uuid\": \"14365123651274\"}," +
            "    {\"x-amz-server-side-encryption\": \"AES256\"}," +
            "    [\"starts-with\", \"$x-amz-meta-tag\", \"\"]," +
            "    {\"x-amz-credential\": \"AKIAIOSFODNN7EXAMPLE/20151229/us-east-1/s3/aws4_request\"}," +
            "    {\"x-amz-algorithm\": \"AWS4-HMAC-SHA256\"}," +
            "    {\"x-amz-date\": \"20151229T000000Z\" }" +
            "  ]" +
            "}";

    static String secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY";

    public static void main(String[] args) throws Exception {
        // Create a policy using UTF-8 encoding.
        byte[] utf8_policy = policy_document.getBytes("UTF-8");

        // Convert the UTF-8-encoded policy bytes to Base64. The result is the StringToSign.
        String base64_policy = new String(Base64.encodeBase64(utf8_policy));

        // Create a signing key.
        byte[] signing_key = getSignatureKey(secret_key , "20151229", "us-east-1", "s3");

        // Use the signing key to sign the StringToSign using HMAC-SHA256 signing algorithm.
        byte[] signature_bytes = HmacSHA256(base64_policy, signing_key);
        String signature = Hex.encodeHexString(signature_bytes);

        System.out.println(base64_policy);
        System.out.println();
        System.out.println(signature);
    }

    static byte[] getSignatureKey(String key, String dateStamp, String regionName, String serviceName) throws Exception  {
        byte[] kSecret = ("AWS4" + key).getBytes("UTF-8");
        byte[] kDate    = HmacSHA256(dateStamp, kSecret);
        byte[] kRegion  = HmacSHA256(regionName, kDate);
        byte[] kService = HmacSHA256(serviceName, kRegion);
        byte[] kSigning = HmacSHA256("aws4_request", kService);
        return kSigning;
    }

    static byte[] HmacSHA256(String data, byte[] key) throws Exception  {
        String algorithm="HmacSHA256";
        Mac mac = Mac.getInstance(algorithm);
        mac.init(new SecretKeySpec(key, algorithm));
        return mac.doFinal(data.getBytes("UTF-8"));
    }
}

政策文件和访问/密钥对均来自亚马逊的示例here

我的代码返回以下Base64编码策略:

  

eyAiZXhwaXJhdGlvbiI6ICIyMDE1LTEyLTMwVDEyOjAwOjAwLjAwMFoiLCAgImNvbmRpdGlvbnMiOiBbICAgIHsiYnVja2V0IjogInNpZ3Y0ZXhhbXBsZWJ1Y2tldCJ9LCAgICBbInN0YXJ0cy13aXRoIiwgIiRrZXkiLCAidXNlci91c2VyMS8iXSwgICAgeyJhY2wiOiAicHVibGljLXJlYWQifSwgICAgeyJzdWNjZXNzX2FjdGlvbl9yZWRpcmVjdCI6ICJodHRwOi8vc2lndjRleGFtcGxlYnVja2V0LnMzLmFtYXpvbmF3cy5jb20vc3VjY2Vzc2Z1bF91cGxvYWQuaHRtbCJ9LCAgICBbInN0YXJ0cy13aXRoIiwgIiRDb250ZW50LVR5cGUiLCAiaW1hZ2UvIl0sICAgIHsieC1hbXotbWV0YS11dWlkIjogIjE0MzY1MTIzNjUxMjc0In0sICAgIHsieC1hbXotc2VydmVyLXNpZGUtZW5jcnlwdGlvbiI6ICJBRVMyNTYifSwgICAgWyJzdGFydHMtd2l0aCIsICIkeC1hbXotbWV0YS10YWciLCAiIl0sICAgIHsieC1hbXotY3JlZGVudGlhbCI6ICJBS0lBSU9TRk9ETk43RVhBTVBMRS8yMDE1MTIyOS91cy1lYXN0LTEvczMvYXdzNF9yZXF1ZXN0In0sICAgIHsieC1hbXotYWxnb3JpdGhtIjogIkFXUzQtSE1BQy1TSEEyNTYifSwgICAgeyJ4LWFtei1kYXRlIjogIjIwMTUxMjI5VDAwMDAwMFoiIH0gIF19

以及以下签名

  

1df5972015a56d4fdef92944436b91ce1f39b5cc684dcce9f4dab74b82734e84

与亚马逊在上述链接中提供的内容不同。

我错过了什么吗?我有一种感觉,policy_document变量中的String格式可能会搞乱,但无论我如何格式化它(即新行,转义等),我似乎无法使其正常工作。

1 个答案:

答案 0 :(得分:1)

解码亚马逊和你的,它们不一样,主要是格式化。简单的格式差异将导致不同的签名哈希值。

在您的情况下,您需要在每行的末尾添加换行符。

亚马逊

{ "expiration": "2015-12-30T12:00:00.000Z",
  "conditions": [
    {"bucket": "sigv4examplebucket"},
    ["starts-with", "$key", "user/user1/"],
    {"acl": "public-read"},
    {"success_action_redirect": "http://sigv4examplebucket.s3.amazonaws.com/successful_upload.html"},
    ["starts-with", "$Content-Type", "image/"],
    {"x-amz-meta-uuid": "14365123651274"},
    {"x-amz-server-side-encryption": "AES256"},
    ["starts-with", "$x-amz-meta-tag", ""],

    {"x-amz-credential": "AKIAIOSFODNN7EXAMPLE/20151229/us-east-1/s3/aws4_request"},
    {"x-amz-algorithm": "AWS4-HMAC-SHA256"},
    {"x-amz-date": "20151229T000000Z" }
  ]
}

你的:

{ "expiration": "2015-12-30T12:00:00.000Z",  "conditions": [    {"bucket": "sigv4examplebucket"},    ["starts-with", "$key", "user/user1/"],    {"acl": "public-read"},    {"success_action_redirect": "http://sigv4examplebucket.s3.amazonaws.com/successful_upload.html"},    ["starts-with", "$Content-Type", "image/"],    {"x-amz-meta-uuid": "14365123651274"},    {"x-amz-server-side-encryption": "AES256"},    ["starts-with", "$x-amz-meta-tag", ""],    {"x-amz-credential": "AKIAIOSFODNN7EXAMPLE/20151229/us-east-1/s3/aws4_request"},    {"x-amz-algorithm": "AWS4-HMAC-SHA256"},    {"x-amz-date": "20151229T000000Z" }  ]}
'