1

Amazonは一貫してPHPまたはCFとは異なるハッシュを生成するため、永続的な「SignatureDoesNotMatch」エラーが発生します。

ドキュメントによると、 [RESTヘッダーなしの]GETリクエストは次のように署名されています。

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; 

サンプルデータ:

  • SecretAccessKey:wJalrXUtnFEMI / K7MDENG / bPxRfiCYEXAMPLEKEY
  • Content-MD5およびContent-Type:(オプション-スキップ)
  • CanonicalizedAmzHeaders :(ヘッダーなし-スキップ)
  • リソース:johnsmith.s3.amazonaws.com/photos/puppy.jpg
  • CanonicalizedResource:/johnsmith/photos/puppy.jpg

2つの例が提供されています。

  1. 有効期限1175139620 ; 署名:rucSbH0yNEcP9oM2XNlouVI3BH4%3D
  2. 有効期限1141889120 ; 署名:vjbyPxybdZaNmGa%2ByT272YEAiv4%3D

これを再作成するには(ここからCFHMAC ):

// 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))>

両方の言語によって返される$signatureが次のとおりであることを除いて:

  1. 有効期限1175139620 ; 署名:NpgCjnDzrM%2BWFzoENXmpNDUsSn8%3D
  2. 有効期限1141889120 ; 署名:fScKGHCDI0NY5E7CYp9Vc8VKMbY%3D

私たちは他の人が言及しているこれらの落とし穴に注意してきました:

  1. hash_macには3番目の引数rawがあり、これはtrueに設定する必要があります。
  2. S3擬似コードのstringToSignとキーの順序を逆にする必要があります。
  3. stringToSign全体が1行にある必要があります(余分な改行文字が作成されないようにするため)。

編集:リーの答えに基づいてCFコードの改行を更新しました。これで、CFはPHPと一致します。

私は明らかに何か間違ったことをしていますが、何がわからないのです。
[Amazon S3はCSSと呼ばれるだろうと聞いたことがあります-「複雑なストレージサービス」ですが、その名前はすでに使われています!]

助けてください!

4

2 に答える 2

0

これは役に立ちますか?

<cffunction name="getRequestSignature" access="private" output="false" returntype="string">
    <cfargument name="verb" type="string" required="true" />
    <cfargument name="bucket" type="string" required="true" />
    <cfargument name="objectKey" type="string" required="true" />
    <cfargument name="dateOrExpiration" type="string" required="true" />
    <cfargument name="contentType" type="string" default="" />
    <cfargument name="contentMd5" type="string" default="" />
    <cfargument name="canonicalizedAmzHeaders" type="string" default=""
        hint="A newline-delimited list of headers, in lexographical order, duplicates collapsed, and no extraneous whitespace.  See Amazon's description of 'CanonicalizedAmzHeaders' for specifics." />
    <cfscript>
        var stringToSign = "";
        var algo = "HmacSHA1";
        var signingKey = "";
        var mac = "";
        var signature = "";

        stringToSign = uCase(verb) & chr(10)
            & contentMd5 & chr(10)
            & contentType & chr(10)
            & dateOrExpiration & chr(10)
            & iif(len(canonicalizedAmzHeaders) GT 0, de(canonicalizedAmzHeaders & chr(10)), de(''))
            & "/" & listAppend(bucket, objectKey, "/");
        signingKey = createObject("java", "javax.crypto.spec.SecretKeySpec").init(variables.awsSecret.getBytes(), algo);
        mac = createObject("java", "javax.crypto.Mac").getInstance(algo);
        mac.init(signingKey);
        signature = toBase64(mac.doFinal(stringToSign.getBytes()));

        return signature;
    </cfscript>
</cffunction>

ここから完全に盗んだ: http ://www.barneyb.com/barneyblog/projects/amazon-s3-cfc/

:)

于 2012-08-22T20:47:39.850 に答える
0

(私はすでにそれを書いていたので、これを投稿することもできます.. :)

私が見ることができる2つの問題

  1. 日付は特定の方法でフォーマットする必要があります
  2. LF文字通りの「\n」ではなく、を使用する必要があります

以下 の結果は、認証例の結果と一致しbWq2s1WEIj+Ydj0vQ697zp+IXMU=ます。注:ここからhmacSHA1関数を使用しましたが、使用するように変更しましたgetBytes("UTF-8)

コード:

    <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でこれらの値を使用すると、同じ署名が得られますだから私はそれが単なるドキュメントエラーかもしれないのだろうかと思っていますか?

     <cfset secretAccessKey = "OtxrzxIsfpFjA7SwPzILwy8Bw21TLhquhboDYROV">
     <cfset stringToSign = "GET#newLine##newLine##newLine#1141889120#newLine#/quotes/nelson">



**編集2:

私はRESTの例が間違っていると確信しています。検索の結果、さらに別のサンプルキーを含むこのリンクが見つかりました。CFコードでそれを置き換えると、署名は期待どおりになりますrucSbH0yNEcP9oM2XNlouVI3BH4%3D

    <cfset secretAccessKey = "uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o">
    <cfset stringToSign = "GET#newLine##newLine##newLine#1175139620#newLine#/johnsmith/photos/puppy.jpg">
于 2012-08-22T20:58:41.060 に答える