在 Haxe 中为 AWS S3 REST 生成 Content-MD5
Generating Content-MD5 for AWS S3 REST in Haxe
我正在尝试将 Content-MD5 header 添加到我在 Haxe 中对 AWS S3 的 REST 调用(编译为 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 在我之前的(非删除)调用中接受了 header。
我在这里错过了什么?为什么我的 MD5 值与 AWS 生成的不同?
你非常接近。
这是问题所在:
一个 md5 散列在二进制表示中为 16 个字节,在十六进制表示中为 32 个字符,在 base64 中为 24 个字符(包括填充)。
你的大约是你的两倍。您似乎采用了 32 个字符的十六进制 md5 和 base64 编码 that,从而产生了大约 44 个字符的 base64 字符串,而不仅仅是编码二进制形式。
请注意,尽管我断言您编码的是 32 个初始字节而不是 16 个字节,但输出的长度 44 与 24 不是两倍。这是预期的,因为 base64 output_bytes = ceil (input_bytes/3) * 4.
我的专长是 S3 API -- 不是 haxe,我从未使用过它 -- 所以上面的内容几乎可以肯定是正确的,但以下是疯狂的猜测。
var contentMD5 = haxe.crypto.Base64.encode(haxe.crypto.Md5.make(_data));
任何想在 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);
}
}
评论的代码是大多数人将其更改为十六进制时弄错的地方
我正在尝试将 Content-MD5 header 添加到我在 Haxe 中对 AWS S3 的 REST 调用(编译为 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 在我之前的(非删除)调用中接受了 header。
我在这里错过了什么?为什么我的 MD5 值与 AWS 生成的不同?
你非常接近。
这是问题所在:
一个 md5 散列在二进制表示中为 16 个字节,在十六进制表示中为 32 个字符,在 base64 中为 24 个字符(包括填充)。
你的大约是你的两倍。您似乎采用了 32 个字符的十六进制 md5 和 base64 编码 that,从而产生了大约 44 个字符的 base64 字符串,而不仅仅是编码二进制形式。
请注意,尽管我断言您编码的是 32 个初始字节而不是 16 个字节,但输出的长度 44 与 24 不是两倍。这是预期的,因为 base64 output_bytes = ceil (input_bytes/3) * 4.
我的专长是 S3 API -- 不是 haxe,我从未使用过它 -- 所以上面的内容几乎可以肯定是正确的,但以下是疯狂的猜测。
var contentMD5 = haxe.crypto.Base64.encode(haxe.crypto.Md5.make(_data));
任何想在 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);
}
}
评论的代码是大多数人将其更改为十六进制时弄错的地方