

# 适用于 API 请求的 AWS 签名版本 4
<a name="reference_sigv"></a>

**重要**  
如果您使用 AWS SDK（请参阅[示例代码和库](https://aws.amazon.com/developer/)）或 AWS Command Line Interface（AWS CLI）工具向 AWS 发送 API 请求，则可以跳过签名过程，因为 SDK 和 CLI 客户端会使用您提供的访问密钥来验证您的请求。除非您有充分的理由不这样做，否则我们建议您始终使用 SDK 或 CLI。  
在支持多个签名版本的区域中，手动签名请求意味着您必须指定要使用的签名版本。当您向多区域访问点提供请求时，SDK 和 CLI 会自动切换为使用签名版本 4A，而无需进行其他配置。

您在请求中发送的身份验证信息必须包含签名。AWS签名版本 4（SigV4）是将身份验证信息添加到 AWS API 请求的 AWS 签名协议。

您无法使用秘密访问密钥对 API 请求进行签名。相反，您可以使用 Sigv4 签名过程。签名请求涉及：

1. 根据请求详细信息创建规范请求。

1. 使用 AWS 凭证计算签名。

1. 将此签名作为授权标头添加到请求。

然后 AWS 复制此过程并验证签名，相应地授予或拒绝访问权限。

Symmetric SigV4 要求您在特定日期派生一个密钥，该密钥的作用域限定为单个 AWS 区域的单个 AWS 服务。这让各区域的密钥和计算得出的签名均会有所不同，也就是说，您必须知道签名要发送到哪个区域。

非对称签名版本 4（SigV4a）是支持使用新算法进行签名的扩展版本，可以生成可在多个 AWS 区域验证的单个签名。借助 SigV4a，您可以签署多个区域的请求，在多个区域之间实现无缝路由和失效转移。在使用 AWS SDK 或 AWS CLI 来调用需要多区域签名的功能时，签名类型会自动改为使用 SigV4a。有关详细信息，请参阅[AWS SigV4a 的工作原理](#how-sigv4a-works)。

## 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 SDK 和 AWS CLI 使用您提供的访问密钥对您的请求进行身份验证。有关使用 AWS SDK 和 AWS CLI 进行身份验证的更多信息，请参阅 [其他资源](#reference_aws-signing-resources)。

## 为什么签署请求
<a name="why-requests-are-signed"></a>

签名过程通过以下方式帮助保护请求：
+ **验证请求者的身份**

  经过身份验证的请求需要您使用访问密钥（访问密钥 ID、秘密访问密钥）创建的签名。如果您使用的是临时安全凭证，则签名计算还需要安全令牌。有关更多信息，请参阅 [AWS 安全凭证以编程方式访问](security-creds-programmatic-access.md)。
+ **保护传输中的数据**

  为了防止传输时请求被篡改，一些请求元素将用于计算请求的哈希（摘要），得到的哈希值将包括在请求中。在 AWS 服务 收到请求时，它将使用相同信息计算哈希，并将其与您的请求中包括的哈希值进行匹配。如果值不匹配，AWS 将拒绝请求。
+ **防止潜在的反演攻击**

  在大多数情况下，请求必须在请求中的时间戳的 5 分钟内到达 AWS。否则，AWS 将拒绝该请求。

AWS Sigv4 可以在 HTTP 授权标头中表示，也可以作为 URL 中的查询字符串表示。有关更多信息，请参阅 [身份验证方法](reference_sigv-authentication-methods.md)。

## 其他资源
<a name="reference_aws-signing-resources"></a>
+ 有关不同服务的 Sigv4 签名过程的更多信息，请参阅 [请求签名示例](reference_sigv-examples.md)。
+ 要为 AWS CLI 的编程访问配置凭证，请参阅《AWS Command Line Interface User Guide》**中的 [Authentication and access credentials](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-authentication.html)。
+ AWS SDK 包括 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)
  + AWS SDK for Python (Boto) – [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)