在Haxe中为AWS S3 REST生成Content-MD5

时间:2015-09-24 05:20:14

标签: rest amazon-web-services amazon-s3 haxe

我正在尝试在Haxe中对AWS S3的REST调用中添加Content-MD5标头(编译为PHP)。它是由

生成的
var contentMD5 = haxe.crypto.Base64.encode(haxe.io.Bytes.ofString(haxe.crypto.Md5.encode(_data)));

我的示例中的_data

<Delete><Object><Key>nathan/storage/72ENgrtnpA5VAoy7zEpzPRNEChN0TRGc</Key></Object><Object><Key>nathan/storage/7rlZZSJFvZ7AxUhQZsh4ufn9M2x8m1ae</Key></Object><Object><Key>nathan/storage/HN8NFlUnJiiGo7qlddvRrlGE6hPmWMnZ</Key></Object><Object><Key>nathan/storage/SFsZ8z63DswEVFJQJqmUwbenaWyfZ8zb</Key></Object><Object><Key>nathan/storage/YSYXXgYbSZixOKo27PL65ii6nCeiFesl</Key></Object></Delete>

我的完整请求使用AWS签名版本4(存储桶,签名和凭据缩短)发送到AWS(针对此处所述的多次删除调用http://docs.aws.amazon.com/AmazonS3/latest/API/multiobjectdeleteapi.html):

POST /?delete= HTTP/1.1
Host: mybucket.s3-eu-central-1.amazonaws.com
Content-Length: 392
x-amz-content-sha256: 53da469cb6fc9d0701a1c6ff98d48edd361cd8a90d8a290a2dd224b2681bf7fb
x-amz-date: 20150923T195117Z
Authorization: AWS4-HMAC-SHA256 Credential=zzzzz/20150923/eu-central-1/s3/aws4_request, SignedHeaders=content-md5;host;x-amz-date, Signature=xxxxx
Content-MD5: MDAzNDZmZjJiMGJkMDFkNzVjYzFiOGE4MzI5NTc0NGY=

<Delete><Object><Key>nathan/storage/72ENgrtnpA5VAoy7zEpzPRNEChN0TRGc</Key></Object><Object><Key>nathan/storage/7rlZZSJFvZ7AxUhQZsh4ufn9M2x8m1ae</Key></Object><Object><Key>nathan/storage/HN8NFlUnJiiGo7qlddvRrlGE6hPmWMnZ</Key></Object><Object><Key>nathan/storage/SFsZ8z63DswEVFJQJqmUwbenaWyfZ8zb</Key></Object><Object><Key>nathan/storage/YSYXXgYbSZixOKo27PL65ii6nCeiFesl</Key></Object></Delete>

响应如下(RequestId和HostId缩短)

<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>InvalidDigest</Code><Message>The Content-MD5 you specified was invalid.</Message><Content-MD5>MDAzNDZmZjJiMGJkMDFkNzVjYzFiOGE4MzI5NTc0NGY=</Content-MD5><RequestId>rrrrrr</RequestId><HostId>ccccccc</HostId></Error>

在我看来,生成的MD5是正确的。我用其他工具验证了这个值。另请注意,x-amz-content-sha256基于相同的_data,AWS在之前(非删除)调用中接受了该标头。

我在这里缺少什么?为什么我的MD5值与AWS生成的值不同?

2 个答案:

答案 0 :(得分:2)

你非常接近。

问题在于:

md5哈希是二进制表示的16个字节,十六进制表示的32个字符,以及base64中的24个字符(包括填充)。

你的约为两倍。您似乎使用32个字符的十六进制md5和base64编码的 ,从而产生一个大约44个字符的base64字符串,而不是仅编码二进制形式。

请注意,尽管我断言您正在编码32个初始字节而不是16,但输出的长度44和24不是2的因子。这是预期的,因为base64 output_bytes = ceil(input_bytes) / 3)* 4。

我的专长是使用S3 API - 而不是haxe,我从未使用过 - 所以上面几乎肯定是正确的,但以下是疯狂的推测。

var contentMD5 = haxe.crypto.Base64.encode(haxe.crypto.Md5.make(_data));

答案 1 :(得分:0)

任何想在java中执行此操作的人都可以使用此代码

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.codec.binary.Base64;
public class GenerateMD5 {
public static void main(String args[]) throws Exception{
    String s = "<CORSConfiguration> <CORSRule> <AllowedOrigin>http://www.example.com</AllowedOrigin> <AllowedMethod>PUT</AllowedMethod> <AllowedMethod>POST</AllowedMethod> <AllowedMethod>DELETE</AllowedMethod> <AllowedHeader>*</AllowedHeader> <MaxAgeSeconds>3000</MaxAgeSeconds> </CORSRule> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <AllowedHeader>*</AllowedHeader> <MaxAgeSeconds>3000</MaxAgeSeconds> </CORSRule> </CORSConfiguration>";

        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(s.getBytes());
        byte[] digest = md.digest();
        StringBuffer sb = new StringBuffer();
        /*for (byte b : digest) {
            sb.append(String.format("%02x", b & 0xff));
        }*/
        System.out.println(sb.toString());
        StringBuffer sbi = new StringBuffer();
        byte [] bytes = Base64.encodeBase64(digest);
        String finalString = new String(bytes);
        System.out.println(finalString);
    }
}

评论代码是大多数人错误地将其更改为十六进制

的地方