

# 使用具有 AWS KMS 密钥的服务器端加密（SSE-KMS）
<a name="UsingKMSEncryption"></a>

**重要**  
Amazon S3 现在将具有 Amazon S3 托管密钥的服务器端加密（SSE-S3）作为 Amazon S3 中每个存储桶的基本加密级别。从 2023 年 1 月 5 日起，上传到 Amazon S3 的所有新对象都将自动加密，不会产生额外费用，也不会影响性能。S3 存储桶默认加密配置和上传的新对象的自动加密状态可在 CloudTrail 日志、S3 清单、S3 Storage Lens 存储统计管理工具和 Amazon S3 控制台中查看，并可用作 AWS CLI 和 AWS SDK 中的附加 Amazon S3 API 响应标头。有关更多信息，请参阅[默认加密常见问题解答](https://docs.aws.amazon.com/AmazonS3/latest/userguide/default-encryption-faq.html)。

服务器端加密是指由接收数据的应用程序或服务在目标位置对数据进行加密。

Amazon S3 对于上传的新对象自动启用具有 Amazon S3 托管式密钥的服务器端加密（SSE-S3）。

除非您另行指定，否则默认情况下存储桶使用 SSE-S3 来加密对象。但是，您可以选择将存储桶配置为改为使用具有 AWS Key Management Service（AWS KMS）密钥的服务器端加密（SSE-KMS）。有关更多信息，请参阅 [使用 AWS KMS (SSE-KMS) 指定服务器端加密](specifying-kms-encryption.md)。

AWS KMS 是一项服务，可将安全、高度可用的硬件和软件结合起来，以提供可扩展到云的密钥管理系统。Amazon S3 使用具有 AWS KMS 的服务器端加密（SSE-KMS）来加密您的 S3 对象数据。此外，当为对象请求 SSE-KMS 时，S3 校验和（作为对象元数据的一部分）将以加密形式存储。有关校验和的更多信息，请参阅[在 Amazon S3 中检查对象完整性](checking-object-integrity.md)。

如果使用 KMS 密钥，则可以使用 AWS KMS，通过 [AWS 管理控制台](https://console.aws.amazon.com/kms)或 [AWS KMS API](https://docs.aws.amazon.com/kms/latest/APIReference/) 来执行以下操作：
+ 集中创建、查看、编辑、监控、启用或禁用、轮换以及安排删除 KMS 密钥。
+ 定义控制如何使用和谁可以使用 KMS 密钥的策略。
+ 审计 KMS 密钥的使用情况，以确保正确使用。[AWS KMS API](https://docs.aws.amazon.com/kms/latest/APIReference/) 支持审计，但 [AWS KMS 控制台](https://console.aws.amazon.com/kms)不支持此功能。



AWS KMS 中的安全控制可帮助您满足与加密相关的合规性要求。您可以利用这些 KMS 密钥来保护在 Amazon S3 存储桶中的数据。将 SSE-KMS 加密用于 S3 存储桶时，AWS KMS keys 必须位于该存储桶所在的同一区域中。

使用 AWS KMS keys 密钥需要支付额外费用。有关更多信息，请参阅 *AWS Key Management Service 开发人员指南*中的 [AWS KMS key 概念](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#kms_keys)和 [AWS KMS 定价](https://aws.amazon.com/kms/pricing)。

有关支持 IAM 用户访问 KMS 加密的存储桶的说明，请参阅[我的 Amazon S3 存储桶默认使用自定义 AWS KMS 密钥进行加密。我如何允许用户从存储桶下载和上传到存储桶？](https://repost.aws/knowledge-center/s3-bucket-access-default-encryption)（位于 AWS re:Post 知识中心中）。

**权限**  
要成功向 Amazon S3 发出 `PutObject` 请求以使用 AWS KMS 密钥来加密对象，您需要对密钥拥有 `kms:GenerateDataKey` 权限。要下载使用 AWS KMS key加密的对象，您需要对密钥拥有 `kms:Decrypt` 权限。要[执行分段上传](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html#mpuAndPermissions)以使用 AWS KMS key来加密对象，您必须对密钥拥有 `kms:GenerateDataKey` 和 `kms:Decrypt` 权限。

**重要**  
仔细查看在您的 KMS 密钥政策中授予的权限。始终将客户自主管理型 KMS 密钥政策权限仅限制为必须访问相关 AWS KMS 密钥操作的 IAM 主体和 AWS 服务。有关更多信息，请参阅[AWS KMS 中的密钥策略](https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html)。

**Topics**
+ [AWS KMS keys](#aws-managed-customer-managed-keys)
+ [Amazon S3 存储桶密钥](#sse-kms-bucket-keys)
+ [需要服务器端加密](#require-sse-kms)
+ [加密上下文](#encryption-context)
+ [发送对 AWS KMS 加密对象的请求](#aws-signature-version-4-sse-kms)
+ [使用 AWS KMS (SSE-KMS) 指定服务器端加密](specifying-kms-encryption.md)
+ [使用 Amazon S3 存储桶密钥降低 SSE-KMS 的成本](bucket-key.md)

## AWS KMS keys
<a name="aws-managed-customer-managed-keys"></a>

当您使用具有 AWS KMS 的服务器端加密（SSE-KMS）时，您可以使用默认的 [AWS 托管式密钥](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-managed-cmk)，也可以指定您已创建的[客户托管式密钥](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#customer-cmk)。AWS KMS 支持*信封加密*。S3 将 AWS KMS 特征用于*信封加密*来进一步保护您的数据。信封加密是一种加密方法，它使用数据密钥对明文数据进行加密，然后使用 KMS 密钥对该数据密钥进行加密。有关信封加密的更多信息，请参阅 *AWS Key Management Service 开发人员指南*中的[信封加密](https://docs.aws.amazon.com//kms/latest/developerguide/concepts.html#enveloping)。

如果未指定客户托管密钥，首次将使用 SSE-KMS 加密的对象添加到存储桶时，Amazon S3 会自动在 AWS 账户 中创建 AWS 托管式密钥。默认情况下，Amazon S3 将此 KMS 密钥用于 SSE-KMS。

**注意**  
通过 SSE-KMS（使用 [AWS 托管式密钥](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#aws-managed-cmk)）加密的对象不能跨账户共享。如果您需要跨账户共享 SSE-KMS 数据，则必须使用来自 AWS KMS 的[客户自主管理型密钥](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#customer-cmk)。

如果要使用客户托管式密钥进行 SSE-KMS 加密，可以在配置 SSE-KMS 之前创建对称加密客户托管式密钥。然后，为存储桶配置 SSE-KMS 时，请指定现有的客户托管密钥。有关对称加密密钥的更多信息，请参阅《AWS Key Management Service 开发人员指南》**中的[对称加密 KMS 密钥](https://docs.aws.amazon.com//kms/latest/developerguide/concepts.html#symmetric-cmks)。

创建客户托管密钥可为您提供更大的灵活性和控制力。例如，您可以创建、轮换和禁用客户托管密钥。您还可以定义访问控制和审核用于保护数据的客户托管密钥。有关客户托管式密钥和 AWS 托管式密钥的更多信息，请参阅《AWS Key Management Service 开发人员指南》**中的[客户密钥和 AWS 密钥](https://docs.aws.amazon.com//kms/latest/developerguide/concepts.html#key-mgmt)。

**注意**  
与标准 KMS 密钥不同，当您将服务器端加密与存储在外部密钥存储中的客户托管式密钥结合使用时，您有责任确保密钥材料的可用性和耐久性。有关外部密钥存储及其如何更改责任共担模式的更多信息，请参阅《AWS Key Management Service 开发者指南》**中的[外部密钥存储](https://docs.aws.amazon.com//kms/latest/developerguide/keystore-external.html)。

### 使用 SSE-KMS 加密进行跨账户操作
<a name="sse-kms-cross-account-operations"></a>

在对跨账户操作使用加密时，请注意以下事项：
+ 如果未在请求时提供 AWS KMS key Amazon 资源名称（ARN）或别名，也未通过存储桶的默认加密配置提供它们，则使用发出上传的账户中的 AWS 托管式密钥（`aws/s3`）来进行加密，并且加密需要使用此密钥。
+ 当进行上传和访问的 AWS Identity and Access Management（IAM）主体来自同一 AWS 账户时，AWS 托管式密钥（`aws/s3`）可以用作跨账户操作的 KMS 密钥。
+ 如果您希望授予对 S3 对象的跨账户访问权限，请使用客户自主管理型密钥。您可以配置客户托管式密钥的策略，以便允许从其他账户进行访问。
+ 如果您指定客户托管式 KMS 密钥，我们建议您使用完全限定的 KMS 密钥 ARN。如果您改为使用 KMS 密钥别名，AWS KMS 将解析请求者账户中的密钥。这一行为可能导致使用属于请求者而不是存储桶拥有者的 KMS 密钥来加密数据。
+ 您必须指定您（请求者）已被授予 `Encrypt` 权限的密钥。有关更多信息，请参阅《AWS Key Management Service 开发人员指南》**中的[允许密钥用户使用 KMS 密钥进行加密操作](https://docs.aws.amazon.com/kms/latest/developerguide/key-policies.html#key-policy-users-crypto)。

有关何时使用客户自主管理型密钥和 AWS KMS 托管密钥的更多信息，请参阅[我是应使用 AWS 托管式密钥 还是使用客户自主管理型密钥来加密 Amazon S3 中的对象？](https://aws.amazon.com/premiumsupport/knowledge-center/s3-object-encryption-keys/)

### SSE-KMS 加密工作流程
<a name="sse-kms-encryption-workflow"></a>

如果您选择使用 AWS 托管式密钥或客户托管式密钥加密数据，则 AWS KMS 和 Amazon S3 执行以下信封加密操作：

1. Amazon S3 请求明文[数据密钥](https://docs.aws.amazon.com//kms/latest/developerguide/concepts.html#data-keys)以及使用指定 KMS 密钥加密的数据密钥的副本。

1. AWS KMS 生成数据密钥，使用 KMS 密钥为其进行加密，然后将明文数据密钥和加密的数据密钥发送到 Amazon S3。

1. Amazon S3 使用数据密钥加密数据，并在使用后尽快从内存中删除该明文密钥。

1. Amazon S3 将加密的数据密钥作为元数据与加密数据一起存储。

当请求解密数据时，Amazon S3 和 AWS KMS 将执行以下操作：

1. Amazon S3 在 `Decrypt` 请求中向 AWS KMS 发送加密的数据密钥。

1. AWS KMS 使用相同的 KMS 密钥为加密的数据密钥解密，然后将明文数据密钥返回到 Amazon S3。

1. Amazon S3 使用明文数据密钥解密已加密的数据，并尽快从内存中删除该明文数据密钥。

**重要**  
在 Amazon S3 中使用 AWS KMS key 进行服务器端加密时，您必须选择对称加密 KMS 密钥。Amazon S3 仅支持对称加密 KMS 密钥。有关这些密钥的更多信息，请参阅《AWS Key Management Service 开发人员指南》**中的[对称加密 KMS 密钥](https://docs.aws.amazon.com//kms/latest/developerguide/concepts.html#symmetric-cmks)。

### 审计 SSE-KMS 加密
<a name="sse-kms-encryption-audit"></a>

要识别指定 SSE-KMS 的请求，您可以使用 Amazon S3 Storage Lens 存储统计管理工具指标中的 **All SSE-KMS requests**（所有 SSE-KMS 请求）和 **% all SSE-KMS requests**（所有 SSE-KMS 请求的百分比）指标。S3 Storage Lens 存储统计管理工具是一项云存储分析功能，您可以使用它在整个组织范围内了解对象存储的使用情况和活动。还可以使用启用 SSE-KMS 的存储桶计数和启用 SSE-KMS 的存储桶百分比，来了解使用 SSE-KMS 进行[默认存储桶加密](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-encryption.html)的存储桶计数。有关更多信息，请参阅[使用 S3 Storage Lens 存储统计管理工具访问存储活动和使用情况](https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage_lens.html?icmpid=docs_s3_user_guide_UsingKMSEncryption.html)。有关指标的完整列表，请参阅 [S3 Storage Lens 存储统计管理工具指标词汇表](https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage_lens_metrics_glossary.html?icmpid=docs_s3_user_guide_UsingKMSEncryption.html)。

要审计为 SSE-KMS 加密数据使用 AWS KMS 密钥的情况，您可以使用 AWS CloudTrail 日志。您可以深入了解自己的[加密操作](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#cryptographic-operations)，例如 [https://docs.aws.amazon.com/kms/latest/developerguide/ct-generatedatakey.html](https://docs.aws.amazon.com/kms/latest/developerguide/ct-generatedatakey.html) 和 [https://docs.aws.amazon.com/kms/latest/developerguide/ct-decrypt.html](https://docs.aws.amazon.com/kms/latest/developerguide/ct-decrypt.html)。CloudTrail 支持多种[属性值](https://docs.aws.amazon.com/awscloudtrail/latest/APIReference/API_LookupEvents.html)来筛选您的搜索，包括事件名称、用户名和事件源。

## Amazon S3 存储桶密钥
<a name="sse-kms-bucket-keys"></a>

当您配置使用 AWS KMS 的服务器端加密（SSE-KMS）时，您可以将存储桶配置为使用 S3 存储桶密钥实现 SSE-KMS。使用 SSE-KMS 的存储桶级别密钥可以通过减少从 Amazon S3 到 AWS KMS 的流量请求，从而使您可以将 AWS KMS 请求成本最高降低 99％。

当您将存储桶配置为使用 S3 存储桶密钥对新对象实现 SSE-KMS 时，AWS KMS 会生成存储桶级别密钥，该密钥用于为存储桶中的对象创建唯一的[数据密钥](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#data-keys)。此 S3 存储桶密钥在 Amazon S3 内限时使用，从而进一步减少了 Amazon S3 向 AWS KMS 发出请求以完成加密操作的需求。有关使用 S3 存储桶密钥的更多信息，请参阅 [使用 Amazon S3 存储桶密钥降低 SSE-KMS 的成本](bucket-key.md)。

## 需要服务器端加密
<a name="require-sse-kms"></a>

如果要求对特定 Amazon S3 存储桶中的所有对象进行服务器端加密，请使用存储桶策略。例如，如果请求不包含用于请求服务器端加密（SSE-KMS）的 `x-amz-server-side-encryption-aws-kms-key-id` 标头，则下面的存储桶策略将拒绝所有人的上传对象（`s3:PutObject`）权限。

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Id":"PutObjectPolicy",
   "Statement":[{
         "Sid":"DenyObjectsThatAreNotSSEKMS",
         "Effect":"Deny",
         "Principal":"*",
         "Action":"s3:PutObject",
         "Resource":"arn:aws:s3:::amzn-s3-demo-bucket1/*",
         "Condition":{
            "Null":{
               "s3:x-amz-server-side-encryption-aws-kms-key-id":"true"
            }
         }
      }
   ]
}
```

------

如要求使用特定 AWS KMS key 对存储桶中的对象进行加密，可以使用 `s3:x-amz-server-side-encryption-aws-kms-key-id` 条件键。要指定 KMS 密钥，必须使用 `arn:aws:kms:{{region}}:{{acct-id}}:key/{{key-id}}` 格式的键 Amazon 资源名称（ARN）。AWS Identity and Access Management 不验证 `s3:x-amz-server-side-encryption-aws-kms-key-id` 的字符串是否存在。

**注意**  
在上传对象时，可以使用 `x-amz-server-side-encryption-aws-kms-key-id` 标头指定 KMS 密钥，也可以依赖您的[默认存储桶加密配置](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-encryption.html)。如果 PutObject 请求在 `x-amz-server-side-encryption` 标头中指定 `aws:kms`，但未指定 `x-amz-server-side-encryption-aws-kms-key-id` 标头，则 Amazon S3 会假定您要使用 AWS 托管式密钥。无论如何，Amazon S3 用于对象加密的 AWS KMS 密钥 ID 必须与策略中的 AWS KMS 密钥 ID 匹配，否则 Amazon S3 会拒绝请求。

要查看 Amazon S3 特定条件键的列表，请参阅《Service Authorization Reference》**中的 [Condition keys for Amazon S3](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazons3.html#amazons3-policy-keys)。

## 加密上下文
<a name="encryption-context"></a>

*加密上下文*是一组键值对，其中包含有关数据的其他上下文信息。加密上下文没有加密。在为加密操作指定加密上下文时，Amazon S3 必须指定与解密操作相同的加密上下文。否则，解密将失败。AWS KMS 会将加密上下文用作[其他已经过验证的数据](https://docs.aws.amazon.com/database-encryption-sdk/latest/devguide/concepts.html#digital-sigs) (AAD) 以支持[经过身份验证的加密](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#cryptographic-operations#digital-sigs)。有关加密上下文的更多信息，请参阅 *AWS Key Management Service 开发人员指南*中的[加密上下文](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)。

默认情况下，Amazon S3 使用对象或存储桶 Amazon 资源名称（ARN）作为加密上下文对：
+ **如果您在不启用 S3 存储桶密钥的情况下使用 SSE-KMS**，则将对象 ARN 用作加密上下文。

  ```
  arn:aws:s3:::{{object_ARN}}
  ```
+ **如果您使用 SSE-KMS 并启用 S3 存储桶密钥**，则将存储桶 ARN 用作加密上下文。有关 S3 存储桶的更多信息，请参阅 [使用 Amazon S3 存储桶密钥降低 SSE-KMS 的成本](bucket-key.md)。

  ```
  arn:aws:s3:::{{bucket_ARN}}
  ```

您可以选择使用 [s3:PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html#API_PutObject_RequestSyntax) 请求中的 `x-amz-server-side-encryption-context` 标头提供其他的加密上下文对。但是，由于加密上下文未加密，请确保它不包含敏感信息。Amazon S3 将此额外的密钥对与默认加密上下文一起存储。当处理 `PUT` 请求时，Amazon S3 会将 `aws:s3:arn` 的默认加密上下文附加到您提供的上下文中。

您可以使用加密上下文来标识和分类加密操作。您还可以使用默认的加密上下文 ARN 值来跟踪 AWS CloudTrail 中的相关请求，方法是通过查看哪个 Amazon S3 ARN 与哪个加密密钥一起使用。

在 CloudTrail 日志文件的 `requestParameters` 字段中，加密上下文与以下内容类似。

```
"encryptionContext": {
    "aws:s3:arn": "arn:aws:s3:::{{{{amzn-s3-demo-bucket1}}/file_name}}"
}
```

在将 SSE-KMS 与可选的 S3 存储桶密钥特征一起使用时，加密上下文值是存储桶的 ARN。

```
"encryptionContext": {
    "aws:s3:arn": "arn:aws:s3:::{{{{amzn-s3-demo-bucket1}}}}"
}
```

## 发送对 AWS KMS 加密对象的请求
<a name="aws-signature-version-4-sse-kms"></a>

**重要**  
对 AWS KMS 加密对象的所有 `GET` 和 `PUT` 请求必须使用安全套接字层协议（SSL）和传输层安全性协议（TLS）发出。还必须使用有效的凭证对请求进行签名，例如 AWS 签名版本 4（或 AWS 签名版本 2）。

AWS 签名版本 4 是将身份验证信息添加到通过 HTTP 发送的 AWS 请求的过程。出于安全考虑，大多数 AWS 请求都必须使用访问密钥（包括访问密钥 ID 和秘密访问密钥）进行签名。这两个密钥通常称为您的安全凭证。有关更多信息，请参阅[对请求进行身份验证（AWS Signature Version 4）](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html)和 [Signature Version 4 签名过程](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html)。

**重要**  
如果对象使用 SSE-KMS，则不应对 `GET` 请求和 `HEAD` 请求发送加密请求标头。否则，您会收到 HTTP 400 错误请求错误。

**Topics**
+ [AWS KMS keys](#aws-managed-customer-managed-keys)
+ [Amazon S3 存储桶密钥](#sse-kms-bucket-keys)
+ [需要服务器端加密](#require-sse-kms)
+ [加密上下文](#encryption-context)
+ [发送对 AWS KMS 加密对象的请求](#aws-signature-version-4-sse-kms)
+ [使用 AWS KMS (SSE-KMS) 指定服务器端加密](specifying-kms-encryption.md)
+ [使用 Amazon S3 存储桶密钥降低 SSE-KMS 的成本](bucket-key.md)