

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

在将对象上传到 Amazon S3 时，使用具有 AWS Key Management Service（AWS KMS）密钥的双层服务器端加密（DSSE-KMS）将会对于对象应用两层加密。DSSE-KMS 可帮助您更轻松地满足合规性标准，这些标准要求您对数据应用多层加密并完全控制您的加密密钥。

DSSE-KMS 中的“双”是指应用于数据的两个独立的 AES-256 加密层：
+ *第一层：*数据使用由 AWS KMS 生成的唯一数据加密密钥（DEK）进行加密
+ *第二层：*已加密的数据使用由 Amazon S3 管理的单独 AES-256 加密密钥再次加密

这与标准 SSE-KMS 不同，后者仅应用单层加密。双层方法可确保即使一个加密层遭到破坏，您的数据仍受到第二层保护，从而增强了安全性。这种额外的安全性伴随着处理开销和 AWS KMS API 调用的增加，与标准 SSE-KMS 相比，这会导致成本更高。有关 DSSE-KMS 定价的更多信息，请参阅《AWS Key Management Service Developer Guide》中的 [AWS KMS key concepts](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#kms_keys) 以及 [AWS KMS 定价](https://aws.amazon.com/kms/pricing)。

将 DSSE-KMS 加密用于 Amazon S3 存储桶时，AWS KMS 密钥必须位于该存储桶所在的同一区域中。此外，当为对象请求 DSSE-KMS 时，作为对象元数据一部分的 S3 校验和将以加密形式存储。有关校验和的更多信息，请参阅[在 Amazon S3 中检查对象完整性](checking-object-integrity.md)。

**注意**  
DSSE-KMS 不支持 S3 存储桶密钥。

DSSE-KMS 和标准 SSE-KMS 之间的主要区别在于：
+ **加密层：**DSSE-KMS 应用两个独立的 AES-256 加密层，而标准 SSE-KMS 应用一层
+ **安全性：**DSSE-KMS 提供针对潜在加密漏洞的增强保护
+ **合规性：**DSSE-KMS 有助于满足强制要求多层加密的监管要求
+ **性能：**由于额外的加密处理，DSSE-KMS 的延迟稍高
+ **成本：**由于计算开销增加和额外的 AWS KMS 操作，DSSE-KMS 会产生更高的费用

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

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

****  

```
{
             "Version":"2012-10-17",		 	 	 
             "Id": "PutObjectPolicy",
             "Statement": [{
                   "Sid": "DenyUnEncryptedObjectUploads",
                   "Effect": "Deny",
                   "Principal": {
                       "AWS": "arn:aws:iam::111122223333:root"
                   },
                   "Action": "s3:PutObject",
                   "Resource": "arn:aws:s3:::amzn-s3-demo-bucket/*",
                   "Condition": {
                      "StringNotEquals": {
                         "s3:x-amz-server-side-encryption": "aws:kms:dsse"
                      }
                   }
                }
             ]
          }
```

------

**Topics**
+ [

# 指定具有 AWS KMS 密钥的双层服务器端加密（DSSE-KMS）
](specifying-dsse-encryption.md)

# 指定具有 AWS KMS 密钥的双层服务器端加密（DSSE-KMS）
<a name="specifying-dsse-encryption"></a>

当您上传新对象或复制现有对象时，您可以应用加密。

您可以使用 Amazon S3 控制台、Amazon S3 REST API 和 AWS Command Line Interface（AWS CLI）指定 DSSE-KMS。有关更多信息，请参阅以下主题。

**注意**  
您可以在 Amazon S3 中使用多区域 AWS KMS keys。但是，Amazon S3 目前将多区域密钥视为单区域密钥，且不使用密钥的多区域特征。有关更多信息，请参阅《AWS Key Management Service 开发人员指南》**中的 [Using multi-Region keys](https://docs.aws.amazon.com/kms/latest/developerguide/multi-region-keys-overview.html)。

**注意**  
如果您希望使用其他账户拥有的 KMS 密钥，则您必须有权使用该密钥。有关 KMS 密钥的跨账户权限的更多信息，请参阅《AWS Key Management Service 开发人员指南》**中的[创建其他账户可以使用的 KMS 密钥](https://docs.aws.amazon.com//kms/latest/developerguide/key-policy-modifying-external-accounts.html#cross-account-console)。

## 使用 S3 控制台
<a name="add-object-encryption-dsse"></a>

本节介绍如何使用 Amazon S3 控制台，将对象的加密类型设置或更改为使用具有 AWS Key Management Service（AWS KMS）密钥的双层服务器端加密（DSSE-KMS）。

**注意**  
如果对象小于 5 GB，则可以更改对象的加密。如果对象大于 5GB，必须使用 [AWS CLI](mpu-upload-object.md#UsingCLImpUpload) 或 [AWS SDK](CopyingObjectsMPUapi.md) 来更改对象的加密。
有关更改对象的加密所需的其它权限的列表，请参阅 [Amazon S3 API 操作所需的权限](using-with-s3-policy-actions.md)。有关授予此权限的示例策略，请参阅[Amazon S3 基于身份的策略示例](example-policies-s3.md)。
如果更改对象的加密，则会创建一个新对象来替换旧对象。如果启用 S3 版本控制，则会创建对象的新版本，而现有对象将变为旧版本。更改属性的角色也会成为新对象（或对象版本）的拥有者。

**添加或更改对象的加密**

1. 登录到 AWS 管理控制台，然后通过以下网址打开 Amazon S3 控制台：[https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/)。

1. 在导航窗格中，选择**存储桶**，然后选择**通用存储桶**选项卡。导航到包含要更改的对象的 Amazon S3 存储桶或文件夹。

1. 选中要更改的对象所对应的复选框。

1. 在**操作**菜单上，从显示的选项列表中选择**编辑服务器端加密**。

1. 滚动到**服务器端加密**部分。

1. 在**加密设置**下，选择**使用默认加密的存储桶设置**或**覆盖默认加密的存储桶设置**。

1. 如果您选择**覆盖默认加密的存储桶设置**，请配置以下加密设置。

   1. 在**加密类型**下，选择**具有 AWS Key Management Service 密钥的双层服务器端加密（DSSE-KMS）**。

   1. 在 **AWS KMS 密钥**下，执行以下操作以选择您的 KMS 密钥：
      + 要从可用的 KMS 密钥列表中进行选择，请选择**从您的 AWS KMS keys 中进行选择**，然后从可用密钥的列表中选择您的 **KMS 密钥**。

        AWS 托管式密钥（`aws/s3`）和您的客户自主管理型密钥都显示在此列表中。有关客户自主管理型密钥的更多信息，请参阅《AWS Key Management Service 开发人员指南》**中的[客户密钥和 AWS 密钥](https://docs.aws.amazon.com//kms/latest/developerguide/concepts.html#key-mgmt)。
      + 要输入 KMS 密钥 ARN，请选择**输入 AWS KMS key ARN**，然后在显示的字段中输入您的 KMS 密钥 ARN。
      + 要在 AWS KMS 控制台中创建新的客户自主管理型密钥，请选择**创建 KMS 密钥**。

        有关创建 AWS KMS key 的更多信息，请参阅《AWS Key Management Service 开发人员指南》**中的[创建密钥](https://docs.aws.amazon.com//kms/latest/developerguide/create-keys.html)。
**重要**  
您只能使用与存储桶所在相同的 AWS 区域中可用的 KMS 密钥。Amazon S3 控制台仅列出与存储桶位于同一区域中的前 100 个 KMS 密钥。要使用未列出的 KMS 密钥，您必须输入 KMS 密钥 ARN。如果您希望使用其他账户拥有的 KMS 密钥，则必须首先有权使用该密钥，然后必须输入相应的 KMS 密钥 ARN。  
Amazon S3 仅支持对称加密 KMS 密钥，不支持非对称 KMS 密钥。有关更多信息，请参阅《AWS Key Management Service 开发人员指南》**中的[确定非对称 KMS 密钥](https://docs.aws.amazon.com//kms/latest/developerguide/find-symm-asymm.html)。

1. 对于**存储桶密钥**，选择**禁用**。DSSE-KMS 不支持 S3 存储桶密钥。

1. 在**其它复制设置**下，选择是要**复制源设置**、**请勿指定设置**还是**指定设置**。**复制源设置**是默认选项。如果您只想复制不带源设置属性的对象，请选择**请勿指定设置**。选择**指定设置**，来指定存储类、ACL、对象标签、元数据、服务器端加密和其它校验和的设置。

1. 选择**保存更改**。

**注意**  
此操作将加密应用于所有指定的对象。加密文件夹时，请等待保存操作完成，然后再将新对象添加到文件夹。

## 使用 REST API
<a name="DSSEUsingRESTAPI"></a>

创建对象时（即上传新对象或复制现有对象时），您可以指定使用具有 AWS KMS keys 的双层服务器端加密（DSSE-KMS）来加密数据。为此，请将 `x-amz-server-side-encryption` 标头添加到请求。将标头的值设置为加密算法 `aws:kms:dsse`。Amazon S3 通过返回响应标头 `x-amz-server-side-encryption` 来确认已使用 DSSE-KMS 加密来存储对象。

如果您指定值为 `x-amz-server-side-encryption` 的 `aws:kms:dsse` 标头，则还可以使用以下请求标头：
+ `x-amz-server-side-encryption-aws-kms-key-id: SSEKMSKeyId`
+ `x-amz-server-side-encryption-context: SSEKMSEncryptionContext`

**Topics**
+ [

### 支持 DSSE-KMS 的 Amazon S3 REST API 操作
](#dsse-request-headers-kms)
+ [

### 加密上下文（`x-amz-server-side-encryption-context`）
](#s3-dsse-encryption-context)
+ [

### AWS KMS 密钥 ID（`x-amz-server-side-encryption-aws-kms-key-id`）
](#s3-dsse-key-id-api)

### 支持 DSSE-KMS 的 Amazon S3 REST API 操作
<a name="dsse-request-headers-kms"></a>

以下 REST API 操作接受 `x-amz-server-side-encryption`、`x-amz-server-side-encryption-aws-kms-key-id` 和 `x-amz-server-side-encryption-context` 请求标头。
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html) – 使用 `PUT` API 操作上传数据时，您可以指定这些请求标头。
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html) – 复制对象时，您同时具有源对象和目标对象。如果使用 `CopyObject` 操作传递 DSSE-KMS 标头，它们仅应用于目标对象。复制现有对象时，不论源对象是否已经加密，都不会加密目标对象，除非您显式请求服务器端加密。
+ [POST Object](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) – 使用 `POST` 操作上传对象时，可在表单字段（而不是在请求标头）中提供相同的信息。
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html) – 使用分段上传来上传大型对象时，可以在 `CreateMultipartUpload` 请求中指定这些标头。

使用服务器端加密存储对象时，以下 REST API 操作的响应标头将返回 `x-amz-server-side-encryption` 标头。
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html)
+ [POST 对象](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html)

**重要**  
如果您不让使用安全套接字层（SSL）、传输层安全性协议（TLS）或签名版本 4 发出针对受 AWS KMS 保护的对象的所有 `GET` 和 `PUT` 请求，则这些请求都将失败。
如果对象使用 DSSE-KMS，则不应对 `GET` 请求和 `HEAD` 请求发送加密请求标头，否则您将得到 HTTP 400（错误请求）错误。

### 加密上下文（`x-amz-server-side-encryption-context`）
<a name="s3-dsse-encryption-context"></a>

如果您指定 `x-amz-server-side-encryption:aws:kms:dsse`，Amazon S3 API 将支持带有 `x-amz-server-side-encryption-context` 标头的加密上下文。加密上下文是一组键值对，其中包含有关数据的其他上下文信息。

Amazon S3 自动使用对象的 Amazon 资源名称（ARN）作为加密上下文对；例如 `arn:aws:s3:::object_ARN`。

您可以选择使用 `x-amz-server-side-encryption-context` 标头提供其他的加密上下文对。但是，由于加密上下文未加密，请确保它不包含敏感信息。Amazon S3 将此额外的密钥对与默认加密上下文一起存储。

有关 Amazon S3 中加密上下文的信息，请参阅 [加密上下文](UsingKMSEncryption.md#encryption-context)。有关加密上下文的一般信息，请参阅 *AWS Key Management Service 开发人员指南*中的 [AWS Key Management Service 概念 - 加密上下文](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#encrypt_context)。

### AWS KMS 密钥 ID（`x-amz-server-side-encryption-aws-kms-key-id`）
<a name="s3-dsse-key-id-api"></a>

您可以使用 `x-amz-server-side-encryption-aws-kms-key-id` 标头指定用于保护数据的客户自主管理型密钥的 ID。如果您指定 `x-amz-server-side-encryption:aws:kms:dsse` 标头但未提供 `x-amz-server-side-encryption-aws-kms-key-id` 标头，Amazon S3 将使用 AWS 托管式密钥（`aws/s3`）来保护数据。如果要使用客户托管密钥，则必须提供客户托管密钥的 `x-amz-server-side-encryption-aws-kms-key-id` 标头。

**重要**  
在 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)。

## 使用 AWS CLI
<a name="DSSEUsingCLI"></a>

当您上传新对象或复制现有对象时，可以指定使用 DSSE-KMS 来加密数据。为此，请将 `--server-side-encryption aws:kms:dsse` 参数添加到请求。使用 `--ssekms-key-id example-key-id` 参数添加您创建的[客户自主管理型 AWS KMS 密钥](https://docs.aws.amazon.com//kms/latest/developerguide/concepts.html#customer-cmk)。如果您指定 `--server-side-encryption aws:kms:dsse`，但未提供 AWS KMS 密钥 ID，则 Amazon S3 将使用 AWS 托管式密钥（`aws/s3`）。

```
aws s3api put-object --bucket amzn-s3-demo-bucket --key example-object-key --server-side-encryption aws:kms:dsse --ssekms-key-id example-key-id --body filepath
```

您可以通过将未加密的对象复制回原位来加密该对象以使用 DSSE-KMS。

```
aws s3api copy-object --bucket amzn-s3-demo-bucket --key example-object-key --copy-source amzn-s3-demo-bucket/example-object-key --server-side-encryption aws:kms:dsse --ssekms-key-id example-key-id
```