View a markdown version of this page

授權標頭的簽章計算:在單一區塊中傳輸承載AWS (簽章第 4 版) - Amazon Simple Storage Service

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

授權標頭的簽章計算:在單一區塊中傳輸承載AWS (簽章第 4 版)

使用 Authorization 標頭來驗證請求時,標頭值包含簽章等等。簽章計算取決於您傳輸承載的選擇 (概觀)。本節說明當您選擇在單一區塊中傳輸承載時的簽章計算。範例區段 (請參閱 範例:簽章計算) 顯示簽章計算和產生的Authorization標頭,您可以用作測試套件來驗證程式碼。

重要

在單一區塊中傳輸承載時,您可以選擇在簽章計算中包含承載雜湊,稱為已簽章的承載 (如果您未包含,則承載會被視為未簽章)。以下章節討論的簽署程序適用於兩者,但請注意下列差異:

  • 已簽章的承載選項 – 您在建構正式請求時包含承載雜湊 (然後會成為 StringToSign 的一部分,如簽章計算一節所述)。傳送請求至 S3 時,您也可以指定與x-amz-content-sha256標頭值相同的值。

  • 未簽署的承載選項 – 您在建構正式請求UNSIGNED-PAYLOAD時包含常值字串,並在將請求傳送至 Amazon S3 時設定與x-amz-content-sha256標頭值相同的值。

當您將請求傳送至 Amazon S3 時,x-amz-content-sha256標頭值會通知 Amazon S3 承載是否已簽署。然後,Amazon S3 可以相應地建立簽章以進行驗證。

在這兩種情況下,由於x-amz-content-sha256標頭值已經是 的一部分HashedPayload,因此您不需要將x-amz-content-sha256標頭包含為正式標頭。

計算簽章

若要計算簽章,首先需要一個要簽名的字串。然後,您可以使用簽署金鑰計算要簽署的字串雜HMAC-SHA256湊。下圖說明 程序,包括您為簽署所建立字串的各種元件

當 Amazon S3 收到已驗證的請求時,它會計算簽章,然後將其與您在請求中提供的簽章進行比較。因此,您必須使用與 Amazon S3 相同的方法來計算簽章。以商定格式提出簽署請求的程序稱為正式化。

AWS4-HMAC-SHA256 簽章流程圖顯示正式請求、StringToSign 和簽章步驟。

下表描述圖表中顯示的函數。您需要為這些函數實作程式碼。

函式 說明
Lowercase() 將字串轉換成小寫。
Hex() 小寫基數 16 編碼。
SHA256Hash() 安全雜湊演算法 (SHA) 加密雜湊函數。
HMAC-SHA256() 使用 SHA256 演算法搭配提供的簽署金鑰來計算 HMAC。這是最後的簽章。
Trim() 移除任何前置和結尾空格。
UriEncode()

URI 編碼每個位元組。UriEncode() 必須強制執行下列規則:

  • URI 對除未預留字元之外的每個位元組進行編碼:'A'-'Z', 'a'-'z', '0'-'9', '-', '.', '_', and '~'。

  • 空格字元是預留字元,必須編碼為 "%20" (而不是 "+")。

  • 每個 URI 編碼的位元組都是由 '%' 和位元組的兩位數十六進位值組成。

  • 十六進位值中的字母必須為大寫,例如 "%1A"。

  • 對所有位置的正斜線字元 '/' 進行編碼 (物件索引鍵名稱除外)。例如,如果物件索引鍵名稱為 photos/Jan/sample.jpg,則不會對索引鍵名稱中的正斜線進行編碼。

重要

由於基礎 RFC 中的實作差異和相關模糊性,您的開發平台提供的標準 UriEncode 函數可能無法工作。我們建議您編寫自己的自訂 UriEncode 函數,以確保您的編碼能夠正常工作。

以下是 Java 中的 UriEncode() 函數範例。

public static String UriEncode(CharSequence input, boolean encodeSlash) { StringBuilder result = new StringBuilder(); for (int i = 0; i < input.length(); i++) { char ch = input.charAt(i); if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '_' || ch == '-' || ch == '~' || ch == '.') { result.append(ch); } else if (ch == '/') { result.append(encodeSlash ? "%2F" : ch); } else { result.append(toHexUTF8(ch)); } } return result.toString(); }

任務 1:建立正式請求

本節提供建立正式請求的概觀。

以下是 Amazon S3 用來計算簽章的正式請求格式。若要符合簽章,您必須以下列格式建立正式請求:

<HTTPMethod>\n <CanonicalURI>\n <CanonicalQueryString>\n <CanonicalHeaders>\n <SignedHeaders>\n <HashedPayload>

其中:

  • HTTPMethod 是其中一個 HTTP 方法,例如 GET、PUT、HEAD 和 DELETE。

  • CanonicalURI 是 URI 絕對路徑元件的 URI 編碼版本,從網域名稱後面的「/」開始,直到字串結尾或問號字元 ('?') 如果您有查詢字串參數。下列範例中的 URI /examplebucket/myphoto.jpg 是絕對路徑,您不會在絕對路徑中編碼 "/":

    http://s3.amazonaws.com/examplebucket/myphoto.jpg

    注意

    您不會標準化 Amazon S3 請求的 URI 路徑。例如,您可能有一個儲存貯體,其中包含名為 "my-object//example//photo.user" 的物件。標準化路徑會將請求中的物件名稱變更為「my-object/example/photo.user」。這是該物件的不正確路徑。

  • CanonicalQueryString 會指定 URI 編碼的查詢字串參數。您可以個別對名稱和值進行 URI 編碼。您還必須依索引鍵名稱的字母順序來排序正式查詢字串中的參數。編碼後進行排序。下列 URI 範例中的查詢字串為 prefix=somePrefix&marker=someMarker&max-keys=20

    http://s3.amazonaws.com/examplebucket?prefix=somePrefix&marker=someMarker&max-keys=20

    正式查詢字串如下所示 (為了便於閱讀,向此範例新增了分行符號):

    UriEncode("marker")+"="+UriEncode("someMarker")+"&"+ UriEncode("max-keys")+"="+UriEncode("20") + "&" + UriEncode("prefix")+"="+UriEncode("somePrefix")

    請求以子資源為目標時,對應的查詢參數值將是空字串 ("")。例如,下列 URI 會識別 examplebucket 儲存貯體上的 ACL 子資源:

    http://s3.amazonaws.com/examplebucket?acl

    在這種情況下,CanonicalQueryString 如下所示:

    UriEncode("acl") + "=" + ""

    如果 URI 不包含 '?',則請求中沒有查詢字串,並且您將正式查詢字串設定為空字串 ("")。您仍然需要包含 "\n"。

  • CanonicalHeaders 是包含其值的請求標頭清單。個別標頭名稱和值對以新行字元 ("\n") 分隔。標頭名稱必須為小寫。您必須依字母順序排序標頭名稱來建構字串,如下列範例所示:

    Lowercase(<HeaderName1>)+":"+Trim(<value>)+"\n" Lowercase(<HeaderName2>)+":"+Trim(<value>)+"\n" ... Lowercase(<HeaderNameN>)+":"+Trim(<value>)+"\n"

    本範例中使用的 Lowercase()Trim() 函數在上一節中進行了描述。

    CanonicalHeaders 清單必須包含下列項目:

    • HTTP host 標頭。

    • 如果 Content-MD5 標頭存在於請求中,您必須將其新增至 CanonicalHeaders 清單。

    • 還必須新增您計劃包含在請求中的任何 x-amz-* 標頭。例如,如果您使用的是暫時安全憑證,需要將 x-amz-security-token 包含在您的請求中。您必須將此標頭新增在 CanonicalHeader 的清單中。

    注意
    • 所有 AWS Signature 第 4 版請求都需要 x-amz-content-sha256標頭。其提供請求承載的雜湊。不過,您不需要將 包含x-amz-content-sha256為正式標頭,因為在計算請求中傳送的承載雜湊時,S3 會自動使用其值。

    • 如果沒有承載,您必須提供空字串的雜湊。

    • 如果您不希望 S3 檢查請求的雜湊,您可以"UNSIGNED-PAYLOAD"改為使用常值字串。

    以下是範例CanonicalHeaders字串。標頭名稱為小寫且已排序。

    範例範例 1
    host:s3.amazonaws.com x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 x-amz-date:20130708T220855Z
    範例範例 2
    host:s3.amazonaws.com x-amz-content-sha256:UNSIGNED-PAYLOAD x-amz-date:20130708T220855Z
    範例範例 3
    host:s3.amazonaws.com x-amz-date:20130708T220855Z
    注意

    為了計算授權簽章,x-amz-content-sha256需要主機標頭和 以外的所有x-amz-*標頭。不過,為了防止資料竄改,您應該考慮在簽章計算中包含所有標頭。

    簽署 x-amz-content-sha256標頭是選用的,因為 S3 會在計算收到的請求承載雜湊時使用其值。

  • SignedHeaders 是按字母順序排序、分號分隔的小寫請求標頭名稱清單。清單中的請求標頭與您在 CanonicalHeaders 字串中包含的標頭相同。在先前的範例中,SignedHeaders 的值如下:

    範例範例 1 和 2
    host;x-amz-content-sha256;x-amz-date
    範例範例 3
    host;x-amz-date
  • HashedPayload 是請求承載之 SHA256 雜湊的十六進位值。

    Hex(SHA256Hash(<payload>)

    如果請求中沒有承載,則計算空字串的雜湊,如下所示:

    Hex(SHA256Hash(""))

    雜湊會傳回下列值:

    e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

    例如,使用 PUT 請求上傳物件時,請在主體中提供物件資料。當您使用 GET 請求擷取物件時,會計算空字串雜湊。

任務 2:建立登入字串

本節概述如何建立要簽署的字串。如需step-by-step說明,請參閱 中的任務 2:建立要簽署的字串AWS 一般參考

要簽署的字串是下列字串的串連:

"AWS4-HMAC-SHA256" + "\n" + timeStampISO8601Format + "\n" + <Scope> + "\n" + Hex(SHA256Hash(<CanonicalRequest>))

常數字串AWS4-HMAC-SHA256指定您正在使用的雜湊演算法 HMAC-SHA256。timeStamp 是 ISO 8601 格式的目前 UTC 時間 (例如 20130524T000000Z)。

Scope 會將產生的簽章繫結至特定日期 AWS 區域、 和服務。因此,產生的簽章僅適用於特定區域和特定服務。簽章在指定日期後七天內有效。

date.Format(<YYYYMMDD>) + "/" + <region> + "/" + <service> + "/aws4_request"

對於 Amazon S3,服務字串為 s3。如需區域字串清單,請參閱《》中的區域和端點AWS 一般參考。此表格中的區域欄提供有效的區域字串清單。

下列範圍會將產生的簽章限制為 us-east-1區域和 Amazon S3。

20130606/us-east-1/s3/aws4_request

注意

Scope 必須使用您用來計算簽署金鑰的相同日期,如下節所述。

任務 3:計算簽章

在 AWS Signature 第 4 版中,您首先會建立範圍限定於特定區域和服務的簽署金鑰,而不是使用您的 AWS 存取金鑰來簽署請求。 如需簽署金鑰的詳細資訊,請參閱 簽署請求簡介

DateKey = HMAC-SHA256("AWS4"+"<SecretAccessKey>", "<YYYYMMDD>") DateRegionKey = HMAC-SHA256(<DateKey>, "<aws-region>") DateRegionServiceKey = HMAC-SHA256(<DateRegionKey>, "<aws-service>") SigningKey = HMAC-SHA256(<DateRegionServiceKey>, "aws4_request")

注意

有些使用案例最多可以處理 7 天的簽章金鑰。如需詳細資訊,請參閱與他人共用物件

如需區域字串清單,請參閱《》中的區域和端點AWS 一般參考

使用簽署金鑰可讓您將 AWS 登入資料保存在安全的地方。例如,如果您有多個伺服器與 Amazon S3 通訊,您會與這些伺服器共用簽署金鑰;您不需要在每個伺服器上保留私密存取金鑰的副本。簽署金鑰的有效期最長為七天。因此,每次計算簽署金鑰時,都需要與伺服器共用簽署金鑰。如需詳細資訊,請參閱驗證請求AWS (簽章第 4 版)

最終簽章是要簽署之字串的 HMAC-SHA256 雜湊,使用簽署金鑰做為金鑰。

HMAC-SHA256(SigningKey, StringToSign)

如需建立簽章的step-by-step說明,請參閱《》中的任務 3:建立簽章AWS 一般參考

範例:簽章計算

您可以使用本節中的範例做為參考,以檢查程式碼中的簽章計算。範例中顯示的計算會使用下列資料:

  • 存取金鑰範例。

    參數 Value
    AWSAccessKeyId AKIAIOSFODNN7EXAMPLE
    AWSSecretAccessKey wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
  • 請求時間戳記 20130524T000000Z (Fri, 24 May 2013 00:00:00 GMT)。

  • 儲存貯體名稱 examplebucket

  • 儲存貯體假設位於美國東部 (維吉尼亞北部) 區域。登入資料ScopeSigning Key計算使用 us-east-1做為區域指標。如需其他區域的資訊,請參閱《》中的區域和端點AWS 一般參考

  • 您可以使用路徑樣式或虛擬託管樣式的請求。下列範例示範如何簽署虛擬託管樣式請求,例如:

    https://examplebucket.s3.amazonaws.com/photos/photo1.jpg

    如需詳細資訊,請參閱《Amazon Simple Storage Service 使用者指南》中的儲存貯體虛擬託管

範例:GET 物件

下列範例會從 取得物件的前 10 個位元組 (test.txt)。 examplebucket如需 API 動作的詳細資訊,請參閱 GetObject

GET /test.txt HTTP/1.1 Host: examplebucket.s3.amazonaws.com Authorization: SignatureToBeCalculated Range: bytes=0-9 x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 x-amz-date: 20130524T000000Z

由於此 GET 請求不提供任何內文內容,因此x-amz-content-sha256值可以是空白請求內文的雜湊或常值字串 "UNSIGNED-PAYLOAD"。下列步驟顯示使用空字串雜湊的 Authorization標頭的簽章計算和建構。

  1. StringToSign
    1. CanonicalRequest

      GET /test.txt host:examplebucket.s3.amazonaws.com range:bytes=0-9 x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 x-amz-date:20130524T000000Z host;range;x-amz-content-sha256;x-amz-date e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

      在正式請求字串中,最後一行是空白請求內文的雜湊。第三行是空的,因為請求中沒有查詢參數。

    2. StringToSign

      AWS4-HMAC-SHA256 20130524T000000Z 20130524/us-east-1/s3/aws4_request 7344ae5b7ee6c3e7e6b0fe0640412a37625d1fbfff95c48bbb2dc43964946972

  2. SigningKey

    signing key = HMAC-SHA256(HMAC-SHA256(HMAC-SHA256(HMAC-SHA256("AWS4" + "<YourSecretAccessKey>","20130524"),"us-east-1"),"s3"),"aws4_request")

  3. 簽章

    f0e8bdb87c964420e857bd35b5d6ed310bd44f0170aba48dd91039c6036bdb41

  4. 授權標頭

    產生的Authorization標頭如下:

    AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request,SignedHeaders=host;range;x-amz-content-sha256;x-amz-date,Signature=f0e8bdb87c964420e857bd35b5d6ed310bd44f0170aba48dd91039c6036bdb41

範例:PUT 物件

此範例 PUT 請求會在 中建立物件 examplebucket (test$file.text)。該範例假設如下:

  • 您透過新增請求標頭來x-amz-storage-class請求 REDUCED_REDUNDANCY 做為儲存體方案。如需儲存類別的資訊,請參閱《Amazon Simple Storage Service 使用者指南》中的儲存類別

  • 上傳檔案的內容是字串,請求x-amz-content-sha256中的 "Welcome to Amazon S3." 值是以此字串為基礎。

如需 API 動作的相關資訊,請參閱 PutObject

PUT test$file.text HTTP/1.1 Host: examplebucket.s3.amazonaws.com Date: Fri, 24 May 2013 00:00:00 GMT Authorization: SignatureToBeCalculated x-amz-date: 20130524T000000Z x-amz-storage-class: REDUCED_REDUNDANCY x-amz-content-sha256: 44ce7dd67c959e0d3524ffac1771dfbba87d2b6b4b4e99e42034a8b803f8b072 <Payload>

下列步驟顯示簽章計算。

  1. StringToSign
    1. CanonicalRequest

      PUT /test%24file.text date:Fri, 24 May 2013 00:00:00 GMT host:examplebucket.s3.amazonaws.com x-amz-content-sha256:44ce7dd67c959e0d3524ffac1771dfbba87d2b6b4b4e99e42034a8b803f8b072 x-amz-date:20130524T000000Z x-amz-storage-class:REDUCED_REDUNDANCY date;host;x-amz-content-sha256;x-amz-date;x-amz-storage-class 44ce7dd67c959e0d3524ffac1771dfbba87d2b6b4b4e99e42034a8b803f8b072

      在正式請求中,第三行是空的,因為請求中沒有查詢參數。x-amz-content-sha256 正式標頭可以選擇性地簽署,因為其承載雜湊已在請求底部提供。最後一行是內文的雜湊,應與 HTTP 請求中傳送至 S3 x-amz-content-sha256 header的值相同。

    2. StringToSign

      AWS4-HMAC-SHA256 20130524T000000Z 20130524/us-east-1/s3/aws4_request 9e0e90d9c76de8fa5b200d8c849cd5b8dc7a3be3951ddb7f6a76b4158342019d

  2. SigningKey

    signing key = HMAC-SHA256(HMAC-SHA256(HMAC-SHA256(HMAC-SHA256("AWS4" + "<YourSecretAccessKey>","20130524"),"us-east-1"),"s3"),"aws4_request")

  3. 簽章

    98ad721746da40c64f1a55b78f14c238d841ea1380cd77a1b5971af0ece108bd

  4. 授權標頭

    產生的Authorization標頭如下:

    AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request,SignedHeaders=date;host;x-amz-content-sha256;x-amz-date;x-amz-storage-class,Signature=98ad721746da40c64f1a55b78f14c238d841ea1380cd77a1b5971af0ece108bd

範例:GET 儲存貯體生命週期

下列 GET 請求會擷取 的生命週期組態examplebucket。如需 API 動作的相關資訊,請參閱 GetBucketLifecycleConfiguration

GET ?lifecycle HTTP/1.1 Host: examplebucket.s3.amazonaws.com Authorization: SignatureToBeCalculated x-amz-date: 20130524T000000Z x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

由於請求不提供任何內文內容,x-amz-content-sha256標頭值是空白請求內文的雜湊。下列步驟顯示簽章計算。

  1. StringToSign
    1. CanonicalRequest

      GET / lifecycle= host:examplebucket.s3.amazonaws.com x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 x-amz-date:20130524T000000Z host;x-amz-content-sha256;x-amz-date e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

      在正式請求中,最後一行是空白請求內文的雜湊。

    2. StringToSign

      AWS4-HMAC-SHA256 20130524T000000Z 20130524/us-east-1/s3/aws4_request 9766c798316ff2757b517bc739a67f6213b4ab36dd5da2f94eaebf79c77395ca

  2. SigningKey

    signing key = HMAC-SHA256(HMAC-SHA256(HMAC-SHA256(HMAC-SHA256("AWS4" + "<YourSecretAccessKey>","20130524"),"us-east-1"),"s3"),"aws4_request")

  3. 簽章

    fea454ca298b7da1c68078a5d1bdbfbbe0d65c699e0f91ac7a200a0136783543

  4. 授權標頭

    產生的Authorization標頭如下:

    AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=fea454ca298b7da1c68078a5d1bdbfbbe0d65c699e0f91ac7a200a0136783543

範例:取得儲存貯體 (列出物件)

下列範例會從儲存examplebucket貯體擷取物件清單。如需 API 動作的相關資訊,請參閱 ListObjects

GET ?max-keys=2&prefix=J HTTP/1.1 Host: examplebucket.s3.amazonaws.com Authorization: SignatureToBeCalculated x-amz-date: 20130524T000000Z x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

由於請求不提供內文,因此 的值x-amz-content-sha256是空白請求內文的雜湊。下列步驟顯示簽章計算。

  1. StringToSign
    1. CanonicalRequest

      GET / max-keys=2&prefix=J host:examplebucket.s3.amazonaws.com x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 x-amz-date:20130524T000000Z host;x-amz-content-sha256;x-amz-date e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

      在正式字串中,最後一行是空白請求內文的雜湊。

    2. StringToSign

      AWS4-HMAC-SHA256 20130524T000000Z 20130524/us-east-1/s3/aws4_request df57d21db20da04d7fa30298dd4488ba3a2b47ca3a489c74750e0f1e7df1b9b7

  2. SigningKey

    signing key = HMAC-SHA256(HMAC-SHA256(HMAC-SHA256(HMAC-SHA256("AWS4" + "<YourSecretAccessKey>","20130524"),"us-east-1"),"s3"),"aws4_request")

  3. 簽章

    34b48302e7b5fa45bde8084f4b7868a86f0a534bc59db6670ed5711ef69dc6f7

  4. 授權標頭

    產生的Authorization標頭如下:

    AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request,SignedHeaders=host;x-amz-content-sha256;x-amz-date,Signature=34b48302e7b5fa45bde8084f4b7868a86f0a534bc59db6670ed5711ef69dc6f7