

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

# AWS API 請求的簽章版本 4
<a name="reference_sigv"></a>

**重要**  
如果您使用 AWS SDK （請參閱[範例程式碼和程式庫](https://aws.amazon.com/developer/)) 或 AWS Command Line Interface (AWS CLI) 工具來傳送 API 請求 AWS，您可以略過簽章程序，因為 SDK 和 CLI 用戶端會使用您提供的存取金鑰來驗證您的請求。除非有充分的理由不這樣做，否則建議您始終使用 SDK 或 CLI。  
在支援多個簽章版本的區域中，手動簽署要求意味著您必須指定要使用的簽章版本。當您向多區域存取點提供請求時，SDK 和 CLI 會自動切換為使用第 4A 版簽署程序，而不需其他組態。

您在請求中傳送的身分驗證資訊必須包含簽章。 AWS Signature 第 4 版 (SigV4) 是將身分驗證資訊新增至 AWS API 請求的 AWS 簽署通訊協定。

您不會使用私密存取金鑰來簽署請求。相反，您使用 SigV4 簽署程序。簽署請求涉及：

1. 根據請求詳細資訊來建立正式請求。

1. 使用您的 AWS 登入資料計算簽章。

1. 將此簽章作為授權標頭新增至請求。

AWS 然後， 會複寫此程序，並驗證簽章、授予或拒絕相應存取。

對稱 SigV4 要求您在特定日期，在特定 AWS 區域中衍生範圍限定為單一 AWS 服務的金鑰。這使得每個區域的金鑰和計算簽章不同，意味著您必須知道簽章的目的地區域。

非對稱簽章程序第 4 版 (SigV4a) 是支援使用新演算法進行簽署的延伸版，並產生可在多個 AWS 區域中驗證的個別簽章。使用 SigV4a，您可以簽署多個區域的請求，並在區域之間進行無縫路由和容錯移轉。當您使用 AWS SDK 或 AWS CLI 叫用需要多區域簽署的功能時，簽章類型會自動變更為使用 SigV4a。如需詳細資訊，請參閱[如何運作 AWS SigV4a](#how-sigv4a-works)。

## How AWS SigV4 運作方式
<a name="how-aws-signing-works"></a>

下列步驟說明使用 SigV4 來計算簽章的一般程序：

1. **要簽署的字串**取決於請求類型。例如，當您使用 HTTP 授權標頭或查詢參數進行驗證時，請使用請求元素組合來建立要簽署的字串。對於 HTTP POST 請求，請求中的 `POST` 政策是您簽署的字串。

1. **簽署金鑰**是一系列計算，每個步驟的結果會饋送至下一個步驟。最後的步驟是簽署金鑰。

1. 當 AWS 服務收到已驗證的請求時，它會使用請求中包含的身分驗證資訊重新建立**簽章**。如果簽章相符，則服務會處理請求。否則，它會拒絕請求。

如需詳細資訊，請參閱[AWS API 請求簽章的元素](reference_sigv-signing-elements.md)。

## 如何運作 AWS SigV4a
<a name="how-sigv4a-works"></a>

SigV4a 使用基於公有/私有金鑰密碼的非對稱簽章。SigV4a 會經歷與 SigV4 類似的限定範圍的憑證衍生程序，但 Sigv4a 使用相同的金鑰來簽署所有請求，而不需要根據日期、服務和區域衍生不同的簽署金鑰。[橢圓曲線數位簽章演算法](https://csrc.nist.gov/glossary/term/ecdsa) (ECDSA) 金鑰對可以從您現有的 AWS 私密存取金鑰衍生。

系統使用非對稱密碼編譯來驗證多區域簽章，因此 AWS 僅需要存放您的公有金鑰。公有金鑰不是秘密，無法用於簽署請求。多區域 API 請求需要非對稱簽章，例如使用 Amazon S3 多區域存取點。

下列步驟說明使用 SigV4a 運算簽章的一般程序：

1. **要簽署的字串**取決於請求類型。例如，當您使用 HTTP 授權標頭或查詢參數進行驗證時，請使用請求元素組合來建立要簽署的字串。對於 HTTP POST 請求，請求中的 `POST` 政策是您簽署的字串。

1. **簽署金鑰**是透過一系列計算衍生自 AWS 私密存取金鑰，每個步驟的結果會饋送至下一個步驟。最後一個步驟會產生金鑰對。

1. 當 AWS 服務收到使用 Sigv4a 簽署的請求時， 只會使用金鑰對的公有半部來 AWS 驗證簽章。如果簽章有效，則會驗證請求，並且服務會處理請求。會拒絕具有無效簽章的請求。

如需有關多區域 API 請求的 SigV4a 詳細資訊，請參閱 GitHub 上的 [sigv4a-signing-examples](https://github.com/aws-samples/sigv4a-signing-examples) 專案。

## 簽署請求的時機
<a name="when-do-you-need-to-sign"></a>

當您編寫傳送 API 請求的自訂程式碼時 AWS，必須包含簽署請求的程式碼。您可能會因為以下原因編寫自訂程式碼：
+ 您使用的程式設計語言沒有 AWS 軟體開發套件。
+ 您需要完全控制請求的傳送方式 AWS。

當 API 請求使用 AWS SigV4 來驗證存取時 AWS CLI ， AWS SDKs會使用您提供的存取金鑰來驗證您的請求。如需使用 AWS SDKs和 驗證 的詳細資訊 AWS CLI，請參閱 [其他資源](#reference_aws-signing-resources)。

## 為什麼要簽署請求
<a name="why-requests-are-signed"></a>

簽署程序有助於以下列方式保護請求的安全：
+ **驗證請求者的身分**

  經過驗證的請求需要您使用存取金鑰 (存取金鑰 ID、私密存取金鑰) 建立的簽章。如果您使用暫時安全憑證，則簽章計算還需要安全字符。如需詳細資訊，請參閱 [AWS 安全憑證程式設計存取權](security-creds-programmatic-access.md)。
+ **保護傳輸中的資料**

  為了防止傳送中的請求遭到竄改，有些請求元素可用來計算請求的雜湊 (摘要)，而產生的雜湊值會包含在請求中。當 AWS 服務 收到請求時，它會使用相同的資訊來計算雜湊，並將其與請求中的雜湊值相符。如果值不相符， 會 AWS 拒絕請求。
+ **抵禦潛在重播攻擊的侵害**

  在大多數情況下，請求必須在請求中時間戳記的五分鐘 AWS 內到達。否則， 會 AWS 拒絕請求。

AWS SigV4 可以在 HTTP 授權標頭中表示，或在 URL 中表示為查詢字串。如需詳細資訊，請參閱[身分驗證方法](reference_sigv-authentication-methods.md)。

## 其他資源
<a name="reference_aws-signing-resources"></a>
+ 如需不同服務的 SigV4 簽署程序的詳細資訊，請參閱 [請求簽章範例](reference_sigv-examples.md)。
+ 若要設定 CLI AWS 的程式設計存取憑證，請參閱《 *AWS 命令列界面使用者指南*》中的[身分驗證和存取憑證](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-authentication.html)。
+ 此 AWS SDKs包含 GitHub 上用於簽署 AWS API 請求的原始碼。如需程式碼範例，請參閱 [AWS 範例儲存庫中的範例專案](reference_sigv-examples.md#signature-v4-examples-sdk)。
  + 適用於 .NET 的 AWS SDK – [AWS4Signer.cs](https://github.com/aws/aws-sdk-net/blob/master/sdk/src/Core/Amazon.Runtime/Internal/Auth/AWS4Signer.cs)
  + 適用於 C\$1\$1 的 AWS SDK – [AWSAuthV4Signer.cpp](https://github.com/aws/aws-sdk-cpp/blob/main/src/aws-cpp-sdk-core/source/auth/signer/AWSAuthV4Signer.cpp)
  + 適用於 Go 的 AWS SDK – [sigv4.go](https://github.com/aws/smithy-go/blob/a4c9efcda6aa54c75d1a130d1320a2709eebf51d/aws-http-auth/sigv4/sigv4.go)
  + 適用於 Java 的 AWS SDK – [BaseAws4Signer.java](https://github.com/aws/aws-sdk-java-v2/blob/master/core/auth/src/main/java/software/amazon/awssdk/auth/signer/internal/BaseAws4Signer.java)
  + 適用於 JavaScript 的 AWS SDK – [signature-v4](https://github.com/smithy-lang/smithy-typescript/tree/main/packages/signature-v4)
  + 適用於 PHP 的 AWS SDK – [SignatureV4.php](https://github.com/aws/aws-sdk-php/blob/master/src/Signature/SignatureV4.php)
  + 適用於 Python (Boto) 的 AWS SDK – https：//[signers.py](https://github.com/boto/botocore/blob/develop/botocore/signers.py)
  + 適用於 Ruby 的 AWS SDK – [signer.rb](https://github.com/aws/aws-sdk-ruby/blob/version-3/gems/aws-sigv4/lib/aws-sigv4/signer.rb)

# AWS API 請求簽章的元素
<a name="reference_sigv-signing-elements"></a>

**重要**  
除非您使用 AWS SDKs或 CLI，否則您必須撰寫程式碼來計算在請求中提供身分驗證資訊的簽章。Signature 第 4 版中的 AWS 簽章計算可能是一項複雜的任務，我們建議您盡可能使用 AWS SDKs或 CLI。

凡是使用 Signature Version 4 簽署的每個 HTTP/HTTPS 請求都必須包含下列元素。

**Topics**
+ [端點規格](#endpoint-specification)
+ [Action](#action)
+ [動作參數](#parameters)
+ [Date](#date)
+ [身分驗證資訊](#authentication)

## 端點規格
<a name="endpoint-specification"></a>

指定您要向其傳送請求的端點的 DNS 名稱。此名稱通常包含服務代碼和區域。例如，`us-east-1` 區域中 Amazon DynamoDB 的端點為 `dynamodb.us-east-1.amazonaws.com`。

若為 HTTP/1.1 請求，必須包含 `Host` 標頭。若為 HTTP/2 請求，則可包含 `:authority` 標頭或 `Host` 標頭。為符合 HTTP/2 規格，應僅使用 `:authority` 標頭。並非所有服務都支援 HTTP/2 請求。

如需每個服務支援的端點，請參閱 *AWS 一般參考* 中的[服務端點和配額](https://docs.aws.amazon.com/general/latest/gr/aws-service-information.html)。

## Action
<a name="action"></a>

指定服務的 API 動作。例如，DynamoDB `CreateTable` 動作或 Amazon EC2 `DescribeInstances` 動作。

如需每個服務支援的動作，請參閱[服務授權參考](https://docs.aws.amazon.com//service-authorization/latest/reference/reference.html)。

## 動作參數
<a name="parameters"></a>

指定請求中指定的動作參數。每個 AWS API 動作都有一組必要和選用的參數。API 版本通常是必要參數。

如需 API 動作支援的參數，請參閱服務的《API 參考》。

## Date
<a name="date"></a>

指定請求的日期和時間。請求中附上日期和時間有助於防止第三方攔截您的請求再於稍後重新提交。您在憑證範圍中指定的日期必須與請求日期相符。

此時間戳記必須為 UTC 時間，而且必須使用下列 ISO 8601 格式：*YYYYMMDD*T*HHMMSS*Z。例如 `20220830T123600Z`。不包含時間戳記的毫秒數。

您可以使用 `date` 標頭或 `x-amz-date` 標頭，或包含 `x-amz-date` 作為查詢參數。如果找不到 `x-amz-date` 標頭，那麼我們會尋找 `date` 標頭。

## 身分驗證資訊
<a name="authentication"></a>

您傳送的每個請求必須包含以下資訊。 AWS 會使用此資訊來確保請求的有效性和真實性。
+ 演算法 – 簽署程序中所使用的演算法。
  + SigV4 – 使用 `AWS4-HMAC-SHA256` 來指定採用 `HMAC-SHA256` 雜湊演算法的第 4 版簽署程序。
  + SigV4a – 使用 `AWS4-ECDSA-P256-SHA256` 指定 `ECDSA-P256-SHA-256` 雜湊演算法。
+ 憑證 – 透過串連存取金鑰 ID 和憑證範圍元件所形成的字串。
  + SigV4 – 憑證範圍包括存取金鑰 ID、*YYYYMMDD* 格式的日期、區域代碼、服務代碼和 `aws4_request` 終止字串，以斜線 (/) 分隔。區域代碼、服務代碼和終止字串必須使用小寫字元。

    ```
    AKIAIOSFODNN7EXAMPLE/YYYYMMDD/region/service/aws4_request
    ```
  + SigV4a – 憑證範圍包括 YYYYMMDD 格式的日期、服務名稱和 `aws4_request` 終止字串，以斜線 (/) 分隔。請注意，憑證範圍不包括區域，因為區域涵蓋在單獨的標頭 `X-Amz-Region-Set` 中。

    ```
    AKIAIOSFODNN7EXAMPLE/YYYYMMDD/service/aws4_request
    ```
+ 已簽署的標頭 – 要包含在簽章中的 HTTP 標頭，以分號 (;) 分隔。例如 `host;x-amz-date`。

  對於 SigV4a，您必須包含區域集標頭，指定請求將在其中生效的區域集。標頭 `X-Amz-Region-Set` 將指定為逗號分隔值的清單。下列範例展示了區域標頭，其允許在 us-east-1 和 us-west-1 區域中發出請求。

  ```
  X-Amz-Region-Set=us-east-1,us-west-1
  ```

  您可以在區域中使用萬用字元 (\$1) 來指定多個區域。在下列範例中，標頭允許在 us-west-1 和 us-west-2 中發出請求。

  ```
  X-Amz-Region-Set=us-west-*
  ```
+ 簽章 – 表示已計算出之簽章的十六進位編碼字串。您必須使用 `Algorithm` 參數所指定的演算法計算簽章。

如需詳細資訊，請參閱[身分驗證方法](reference_sigv-authentication-methods.md)

# 身分驗證方法
<a name="reference_sigv-authentication-methods"></a>

**重要**  
除非您使用 AWS SDKs或 CLI，否則您必須撰寫程式碼來計算在請求中提供身分驗證資訊的簽章。Signature 第 4 版中的 AWS 簽章計算可能是一項複雜的任務，我們建議您盡可能使用 AWS SDKs或 CLI。

您可以使用下列其中一種方法來表示身分驗證資訊。

## HTTP 授權標頭
<a name="aws-signing-authentication-methods-http"></a>

HTTP `Authorization` 標頭是驗證請求的最常見方法。所有 REST API 操作 (使用 `POST` 請求的以瀏覽器為基礎的上傳除外) 需要此標頭。

下列範例展示了 SigV4 和 SigV4a 的 `Authorization` 標頭值。為了便於閱讀，向此範例新增了分行符號。在程式碼中，標頭必須是一個連續字串。演算法與憑證之間沒有逗號，但其他元素必須以逗號分隔。

**Example SigV4**  

```
Authorization: AWS4-HMAC-SHA256
Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request, 
SignedHeaders=host;range;x-amz-date, 
Signature=fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024
```

**Example SigV4a**  

```
Authorization: AWS4-ECDSA-P256-SHA256
Credential=AKIAIOSFODNN7EXAMPLE/20130524/s3/aws4_request, 
SignedHeaders=host;range;x-amz-date;x-amz-region-set,
Signature=fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024
```

下表描述上述範例中授權標頭值的各種元件：


| 元件 | Description | 
| --- | --- | 
|  Authorization  | 用於計算簽章的演算法。 [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/IAM/latest/UserGuide/reference_sigv-authentication-methods.html)  | 
|  Credential  |  存取金鑰 ID 和範圍資訊。 [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/IAM/latest/UserGuide/reference_sigv-authentication-methods.html) 使用 YYYYMMDD 格式指定 <date> 值。將請求傳送至 Amazon S3 時 <aws-service> 值為 S3。  | 
|  SignedHeaders  |   用於計算簽章的請求標頭清單 (以分號分隔)。此清單僅包含標頭名稱，且標頭名稱必須為小寫。例如：`host;range;x-amz-date` 對於 SigV4a，您必須包含區域集標頭，指定請求將在其中生效的區域集。標頭 X-Amz-Region-Set 將指定為逗號分隔值的清單。  | 
|  簽章  |  256 位元簽章以 64 個小寫十六進位字元表示。例如：`fe5f80f77d5fa3beca038a248ff027d0445342fe2855ddc963176630326f1024` 請注意，簽章計算因您選擇傳輸承載的選項而異。  | 

## 查詢字串參數
<a name="aws-signing-authentication-methods-query"></a>

您可以使用查詢字串以完全在 URL 中表達請求。在此情況下，您可以使用查詢參數來提供請求資訊，包括驗證資訊。由於請求簽章是 URL 的一部分，因此此類型 URL 通常稱為預先簽章的 URL。您可以使用預先簽章的 URL 在 HTML 中嵌入可點選連結，有效期最長可達七天。如需詳細資訊，請參閱《*Amazon S3 API 參考*》中的[驗證請求：使用查詢參數 (AWS 簽章第 4 版）](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-query-string-auth.html)。

下列範例展示了 SigV4 和 SigV4a 預先簽章的 URL。為了便於閱讀，向此範例新增了分行符號：

**Example SigV4**  

```
https://s3.amazonaws.com/amzn-s3-demo-bucket/test.txt ?
X-Amz-Algorithm=AWS4-HMAC-SHA256 &
X-Amz-Credential=<your-access-key-id>/20130721/<region>/s3/aws4_request &
X-Amz-Date=20130721T201207Z &
X-Amz-Expires=86400 &
X-Amz-SignedHeaders=host &X-Amz-Signature=<signature-value>
```

**Example SigV4a**  

```
http://s3.amazonaws.com/amzn-s3-demo-bucket/test.txt ?
X-Amz-Algorithm=AWS4-ECDSA-P256-SHA256 &
X-Amz-Credential=<your-access-key-id>/20240721/s3/aws4_request &
X-amz-Region-Set=<regionset> &
X-Amz-Date=20240721T201207Z &
X-Amz-Expires=86400 &
X-Amz-SignedHeaders=host;x-amz-region-set &
X-Amz-Signature=<signature-value>
```

**注意**  
URL 中的 `X-Amz-Credential` 值僅為了便於閱讀而顯示 "/" 字元。實際上，應將其編碼為 %2F。例如：  
`&X-Amz-Credential=<your-access-key-id>%2F20130721%2Fus-east-1%2Fs3%2Faws4_request`

下表描述 URL 中提供驗證資訊的查詢參數。


| 查詢字串參數名稱 | Description | 
| --- | --- | 
|  X-Amz-Algorithm  |   AWS 簽章的版本，以及您用來計算簽章的演算法。 [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/IAM/latest/UserGuide/reference_sigv-authentication-methods.html)  | 
|  X-Amz-Credential  |  除了存取金鑰 ID 外，此參數還提供了簽章有效的範圍。此值必須與您在簽章計算中使用的範圍相符，這將在下一節中討論。 [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/IAM/latest/UserGuide/reference_sigv-authentication-methods.html) 如需 AWS 區域字串清單，請參閱《 *AWS 一般參考*》中的[區域端點](https://docs.aws.amazon.com//general/latest/gr/rande.html#regional-endpoints)。  | 
|  X-Amz-Region-Set  |  請求將在其中生效的區域集。標頭 x-amz-region-set 將指定為逗號分隔值的清單。  | 
|  X-Amz-Date  |  日期和時間格式必須遵循 ISO 8601 標準，且必須使用 `yyyyMMddTHHmmssZ` 格式進行格式化。例如，如果日期和時間是 "08/01/2016 15:32:41.982-700"，則必須先將其轉換為 UTC (國際標準時間)，然後以 "20160801T223241Z" 形式提交。  | 
|  X-Amz-Expires  |  提供所產生預先簽章的 URL 有效的時段 (以秒為單位)。例如，86400 (24 小時)。此值為整數。您可以設定的最小值為 1，最大值為 604,800 (七天)。預先簽章的 URL 的有效期最長為七天，因為您在簽章計算中使用的簽署金鑰有效期最長為七天。  | 
|  X-Amz-SignedHeaders  |  列出您用來計算簽章的標頭。簽章計算中需要下列標頭： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/IAM/latest/UserGuide/reference_sigv-authentication-methods.html) 為了提高安全性，您應簽署計劃包含在請求中的所有請求標頭。  | 
|  X-Amz-Signature  |  提供簽章以驗證您的請求。此簽章必須與服務計算的簽章相符；否則，服務會拒絕請求。例如 `733255ef022bec3f2a8701cd61d4b371f3f28c9f193a1f02279211d48d5193d7` 簽章計算將在下一節中描述。  | 
|  X-Amz-Security-Token  |  選用的憑證參數 (如果使用來自 STS 服務的憑證)。  | 

# 建立已簽署的 AWS API 請求
<a name="reference_sigv-create-signed-request"></a>

**重要**  
如果您使用 AWS SDK （請參閱[範例程式碼和程式庫](https://aws.amazon.com/developer/)) 或 AWS Command Line Interface (AWS CLI) 工具來傳送 API 請求 AWS，您可以略過本節，因為 SDK 和 CLI 用戶端會使用您提供的存取金鑰來驗證您的請求。除非有充分的理由不這樣做，否則建議您始終使用 SDK 或 CLI。  
在支援多個簽章版本的區域中，手動簽署要求意味著您必須指定要使用的簽章版本。當您向多區域存取點提供請求時，SDK 和 CLI 會自動切換為使用第 4A 版簽署程序，而不需其他組態。

您可以使用 AWS SigV4 簽署通訊協定來建立 AWS API 請求的已簽署請求。

1. 根據請求詳細資訊來建立正式請求。

1. 使用您的 AWS 登入資料計算簽章。

1. 將此簽章作為授權標頭新增至請求。

AWS 然後， 會複寫此程序，並驗證簽章、授予或拒絕相應存取。

若要了解如何使用 AWS SigV4 簽署 API 請求，請參閱 [請求簽章範例](reference_sigv-examples.md)。

下表描述了在建立已簽署請求的過程中所使用的函數。您需要為這些函數實作程式碼。如需詳細資訊，請參閱 [AWS SDK 中的程式碼範例](reference_sigv.md#reference_aws-signing-resources)。


| 函式 | Description | 
| --- | --- | 
|  `Lowercase()`  |  將字串轉換成小寫。  | 
|  `Hex()`  |  小寫基數 16 編碼。  | 
|  `SHA256Hash()`  |  安全雜湊演算法 (SHA) 加密雜湊函數。  | 
|  `HMAC-SHA256()`  |  使用 SHA256 演算法搭配提供的簽署金鑰來計算 HMAC。這是使用 SigV4 簽署時的最終簽章。  | 
|  `ECDSA-Sign`  |  橢圓曲線數位簽章演算法 (ECDSA) 簽章，使用以公有-私有金鑰密碼編譯為基礎的非對稱簽章進行計算。  | 
|  `KDF(K, Label, Context, L)`  |  使用 PRF 函數 HMAC-SHA256 的計數器模式下的 NIST SP800-108 KDF，如 [NIST SP 800-108r1](https://doi.org/10.6028/NIST.SP.800-108r1-upd1) 中所定義。  | 
|  `Oct2Int(byte[ ])`  |  八位元轉整數函數，如 ANSI X9.62 中所述。  | 
|  `Trim()`  |  移除任何前置和結尾空格。  | 
|  `UriEncode()`  |  URI 編碼每個位元組。UriEncode() 必須強制執行下列規則： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/IAM/latest/UserGuide/reference_sigv-create-signed-request.html)  由於基礎 RFC 中的實作差異和相關模糊性，您的開發平台提供的標準 UriEncode 函數可能無法工作。我們建議您編寫自己的自訂 UriEncode 函數，以確保您的編碼能夠正常工作。  若要查看 Java 中的 UriEncode 函數範例，請參閱 GitHub 網站上的 [Java 公用程式](https://github.com/aws/aws-sdk-java/blob/master/aws-java-sdk-core/src/main/java/com/amazonaws/util/SdkHttpUtils.java#L66)。  | 

**注意**  
簽署請求時，您可以使用 AWS SigV4 或 AWS SigV4a。兩者之間的主要差異取決於簽章的計算方式。對於 SigV4a，區域集包含在要簽署的字串中，但不是憑證衍生步驟的一部分。

## 具有臨時安全憑證的簽署請求
<a name="temporary-security-credentials"></a>

您可以使用由 AWS Security Token Service () 提供的臨時安全登入資料，而不是使用長期登入資料來簽署請求AWS STS。

當您使用臨時安全憑證時，必須將 `X-Amz-Security-Token` 新增至授權標頭或將它包含在查詢字串中，以保留工作階段權杖。某些服務會要求您將 `X-Amz-Security-Token` 新增至正式請求。其他服務只需要您在計算簽章之後於結尾新增 `X-Amz-Security-Token`。檢查每個 的文件 AWS 服務 ，了解特定需求。

## 簽署步驟摘要
<a name="create-signed-request-steps"></a>

**建立正式請求**  
將您的請求內容 (主機、動作、標頭等) 編排為標準正式格式。正式請求就是其中一個用於建立登入字串的輸入。如需有關建立正式請求的詳細資訊，請參閱 [AWS API 請求簽章的元素](reference_sigv-signing-elements.md)。

**建立正式請求的雜湊**  
使用與您用來建立承載雜湊相同的演算法，對正式請求進行雜湊。正式請求的雜湊是小寫十六進位字元字串。

**建立要簽署的字串**  
使用正式請求和額外資訊，例如演算法、請求日期、憑證範圍及正式請求的雜湊，建立登入字串。

**衍生簽署金鑰**  
使用私密存取金鑰衍生用於簽署請求的金鑰。

**計算簽章**  
使用衍生的簽署金鑰作為雜湊金鑰，對要簽署的字串執行金鑰式雜湊操作。

**將簽章新增至請求**  
將計算簽章新增至 HTTP 標頭，或新增至請求的查詢字串。

## 建立正式請求
<a name="create-canonical-request"></a>

若要建立正式請求，請串連以下字串 (以換行符號字元分隔)。這有助於確保您計算的簽章符合 AWS 計算的簽章。

```
<HTTPMethod>\n
<CanonicalURI>\n
<CanonicalQueryString>\n
<CanonicalHeaders>\n
<SignedHeaders>\n
<HashedPayload>
```
+ *HTTPMethod* – HTTP 方法，例如 `GET`、`PUT`、`HEAD` 和 `DELETE`。
+ *CanonicalUri*– 絕對路徑元件 URI 的 URI 編碼版本，以 `/` 開頭，後接網域名稱，一直到字串結尾，或者如果具有查詢字串參數，則一直到問號字元 (`?`)。如果絕對路徑空白，請使用斜線字元 (`/`)。下列範例中的 URI `/amzn-s3-demo-bucket/myphoto.jpg` 是絕對路徑，您不會在絕對路徑中編碼 `/`：

  ```
  http://s3.amazonaws.com/amzn-s3-demo-bucket/myphoto.jpg
  ```
+ *CanonicalQueryString* – URI 編碼的查詢字串參數。您可以單獨對每個名稱和值進行 URI 編碼。您還必須依索引鍵名稱的字母順序來排序正式查詢字串中的參數。編碼後進行排序。下列 URI 範例中的查詢字串為：

  ```
  http://s3.amazonaws.com/amzn-s3-demo-bucket?prefix=somePrefix&marker=someMarker&max-keys=2
  ```

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

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

  請求以子資源為目標時，對應的查詢參數值將是空字串 (`""`)。例如，下列 URI 會識別 `amzn-s3-demo-bucket` 儲存貯體上的 `ACL` 子資源：

   

  ```
  http://s3.amazonaws.com/amzn-s3-demo-bucket?acl
  ```

  在這種情況下，CanonicalQueryString 為：

   

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

  如果 URI 不包含 `?`，則請求中沒有查詢字串，並且您將正式查詢字串設定為空字串 (`""`)。您仍然需要包含換行符號字元 (`"\n"`)。
+ *CanonicalHeaders* – 請求標頭清單及其值。個別標頭名稱和值對以換行符號字元 (`"\n"`) 分隔。以下是 CanonicalHeader 的範例：

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

  CanonicalHeaders 清單必須包含以下內容：
  + HTTP `host` 標頭。
  + 如果 `Content-Type` 標頭存在於請求中，您必須將其新增至 *CanonicalHeaders* 清單。
  + 還必須新增您計劃包含在請求中的任何 `x-amz-*` 標頭。例如，如果您使用的是暫時安全憑證，需要將 `x-amz-security-token` 包含在您的請求中。您必須將此標頭新增在 *CanonicalHeader* 的清單中。
  + 對於 SigV4a，您必須包含區域集標頭，指定請求將在其中生效的區域集。標頭 `X-Amz-Region-Set` 將指定為逗號分隔值的清單。下列範例展示了區域標頭，其允許在 us-east-1 和 us-west-1 區域中發出請求。

    `X-Amz-Region-Set=us-east-1,us-west-1 `

    您可以在區域中使用萬用字元 (\$1) 來指定多個區域。在下列範例中，標頭允許在 us-west-1 和 us-west-2 中發出請求。

    `X-Amz-Region-Set=us-west-*`
**注意**  
Amazon S3 AWS 請求需要 `x-amz-content-sha256` 標頭。其提供請求承載的雜湊。如果沒有承載，您必須提供空字串的雜湊。

  每個標頭名稱必須：
  + 使用小寫字元。
  + 依字母順序顯示。
  + 後接冒號 (`:`)。

  對於值，您必須：
  + 修剪任何前置或結尾空格。
  + 將連續空格轉換為單一空格。
  + 使用逗號分隔多值標頭的值。
  + 簽章中必須包含主機標頭 (HTTP/1.1) 或 :authority 標頭 (HTTP/2)，以及簽章中的任何 `x-amz-*` 標頭。可以選擇性地在簽章中包含其他標準標頭，例如 content-type。

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

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

   

  ```
  host:s3.amazonaws.com
  x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
  x-amz-date:20130708T220855Z
  ```

   
**注意**  
對於計算授權簽章而言，僅需要主機和任何 `x-amz-*` 標頭；但是，為了防止資料竄改，應考慮在簽章計算中包含其他標頭。  
請勿包含跨複雜系統傳輸期間經常變更的逐個躍點標頭。這包括所有易變的傳輸標頭，這些標頭可能會由代理、負載平衡器和分散式系統中的節點變更，包括 `connection`、`x-amzn-trace-id`、`user-agent`、`keep-alive`、`transfer-encoding`、`TE`、`trailer`、`upgrade`、`proxy-authorization` 和 `proxy-authenticate`。
+ *SignedHeaders* – 依字母順序排序、以分號分隔的小寫請求標頭名稱清單。清單中的請求標頭與您在 `CanonicalHeaders` 字串中包含的標頭相同。對於上一個範例，*SignedHeaders* 值將如下所示：

  ```
  host;x-amz-content-sha256;x-amz-date
  ```
+ *HashedPayload* – 使用 HTTP 請求內文中的承載作為雜湊函數的輸入所建立的字串。此字串使用小寫十六進位字元。

  ```
  Hex(SHA256Hash(<payload>>))
  ```

  如果請求中沒有承載，您可以計算空字串的雜湊，例如當您使用 `GET` 請求擷取物件時，承載中沒有任何內容。

  ```
  Hex(SHA256Hash(""))
  ```
**注意**  
對於 Amazon S3，請在建構正式請求時包含文字字串 `UNSIGNED-PAYLOAD`，並在傳送請求時設定與 `x-amz-content-sha256` 標頭值相同的值。  
`Hex(SHA256Hash("UNSIGNED-PAYLOAD"))`

## 建立正式請求的雜湊
<a name="create-canonical-request-hash"></a>

使用與您用來建立承載雜湊相同的演算法，建立正式請求的雜湊 (摘要)。正式請求的雜湊是小寫十六進位字元字串。

## 建立要簽署的字串
<a name="create-string-to-sign"></a>

若要建立要簽署的字串，請串連以下字串 (以換行符號字元分隔)。請勿以換行符號字元結束此字串。

```
Algorithm \n
RequestDateTime \n
CredentialScope  \n
HashedCanonicalRequest
```
+ *Algorithm* - 用來建立正式請求雜湊的演算法。
  + SigV4 – 使用 `AWS4-HMAC-SHA256` 來指定 `HMAC-SHA256` 雜湊演算法。
  + SigV4a – 使用 `AWS4-ECDSA-P256-SHA256` 指定 `ECDSA-P256-SHA-256` 雜湊演算法。
+ *RequestDateTime* - 憑證範圍中使用的日期和時間。此值是 ISO 8601 格式的目前 UTC 時間 (例如，`20130524T000000Z`)。
+ *CredentialScope* – 憑證範圍會將產生的簽章限制到指定的區域和服務。
  + SigV4 – 憑證包括存取金鑰 ID、`YYYYMMDD` 格式的日期、區域代碼、服務代碼和 `aws4_request` 終止字串，以斜線 (/) 分隔。區域代碼、服務代碼和終止字串必須使用小寫字元。此字串採用下列格式：`YYYYMMDD/region/service/aws4_request`。
  + SigV4a – 憑證包括 `YYYYMMDD` 格式的日期、服務名稱和 `aws4_request` 終止字串，以斜線 (/) 分隔。請注意，憑證範圍不包括區域，因為區域涵蓋在單獨的標頭 `X-Amz-Region-Set` 中。此字串採用下列格式：`YYYYMMDD/service/aws4_request`。
+ *HashedCanonicalRequest* – 在上一步驟中計算的正式請求的雜湊。

以下是登入字串範例。

```
"<Algorithm>" + "\n" +
timeStampISO8601Format + "\n" +
<Scope> + "\n" +
Hex(<Algorithm>(<CanonicalRequest>))
```

## 衍生簽署金鑰
<a name="derive-signing-key"></a>

若要衍生簽署金鑰，請選擇下列其中一個程序來計算 SigV4 或 SigV4a 的簽署金鑰。

### 衍生 SigV4 的簽署金鑰
<a name="derive-signing-key-sigv4"></a>

若要衍生 SigV4 的簽署金鑰，請在請求日期、區域和服務上執行連續的金鑰雜湊操作 (HMAC)，並將 AWS 私密存取金鑰作為初始雜湊操作的金鑰。

對於每個步驟，使用所需金鑰和資料呼叫雜湊函數。對雜湊函數的每次呼叫結果都會變成雜湊函數的下一次呼叫輸入。

下列範例顯示如何衍生此程序下一節中使用的 `SigningKey`，顯示您的輸入串連和雜湊的順序。`HMAC-SHA256` 是用於雜湊資料的雜湊函數，如下所示。

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

**需要輸入**
+ `Key` – 包含私密存取金鑰的字串。
+ `Date` – 包含憑證範圍中所使用日期的字串，格式為 *YYYYMMDD*。
+ `Region` – 包含區域代碼的字串 (例如 `us-east-1`)。

  如需區域字串清單，請參閱《AWS 一般參考》中的[區域端點](https://docs.aws.amazon.com//general/latest/gr/rande.html#regional-endpoints)。**
+ `Service` – 包含服務代碼的字串 (例如 `ec2`)。
+ 在之前步驟中建立的登入字串。

**衍生 SigV4 的簽署金鑰**

1. 串連 `"AWS4"` 和私密存取金鑰。呼叫雜湊函數，將串連的字串作為索引鍵，日期字串做為資料。

   ```
   DateKey = hash("AWS4" + Key, Date)
   ```

1. 呼叫雜湊函數，將上一次呼叫的結果作為索引鍵，區域字串作為資料。

   ```
   DateRegionKey = hash(kDate, Region)
   ```

1. 呼叫雜湊函數，將上一次呼叫的結果作為索引鍵，服務字串作為資料。

   服務代碼由服務定義。可以使用 *AWS Pricing CLI* 中的 [get-products](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/pricing/get-products.html) 來傳回服務的服務代碼。

   ```
   DateRegionServiceKey = hash(kRegion, Service)
   ```

1. 呼叫雜湊函數，將上一次呼叫的結果作為索引鍵，"aws4\$1request" 作為資料。

   ```
   SigningKey = hash(kService, "aws4_request")
   ```

### 衍生 SigV4a 的簽署金鑰
<a name="derive-signing-key-sigv4a"></a>

若要建立 SigV4a 的簽署金鑰，請使用下列程序從私密存取金鑰衍生金鑰對。如需此衍生的實作範例，請參閱[AWS 用戶端身分驗證的 C99 程式庫實作](https://github.com/awslabs/aws-c-auth/blob/e8360a65e0f3337d4ac827945e00c3b55a641a5f/source/key_derivation.c#L291.) 

```
n = [NIST P-256 elliptic curve group order]
G = [NIST P-256 elliptic curve base point]
label = "AWS4-ECDSA-P256-SHA256"

akid = [AWS access key ID as a UTF8 string]
sk = [AWS secret access Key as a UTF8 Base64 string]

input_key = "AWS4A" || sk
count = 1
while (counter != 255) {
  context = akid || counter // note: counter is one byte
  key = KDF(input_key, label, context, 256)
  c = Oct2Int(key)
  if (c > n - 2) {
    counter++
  } else {
    k = c + 1   // private key
    Q = k * G   // public key
  }
}

if (c < 255) {
  return [k, Q]
} else {
  return FAILURE
}
```

## 計算簽章
<a name="calculate-signature"></a>

衍生簽署金鑰之後，即可計算要新增至請求的簽章。此程序根據所使用的簽章版本而有所不同。

**計算 SigV4 的簽章**

1. 呼叫雜湊函數，將上一次呼叫的結果作為索引鍵，**待簽署字串**作為資料。使用衍生的金鑰做為此操作的雜湊金鑰。結果是作為二進位值的簽章。

   ```
   signature = hash(SigningKey, string-to-sign)
   ```

1. 將簽章的表示形式從二進位轉換為十六進位，使用小寫字元。

**計算 SigV4a 的簽章**

1. 使用數位簽署演算法 (ECDSA P-256)，簽署上一步驟中建立的**待簽署字串**。用於此簽章的金鑰是衍生自上述私密存取金鑰的私有非對稱金鑰。

   ```
   signature = base16(ECDSA-Sign(k, string-to-sign))
   ```

1. 將簽章的表示形式從二進位轉換為十六進位，使用小寫字元。

## 將簽章新增至請求
<a name="add-signature-to-request"></a>

將計算簽章新增至您的請求。

**Example 範例：授權標頭**  
**SigV4**  
下列範例顯示使用 AWS SigV4 之`DescribeInstances`動作的 `Authorization`標頭。為了便於閱讀，此範例使用換行符號進行格式化。在代碼中，這必須是一個連續字串。演算法和 `Credential` 之間沒有逗號。但是，必須使用逗號分隔其他元素。

```
Authorization: AWS4-HMAC-SHA256
Credential=AKIAIOSFODNN7EXAMPLE/20220830/us-east-1/ec2/aws4_request,
SignedHeaders=host;x-amz-date,
Signature=calculated-signature
```

**SigV4a**  
下列範例顯示使用 AWS SigV4a `CreateBucket`之動作的授權標頭。為了便於閱讀，此範例使用換行符號進行格式化。在代碼中，這必須是一個連續字串。演算法和憑證之間沒有逗號。但是，必須使用逗號分隔其他元素。

```
Authorization: AWS4-ECDSA-P256-SHA256
Credential=AKIAIOSFODNN7EXAMPLE/20220830/s3/aws4_request,
SignedHeaders=host;x-amz-date;x-amz-region-set,
Signature=calculated-signature
```

**Example 範例：查詢字串中包含身分驗證參數的請求**  
**SigV4**  
下列範例顯示使用 AWS SigV4 `DescribeInstances`之動作的查詢，其中包含身分驗證資訊。為了便於閱讀，此範例使用換行符號進行格式化，而不是 URL 編碼。在程式碼中，查詢字串必須是 URL 編碼的連續字串。

```
https://ec2.amazonaws.com/?
Action=DescribeInstances&
Version=2016-11-15&
X-Amz-Algorithm=AWS4-HMAC-SHA256&
X-Amz-Credential=AKIAIOSFODNN7EXAMPLE/20220830/us-east-1/ec2/aws4_request&
X-Amz-Date=20220830T123600Z&
X-Amz-SignedHeaders=host;x-amz-date&
X-Amz-Signature=calculated-signature
```

**SigV4a**  
下列範例展示了針對 `CreateBucket` 動作使用 AWS SigV4a 的查詢，其中包含身分驗證資訊。為了便於閱讀，此範例使用換行符號進行格式化，而不是 URL 編碼。在程式碼中，查詢字串必須是 URL 編碼的連續字串。

```
https://ec2.amazonaws.com/?
Action=CreateBucket&
Version=2016-11-15&
X-Amz-Algorithm=AWS4-ECDSA-P256-SHA256&
X-Amz-Credential=AKIAIOSFODNN7EXAMPLE/20220830/s3/aws4_request&
X-Amz-Region-Set=us-west-1&
X-Amz-Date=20220830T123600Z&
X-Amz-SignedHeaders=host;x-amz-date;x-amz-region-set&
X-Amz-Signature=calculated-signature
```

# 請求簽章範例
<a name="reference_sigv-examples"></a>

下列 AWS 簽署請求範例示範如何使用 SigV4 簽署在沒有 AWS SDK 或 AWS 命令列工具的情況下傳送的請求。

## 使用 HTTP POST 的基於瀏覽器的 Amazon S3 上傳
<a name="signature-v4-examples-s3-browser"></a>

 [驗證請求：基於瀏覽器的上傳](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-authentication-HTTPPOST.html)描述簽章和相關資訊，Amazon S3 在收到請求時會使用其來計算簽章。

[範例：使用 HTTP POST 的瀏覽器型上傳 （使用 AWS Signature 第 4 版）](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-post-example.html) 提供更多資訊，其中包含範例 POST 政策和可用來上傳檔案的表單。範例政策和虛擬憑證會顯示工作流程以及產生的簽章和政策雜湊。

## VPC Lattice 驗證的請求
<a name="signature-v4-examples-lattice"></a>

 [第 4 版簽署程序 (SigV4) 驗證的請求範例](https://docs.aws.amazon.com/vpc-lattice/latest/ug/sigv4-authenticated-requests.html)提供了 Python 和 Java 範例，顯示如何在使用和不使用自訂攔截器的情況下執行請求簽署。

## 搭配使用第 4 版簽署程序與 Amazon Translate
<a name="signature-v4-examples-translate"></a>

 [Metaverse 中的即時轉譯](https://aws.amazon.com/blogs/spatial/live-translations-in-the-metaverse/)示範如何建置應用程式，以產生近乎即時的翻譯解決方案。此speech-to-speech翻譯程式解決方案在事件串流編碼中使用 AWS SigV4 來產生即時轉錄。

## 搭配使用第 4 版簽署程序與 Neptune
<a name="signature-v4-examples-neptune"></a>

[範例：搭配使用 Python 與第 4 版簽署程序來連接到 Neptune](https://docs.aws.amazon.com/neptune/latest/userguide/iam-auth-connecting-python.html) 說明如何使用 Python 向 Neptune 發出已簽署的請求。此範例包括使用存取金鑰或暫時憑證的變化情況。

## 簽署對 Amazon Glacier 的 HTTP 請求
<a name="signature-v4-examples-streaming-glacier"></a>

[串流 API 的簽章計算範例](https://docs.aws.amazon.com/amazonglacier/latest/dev/amazon-glacier-signing-requests.html)將逐步說明為上傳封存 (POST 封存) 建立簽章的詳細資訊，這是 Amazon Glacier 中的兩個串流 API 之一。

## 向 Amazon SWF 發出 HTTP 請求
<a name="signature-v4-examples-swf"></a>

[向 Amazon SWF 發出 HTTP 請求](https://docs.aws.amazon.com/amazonswf/latest/developerguide/UsingJSON-swf.html#HTTPHeader)顯示向 Amazon SWF 發出 JSON 請求的標頭內容。

## Amazon OpenSearch Service 中的串流 API 的簽章計算
<a name="signature-v4-examples-open-search"></a>

[使用適用於 PHP 的 AWS SDK 第 3 版簽署 Amazon OpenSearch Service 搜尋請求](https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/service_es-data-plane.html)包括如何將已簽署 HTTP 請求傳送至 Amazon OpenSearch Service 的範例。

## AWS 範例儲存庫中的範例專案
<a name="signature-v4-examples-sdk"></a>

下列範例專案示範如何簽署請求，以對 Python、Node.js、Java、C\$1、Go 和 Rust 等常用語言 AWS 的服務提出 Rest API 請求。

### 4a 版簽署程序專案
<a name="signature-v4-examples-sigv4a"></a>

[sigv4-signing-examples](https://github.com/aws-samples/sigv4-signing-examples) 專案提供如何使用 SigV4 簽署請求的範例，以 AWS 服務 使用 Python、Node.js、Java、C\$1、Go 和 Rust 等常用語言向 發出 Rest API 請求。

[sigv4a-signing-examples](https://github.com/aws-samples/sigv4a-signing-examples) 專案提供簽署多區域 API 請求的範例，例如 [Amazon S3 中的多區域存取點](https://docs.aws.amazon.com/AmazonS3/latest/userguide/MultiRegionAccessPoints.html)。

### 發佈至 AWS IoT Core
<a name="signature-v4-examples-iot-python"></a>

[AWS IoT Core 使用 HTTPs 通訊協定發佈至 的 Python 程式碼](https://github.com/aws-samples/aws-iot-core-python-node-sigv4-https)提供如何使用 AWS IoT Core HTTPS 通訊協定和 AWS SigV4 身分驗證將訊息發佈至 的指引。兩種參考實作分別採用 Python 和 NodeJs 語言。

[AWS IoT Core 使用 HTTPs 通訊協定發佈至 的 .Net Framework 應用程式](https://github.com/aws-samples/aws-iot-core-http-sigv4-dotnet-app)提供如何使用 HTTPS 通訊協定和 AWS SigV4 身分驗證將訊息發佈至 AWS IoT Core 的指引。此專案還包括 .NET 核心同等實作。

# 針對 AWS API 請求的 Signature 第 4 版簽署進行故障診斷
<a name="reference_sigv-troubleshooting"></a>

**重要**  
除非您使用 AWS SDKs或 CLI，否則您必須撰寫程式碼來計算在請求中提供身分驗證資訊的簽章。SigV4 簽章計算可能是一項複雜的任務，我們建議您盡可能使用 AWS SDKs或 CLI。

當您開發建立已簽署請求的程式碼時，您可能會`SignatureDoesNotMatch`從中收到 HTTP 403 AWS 服務。這些錯誤表示 HTTP 請求中的簽章值與 AWS 服務 計算的簽章 AWS 不相符。當許可不允許呼叫者發出請求時，將傳回 HTTP 401 `Unauthorized` 錯誤。

如有以下情形，API 請求可能傳回錯誤：
+ API 請求未簽署，且 API 請求使用 IAM 身分驗證。
+ 用於簽署請求的 IAM 憑證不正確或沒有調用 API 的許可。
+ 已簽署 API 要求的簽章與 AWS 服務計算的簽章不符。
+ API 請求標頭不正確。

**注意**  
在探索其他錯誤解決方案之前，將您的簽署通訊協定從 AWS Signature 第 2 版 (SigV2) 更新為 AWS Signature 第 4 版 (SigV4)。服務 (例如 Amazon S3) 和區域不再支援 SigV2 簽署。

**Topics**
+ [憑證錯誤](#signature-v4-troubleshooting-credential)
+ [正式請求與簽署字串錯誤](#signature-v4-troubleshooting-canonical-errors)
+ [憑證範圍錯誤](#signature-v4-troubleshooting-credential-scope)
+ [金鑰簽署錯誤](#signature-v4-troubleshooting-key-signing)

## 憑證錯誤
<a name="signature-v4-troubleshooting-credential"></a>

確保使用 SigV4 簽署 API 請求。如果 API 請求未簽署，則您有可能收到錯誤：`Missing Authentication Token`。[新增缺少的簽章](https://docs.aws.amazon.com/IAM/latest/UserGuide/create-signed-request.html#add-signature-to-request)並重新傳送請求。

驗證存取金鑰和私密金鑰的身分驗證憑證是正確的。如果存取金鑰錯誤，則您有可能收到錯誤：`Unauthorized`。確保用於簽署請求的實體有權發出請求。如需詳細資訊，請參閱[對拒絕存取錯誤訊息進行疑難排解](troubleshoot_access-denied.md)。

## 正式請求與簽署字串錯誤
<a name="signature-v4-troubleshooting-canonical-errors"></a>

如果您錯誤計算 [建立正式請求的雜湊](reference_sigv-create-signed-request.md#create-canonical-request-hash) 或 [建立要簽署的字串](reference_sigv-create-signed-request.md#create-string-to-sign) 中正式請求，則該服務執行的簽章驗證步驟便會失敗，並顯示錯誤訊息：

```
The request signature we calculated does not match the signature you provided
```

當 AWS 服務收到已簽署的請求時，它會重新計算簽章。如果值之間有差異，則簽名不匹配。使用錯誤訊息中的值，比對正式請求和字串以及您的已簽署請求。若有任何差異，請修改簽署程序。

**注意**  
您也可以驗證您未透過可修改標頭或請求的代理傳送請求。

**Example 正式請求範例**  

```
GET                                                      -------- HTTP method
/                                                        -------- Path. For API stage endpoint, it should be /{stage-name}/{resource-path}
                                                         -------- Query string key-value pair. Leave it blank if the request doesn't have a query string.
content-type:application/json                            -------- Header key-value pair. One header per line.
host:0123456789.execute-api.us-east-1.amazonaws.com      -------- Host and x-amz-date are required headers for all signed requests.                       
x-amz-date:20220806T024003Z                              

content-type;host;x-amz-date                             -------- A list of signed headers
d167e99c53f15b0c105101d468ae35a3dc9187839ca081095e340f3649a04501        -------- Hash of the payload
```

要驗證私密金鑰是否與存取金鑰 ID 相符，可以使用已知有效的實作來測試它們。例如，使用 AWS SDK 或 AWS CLI 向 提出請求 AWS。

### API 請求標頭
<a name="signature-v4-troubleshooting-credential-header"></a>

當授權標頭為空、憑證金鑰或簽章遺失或不正確、標頭不是以演算法名稱開頭，或金鑰值對不包含等號時，您會收到下列其中一個錯誤：
+ 授權標頭不能為空白。
+ 授權標頭需要 'Credential' 參數。
+ 授權標頭需要 'Signature' 參數。
+ 簽章在授權標頭中包含無效的 key=value 對 (缺少等號)。

確保您在 [計算簽章](reference_sigv-create-signed-request.md#calculate-signature) 中新增的 SigV4 授權標頭包含正確的憑證金鑰，且還包含使用 HTTP Date 或 `x-amz-date` 標頭的請求日期。

如果您收到 IncompleteSignatureException 錯誤且簽章的建構正確，您可以透過計算用戶端請求中授權標頭的 SHA-256 雜湊和 B64 編碼 AWS 服務 ，來驗證授權標頭未在傳輸到 時遭到修改。

1. 取得您在請求中傳送的[授權標頭](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_sigv-authentication-methods.html)。授權標頭看起來類似下列範例：

   ```
   Authorization: AWS4-HMAC-SHA256 
   Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request, 
   SignedHeaders=host;range;x-amz-date,
   Signature=example-generated-signature
   ```

1. 計算授權標頭的 SHA-256 雜湊。

   ```
   hashSHA256(rawAuthorizationHeader) = hashedAuthorizationHeader
   ```

1. 將雜湊授權標頭編碼為 Base64 格式。

   ```
   base64(hashedAuthorizationHeader) = encodedHashedAuthorizationHeader
   ```

1. 將剛計算的雜湊和編碼字串與錯誤訊息中收到的字串進行比較。錯誤訊息應類似於如下範例：

   ```
   com.amazon.coral.service#IncompleteSignatureException: 
   The signature contains an in-valid key=value pair (missing equal-sign) 
   in Authorization header (hashed with SHA-256 and encoded with Base64): 
   '9c574f83b4b950926da4a99c2b43418b3db8d97d571b5e18dd0e4f3c3ed1ed2c'.
   ```
+ 如果兩個雜湊不同，授權標頭的某些部分會在傳輸中變更。此變更可能是由於您的網路或用戶端處理常式連接了已簽章的標頭，或以某種方式變更授權標頭。
+ 如果兩個雜湊相符，您在請求中傳送的授權標頭會符合 AWS 收到的內容。檢閱收到的錯誤訊息，以判斷問題是否是因為憑證或簽章不正確所致。此頁面的其他區段會涵蓋這些錯誤。

## 憑證範圍錯誤
<a name="signature-v4-troubleshooting-credential-scope"></a>

您在 [建立要簽署的字串](reference_sigv-create-signed-request.md#create-string-to-sign) 中建立的憑證範圍會將簽章限制在特定日期、區域和服務。此字串的格式如下所示：

```
YYYYMMDD/region/service/aws4_request
```

**注意**  
如果您使用的是 SigV4a，區域不包含在憑證範圍之中。

**Date**  
如果憑證範圍未指定與 x-amz-date 標頭相同的日期，則簽名驗證步驟會失敗，並顯示下列錯誤訊息：

```
Date in Credential scope does not match YYYYMMDD from ISO-8601 version of date from HTTP
```

如果請求指定未來的時間，則簽章驗證步驟會失敗，並顯示下列錯誤訊息：

```
Signature not yet current: date is still later than date
```

如果請求已過期，簽章驗證步驟會失敗，並顯示下列錯誤訊息：

```
Signature expired: date is now earlier than date
```

**區域**  
如果憑證範圍未指定與請求相同的區域，則簽名驗證步驟會失敗，並顯示下列錯誤訊息：

```
Credential should be scoped to a valid Region, not region-code
```

**服務**  
如果憑證範圍未指定與 host 標頭相同的服務，則簽名驗證步驟會失敗，並顯示下列錯誤訊息：

```
Credential should be scoped to correct service: 'service'
```

**終止字串**  
如果憑證範圍沒有以 aws4\$1request 結尾，則簽名驗證步驟會失敗，並顯示下列錯誤訊息：

```
Credential should be scoped with a valid terminator: 'aws4_request'
```

## 金鑰簽署錯誤
<a name="signature-v4-troubleshooting-key-signing"></a>

簽署金鑰衍生不正確或不當使用密碼編譯而造成的錯誤，較難進行故障診斷。確認正式字串和登入字串正確無誤之後，您也可以檢查下列其中一個問題：
+ 私密存取金鑰與您指定的存取金鑰 ID 不符。
+ 您的金鑰衍生程式碼發生問題。

要驗證私密金鑰是否與存取金鑰 ID 相符，可以使用已知有效的實作來測試它們。例如，使用 AWS SDK 或 AWS CLI 向 提出請求 AWS。如需取得範例，請參閱「[請求簽章範例](reference_sigv-examples.md)」。