问题描述
亚马逊始终产生不同的散列比PHP或CF,这会导致持久性SignatureDoesNotMatch错误。
Amazon consistently generates a different hash than PHP or CF, which causes a persistent "SignatureDoesNotMatch" error.
根据到文档,GET请求[没有休息头]签署如下:
According to the docs, GET requests [without REST headers] are signed as follows:
Signature = URL-Encode( Base64( HMAC-SHA1( SecretAccessKey, UTF-8-Encoding-Of( StringToSign ) ) ) );
StringToSign = HTTP-VERB + "\n" +
Content-MD5 + "\n" +
Content-Type + "\n" +
Expires + "\n" +
CanonicalizedAmzHeaders +
CanonicalizedResource;
该示例数据:
The example data:
- SecretAccessKey: wJalrXUtnFEMI / K7MDENG / bPxRfiCYEXAMPLEKEY
- 内容-MD5和内容类型:(可选 - 跳过)
- CanonicalizedAmzHeaders:(无标题 - 跳过)
- 资源:johnsmith.s3.amazonaws.com/photos/puppy.jpg
- CanonicalizedResource: /johnsmith/photos/puppy.jpg
- SecretAccessKey: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
- Content-MD5 and Content-Type: (optional - skipped)
- CanonicalizedAmzHeaders: (no headers - skipped)
- Resource: johnsmith.s3.amazonaws.com/photos/puppy.jpg
- CanonicalizedResource: /johnsmith/photos/puppy.jpg
提供了两个例子:
- 过期 1175139620 ;签名: rucSbH0yNEcP9oM2XNlouVI3BH4%3D
- 过期 1141889120 ;签名: vjbyPxybdZaNmGa%2ByT272YEAiv4%3D
- Expires 1175139620; Signature: rucSbH0yNEcP9oM2XNlouVI3BH4%3D
- Expires 1141889120; Signature: vjbyPxybdZaNmGa%2ByT272YEAiv4%3D
要(从这里 CFHMAC)重建这样的:
To recreate this (CFHMAC from here):
// PHP
$expires = 1175139620;
$SecretAccessKey = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY";
$StringToSign = "GET\n\n\n$expires\n/johnsmith/photos/puppy.jpg";
$signature = urlencode( base64_encode( hash_hmac('sha1', utf8_encode($StringToSign), $SecretAccessKey, true)));
// ColdFusion
<cfset LF = chr(10)>
<cfset expires = 1141889120>
<cfset SecretAccessKey = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY">
<cfset StringToSign = "GET#LF##LF##LF##expires##LF#/johnsmith/photos/puppy.jpg">
<cfset signature = URLEncodedFormat( CFHMAC(StringToSign, SecretAccessKey))>
除返回两种语言的$签名是:
EXCEPT that $signature as returned by both languages is:
- 过期 1175139620 ;签名: NpgCjnDzrM%2BWFzoENXmpNDUsSn8%3D
- 过期 1141889120 ;签名: fScKGHCDI0NY5E7CYp9Vc8VKMbY%3D
- Expires 1175139620; Signature: NpgCjnDzrM%2BWFzoENXmpNDUsSn8%3D
- Expires 1141889120; Signature: fScKGHCDI0NY5E7CYp9Vc8VKMbY%3D
我们一直在谨慎,其他人已经提到的这些陷阱的:
We have been careful of these gotchas that others have mentioned:
- hash_mac有第三个参数,原料,必须设置为true。
- 的stringToSign在S3伪code的顺序和重点应该是相反的。
- 在整个stringToSign必须在同一行(以免产生额外的换行符)。
编辑:更新的基础上Leigh的答案CF code中的新行;现在CF相匹配的PHP。
Updated the newlines in the CF code based on Leigh's answer; now the CF matches the PHP.
我明明做错事,但无法弄清。
[我听说它打趣说,亚马逊S3将被称为CSS - !复杂的存储服务,但这个名字已经取]
I am obviously doing something wrong, but can't figure out what.
[I have heard it quipped that Amazon S3 would have been called CSS - "complicated storage service", but the name was already taken!]
帮助,请!
推荐答案
(可能也张贴这一点,因为我已经写了起来..:)
(May as well post this since I had already written it up .. :)
有两个问题,我可以看到
Two problems I can see
- 的日期需要格式化某个特定的方式
- 您需要使用
LF
,而不是文字\ N
- The date needs to be formatted a specific way
- You need to use a
LF
rather than a literal "\n"
结果如下匹配的验证例子即 bWq2s1WEIj + Ydj0vQ697zp + IXMU =
。注:我使用 href="http://stackoverflow.com/a/2960258/104223">的HMACSHA1功能,但改变了它使用的GetBytes(UTF-8 )
The result below matches that in Authentication Examples ie bWq2s1WEIj+Ydj0vQ697zp+IXMU=
. Note: I used the hmacSHA1 function from here, but changed it use getBytes("UTF-8)
code:
<cfset newLine = chr(10)>
<cfset secretAccessKey = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY">
<cfset stringToSign = "GET#newLine##newLine##newLine#Tue, 27 Mar 2007 19:36:42 +0000#newLine#/johnsmith/photos/puppy.jpg">
<cfset signature = hmacSHA1(secretAccessKey, stringToSign)>
<cfset finalSignature = URLEncodedFormat(binaryEncode(signature, "base64"))>
<cfoutput>finalSignature = #finalSignature#</cfoutput>
* *编辑1:
了什么事。最重要的是在该网页匹配起来的例子。但是, Rest认证示例3:查询字符串认证范例这里显示不同的密钥和字符串产生的签名 vjbyPxybdZaNmGa%2ByT272YEAiv4%3D
。如果你使用这些值在CF您的不的得到相同的签名。所以我想知道如果它可能只是一个文档的错误?
Something is fishy. Most all of the examples on that page match up. But REST Authentication Example 3: Query String Authentication Example here shows a different key and string that produce the signature vjbyPxybdZaNmGa%2ByT272YEAiv4%3D
. If you use those values in CF you do get the same signature. So I am wondering if it might just be a documentation error?
<cfset secretAccessKey = "OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV">
<cfset stringToSign = "GET#newLine##newLine##newLine#1141889120#newLine#/quotes/nelson">
** 修改2:
** EDIT 2:
我是pretty的确保REST的例子是错误的。一个搜索打开了包含另一个示例键此链接。如果替换,在CF code,签名是你所期望的: rucSbH0yNEcP9oM2XNlouVI3BH4%3D
。
I am pretty sure the REST examples are wrong. A search turned up this link containing yet another sample key. If you substitute that in the CF code, the signature is what you expected: rucSbH0yNEcP9oM2XNlouVI3BH4%3D
.
<cfset secretAccessKey = "uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o">
<cfset stringToSign = "GET#newLine##newLine##newLine#1175139620#newLine#/johnsmith/photos/puppy.jpg">
这篇关于错误的SHA1从PHP和放大器;根据Amazon S3的CF的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!