

# 使用服务器端加密保护数据
<a name="serv-side-encryption"></a>

**重要**  
从 2026 年 4 月开始，AWS 将对所有新存储桶禁用具有客户提供密钥的服务器端加密（SSE-C）。此外，对于 AWS 账户中没有任何 SSE-C 加密数据的所有现有存储桶，都将禁用 SSE-C 加密。通过这些更改，少数需要 SSE-C 加密的应用程序必须在创建存储桶后，专门通过 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) API 启用 SSE-C。在这些情况下，您可能需要更新自动化脚本、CloudFormation 模板或其他基础设施配置工具来配置这些设置。有关更多信息，请参阅 [AWS Storage 博客文章](https://aws.amazon.com/blogs/storage/advanced-notice-amazon-s3-to-disable-the-use-of-sse-c-encryption-by-default-for-all-new-buckets-and-select-existing-buckets-in-april-2026/)。

**重要**  
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 在将您的数据写入 AWS 数据中心内的磁盘时会在对象级别加密这些数据，并在您访问这些数据时解密这些数据。只要您验证了您的请求并且拥有访问权限，您访问加密和未加密对象的方式就没有区别。例如，如果您使用预签名的 URL 来共享您的对象，那么对于加密和解密的对象，该 URL 的工作方式是相同的。此外，在您列出存储桶中的对象时，列表 API 操作会返回所有对象的列表（无论对象是否加密）。

默认情况下，所有 Amazon S3 存储桶都配置了加密，所有上传到 S3 存储桶的新对象都会自动静态加密。具有 Amazon S3 托管密钥的服务器端加密（SSE-S3）是 Amazon S3 中每个存储桶的默认加密配置。要使用其它类型的加密，您可以指定要在 S3 `PUT` 请求中使用的服务器端加密类型，也可以在目标存储桶中更新默认加密配置。

如果您想在 `PUT` 请求中指定不同的加密类型，则可以使用具有 AWS Key Management Service（AWS KMS）密钥的服务器端加密（SSE-KMS）、具有 AWS KMS 密钥的双层服务器端加密（DSSE-KMS）或具有客户提供的密钥的服务器端加密（SSE-C）。如果您想在目标存储桶中设置不同的默认加密配置，则可以使用 SSE-KMS 或 DSSE-KMS。

有关更改通用存储桶的默认加密配置的更多信息，请参阅[配置默认加密](default-bucket-encryption.md)。

在将存储桶的默认加密配置更改为 SSE-KMS 时，不会更改存储桶中现有 Amazon S3 对象的加密类型。要在将默认加密配置更新为 SSE-KMS 后更改先前存在对象的加密类型，可以使用 Amazon S3 批量操作。您为 S3 批量操作提供对象列表，而批量操作调用相应的 API 操作。可以使用 [复制对象](batch-ops-copy-object.md) 操作来复制现有对象，这会将这些对象写回到与 SSE-KMS 加密对象相同的存储桶中。单个批量操作作业可对数十亿个对象执行指定操作。有关更多信息，请参阅[使用批量操作批量执行对象操作](batch-ops.md)和 *AWS Storage Blog* 博客文章 [How to retroactively encrypt existing objects in Amazon S3 using S3 Inventory, Amazon Athena, and S3 Batch Operations](https://aws.amazon.com/blogs/security/how-to-retroactively-encrypt-existing-objects-in-amazon-s3-using-s3-inventory-amazon-athena-and-s3-batch-operations/)。

**注意**  
您不能对同一个对象应用不同类型的服务器端加密。

如果您需要加密现有对象，请使用 S3 批量操作和 S3 清单。有关更多信息，请参阅[使用 Amazon S3 批量操作加密对象](https://aws.amazon.com/blogs/storage/encrypting-objects-with-amazon-s3-batch-operations/)和[使用批量操作批量执行对象操作](batch-ops.md)。

在 Amazon S3 中存储数据时，对于服务器端加密，您有四个互斥的选项，具体取决于您选择如何管理加密密钥和要应用的加密层数。

**具有 Amazon S3 托管密钥的服务器端加密（SSE-S3）**  
默认情况下，所有 Amazon S3 存储桶都配置了加密。服务器端加密的默认选项是使用 Amazon S3 托管式密钥（SSE-S3）。每个对象都使用唯一的密钥来进行加密。作为额外的保护措施，SSE-S3 使用定期轮换的根密钥加密密钥本身。SSE-S3 使用可用的最强数据块密码之一 [即 256 位高级加密标准（AES-256）] 来加密您的数据。有关更多信息，请参阅 [使用具有 Amazon S3 托管式密钥的服务器端加密（SSE-S3）](UsingServerSideEncryption.md)。

**具有 AWS Key Management Service（AWS KMS）密钥的服务器端加密（SSE-KMS）**  
具有 AWS KMS keys 的服务器端加密（SSE-KMS）是通过将 AWS KMS 服务与 Amazon S3 集成来提供的。使用 AWS KMS，您可以更好地控制您的密钥。例如，您可以查看单独的密钥、编辑控制策略以及遵循 AWS CloudTrail 中的密钥。此外，您还可以创建和管理客户自主管理型密钥，或者使用对于您、服务和区域为唯一的 AWS 托管式密钥。有关更多信息，请参阅 [使用具有 AWS KMS 密钥的服务器端加密（SSE-KMS）](UsingKMSEncryption.md)。

**具有 AWS Key Management Service（AWS KMS）密钥的双层服务器端加密（DSSE-KMS）**  
具有 AWS KMS keys的双层服务器端加密（DSSE-KMS）与 SSE-KMS 类似，但 DSSE-KMS 应用两个独立的 AES-256 加密层而不是一层：首先使用 AWS KMS 数据加密密钥，然后使用单独的 Amazon S3 托管式加密密钥。由于这两层加密都应用于服务器端的对象，因此您可以使用各种 AWS 服务和工具来分析 S3 中的数据，同时使用可以满足多层加密的合规性要求的加密方法。有关更多信息，请参阅 [使用具有 AWS KMS 密钥的双层服务器端加密（DSSE-KMS）](UsingDSSEncryption.md)。

**具有客户提供密钥的服务器端加密（SSE-C）**  
使用具有客户提供的密钥的服务器端加密（SSE-C）时，您管理加密密钥，而 Amazon S3 管理加密（在它对磁盘进行写入时）和解密（在您访问您的对象时）。有关更多信息，请参阅 [使用具有客户提供的密钥的服务器端加密（SSE-C）](ServerSideEncryptionCustomerKeys.md)。

**注意**  
当为 Amazon FSx 文件系统使用接入点时，使用 S3 接入点，您有一个服务器端加密选项。  
所有 Amazon FSx 文件系统默认情况下都配置了加密，并通过使用 AWS Key Management Service 管理的密钥进行静态加密。当向文件系统写入数据和从文件系统读取数据时，数据会在文件系统上自动加密和解密。这些过程由 Amazon FSx 透明地进行处理。

# 为 Amazon S3 存储桶设置默认服务器端加密行为
<a name="bucket-encryption"></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）来自动加密对象。此加密设置适用于 Amazon S3 存储桶中的所有对象。

如果您需要对密钥进行更多控制，例如管理密钥轮换和访问策略授予，则可以选择使用具有 AWS Key Management Service（AWS KMS）密钥的服务器端加密（SSE-KMS），或具有 AWS KMS 密钥的双层服务器端加密（DSSE-KMS）。有关编辑 KMS 密钥的更多信息，请参阅《AWS Key Management Service 开发人员指南》**中的[编辑密钥](https://docs.aws.amazon.com/kms/latest/developerguide/editing-keys.html)。

**注意**  
我们已更改存储桶，以自动加密新上传的对象。如果您之前创建的存储桶没有默认加密，则 Amazon S3 在默认情况下将使用 SSE-S3 为存储桶启用加密。对于已配置 SSE-S3 或 SSE-KMS 的现有存储桶的默认加密配置，不会进行任何更改。如果您想使用 SSE-KMS 加密您的对象，则必须在存储桶设置中更改加密类型。有关更多信息，请参阅 [使用具有 AWS KMS 密钥的服务器端加密（SSE-KMS）](UsingKMSEncryption.md)。

当您将存储桶配置为使用 SSE-KMS 的默认加密时，您还可以启用 S3 存储桶密钥，以减少从 Amazon S3 到 AWS KMS 的请求流量并降低加密成本。有关更多信息，请参阅 [使用 Amazon S3 存储桶密钥降低 SSE-KMS 的成本](bucket-key.md)。

要识别已启用 SSE-KMS 进行默认加密的存储桶，您可以使用 Amazon S3 Storage Lens 存储统计管理工具指标。S3 Storage Lens 存储统计管理工具是一项云存储分析功能，您可以使用它在整个组织范围内了解对象存储的使用情况和活动。有关更多信息，请参阅[使用 S3 Storage Lens 存储统计管理工具保护您的数据](https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage-lens-data-protection.html?icmpid=docs_s3_user_guide_bucket-encryption.html)。

在使用服务器端加密时，Amazon S3 在将对象保存到其磁盘上之前对其进行加密，并在下载对象时对其进行解密。有关使用服务器端加密和加密密钥管理来保护数据的更多信息，请参阅[使用服务器端加密保护数据](serv-side-encryption.md)。

有关默认加密所需的权限的更多信息，请参阅《Amazon Simple Storage Service API 参考》**中的 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html)。

您可以使用 Amazon S3 控制台、AWS SDK、Amazon S3 REST API 和 AWS 命令行界面（AWS CLI）为 S3 存储桶配置 Amazon S3 默认加密行为。

**加密现有对象**  
要加密现有未加密的 Amazon S3 对象，可以使用 Amazon S3 批量操作。您为 S3 批量操作提供了要操作的对象列表，而批量操作调用相应的 API 来执行指定的操作。您可以使用[批量操作复制操作](https://docs.aws.amazon.com/AmazonS3/latest/userguide/batch-ops-copy-object.html)复制现有的未加密对象，并将其作为加密对象写回同一存储桶。单个批量操作作业可对数十亿个对象执行指定操作。有关更多信息，请参阅 [使用批量操作批量执行对象操作](batch-ops.md) 和 *AWS 存储博客*的博客文章：[使用 Amazon S3 批量操作加密对象](https://aws.amazon.com/blogs/storage/encrypting-objects-with-amazon-s3-batch-operations/)。

也可以使用 `CopyObject` API 操作或 `copy-object` AWS CLI 命令加密现有对象。有关更多信息，请参阅 *AWS 存储博客*的博客文章：[使用 AWS CLI 加密现有 Amazon S3 对象](https://aws.amazon.com/blogs/storage/encrypting-existing-amazon-s3-objects-with-the-aws-cli/)。

**注意**  
将默认存储桶加密设置为 SSE-KMS 的 Amazon S3 存储桶不能用作 [使用服务器访问日志记录来记录请求](ServerLogs.md) 的目标存储桶。对于服务器访问日志目标存储桶，仅支持 SSE-S3 默认加密。

## 使用 SSE-KMS 加密进行跨账户操作
<a name="bucket-encryption-update-bucket-policy"></a>

在对跨账户操作使用加密时，请注意以下事项：
+ 如果未在请求时提供 AWS KMS key Amazon 资源名称（ARN）或别名，也未通过存储桶的默认加密配置提供它们时，则使用 AWS 托管式密钥（`aws/s3`）。
+ 如果您使用您的 KMS 密钥所在的相同 AWS 账户中的 AWS Identity and Access Management（IAM）主体上传或访问 S3 对象，则可以使用 AWS 托管式密钥（`aws/s3`）。
+ 如果您希望授予对 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/)

## 将默认加密用于复制
<a name="bucket-encryption-replication"></a>

在为复制目标存储桶启用默认加密后，将应用以下加密行为：
+ 如果未对源存储桶中的对象进行加密，则将使用目标存储桶的默认加密设置对目标存储桶中的副本对象进行加密。因此，源对象的实体标签（ETag）与副本对象的 ETag 不同。如果您有使用 ETag 的应用程序，则必须更新这些应用程序以弥补这种差异。
+ 如果使用具有 Amazon S3 托管密钥的服务器端加密（SSE-S3）、具有 AWS Key Management Service（AWS KMS）密钥的服务器端加密（SSE-KMS）或具有 AWS KMS 密钥的双层服务器端加密（DSSE-KMS）来加密源存储桶中的对象，则目标存储桶中的副本对象使用与源对象相同类型的加密。不会使用目标存储桶的默认加密设置。

有关使用 SSE-KMS 进行默认加密的更多信息，请参阅[复制加密对象](replication-config-for-kms-objects.md)。

## 将 Amazon S3 存储桶密钥用于默认加密
<a name="bucket-key-default-encryption"></a>

当将存储桶配置为使用 SSE-KMS 作为新对象的默认加密行为时，还可以配置 S3 存储桶密钥。S3 存储桶密钥可减少从 Amazon S3 到 AWS KMS 的事务数量，从而降低 SSE-KMS 的成本。

当您将存储桶配置为使用 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 存储桶密钥](bucket-key.md)。

# 配置默认加密
<a name="default-bucket-encryption"></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）来自动加密新对象。这种加密适用于您的 Amazon S3 存储桶中的所有新对象，并且不收取任何费用。

如果您需要对加密密钥进行更多控制，例如管理密钥轮换和访问策略授予，则可以选择使用具有 AWS Key Management Service（AWS KMS）密钥的服务器端加密（SSE-KMS），或具有 AWS KMS 密钥的双层服务器端加密（DSSE-KMS）。有关 SSE-KMS 的更多信息，请参阅 [使用 AWS KMS (SSE-KMS) 指定服务器端加密](specifying-kms-encryption.md)。有关 DSSE-KMS 的更多信息，请参阅[使用具有 AWS KMS 密钥的双层服务器端加密（DSSE-KMS）](UsingDSSEncryption.md)。

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

当您将默认存储桶加密设置为 SSE-KMS 时，还可以配置 S3 存储桶密钥以降低 AWS KMS 请求成本。有关更多信息，请参阅 [使用 Amazon S3 存储桶密钥降低 SSE-KMS 的成本](bucket-key.md)。

**注意**  
如果使用 [PutBucketEncryption](https://docs.aws.amazon.com//AmazonS3/latest/API/API_PutBucketEncryption.html) 将默认存储桶加密设置为 SSE-KMS，则应验证您的 KMS 密钥 ID 是否正确。Amazon S3 不验证 PutBucketEncryption 请求中提供的 KMS 密钥 ID。

对 S3 存储桶使用默认加密不会产生额外的费用。请求配置默认加密行为会产生标准 Amazon S3 请求费用。有关定价的信息，请参阅 [Amazon S3 定价](https://aws.amazon.com/s3/pricing/)。对于 SSE-KMS 和 DSSE-KMS，将会产生 AWS KMS 费用，这些费用在 [AWS KMS 定价](https://aws.amazon.com/kms/pricing/)中列出。

默认加密不支持具有客户提供的密钥的服务器端加密（SSE-C）。

您可以使用 Amazon S3 控制台、AWS SDK、Amazon S3 REST API 和 AWS Command Line Interface（AWS CLI）为 S3 存储桶配置 Amazon S3 默认加密。

**启用默认加密之前需要注意的更改**  
在为存储桶启用默认加密后，将会应用以下加密行为：
+ 在启用默认加密之前，存储桶中已存在的对象的加密没有变化。
+ 在启用默认加密后上传对象时：
  + 如果您的 `PUT` 请求标头不包含加密信息，则 Amazon S3 将使用存储桶的默认加密设置来加密对象。
  + 如果您的 `PUT` 请求标头包含加密信息，则 Amazon S3 将使用 `PUT` 请求中的加密信息加密对象，然后再将对象存储在 Amazon S3 中。
+ 如果您将 SSE-KMS 或 DSSE-KMS 选项用于默认加密配置，则您将受到 AWS KMS 的每秒请求数（RPS）限额限制。有关 AWS KMS 限额以及如何请求增加限额的更多信息，请参阅《AWS Key Management Service 开发人员指南》**中的[限额](https://docs.aws.amazon.com/kms/latest/developerguide/limits.html)。

**注意**  
在启用默认加密之前上传的对象将不会加密。有关加密现有对象的信息，请参阅[为 Amazon S3 存储桶设置默认服务器端加密行为](bucket-encryption.md)。

## 使用 S3 控制台
<a name="bucket-encryption-how-to-set-up-console"></a>

**在 Amazon S3 存储桶上配置默认加密**

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

1. 在左侧导航窗格中，选择**存储桶**。

1. 在 **Buckets**（存储桶）列表中，请选择您想要的存储桶的名称。

1. 选择**属性**选项卡。

1. 在**默认加密**下，选择**编辑**。

1. 要配置加密，请在**加密类型**下，选择以下选项之一：
   + **具有 Amazon S3 托管式密钥的服务器端加密（SSE-S3）**
   + **具有 AWS Key Management Service 密钥的服务器端加密（SSE-KMS）**
   + **具有 AWS Key Management Service 密钥的双层服务器端加密（DSSE-KMS）**
**重要**  
如果您将 SSE-KMS 或 DSSE-KMS 选项用于默认加密配置，则您将受到 AWS KMS 的每秒请求数（RPS）限额限制。有关 AWS KMS 限额以及如何请求增加限额的更多信息，请参阅《AWS Key Management Service 开发人员指南》**中的[限额](https://docs.aws.amazon.com/kms/latest/developerguide/limits.html)。

   默认情况下，存储桶和新对象使用 SSE-S3 加密，除非您为存储桶指定其他类型的默认加密。有关原定设置加密的更多信息，请参阅[为 Amazon S3 存储桶设置默认服务器端加密行为](bucket-encryption.md)。

   有关使用 Amazon S3 服务器端加密对数据进行加密的更多信息，请参阅[使用具有 Amazon S3 托管式密钥的服务器端加密（SSE-S3）](UsingServerSideEncryption.md)。

1. 如果您选择**具有 AWS Key Management Service 密钥的服务器端加密（SSE-KMS）**或**具有 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 密钥。选择**从您的 KMS 密钥中选择**时，S3 控制台每个区域仅列出 100 个 KMS 密钥。如果在同一区域中有超过 100 个 KMS，您只会在 S3 控制台中看到前 100 个 KMS 密钥。要使用控制台中未列出的 KMS 密钥，请选择**输入 AWS KMS key ARN**，然后输入 KMS 密钥 ARN。  
在 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 与 Amazon S3 结合使用的更多信息，请参阅[使用具有 AWS KMS 密钥的服务器端加密（SSE-KMS）](UsingKMSEncryption.md)。有关使用 DSSE-KMS 的更多信息，请参阅[使用具有 AWS KMS 密钥的双层服务器端加密（DSSE-KMS）](UsingDSSEncryption.md)。

   1. 将存储桶配置为使用 SSE-KMS 进行默认加密时，您还可以启用 S3 存储桶密钥。S3 存储桶密钥可通过减少从 Amazon S3 到 AWS KMS 的请求流量，降低加密成本。有关更多信息，请参阅 [使用 Amazon S3 存储桶密钥降低 SSE-KMS 的成本](bucket-key.md)。

      要使用 S3 存储桶密钥，请在 **Bucket Key**（存储桶密钥）下，选择 **Enable**（启用）。
**注意**  
DSSE-KMS 不支持 S3 存储桶密钥。

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

## 使用 AWS CLI
<a name="default-bucket-encryption-cli"></a>

这些示例说明如何使用 SSE-S3 或将 SSE-KMS 与 S3 存储桶密钥结合使用来配置默认加密。

有关默认加密的更多信息，请参阅[为 Amazon S3 存储桶设置默认服务器端加密行为](bucket-encryption.md)。有关使用 AWS CLI 配置默认加密的更多信息，请参阅 [put-bucket-encryption](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/put-bucket-encryption.html)。

**Example – 使用 SSE-S3 进行默认加密**  
此示例使用 Amazon S3 托管密钥来配置默认存储桶加密。  

```
aws s3api put-bucket-encryption --bucket amzn-s3-demo-bucket --server-side-encryption-configuration '{
    "Rules": [
        {
            "ApplyServerSideEncryptionByDefault": {
                "SSEAlgorithm": "AES256"
            }
        }
    ]
}'
```

**Example – 使用 S3 存储桶密钥通过 SSE-KMS 进行默认加密**  
此示例使用 S3 存储桶密钥通过 SSE-KMS 配置默认存储桶加密。  

```
aws s3api put-bucket-encryption --bucket amzn-s3-demo-bucket --server-side-encryption-configuration '{
    "Rules": [
            {
                "ApplyServerSideEncryptionByDefault": {
                    "SSEAlgorithm": "aws:kms",
                    "KMSMasterKeyID": "KMS-Key-ARN"
                },
                "BucketKeyEnabled": true
            }
        ]
    }'
```

## 使用 REST API
<a name="bucket-encryption-how-to-set-up-api"></a>

使用 REST API `PutBucketEncryption` 操作可启用默认加密，并设置要使用的服务器端加密类型：SSE-S3、SSE-KMS 或 DSSE-KMS。

有关更多信息，请参阅《Amazon Simple Storage Service API 参考》**中的 [https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketPUTencryption.html](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketPUTencryption.html)。

# 使用 AWS CloudTrail 和 Amazon EventBridge 监控默认加密
<a name="bucket-encryption-tracking"></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)。

您可以使用 AWS CloudTrail 事件跟踪 Amazon S3 存储桶的默认加密配置请求。CloudTrail 日志中使用以下 API 事件名称：
+ `PutBucketEncryption`
+ `GetBucketEncryption`
+ `DeleteBucketEncryption`

您还可以创建 EventBridge 规则，以匹配这些 API 调用的 CloudTrail 事件。有关 CloudTrail 事件的更多信息，请参阅[使用控制台为存储桶中的对象启用日志记录功能](enable-cloudtrail-logging-for-s3.md#enable-cloudtrail-events)。有关 EventBridge 事件的更多信息，请参阅 [AWS 服务中的事件](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-service-event.html)。

您可以使用 CloudTrail 日志执行对象级 Amazon S3 操作，以跟踪向 Amazon S3 发出的 `PUT` 和 `POST` 请求。您可以使用这些操作来验证在传入 `PUT` 请求不包含加密标头时是否使用默认加密来加密对象。

当 Amazon S3 使用默认加密设置来加密对象时，日志将包含以下字段之一作为名称/值对：`"SSEApplied":"Default_SSE_S3"`、`"SSEApplied":"Default_SSE_KMS"` 或 `"SSEApplied":"Default_DSSE_KMS"`。

当 Amazon S3 使用 `PUT` 加密标头来加密对象时，日志将包含以下字段之一作为名称/值对：`"SSEApplied":"SSE_S3"`、`"SSEApplied":"SSE_KMS"`、`"SSEApplied":"DSSE_KMS"` 或 `"SSEApplied":"SSE_C"`。

对于分段上传，该信息包含在 `InitiateMultipartUpload` API 操作请求中。有关使用 CloudTrail 和 CloudWatch 的更多信息，请参阅[Amazon S3 中的日志记录和监控](monitoring-overview.md)。

# 默认加密常见问题解答
<a name="default-encryption-faq"></a>

Amazon S3 现在将具有 Amazon S3 托管密钥的服务器端加密（SSE-S3）作为 Amazon S3 中每个存储桶的基本加密级别。从 2023 年 1 月 5 日起，上传到 Amazon S3 的所有新对象都将自动加密，不会产生额外费用，也不会影响性能。使用 256 位高级加密标准（AES-256）的 SSE-S3 会自动应用于所有新存储桶和任何尚未配置默认加密的现有 S3 存储桶。S3 存储桶默认加密配置和上传的新对象的自动加密状态可在 AWS CloudTrail 日志、S3 清单、S3 Storage Lens 存储统计管理工具、Amazon S3 控制台中获得，并可用作 AWS Command Line Interface（AWS CLI）和 AWS SDK 中的附加 Amazon S3 API 响应标头。

以下各部分回答了有关此更新的问题。

**Amazon S3 会更改已配置了默认加密的现有存储桶的默认加密设置吗？**  
不会。对于已配置 SSE-S3 或具有 AWS Key Management Service（AWS KMS）密钥的服务器端加密（SSE-KMS）的现有存储桶的默认加密配置，不会发生任何更改。有关如何设置存储桶的默认加密行为的更多信息，请参阅[为 Amazon S3 存储桶设置默认服务器端加密行为](bucket-encryption.md)。有关 SSE-S3 和 SSE-KMS 加密设置的更多信息，请参阅[使用服务器端加密保护数据](serv-side-encryption.md)。

**是否会在未配置默认加密的现有存储桶上启用默认加密？**  
可以。Amazon S3 现在在所有现有未加密的存储桶上配置默认加密，以应用具有 Amazon S3 托管密钥的服务器端加密（SSE-S3），作为对上传到这些存储桶的新对象的基本加密级别。已在现有未加密存储桶中的对象不会自动加密。

**如何查看新对象上传的默认加密状态？**  
目前，您可以在 AWS CloudTrail 日志、S3 清单、S3 Storage Lens 存储统计管理工具、Amazon S3 控制台中查看新上传的对象的默认加密状态，并可将其作为 AWS Command Line Interface（AWS CLI）和 AWS SDK 中的附加 Amazon S3 API 响应标头。
+ 要查看您的 CloudTrail 事件，请参阅《AWS CloudTrail 用户指南》**中的[在 CloudTrail 控制台中查看 CloudTrail 事件](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/view-cloudtrail-events-console.html)。CloudTrail 日志为针对 Amazon S3 的 `PUT` 和 `POST` 请求提供 API 跟踪。当使用默认加密来加密存储桶中的对象时，关于 `PUT` 和 `POST` API 请求的 CloudTrail 日志将包含以下字段作为名称/值对：`"SSEApplied":"Default_SSE_S3"`。
+ 要查看 S3 清单中新对象上传的自动加密状态，请将 S3 清单报告配置为包含 **Encryption**（加密）元数据字段，然后在报告中查看每个新对象的加密状态。有关更多信息，请参阅[设置 Amazon S3 清单](https://docs.aws.amazon.com/AmazonS3/latest/userguide/configure-inventory.html#storage-inventory-setting-up)。
+ 要在 S3 Storage Lens 存储统计管理工具中查看新对象上传的自动加密状态，请配置 S3 Storage Lens 存储统计管理工具控制面板，并在控制面板的 **Data protection**（数据保护）类别中查看 **Encrypted bytes**（加密字节数）和 **Encrypted object count**（加密对象计数）指标。有关更多信息，请参阅[使用 S3 控制台](storage_lens_creating_dashboard.md#storage_lens_console_creating)和[在控制面板上查看 S3 Storage Lens 存储统计管理工具指标](storage_lens_view_metrics_dashboard.md)。
+ 要在 Amazon S3 控制台中查看存储桶级别的自动加密状态，请在 Amazon S3 控制台中查看 Amazon S3 存储桶的**默认加密**。有关更多信息，请参阅 [配置默认加密](default-bucket-encryption.md)。
+ 要在 AWS Command Line Interface（AWS CLI）和 AWS SDK 中将自动加密状态作为附加 Amazon S3 API 响应标头来查看，请在使用对象操作 API（如 [PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html) 和 [GetObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html)）时检查响应标头 `x-amz-server-side-encryption`。

**我需要做什么才能利用这一更改？**  
您无需对现有应用程序进行任何更改。由于针对您的所有存储桶都启用了默认加密，因此上传到 Amazon S3 的所有新对象都会自动加密。

**我能否对正写入我的存储桶的新对象禁用加密？**  
不能。SSE-S3 是新的基本加密级别，适用于上传到您的存储桶的所有新对象。您无法再为新对象上传禁用加密。

**我的费用会受到影响吗？**  
不会。使用 SSE-S3 进行默认加密不会产生额外的成本。像往常一样，将向您收取存储、请求和其他 S3 特征的费用。有关定价信息，请参阅 [Amazon S3 定价](https://aws.amazon.com/s3/pricing/)。

**Amazon S3 会加密我现有的未加密对象吗？**  
不会。从 2023 年 1 月 5 日开始，Amazon S3 仅自动加密新上传的对象。要加密现有对象，您可以使用 S3 批量操作创建对象的加密副本。这些加密副本将保留现有的对象数据和名称，并将使用您指定的加密密钥进行加密。有关更多详细信息，请参阅 *AWS 存储博客*中的 [Encrypting objects with Amazon S3 Batch Operations](https://aws.amazon.com/blogs/storage/encrypting-objects-with-amazon-s3-batch-operations/)（使用 Amazon S3 批量操作加密对象）。

**在此版本之前，我没有为我的存储桶启用加密。我需要更改访问对象的方式吗？**  
不需要。使用 SSE-S3 进行默认加密，在将您的数据写入 Amazon S3 时会自动加密这些数据，并在您访问时解密这些数据。访问自动加密的对象的方式没有变化。

**我需要更改访问客户端加密的对象的方式吗？**  
不需要。所有在上传到 Amazon S3 之前经过加密的客户端加密对象都作为 Amazon S3 中已加密的加密文字对象到达。这些对象现在将具有额外的 SSE-S3 加密层。使用客户端加密对象的工作负载不要求对客户端服务或授权设置进行任何更改。

**注意**  
未使用 AWS 提供者的已更新版本的 HashiCorp Terraform 用户在创建没有客户定义的加密配置的新 S3 存储桶后，可能会看到意想不到的偏差。为避免这种偏差，请将您的 Terraform AWS 提供者版本更新为以下版本之一：任何 4.x 发行版、3.76.1 或 2.70.4。

# 更新现有数据的服务器端加密
<a name="update-sse-encryption"></a>

默认情况下，所有 Amazon S3 存储桶都配置了加密，并且通过具有 Amazon S3 托管密钥的服务器端加密（SSE-S3）来自动加密对象。此默认加密设置适用于 Amazon S3 存储桶中的所有新对象。

使用 `UpdateObjectEncryption` API 操作，您能够以原子方式更新通用存储桶中现有加密对象的服务器端加密类型，即从具有 Amazon S3 托管式密钥的服务器端加密（SSE-S3）更改为具有 AWS Key Management Service（AWS KMS）密钥的服务器端加密（SSE-KMS）。`UpdateObjectEncryption` API 操作使用[信封加密](https://docs.aws.amazon.com/kms/latest/developerguide/kms-cryptography.html#enveloping)，以使用新指定的服务器端加密类型来重新加密用于加密和解密对象的数据密钥。

Amazon S3 在不移动任何数据的情况下执行此加密类型更新。换句话说，当您使用 `UpdateObjectEncryption` 操作时，不会复制您的数据，S3 Glacier Flexible Retrieval 或 S3 Glacier Deep Archive 中的已归档对象不会恢复，S3 Intelligent-Tiering 存储类别中的对象也不会在层之间移动。此外，`UpdateObjectEncryption` 操作会保留所有对象元数据属性，包括存储类别、创建日期、上次修改日期、ETag 以及校验和属性。

通用存储桶支持的所有 S3 存储类别都支持 `UpdateObjectEncryption` 操作。您可以使用 `UpdateObjectEncryption` 操作来执行以下操作：
+ 将加密的对象从具有 Amazon S3 托管式密钥的服务器端加密（SSE-S3）更改为具有 AWS Key Management Service（AWS KMS）加密密钥的服务器端加密（SSE-KMS）。
+ 更新对象级 SSE-KMS 加密对象以使用 S3 存储桶密钥，这会减少从 Amazon S3 到 AWS KMS 的 AWS KMS 请求流量。有关更多信息，请参阅 [使用 Amazon S3 存储桶密钥降低 SSE-KMS 的成本](bucket-key.md)。
+ 更改用于加密数据的客户自主管理型 KMS 密钥，这样您就可以遵守自定义密钥轮换标准。

**注意**  
此操作不支持未加密的对象，也不支持使用具有 AWS KMS keys的双层服务器端加密（DSSE-KMS）或客户提供的加密密钥（SSE-C）进行加密的对象。

无论对象的大小或存储类别（包括 S3 Glacier Flexible Retrieval 或 S3 Glacier Deep Archive）如何，`UpdateObjectEncryption` 操作通常都会在数毫秒内完成。此操作不算作对 S3 Intelligent-Tiering 的访问，因此，如果您更改对象的服务器端加密类型，不频繁访问层或归档即时访问层中的对象将不会自动分层回到频繁访问层。

`UpdateObjectEncryption` 是一种对象级（数据面板）API 操作，已记录到 Amazon S3 服务器访问日志和 AWS CloudTrail 数据事件中。有关更多信息，请参阅 [Amazon S3 的日志记录选项](logging-with-S3.md)。

 `UpdateObjectEncryption` 操作的定价与 `PUT`、`COPY`、`POST` 和 `LIST` 请求相同（每 1000 个请求），并且无论底层对象的存储类别如何，均始终按照 S3 Standard 存储类别请求收费。有关更多信息，请参阅 [Amazon S3 定价](https://aws.amazon.com/s3/pricing/)。

## 限制和注意事项
<a name="update-sse-encryption-restrictions"></a>

当您使用 `UpdateObjectEncryption` 操作时，以下限制和注意事项适用：
+ `UpdateObjectEncryption` 操作不支持未加密的对象，也不支持使用具有 AWS KMS keys 的双层服务器端加密（DSSE-KMS）或客户提供的加密密钥（SSE-C）进行加密的对象。此外，您不能指定 SSE-S3 作为所请求的新加密类型 `UpdateObjectEncryption` 请求。
+ 您可以使用 `UpdateObjectEncryption` 操作来更新存储桶中启用了 S3 版本控制的对象。要更新特定版本的加密类型，您必须在 `UpdateObjectEncryption` 请求中指定版本 ID。如果未指定版本 ID，则 `UpdateObjectEncryption` 请求作用于对象的当前版本。有关 S3 版本控制的更多信息，请参阅[使用 S3 版本控制保留对象的多个版本](Versioning.md)。
+ `UpdateObjectEncryption` 操作对任何应用了 S3 对象锁定保留模式或法定保留的对象都将失败。如果某个对象具有治理模式保留期或法定保留，则在发出 `UpdateObjectEncryption` 请求之前，必须先移除该对象的对象锁定状态。您不能对应用了对象锁定合规模式保留期的对象使用 `UpdateObjectEncryption` 操作。有关 S3 对象锁定的更多信息，请参阅 [使用对象锁定以锁定对象](object-lock.md)。
+ 启用了实时复制功能的源存储桶上的 `UpdateObjectEncryption` 请求不会在目标存储桶中启动副本事件。如果要更改源存储桶和目标存储桶中对象的加密类型，则必须对源存储桶和目标存储桶中的对象发起单独的 `UpdateObjectEncryption` 请求。
+ 默认情况下，所有指定客户自主管理型 KMS 密钥的 `UpdateObjectEncryption` 请求都仅限于存储桶所有者的 AWS 账户拥有的 KMS 密钥。如果您正在使用 AWS Organizations，则可以通过联系 AWS 支持 来请求使用组织内其它成员账户拥有的 AWS KMS keys的能力。
+ 如果您使用 S3 批量复制来跨区域复制数据集，并且您的对象之前已将其服务器端加密类型从 SSE-S3 更新为 SSE-KMS，则您可能需要额外的权限。在源区域存储桶上，您必须拥有 `kms:decrypt` 权限。然后，您将需要针对目标区域中存储桶的 `kms:decrypt` 和 `kms:encrypt` 权限。
+ 您必须在您的 `UpdateObjectEncryption` 请求中提供完整的 KMS 密钥 ARN。您不能使用别名名称或别名 ARN。您可以在 AWS KMS 控制台中或使用 AWS KMS `DescribeKey` API 确定完整的 KMS 密钥 ARN。

## 所需的权限
<a name="update-sse-encryption-permissions"></a>

要执行 `UpdateObjectEncryption` 操作，您必须拥有以下权限：
+ `s3:PutObject`
+ `s3:UpdateObjectEncryption`
+ `kms:Encrypt`
+ `kms:Decrypt`
+ `kms:GenerateDataKey`
+ `kms:ReEncrypt*`

如果您正在使用 AWS Organizations，则要将此操作与组织内其它 AWS 账户提供的客户管理型 KMS 密钥结合使用，您必须具有 `organizations:DescribeAccount` 权限。还可以通过联系 AWS 支持 来请求使用组织内其它成员账户拥有的 AWS KMS keys的能力。

要执行 `UpdateObjectEncryption` 操作，请将以下 AWS Identity and Access Management（IAM）策略添加到您的 IAM 角色。要使用此策略，请将 `amzn-s3-demo-bucket` 替换为通用存储桶的名称，并将另一个 `user input placeholders` 替换为您自己的信息。

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [{
            "Sid": "AllowUpdateObjectEncryption",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:UpdateObjectEncryption",
                "kms:Encrypt",
                "kms:Decrypt",
                "kms:GenerateDataKey",
                "kms:ReEncrypt*",
                "organizations:DescribeAccount"
            ],
            "Resource": [
                "arn:aws:s3:::amzn-s3-demo-bucket",
                "arn:aws:s3:::amzn-s3-demo-bucket/*",
                "arn:aws:kms:us-east-1:111122223333:key/01234567-89ab-cdef-0123-456789abcdef"
            ]
        }
    ]
}
```

## 批量更新加密
<a name="update-sse-encryption-bulk"></a>

要使用单个请求更新多个 Amazon S3 对象的服务器端加密类型，您可以使用 S3 批量操作。您可以为 S3 批量操作提供要操作的对象列表，也可以指示批量操作生成基于对象列表的对象元数据，包括前缀、存储类别、创建日期、加密类型、KMS 密钥 ARN 或 S3 存储桶密钥状态。S3 批量操作调用相应的 API 操作来执行指定的操作。单个批量操作作业可对包含 PB 级数据的存储桶中的数十亿个对象执行指定的操作。有关批处理操作的更多信息，请参阅[使用批量操作批量执行对象操作](batch-ops.md)。

S3 批量操作特征包括跟踪进度、发送通知并存储所有操作的详细完成报告，从而提供完全托管、可审核的无服务器体验。可以通过 Amazon S3 控制台、AWS Command Line Interface（AWS CLI）、AWS SDK 或 Amazon S3 REST API 使用 S3 批量操作。有关更多信息，请参阅 [更新对象加密](batch-ops-update-encryption.md)。

## 更新对象的加密
<a name="update-sse-encryption-single-object"></a>

您可以通过 AWS Command Line Interface（AWS CLI）、AWS SDK 或 Amazon S3 REST API 更新对象的服务器端加密类型。

### 更新对象的加密
<a name="update-sse-encryption-single-object-procedure"></a>

#### 使用 AWS CLI
<a name="update-sse-encryption-single-object-cli"></a>

要运行以下命令，您必须安装并配置 AWS CLI。如果未安装 AWS CLI，请参阅《AWS Command Line Interface 用户指南》**中的[安装或更新最新版本的 AWS CLI](https://docs.aws.amazon.com//cli/latest/userguide/getting-started-install.html)。

或者，可以从控制台中使用 AWS CloudShell 运行 AWS CLI 命令。AWS CloudShell 是一个基于浏览器、预先经过身份验证的 Shell，您可以直接从 AWS 管理控制台中启动它。有关更多信息，请参阅《AWS CloudShell 用户指南》**中的 [What is CloudShell?](https://docs.aws.amazon.com//cloudshell/latest/userguide/welcome.html) 和 [Getting started with AWS CloudShell](https://docs.aws.amazon.com//cloudshell/latest/userguide/getting-started.html)。

**使用 AWS CLI 更新对象的加密**

要使用以下示例命令，请将 `user input placeholders` 替换为您自己的信息。

1. 使用以下命令更新通用存储桶（例如 `amzn-s3-demo-bucket`）中单个对象 (`index.html`) 的加密，以便将 SSE-KMS 与 S3 存储桶密钥结合使用：

   ```
   aws s3api update-object-encryption \
   --bucket amzn-s3-demo-bucket \
   --key index.html \
   --object-encryption '{"SSEKMS": { "KMSKeyArn": "arn:aws:kms:us-east-1:111122223333:key/f12a345a-678e-9bbb-1025-62e317037583", "BucketKeyEnabled": true }}'
   ```
**注意**  
您必须指定完整的 AWS KMS key Amazon 资源名称（ARN）。不支持 KMS 密钥 ID 和 KMS 密钥别名。

1. 运行 `head-object` 命令以查看对象的更新加密类型：

   ```
   aws s3api head-object --bucket amzn-s3-demo-bucket --key index.html
   ```

#### 使用 REST API
<a name="update-sse-encryption-single-object-rest-api"></a>

您可以发送 REST 请求以更新对象的加密。有关更多信息，请参阅 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_UpdateObjectEncryption.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UpdateObjectEncryption.html)。

#### 使用 AWS SDK
<a name="update-sse-encryption-single-object-sdk"></a>

您可以使用 AWS SDK 来更新对象的加密。有关更多信息，请参阅[支持的 SDK 的列表](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UpdateObjectEncryption.html#API_UpdateObjectEncryption_SeeAlso)。

------
#### [ Java ]

**Example**  
以下 AWS SDK for Java 2.x 示例将通用存储桶中对象的加密类型更新为 SSE-KMS。  

```
    public void updateObjectEncryption(String bucketName,
                                       String objectKey,
                                       String versionId,
                                       String kmsKeyArn,
                                       boolean bucketKeyEnabled) {
        // Create the target object encryption type.
        ObjectEncryption objectEncryption = ObjectEncryption.builder()
                .ssekms(SSEKMSEncryption.builder()
                        .kmsKeyArn(kmsKeyArn)
                        .bucketKeyEnabled(bucketKeyEnabled)
                        .build())
                .build();

        // Create the UpdateObjectEncryption request.
        UpdateObjectEncryptionRequest request = UpdateObjectEncryptionRequest.builder()
                .bucket(bucketName)
                .key(objectKey)
                .versionId(versionId)
                .objectEncryption(objectEncryption)
                .build();

        // Update the object encryption.
        try {
            getS3Client().updateObjectEncryption(request);
            logger.info("Object encryption updated to SSE-KMS for {} in bucket {}", objectKey, bucketName);
        } catch (S3Exception e) {
            logger.error("Failed to update to object encryption: {} - Error code: {}", e.awsErrorDetails().errorMessage(),
                    e.awsErrorDetails().errorCode());
            throw e;
        }
    }
```

------
#### [ Python ]

**Example**  
以下 适用于 Python (Boto3) 的 AWS SDK 示例说明如何将通用存储桶中对象的加密类型更新为 SSE-KMS。  

```
response = client.update_object_encryption(
    Bucket='string',
    Key='string',
    VersionId='string',
    ObjectEncryption={
        'SSEKMS': {
                'KMSKeyArn': 'string',
                'BucketKeyEnabled': True|False
        }
    }
)
```

------

# 使用具有 Amazon S3 托管式密钥的服务器端加密（SSE-S3）
<a name="UsingServerSideEncryption"></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）进行加密。

服务器端加密可保护静态数据。Amazon S3 使用唯一的密钥来加密每个对象。作为额外的保护，它将使用定期轮换的密钥加密密钥本身。Amazon S3 服务器端加密使用 256 位高级加密标准 Galois/Counter 模式（AES-GCM）对所有上传的对象进行加密。

使用具有 Amazon S3 托管式密钥的服务器端加密（SSE-S3）不会产生额外费用。然而，请求配置默认加密特征会产生标准 Amazon S3 请求费用。有关定价的信息，请参阅 [Amazon S3 定价](https://aws.amazon.com/s3/pricing/)。

如果您要求仅使用 Amazon S3 托管密钥对上传的数据进行加密，则可以使用以下存储桶策略。例如，以下存储桶策略拒绝上传对象的权限，除非请求包含用于请求服务器端加密的 `x-amz-server-side-encryption` 标头：

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

****  

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

------

**注意**  
服务器端加密仅加密对象数据而非加密对象元数据。

## 服务器端加密的 API 支持
<a name="APISupportforServer-SideEncryption"></a>

默认情况下，所有 Amazon S3 存储桶都配置了加密，所有上传到 S3 存储桶的新对象都会自动静态加密。具有 Amazon S3 托管密钥的服务器端加密（SSE-S3）是 Amazon S3 中每个存储桶的默认加密配置。要使用其它类型的加密，您可以指定要在 S3 `PUT` 请求中使用的服务器端加密类型，也可以在目标存储桶中更新默认加密配置。

如果您想在 `PUT` 请求中指定不同的加密类型，则可以使用具有 AWS Key Management Service（AWS KMS）密钥的服务器端加密（SSE-KMS）、具有 AWS KMS 密钥的双层服务器端加密（DSSE-KMS）或具有客户提供的密钥的服务器端加密（SSE-C）。如果您想在目标存储桶中设置不同的默认加密配置，则可以使用 SSE-KMS 或 DSSE-KMS。

有关更改通用存储桶的默认加密配置的更多信息，请参阅[配置默认加密](default-bucket-encryption.md)。

在将存储桶的默认加密配置更改为 SSE-KMS 时，不会更改存储桶中现有 Amazon S3 对象的加密类型。要在将默认加密配置更新为 SSE-KMS 后更改先前存在对象的加密类型，可以使用 Amazon S3 批量操作。您为 S3 批量操作提供对象列表，而批量操作调用相应的 API 操作。可以使用 [复制对象](batch-ops-copy-object.md) 操作来复制现有对象，这会将这些对象写回到与 SSE-KMS 加密对象相同的存储桶中。单个批量操作作业可对数十亿个对象执行指定操作。有关更多信息，请参阅[使用批量操作批量执行对象操作](batch-ops.md)和 *AWS Storage Blog* 博客文章 [How to retroactively encrypt existing objects in Amazon S3 using S3 Inventory, Amazon Athena, and S3 Batch Operations](https://aws.amazon.com/blogs/security/how-to-retroactively-encrypt-existing-objects-in-amazon-s3-using-s3-inventory-amazon-athena-and-s3-batch-operations/)。

要使用对象创建 REST API 配置服务器端加密，必须提供 `x-amz-server-side-encryption` 请求标头。有关 REST API 的信息，请参阅 [使用 REST API](specifying-s3-encryption.md#SSEUsingRESTAPI)。

以下 Amazon S3 API 支持此标头：
+ **PUT 操作** - 在使用 `PUT` API 上传数据时指定请求标头。有关更多信息，请参阅 [PUT Object](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html)。
+ **启动分段上传** - 当使用分段上传 API 操作上传大型对象时，在启动请求中指定标头。有关更多信息，请参阅[启动分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadInitiate.html)。
+ **COPY 操作** - 在复制对象时，您同时具有源对象和目标对象。有关更多信息，请参阅 [PUT Object - 复制](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectCOPY.html)。

**注意**  
当使用 `POST` 操作上传对象时，请在表单字段中提供相同的信息，而不是提供请求标头。有关更多信息，请参阅 [POST 对象](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html)。

AWS SDK 还提供了一个可用于请求服务器端加密的包装程序 API。您还可以使用 AWS 管理控制台 来上传对象并请求服务器端加密。

有关更多常规信息，请参阅《AWS Key Management Service 开发人员指南》**中的 [AWS KMS 概念](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html)。

**Topics**
+ [服务器端加密的 API 支持](#APISupportforServer-SideEncryption)
+ [指定具有 Amazon S3 托管式密钥的服务器端加密（SSE-S3）](specifying-s3-encryption.md)

# 指定具有 Amazon S3 托管式密钥的服务器端加密（SSE-S3）
<a name="specifying-s3-encryption"></a>

默认情况下，所有 Amazon S3 存储桶都配置了加密，所有上传到 S3 存储桶的新对象都会自动静态加密。具有 Amazon S3 托管密钥的服务器端加密（SSE-S3）是 Amazon S3 中每个存储桶的默认加密配置。要使用其它类型的加密，您可以指定要在 S3 `PUT` 请求中使用的服务器端加密类型，也可以在目标存储桶中更新默认加密配置。

如果您想在 `PUT` 请求中指定不同的加密类型，则可以使用具有 AWS Key Management Service（AWS KMS）密钥的服务器端加密（SSE-KMS）、具有 AWS KMS 密钥的双层服务器端加密（DSSE-KMS）或具有客户提供的密钥的服务器端加密（SSE-C）。如果您想在目标存储桶中设置不同的默认加密配置，则可以使用 SSE-KMS 或 DSSE-KMS。

有关更改通用存储桶的默认加密配置的更多信息，请参阅[配置默认加密](default-bucket-encryption.md)。

在将存储桶的默认加密配置更改为 SSE-KMS 时，不会更改存储桶中现有 Amazon S3 对象的加密类型。要在将默认加密配置更新为 SSE-KMS 后更改先前存在对象的加密类型，可以使用 Amazon S3 批量操作。您为 S3 批量操作提供对象列表，而批量操作调用相应的 API 操作。可以使用 [复制对象](batch-ops-copy-object.md) 操作来复制现有对象，这会将这些对象写回到与 SSE-KMS 加密对象相同的存储桶中。单个批量操作作业可对数十亿个对象执行指定操作。有关更多信息，请参阅[使用批量操作批量执行对象操作](batch-ops.md)和 *AWS Storage Blog* 博客文章 [How to retroactively encrypt existing objects in Amazon S3 using S3 Inventory, Amazon Athena, and S3 Batch Operations](https://aws.amazon.com/blogs/security/how-to-retroactively-encrypt-existing-objects-in-amazon-s3-using-s3-inventory-amazon-athena-and-s3-batch-operations/)。

您可以使用 S3 控制台、REST API、AWS SDK 和 AWS Command Line Interface（AWS CLI）指定 SSE-S3。有关更多信息，请参阅 [为 Amazon S3 存储桶设置默认服务器端加密行为](bucket-encryption.md)。

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

本主题介绍如何使用 AWS 管理控制台设置或更改对象的加密类型。使用控制台复制对象时，Amazon S3 将按原样复制对象。这意味着，如果对源对象加密，则也会对目标对象加密。可以使用控制台添加或更改对象的加密。

**注意**  
如果对象小于 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. 在**加密类型**下，选择**具有 Amazon S3 托管式密钥的服务器端加密（SSE-S3）**。SSE-S3 使用最强的数据块密码之一 [即 256 位高级加密标准（AES-256）] 来加密每个对象。有关更多信息，请参阅 [使用具有 Amazon S3 托管式密钥的服务器端加密（SSE-S3）](UsingServerSideEncryption.md)。

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

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

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

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

创建对象时（即，上传新对象或复制现有对象时），您可以通过向请求添加 `x-amz-server-side-encryption` 标头来指定您是否希望 Amazon S3 使用 Amazon S3 托管式密钥（SSE-S3）加密您的数据。将标头的值设置为 Amazon S3 支持的加密算法 `AES256`。Amazon S3 通过返回响应标头 `x-amz-server-side-encryption` 来确认已使用 SSE-S3 存储对象。

以下 REST 上传 API 操作接受 `x-amz-server-side-encryption` 请求标头。
+ [PUT Object](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html)
+ [PUT Object – 复制](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectCOPY.html)
+ [POST 对象](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html)
+ [开始分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadInitiate.html)

使用分段上传 API 操作上传大型对象时，您可以通过为启动分段上传请求添加 `x-amz-server-side-encryption` 标头来指定服务器端加密。复制现有对象时，不论源对象是否已经加密，都不会加密目标对象，除非您显式请求服务器端加密。

使用 SSE-S3 加密存储对象后，以下 REST API 操作的响应标头将返回 `x-amz-server-side-encryption` 标头。
+ [PUT Object](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html)
+ [PUT Object – 复制](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectCOPY.html)
+ [POST 对象](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html)
+ [开始分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadInitiate.html)
+ [上传分段](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPart.html)
+ [上传分段 – 复制](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPartCopy.html)
+ [完成分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadComplete.html)
+ [GET Object](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectGET.html)
+ [HEAD Object](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectHEAD.html)

**注意**  
如果您的对象使用 SSE-S3，请不要发送 `GET` 请求和 `HEAD` 请求的加密请求标头，否则会收到 HTTP 状态代码 400（错误请求）错误。

## 使用 AWS SDK
<a name="s3-using-sdks"></a>

使用 AWS SDK 时，您可以请求 Amazon S3 使用具有 Amazon S3 托管式加密密钥的服务器端加密（SSE-S3）。这部分提供了以多种语言使用 AWS SDK 的示例。有关其他 SDK 的信息，请转到[示例代码和库](https://aws.amazon.com/code)。

------
#### [ Java ]

当您使用 适用于 Java 的 AWS SDK 上传对象时，可以使用 SSE-S3 为对象加密。要请求服务器端加密，请使用 `ObjectMetadata` 的 `PutObjectRequest` 属性设置 `x-amz-server-side-encryption` 请求标头。当您调用 `putObject()` 的 `AmazonS3Client` 方法时，Amazon S3 将加密并保存数据。

当使用分段上传 API 操作上传对象时，还可以请求 SSE-S3 加密：
+ 使用高级别分段上传 API 操作时，请在上传对象时使用 `TransferManager` 方法将服务器端加密应用于对象。可以使用将 `ObjectMetadata` 视为参数的任一上传方法。有关更多信息，请参阅 [使用分段上传操作上传对象](mpu-upload-object.md)。
+ 当使用低级别分段上传 API 操作时，应在启动分段上传时指定服务器端加密。您通过调用 `ObjectMetadata` 方法添加 `InitiateMultipartUploadRequest.setObjectMetadata()` 属性。有关更多信息，请参阅 [使用 AWS SDK（低级别 API）](mpu-upload-object.md#mpu-upload-low-level)。

不能直接更改对象的加密状态 (加密未加密的对象或解密已加密的对象)。要更改对象的加密状态，请为对象创建一个副本，从而为副本指定所需的加密状态，然后删除原始对象。仅当您显式请求服务器端加密时，Amazon S3 才会加密复制的对象。要通过 Java API 请求加密复制的对象，请使用 `ObjectMetadata` 属性在 `CopyObjectRequest` 中指定服务器端加密。

**Example 示例**  
以下示例演示如何使用 适用于 Java 的 AWS SDK 设置服务器端加密。它展示了如何执行以下任务：  
+ 使用 SSE-S3 上传新对象。
+ 通过为对象创建副本来更改对象的加密状态 (本示例中为加密之前未加密的对象)。
+ 检查对象的加密状态。
有关服务器端加密的更多信息，请参阅[使用 REST API](#SSEUsingRESTAPI)。有关创建和测试有效示例的说明，请参阅《适用于 Java 的 AWS SDK 开发人员指南》中的[入门](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/getting-started.html)。  

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.internal.SSEResultBase;
import com.amazonaws.services.s3.model.*;

import java.io.ByteArrayInputStream;

public class SpecifyServerSideEncryption {

    public static void main(String[] args) {
        Regions clientRegion = Regions.DEFAULT_REGION;
        String bucketName = "*** Bucket name ***";
        String keyNameToEncrypt = "*** Key name for an object to upload and encrypt ***";
        String keyNameToCopyAndEncrypt = "*** Key name for an unencrypted object to be encrypted by copying ***";
        String copiedObjectKeyName = "*** Key name for the encrypted copy of the unencrypted object ***";

        try {
            AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                    .withRegion(clientRegion)
                    .withCredentials(new ProfileCredentialsProvider())
                    .build();

            // Upload an object and encrypt it with SSE.
            uploadObjectWithSSEEncryption(s3Client, bucketName, keyNameToEncrypt);

            // Upload a new unencrypted object, then change its encryption state
            // to encrypted by making a copy.
            changeSSEEncryptionStatusByCopying(s3Client,
                    bucketName,
                    keyNameToCopyAndEncrypt,
                    copiedObjectKeyName);
        } catch (AmazonServiceException e) {
            // The call was transmitted successfully, but Amazon S3 couldn't process
            // it, so it returned an error response.
            e.printStackTrace();
        } catch (SdkClientException e) {
            // Amazon S3 couldn't be contacted for a response, or the client
            // couldn't parse the response from Amazon S3.
            e.printStackTrace();
        }
    }

    private static void uploadObjectWithSSEEncryption(AmazonS3 s3Client, String bucketName, String keyName) {
        String objectContent = "Test object encrypted with SSE";
        byte[] objectBytes = objectContent.getBytes();

        // Specify server-side encryption.
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentLength(objectBytes.length);
        objectMetadata.setSSEAlgorithm(ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION);
        PutObjectRequest putRequest = new PutObjectRequest(bucketName,
                keyName,
                new ByteArrayInputStream(objectBytes),
                objectMetadata);

        // Upload the object and check its encryption status.
        PutObjectResult putResult = s3Client.putObject(putRequest);
        System.out.println("Object \"" + keyName + "\" uploaded with SSE.");
        printEncryptionStatus(putResult);
    }

    private static void changeSSEEncryptionStatusByCopying(AmazonS3 s3Client,
            String bucketName,
            String sourceKey,
            String destKey) {
        // Upload a new, unencrypted object.
        PutObjectResult putResult = s3Client.putObject(bucketName, sourceKey, "Object example to encrypt by copying");
        System.out.println("Unencrypted object \"" + sourceKey + "\" uploaded.");
        printEncryptionStatus(putResult);

        // Make a copy of the object and use server-side encryption when storing the
        // copy.
        CopyObjectRequest request = new CopyObjectRequest(bucketName,
                sourceKey,
                bucketName,
                destKey);
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setSSEAlgorithm(ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION);
        request.setNewObjectMetadata(objectMetadata);

        // Perform the copy operation and display the copy's encryption status.
        CopyObjectResult response = s3Client.copyObject(request);
        System.out.println("Object \"" + destKey + "\" uploaded with SSE.");
        printEncryptionStatus(response);

        // Delete the original, unencrypted object, leaving only the encrypted copy in
        // Amazon S3.
        s3Client.deleteObject(bucketName, sourceKey);
        System.out.println("Unencrypted object \"" + sourceKey + "\" deleted.");
    }

    private static void printEncryptionStatus(SSEResultBase response) {
        String encryptionStatus = response.getSSEAlgorithm();
        if (encryptionStatus == null) {
            encryptionStatus = "Not encrypted with SSE";
        }
        System.out.println("Object encryption status is: " + encryptionStatus);
    }
}
```

------
#### [ .NET ]

在上传对象时，可指示 Amazon S3 加密对象。要更改现有对象的加密状态，请复制该对象并删除源对象。默认情况下，仅当您显式请求目标对象的服务器端加密时，复制操作才会加密目标。要在 `CopyObjectRequest` 中指定 SSE-S3，请添加以下内容：

```
 ServerSideEncryptionMethod = ServerSideEncryptionMethod.AES256
```

有关如何复制对象的有效示例，请参阅 [使用 AWS SDK](copy-object.md#CopyingObjectsUsingSDKs)。

以下示例将上传对象。在请求中，该示例指示 Amazon S3 加密对象。该示例随后检索对象元数据并验证使用的加密方法。有关设置和运行代码示例的信息，请参阅《适用于 .NET 的 AWS SDK 开发人员指南》**中的[适用于 .NET 的 AWS SDK 入门](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html)。

```
using Amazon;
using Amazon.S3;
using Amazon.S3.Model;
using System;
using System.Threading.Tasks;

namespace Amazon.DocSamples.S3
{
    class SpecifyServerSideEncryptionTest
    {
        private const string bucketName = "*** bucket name ***";
        private const string keyName = "*** key name for object created ***";
        // Specify your bucket region (an example region is shown).
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2;
        private static IAmazonS3 client;

        public static void Main()
        {
            client = new AmazonS3Client(bucketRegion);
            WritingAnObjectAsync().Wait();
        }

        static async Task WritingAnObjectAsync()
        {
            try
            {
                var putRequest = new PutObjectRequest
                {
                    BucketName = bucketName,
                    Key = keyName,
                    ContentBody = "sample text",
                    ServerSideEncryptionMethod = ServerSideEncryptionMethod.AES256
                };

                var putResponse = await client.PutObjectAsync(putRequest);

                // Determine the encryption state of an object.
                GetObjectMetadataRequest metadataRequest = new GetObjectMetadataRequest
                {
                    BucketName = bucketName,
                    Key = keyName
                };
                GetObjectMetadataResponse response = await client.GetObjectMetadataAsync(metadataRequest);
                ServerSideEncryptionMethod objectEncryption = response.ServerSideEncryptionMethod;

                Console.WriteLine("Encryption method used: {0}", objectEncryption.ToString());
            }
            catch (AmazonS3Exception e)
            {
                Console.WriteLine("Error encountered ***. Message:'{0}' when writing an object", e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
            }
        }
    }
}
```

------
#### [ PHP ]

本主题介绍如何使用 适用于 PHP 的 AWS SDK 版本 3 中的类来将 SSE-S3 添加到您上传到 Amazon S3 的对象。有关适用于 Ruby 的 AWS 开发工具包 API 的更多信息，请转到[适用于 Ruby 的 AWS 开发工具包 – 版本 2](https://docs.aws.amazon.com/sdkforruby/api/index.html)。

要将对象上传到 Amazon S3，请使用 [Aws\$1S3\$1S3Client::putObject()](https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-s3-2006-03-01.html#putobject) 方法。要将 `x-amz-server-side-encryption` 请求标头添加到您的上传请求，请使用值 `ServerSideEncryption` 指定 `AES256` 参数，如以下代码示例中所示。有关服务器端加密请求的信息，请参阅 [使用 REST API](#SSEUsingRESTAPI)。

```
 require 'vendor/autoload.php';

use Aws\S3\S3Client;

$bucket = '*** Your Bucket Name ***';
$keyname = '*** Your Object Key ***';

// $filepath should be an absolute path to a file on disk.
$filepath = '*** Your File Path ***';

$s3 = new S3Client([
    'version' => 'latest',
    'region'  => 'us-east-1'
]);

// Upload a file with server-side encryption.
$result = $s3->putObject([
    'Bucket'               => $bucket,
    'Key'                  => $keyname,
    'SourceFile'           => $filepath,
    'ServerSideEncryption' => 'AES256',
]);
```

作为响应，Amazon S3 会返回 `x-amz-server-side-encryption` 标头以及已用于加密对象数据的加密算法的值。

在使用分段上传 API 操作上传大型对象时，您可以为正在上传的对象指定 SSE-S3，如下所示：
+ 如果您使用低级别分段上传 API 操作，请在调用 [ Aws\$1S3\$1S3Client::createMultipartUpload()](https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-s3-2006-03-01.html#createmultipartupload) 方法时指定服务器端加密。要向请求添加 `x-amz-server-side-encryption` 请求标头，请使用值 `array` 指定 `ServerSideEncryption` 参数的 `AES256` 密钥。有关低级别分段上传 API 操作的更多信息，请参阅[使用 AWS SDK（低级别 API）](mpu-upload-object.md#mpu-upload-low-level)。
+ 当使用高级别分段上传 API 操作时，请使用 [CreateMultipartUpload](https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-s3-2006-03-01.html#createmultipartupload) API 操作的 `ServerSideEncryption` 参数来指定服务器端加密。有关将 `setOption()` 方法与高级别分段上传 API 操作结合使用的示例，请参阅[使用分段上传操作上传对象](mpu-upload-object.md)。

要确定现有对象的加密状态，请通过调用 [Aws\$1S3\$1S3Client::headObject()](https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-s3-2006-03-01.html#headobject) 方法检索对象元数据，如下面的 PHP 代码示例所示。

```
 require 'vendor/autoload.php';

use Aws\S3\S3Client;

$bucket = '*** Your Bucket Name ***';
$keyname = '*** Your Object Key ***';

$s3 = new S3Client([
    'version' => 'latest',
    'region'  => 'us-east-1'
]);

// Check which server-side encryption algorithm is used.
$result = $s3->headObject([
    'Bucket' => $bucket,
    'Key'    => $keyname,
]);
echo $result['ServerSideEncryption'];
```

要更改现有对象的加密状态，请使用 [Aws\$1S3\$1S3Client::copyObject()](https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-s3-2006-03-01.html#copyobject) 方法复制对象并删除源对象。默认情况下，`copyObject()` 不会加密目标，除非您通过将值 `AES256` 用于 `ServerSideEncryption` 参数，显式请求对目标对象进行服务器端加密。以下 PHP 代码示例将复制对象并向复制的对象添加服务器端加密。

```
 require 'vendor/autoload.php';

use Aws\S3\S3Client;

$sourceBucket = '*** Your Source Bucket Name ***';
$sourceKeyname = '*** Your Source Object Key ***';

$targetBucket = '*** Your Target Bucket Name ***';
$targetKeyname = '*** Your Target Object Key ***';

$s3 = new S3Client([
    'version' => 'latest',
    'region'  => 'us-east-1'
]);

// Copy an object and add server-side encryption.
$s3->copyObject([
    'Bucket'               => $targetBucket,
    'Key'                  => $targetKeyname,
    'CopySource'           => "$sourceBucket/$sourceKeyname",
    'ServerSideEncryption' => 'AES256',
]);
```

有关更多信息，请参阅以下主题：
+ [适用于 PHP 的 AWS SDK面向 Amazon S3 Aws\$1S3\$1S3Client 类的](https://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.S3.S3Client.html) 
+ [适用于 PHP 的 AWS SDK 文档](https://aws.amazon.com/documentation/sdk-for-php/)

------
#### [ Ruby ]

在使用 适用于 Ruby 的 AWS SDK 上传对象时，您可以指定使用 SSE-S3 对存储的对象进行静态加密。在您读回对象时，它将自动解密。

下面的 适用于 Ruby 的 AWS SDK 版本 3 示例演示了如何指定对上传到 Amazon S3 的文件进行静态加密。

```
require 'aws-sdk-s3'

# Wraps Amazon S3 object actions.
class ObjectPutSseWrapper
  attr_reader :object

  # @param object [Aws::S3::Object] An existing Amazon S3 object.
  def initialize(object)
    @object = object
  end

  def put_object_encrypted(object_content, encryption)
    @object.put(body: object_content, server_side_encryption: encryption)
    true
  rescue Aws::Errors::ServiceError => e
    puts "Couldn't put your content to #{object.key}. Here's why: #{e.message}"
    false
  end
end

# Example usage:
def run_demo
  bucket_name = "amzn-s3-demo-bucket"
  object_key = "my-encrypted-content"
  object_content = "This is my super-secret content."
  encryption = "AES256"

  wrapper = ObjectPutSseWrapper.new(Aws::S3::Object.new(bucket_name, object_content))
  return unless wrapper.put_object_encrypted(object_content, encryption)

  puts "Put your content into #{bucket_name}:#{object_key} and encrypted it with #{encryption}."
end

run_demo if $PROGRAM_NAME == __FILE__
```

下面的代码示例演示了如何确定现有对象的加密状态。

```
require 'aws-sdk-s3'

# Wraps Amazon S3 object actions.
class ObjectGetEncryptionWrapper
  attr_reader :object

  # @param object [Aws::S3::Object] An existing Amazon S3 object.
  def initialize(object)
    @object = object
  end

  # Gets the object into memory.
  #
  # @return [Aws::S3::Types::GetObjectOutput, nil] The retrieved object data if successful; otherwise nil.
  def object
    @object.get
  rescue Aws::Errors::ServiceError => e
    puts "Couldn't get object #{@object.key}. Here's why: #{e.message}"
  end
end

# Example usage:
def run_demo
  bucket_name = "amzn-s3-demo-bucket"
  object_key = "my-object.txt"

  wrapper = ObjectGetEncryptionWrapper.new(Aws::S3::Object.new(bucket_name, object_key))
  obj_data = wrapper.get_object
  return unless obj_data

  encryption = obj_data.server_side_encryption.nil? ? 'no' : obj_data.server_side_encryption
  puts "Object #{object_key} uses #{encryption} encryption."
end

run_demo if $PROGRAM_NAME == __FILE__
```

如果存储在 Amazon S3 中的对象没有使用服务器端加密，则该方法将返回 `null`。

要更改现有对象的加密状态，请复制该对象并删除源对象。默认情况下，复制方法不会加密目标，除非您明确请求服务器端加密。您可以通过在选项的哈希参数中指定 `server_side_encryption` 值来请求对目标对象进行加密，如下面的 Ruby 代码示例所示。此代码示例演示如何复制对象和使用 SSE-S3 加密副本。

```
require 'aws-sdk-s3'

# Wraps Amazon S3 object actions.
class ObjectCopyEncryptWrapper
  attr_reader :source_object

  # @param source_object [Aws::S3::Object] An existing Amazon S3 object. This is used as the source object for
  #                                        copy actions.
  def initialize(source_object)
    @source_object = source_object
  end

  # Copy the source object to the specified target bucket, rename it with the target key, and encrypt it.
  #
  # @param target_bucket [Aws::S3::Bucket] An existing Amazon S3 bucket where the object is copied.
  # @param target_object_key [String] The key to give the copy of the object.
  # @return [Aws::S3::Object, nil] The copied object when successful; otherwise, nil.
  def copy_object(target_bucket, target_object_key, encryption)
    @source_object.copy_to(bucket: target_bucket.name, key: target_object_key, server_side_encryption: encryption)
    target_bucket.object(target_object_key)
  rescue Aws::Errors::ServiceError => e
    puts "Couldn't copy #{@source_object.key} to #{target_object_key}. Here's why: #{e.message}"
  end
end

# Example usage:
def run_demo
  source_bucket_name = "amzn-s3-demo-bucket1"
  source_key = "my-source-file.txt"
  target_bucket_name = "amzn-s3-demo-bucket2"
  target_key = "my-target-file.txt"
  target_encryption = "AES256"

  source_bucket = Aws::S3::Bucket.new(source_bucket_name)
  wrapper = ObjectCopyEncryptWrapper.new(source_bucket.object(source_key))
  target_bucket = Aws::S3::Bucket.new(target_bucket_name)
  target_object = wrapper.copy_object(target_bucket, target_key, target_encryption)
  return unless target_object

  puts "Copied #{source_key} from #{source_bucket_name} to #{target_object.bucket_name}:#{target_object.key} and "\
       "encrypted the target with #{target_object.server_side_encryption} encryption."
end

run_demo if $PROGRAM_NAME == __FILE__
```

------

## 使用 AWS CLI
<a name="sse-s3-aws-cli"></a>

要在使用 AWS CLI 上传对象时指定 SSE-S3，请使用以下示例。

```
aws s3api put-object --bucket amzn-s3-demo-bucket1 --key object-key-name --server-side-encryption AES256  --body file path
```

有关更多信息，请参阅 *AWS CLI 参考*中的 [put-object](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/put-object.html)。要在使用 AWS CLI 复制对象时指定 SSE-S3，请参阅 [copy-object](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/copy-object.html)。

## 使用 CloudFormation
<a name="ss3-s3-cfn"></a>

有关使用 CloudFormation 设置加密的示例，请参阅《AWS CloudFormation 用户指南》**的 `AWS::S3::Bucket ServerSideEncryptionRule` 主题中的[使用默认加密创建存储桶](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-serversideencryptionrule.html#aws-properties-s3-bucket-serversideencryptionrule--examples--Create_a_bucket_with_default_encryption)和[通过 AWS KMS 服务器端加密使用 S3 存储桶密钥创建存储桶](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-serversideencryptionrule.html#aws-properties-s3-bucket-serversideencryptionrule--examples--Create_a_bucket_using_AWS_KMS_server-side_encryption_with_an_S3_Bucket_Key)示例。

# 使用具有 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)

# 使用 AWS KMS (SSE-KMS) 指定服务器端加密
<a name="specifying-kms-encryption"></a>

默认情况下，所有 Amazon S3 存储桶都配置了加密，所有上传到 S3 存储桶的新对象都会自动静态加密。具有 Amazon S3 托管密钥的服务器端加密（SSE-S3）是 Amazon S3 中每个存储桶的默认加密配置。要使用其它类型的加密，您可以指定要在 S3 `PUT` 请求中使用的服务器端加密类型，也可以在目标存储桶中更新默认加密配置。

如果您想在 `PUT` 请求中指定不同的加密类型，则可以使用具有 AWS Key Management Service（AWS KMS）密钥的服务器端加密（SSE-KMS）、具有 AWS KMS 密钥的双层服务器端加密（DSSE-KMS）或具有客户提供的密钥的服务器端加密（SSE-C）。如果您想在目标存储桶中设置不同的默认加密配置，则可以使用 SSE-KMS 或 DSSE-KMS。

有关更改通用存储桶的默认加密配置的更多信息，请参阅[配置默认加密](default-bucket-encryption.md)。

在将存储桶的默认加密配置更改为 SSE-KMS 时，不会更改存储桶中现有 Amazon S3 对象的加密类型。要在将默认加密配置更新为 SSE-KMS 后更改先前存在对象的加密类型，可以使用 Amazon S3 批量操作。您为 S3 批量操作提供对象列表，而批量操作调用相应的 API 操作。可以使用 [复制对象](batch-ops-copy-object.md) 操作来复制现有对象，这会将这些对象写回到与 SSE-KMS 加密对象相同的存储桶中。单个批量操作作业可对数十亿个对象执行指定操作。有关更多信息，请参阅[使用批量操作批量执行对象操作](batch-ops.md)和 *AWS Storage Blog* 博客文章 [How to retroactively encrypt existing objects in Amazon S3 using S3 Inventory, Amazon Athena, and S3 Batch Operations](https://aws.amazon.com/blogs/security/how-to-retroactively-encrypt-existing-objects-in-amazon-s3-using-s3-inventory-amazon-athena-and-s3-batch-operations/)。

您可以使用 Amazon S3 控制台、REST API 操作、AWS SDK 和 AWS Command Line Interface（AWS CLI）指定 SSE-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-kms"></a>

本主题描述如何使用 Amazon S3 控制台，将对象的加密类型设置或更改为使用具有 AWS Key Management Service（AWS KMS）密钥的服务器端加密（SSE-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. 在**加密设置**下，选择**使用默认加密的存储桶设置**或**覆盖默认加密的存储桶设置**。
**重要**  
如果您将 SSE-KMS 选项用于默认加密配置，则您将受到 AWS KMS 的每秒请求数（RPS）限额限制。有关 AWS KMS 限额以及如何请求增加限额的更多信息，请参阅《AWS Key Management Service 开发人员指南》**中的[限额](https://docs.aws.amazon.com/kms/latest/developerguide/limits.html)。

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

   1. 在**加密类型**下，选择**具有 AWS Key Management Service 密钥的服务器端加密（SSE-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. 在**其它复制设置**下，选择是要**复制源设置**、**请勿指定设置**还是**指定设置**。**复制源设置**是默认选项。如果您只想复制不带源设置属性的对象，请选择**请勿指定设置**。选择**指定设置**，来指定存储类、ACL、对象标签、元数据、服务器端加密和其它校验和的设置。

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

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

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

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

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

**Topics**
+ [支持 SSE-KMS 的 Amazon S3 REST API 操作](#sse-request-headers-kms)
+ [加密上下文（`x-amz-server-side-encryption-context`）](#s3-kms-encryption-context)
+ [AWS KMS 密钥 ID（`x-amz-server-side-encryption-aws-kms-key-id`）](#s3-kms-key-id-api)
+ [S3 桶密钥（`x-amz-server-side-encryption-aws-bucket-key-enabled`）](#bucket-key-api)

### 支持 SSE-KMS 的 Amazon S3 REST API 操作
<a name="sse-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` 操作传递 SSE-KMS 标头，这些标头仅应用于目标对象。复制现有对象时，不论源对象是否已加密，都不会对目标对象加密，除非您显式请求服务器端加密。
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html](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) – 使用分段上传 API 操作上传大型对象时，可以指定这些标头。您可以在 `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)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html](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` 请求，则这些请求都将失败。
如果对象使用 SSE-KMS，则不应对 `GET` 请求和 `HEAD` 请求发送加密请求标头，否则将显示 HTTP 400 BadRequest 错误。

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

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

Amazon S3 会自动使用对象或存储桶 Amazon Resource Name（ARN）作为加密上下文对。如果您在不启用 S3 存储桶密钥的情况下使用 SSE-KMS，则将对象 ARN 用作加密上下文；例如 `arn:aws:s3:::object_ARN`。但是，如果您使用 SSE-KMS 并启用 S3 存储桶密钥，则将存储桶 ARN 用于加密上下文；例如 `arn:aws:s3:::bucket_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-kms-key-id-api"></a>

您可以使用 `x-amz-server-side-encryption-aws-kms-key-id` 标头指定用于保护数据的客户自主管理型密钥的 ID。如果您指定 `x-amz-server-side-encryption:aws:kms` 标头但未提供 `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)。

### S3 桶密钥（`x-amz-server-side-encryption-aws-bucket-key-enabled`）
<a name="bucket-key-api"></a>

您可以使用 `x-amz-server-side-encryption-aws-bucket-key-enabled` 请求标头在对象级别启用或禁用 S3 存储桶密钥。S3 存储桶密钥通过减少从 Amazon S3 到 AWS KMS 的请求流量来降低您的 AWS KMS 请求成本。有关更多信息，请参阅 [使用 Amazon S3 存储桶密钥降低 SSE-KMS 的成本](bucket-key.md)。

如果您指定 `x-amz-server-side-encryption:aws:kms` 标头但未提供 `x-amz-server-side-encryption-aws-bucket-key-enabled` 标头，则您的对象将使用目标存储桶的 S3 存储桶密钥设置来加密对象。有关更多信息，请参阅 [在对象级别配置 S3 存储桶密钥](configuring-bucket-key-object.md)。

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

要使用以下示例 AWS CLI 命令，请将 `user input placeholders` 替换为您自己的信息。

当您上传新对象或复制现有对象时，可以指定使用具有 AWS KMS 密钥的服务器端加密来加密数据。为此，请将 `--server-side-encryption aws:kms` 标头添加到请求。使用 `--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`，但未提供 AWS KMS 密钥 ID，Amazon S3 将使用 AWS 托管式密钥。

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

此外，您还可以通过添加 `--bucket-key-enabled` 或 `--no-bucket-key-enabled` 在 PUT 或 COPY 操作中启用或禁用 Amazon S3 存储桶密钥。Amazon S3 存储桶密钥可以通过减少从 Amazon S3 到 AWS KMS 的请求流量来降低您的 AWS KMS 请求成本。有关更多信息，请参阅[使用 Amazon S3 存储桶密钥降低 SSE-KMS 的成本](https://docs.aws.amazon.com//AmazonS3/latest/userguide/bucket-key.html)。

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

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

```
aws s3api copy-object --bucket amzn-s3-demo-bucket --key example-object-key --body filepath --bucket amzn-s3-demo-bucket --key example-object-key --sse aws:kms --sse-kms-key-id example-key-id --body filepath
```

## 使用 AWS SDK
<a name="kms-using-sdks"></a>

使用 AWS SDK 时，您可以请求 Amazon S3 使用 AWS KMS keys 进行服务器端加密。以下示例展示了如何将 SSE-KMS 与适用于 Java 和 .NET 的 AWS SDK 结合使用。有关其它 SDK 的信息，请参阅 AWS 开发人员中心上的[示例代码和库](https://aws.amazon.com/code)。

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

### `CopyObject` 操作
<a name="kms-copy-operation"></a>

在复制对象时，您添加相同的请求属性（`ServerSideEncryptionMethod` 和 `ServerSideEncryptionKeyManagementServiceKeyId`）来请求 Amazon S3 使用 AWS KMS key。有关复制对象的更多信息，请参阅 [复制、移动和重命名对象](copy-object.md)。

### `PUT` 操作
<a name="kms-put-operation"></a>

------
#### [ Java ]

当使用适用于 Java 的 AWS SDK 上传对象时，您可以通过添加 `SSEAwsKeyManagementParams` 属性来请求 Amazon S3 使用 AWS KMS key，如以下请求所示：

```
PutObjectRequest putRequest = new PutObjectRequest(bucketName,
   keyName, file).withSSEAwsKeyManagementParams(new SSEAwsKeyManagementParams());
```

在这种情况下，Amazon S3 使用 AWS 托管式密钥（`aws/s3`）。有关更多信息，请参阅 [使用具有 AWS KMS 密钥的服务器端加密（SSE-KMS）](UsingKMSEncryption.md)。您可以选择创建对称加密 KMS 密钥，并在请求中指定该密钥，如以下示例所示：

```
PutObjectRequest putRequest = new PutObjectRequest(bucketName,
   keyName, file).withSSEAwsKeyManagementParams(new SSEAwsKeyManagementParams(keyID));
```

有关创建客户托管密钥的更多信息，请参阅 *AWS Key Management Service 开发人员指南*中的[对 AWS KMS API 进行编程](https://docs.aws.amazon.com/kms/latest/developerguide/programming-top.html)。

有关上传对象的工作代码示例，请参阅以下主题。要使用这些示例，您必须更新这些代码示例并提供加密信息，如上述代码片段所示。
+ 有关在单个操作中上传对象，请参阅 [上传对象](upload-objects.md)。
+ 有关使用高级或低级分段上传 API 操作的分段上传，请参阅[使用分段上传操作上传对象](mpu-upload-object.md)。

------
#### [ .NET ]

当使用适用于 .NET 的 AWS SDK 上传对象时，您可以通过添加 `ServerSideEncryptionMethod` 属性来请求 Amazon S3 使用 AWS KMS key，如以下请求所示：

```
PutObjectRequest putRequest = new PutObjectRequest
 {
     BucketName = amzn-s3-demo-bucket,
     Key = keyName,
     // other properties
     ServerSideEncryptionMethod = ServerSideEncryptionMethod.AWSKMS
 };
```

在这种情况下，Amazon S3 使用 AWS 托管式密钥。有关更多信息，请参阅 [使用具有 AWS KMS 密钥的服务器端加密（SSE-KMS）](UsingKMSEncryption.md)。您可以选择创建自己的对称加密客户自主管理型密钥，并在请求中指定该密钥，如以下示例所示：

```
PutObjectRequest putRequest1 = new PutObjectRequest
{
  BucketName = amzn-s3-demo-bucket,
  Key = keyName,
  // other properties
  ServerSideEncryptionMethod = ServerSideEncryptionMethod.AWSKMS,
  ServerSideEncryptionKeyManagementServiceKeyId = keyId
};
```

有关创建客户托管密钥的更多信息，请参阅 *AWS Key Management Service 开发人员指南*中的[对 AWS KMS API 进行编程](https://docs.aws.amazon.com/kms/latest/developerguide/programming-top.html)。

有关上传对象的工作代码示例，请参阅以下主题。要使用这些示例，您必须更新这些代码示例并提供加密信息，如上述代码片段所示。
+ 有关在单个操作中上传对象，请参阅 [上传对象](upload-objects.md)。
+ 有关使用高级或低级分段上传 API 操作的分段上传，请参阅[使用分段上传操作上传对象](mpu-upload-object.md)。

------

### 预签名 URL
<a name="kms-presigned-urls"></a>

------
#### [ Java ]

在为使用 AWS KMS key加密的对象创建预签名 URL 时，您必须显式指定签名版本 4，如以下示例所示：

```
ClientConfiguration clientConfiguration = new ClientConfiguration();
clientConfiguration.setSignerOverride("AWSS3V4SignerType");
AmazonS3Client s3client = new AmazonS3Client(
        new ProfileCredentialsProvider(), clientConfiguration);
...
```

有关代码示例，请参阅 [使用预签名 URL 共享对象](ShareObjectPreSignedURL.md)。

------
#### [ .NET ]

在为使用 AWS KMS key加密的对象创建预签名 URL 时，您必须显式指定签名版本 4，如以下示例所示：

```
AWSConfigs.S3Config.UseSignatureVersion4 = true;
```

有关代码示例，请参阅 [使用预签名 URL 共享对象](ShareObjectPreSignedURL.md)。

------

# 使用 Amazon S3 存储桶密钥降低 SSE-KMS 的成本
<a name="bucket-key"></a>

Amazon S3 存储桶密钥降低了具有 AWS Key Management Service（AWS KMS）密钥的 Amazon S3 服务器端加密（SSE-KMS）的成本。使用 SSE-KMS 的存储桶级别密钥可以通过减少从 Amazon S3 到 AWS KMS 的请求流量，从而使您可以将 AWS KMS 请求成本最高降低 99%。只需在 AWS 管理控制台中单击几下，无需对客户端应用程序进行任何更改，您就可以将存储桶配置为使用 S3 存储桶密钥对新对象进行 SSE-KMS 加密。

**注意**  
使用 AWS Key Management Service（AWS KMS）密钥的双层服务器端加密（DSSE-KMS）不支持 S3 存储桶密钥。

## SSE-KMS 的 S3 存储桶密钥
<a name="bucket-key-overview"></a>

访问使用 SSE-KMS 加密的数百万或数十亿个对象的工作负载可以生成大量到 AWS KMS 的请求。当您在没有 S3 存储桶密钥的情况下使用 SSE-KMS 保护数据时，Amazon S3 会为每个对象使用单独的 AWS KMS [数据密钥](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#data-keys)。在这种情况下，每次对 KMS 加密的对象发出请求时，Amazon S3 都会调用 AWS KMS。有关 SSE-KMS 工作原理的信息，请参阅 [使用具有 AWS KMS 密钥的服务器端加密（SSE-KMS）](UsingKMSEncryption.md)。

当您将存储桶配置为使用 S3 存储桶密钥进行 SSE-KMS 加密时，AWS 会从 AWS KMS 生成生存期较短的存储桶级密钥，然后暂时将其保留在 S3 中。此存储桶级密钥将在新对象的生命周期中为其创建数据密钥。S3 存储桶密钥在 Amazon S3 内限时使用，从而减少了 S3 向 AWS KMS 发出请求以完成加密操作的需求。这样可以减少从 S3 到 AWS KMS 的流量，使您能够在 Amazon S3 中访问 AWS KMS 加密的对象，所需成本仅为以前的一小部分。

每个请求者至少获取一次唯一存储桶级密钥，以确保在 AWS KMS CloudTrail 事件中捕获请求者对密钥的访问权限。当调用方使用不同的角色或账户，或使用具有不同范围限定策略的相同角色时，Amazon S3 会将其视为不同的请求者。AWS KMS 节省的请求反映了请求者的数量、请求模式和所请求对象的相对年限。例如，减少请求者数量，在有限的时间窗口内请求多个对象，并使用相同的存储桶级密钥进行加密，可以节省更多费用。

**注意**  
利用 S3 存储桶密钥，可通过使用桶级密钥减少向 AWS KMS 发出的面向 `Encrypt`、`GenerateDataKey` 和 `Decrypt` 操作的请求数，从而节省 AWS KMS 请求成本。根据设计，利用此存储桶级密钥的后续请求不会产生 AWS KMS API 请求或根据 AWS KMS 密钥策略验证访问权限。

配置 S3 存储桶密钥时，存储桶中已存在的对象不使用 S3 存储桶密钥。要为现有对象配置 S3 存储桶密钥，可以使用 `CopyObject` 操作。有关更多信息，请参阅 [在对象级别配置 S3 存储桶密钥](configuring-bucket-key-object.md)。

Amazon S3 将仅为由同一 AWS KMS key 加密的对象共享 S3 存储桶密钥。S3 存储桶密钥与 AWS KMS 创建的 KMS 密钥、[导入的密钥材料](https://docs.aws.amazon.com/kms/latest/developerguide/importing-keys.html)以及[由自定义密钥存储库支持的密钥材料](https://docs.aws.amazon.com/kms/latest/developerguide/custom-key-store-overview.html)兼容。

![\[图中显示了 AWS KMS 生成的存储桶密钥，该密钥为存储桶中的对象创建数据密钥。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/S3-Bucket-Keys.png)


## 配置 S3 存储桶密钥
<a name="configure-bucket-key"></a>

您可以通过 Amazon S3 控制台、AWS SDK、AWS CLI 或 REST API 将存储桶配置为使用 S3 存储桶密钥对新对象进行 SSE-KMS 加密。在您的存储桶上启用 S3 存储桶密钥后，使用其他指定 SSE-KMS 密钥上传的对象将使用其自己的 S3 存储桶密钥。无论您的 S3 存储桶密钥设置如何，您都可以在请求中包含带 `true` 或 `false` 值的 `x-amz-server-side-encryption-bucket-key-enabled` 标头，以覆盖存储桶设置。

在将存储桶配置为使用 S3 存储桶密钥之前，请查看 [启用 S3 存储桶密钥之前需要注意的更改](#bucket-key-changes)。

### 使用 Amazon S3 控制台配置 S3 存储桶密钥
<a name="configure-bucket-key-console"></a>

创建新存储桶时，您可以将存储桶配置为使用 S3 存储桶密钥对新对象进行 SSE-KMS 加密。您还可以通过更新存储桶属性，从而将现有存储桶配置为使用 S3 存储桶密钥对新对象进行 SSE-KMS 加密。 

有关更多信息，请参阅 [将存储桶配置为将 S3 存储桶密钥与 SSE-KMS 结合使用于新对象](configuring-bucket-key.md)。

### REST API、AWS CLI 和 AWS SDK 支持 S3 存储桶密钥
<a name="configure-bucket-key-programmatic"></a>

您可以使用 REST API、AWS CLI 或 AWS SDK 将存储桶配置为使用 S3 存储桶密钥对新对象进行 SSE-KMS 加密。您还可以在对象级别启用 S3 存储桶密钥。

有关更多信息，请参阅下列内容： 
+ [在对象级别配置 S3 存储桶密钥](configuring-bucket-key-object.md)
+ [将存储桶配置为将 S3 存储桶密钥与 SSE-KMS 结合使用于新对象](configuring-bucket-key.md)

以下 API 操作对于 SSE-KMS 支持 S3 存储桶密钥：
+ [PutBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html)
  + `ServerSideEncryptionRule` 接受用于启用和禁用 S3 存储桶密钥的 `BucketKeyEnabled` 参数。
+ [GetBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketEncryption.html)
  + `ServerSideEncryptionRule` 返回 的设置。`BucketKeyEnabled`
+ [PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html)、[CopyObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html)、[CreateMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html) 和 [POST 对象](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html)
  + `x-amz-server-side-encryption-bucket-key-enabled` 请求标头在对象级别启用或禁用 S3 存储桶密钥。
+ [HeadObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html)、[GetObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html)、[UploadPartCopy](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html)、[UploadPart](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html) 和 [CompleteMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html)
  + `x-amz-server-side-encryption-bucket-key-enabled` 响应标头指示是否为对象启用或禁用了 S3 存储桶密钥。

### 使用 CloudFormation
<a name="configure-bucket-key-cfn"></a>

在 CloudFormation 中，`AWS::S3::Bucket` 资源包括名为 `BucketKeyEnabled` 的加密属性，您可以使用该属性来启用或禁用 S3 存储桶密钥。

有关更多信息，请参阅 [使用 CloudFormation](configuring-bucket-key.md#enable-bucket-key-cloudformation)。

## 启用 S3 存储桶密钥之前需要注意的更改
<a name="bucket-key-changes"></a>

在启用 S3 存储桶密钥之前，请注意以下相关更改：

### IAM 或 AWS KMS 密钥策略
<a name="bucket-key-policies"></a>

如果您现有的 AWS Identity and Access Management（IAM）策略或 AWS KMS 密钥策略使用您的对象 Amazon 资源名称（ARN）作为加密上下文来优化或限制对 KMS 密钥的访问，则这些策略将不使用 S3 存储桶密钥。S3 存储桶密钥使用存储桶 ARN 作为加密上下文。在启用 S3 存储桶密钥之前，请更新 IAM 策略或 AWS KMS 密钥策略，以将存储桶 ARN 用作加密上下文。

有关加密上下文和 S3 存储桶密钥的更多信息，请参阅[加密上下文](UsingKMSEncryption.md#encryption-context)。

### AWS KMS 的 CloudTrail 事件
<a name="bucket-key-cloudtrail"></a>

启用 S3 存储桶密钥后，AWS KMS CloudTrail 事件会记录存储桶 ARN 而不是对象 ARN。此外，您在日志中看到的 SSE-KMS 对象的 KMS CloudTrail 事件较少。因为 Amazon S3 中的密钥材料是有时间限制的，所以对 AWS KMS 的请求减少。

## 将 S3 存储桶密钥与复制功能结合使用
<a name="bucket-key-replication"></a>

您可以将 S3 存储桶密钥与同区域复制（SRR）和跨区域复制（CRR）结合使用。

当 Amazon S3 复制加密对象时，它通常会在目标存储桶中保留副本对象的加密设置。但是，如果源对象未加密且目标存储桶使用默认加密或 S3 存储桶密钥，则 Amazon S3 会使用目标存储桶的配置加密对象。

以下示例说明了 S3 存储桶密钥如何与复制结合使用。有关更多信息，请参阅 [复制加密对象（SSE-S3、SSE-KMS、DSSE-KMS、SSE-C）](replication-config-for-kms-objects.md)。 

**Example 示例 1 – 源对象使用 S3 存储桶密钥；目标存储桶使用默认加密**  
如果源对象使用 S3 存储桶密钥，但目标存储桶将默认加密与 SSE-KMS 结合使用，则副本对象将在目标存储桶中维护其 S3 存储桶密钥加密设置。目标存储桶仍将默认加密与 SSE-KMS 结合使用。  


**Example 示例 2 – 源对象未加密；目标存储桶将 S3 存储桶密钥与 SSE-KMS 结合使用**  
如果源对象未加密，而目标存储桶将 S3 存储桶密钥与 SSE-KMS 结合使用，则将通过在目标存储桶中将 S3 存储桶密钥与 SSE-KMS 结合使用来加密复制的对象。这将导致源对象的 `ETag` 与副本对象的 `ETag` 不同。您必须更新使用 `ETag` 的应用程序以应对这种差异。

## 使用 S3 存储桶密钥
<a name="using-bucket-key"></a>

有关启用和使用 S3 存储桶密钥的更多信息，请参阅以下各部分：
+ [将存储桶配置为将 S3 存储桶密钥与 SSE-KMS 结合使用于新对象](configuring-bucket-key.md)
+ [在对象级别配置 S3 存储桶密钥](configuring-bucket-key-object.md)
+ [查看 S3 存储桶密钥的设置](viewing-bucket-key-settings.md)

# 将存储桶配置为将 S3 存储桶密钥与 SSE-KMS 结合使用于新对象
<a name="configuring-bucket-key"></a>

当您配置具有 AWS Key Management Service（AWS KMS）密钥的服务器端加密（SSE-KMS）时，您可以将存储桶配置为使用 S3 存储桶密钥对新对象进行 SSE-KMS 加密。S3 存储桶密钥可减少从 Amazon S3 到 AWS KMS 的请求流量，从而降低 SSE-KMS 的成本。有关更多信息，请参阅 [使用 Amazon S3 存储桶密钥降低 SSE-KMS 的成本](bucket-key.md)。

您可以使用 Amazon S3 控制台、REST API、AWS SDK、AWS Command Line Interface（AWS CLI）或 CloudFormation 将存储桶配置为使用 S3 存储桶密钥对新对象进行 SSE-KMS 加密。如果要为现有对象启用或禁用 S3 存储桶密钥，则可以使用 `CopyObject` 操作。有关更多信息，请参阅[在对象级别配置 S3 存储桶密钥](configuring-bucket-key-object.md)和[使用批量操作为 SSE-KMS 启用 S3 存储桶密钥](batch-ops-copy-example-bucket-key.md)。

当为源存储桶或目标存储桶启用 S3 存储桶密钥时，加密上下文将是存储桶 Amazon Resource Name（ARN），而不是对象 ARN，例如 `arn:aws:s3:::bucket_ARN`。您需要更新 IAM 策略才能将存储桶 ARN 用于加密上下文。有关更多信息，请参阅 [S3 存储桶密钥和复制](replication-config-for-kms-objects.md#bk-replication)。

以下示例说明了 S3 存储桶密钥如何与复制结合使用。有关更多信息，请参阅 [复制加密对象（SSE-S3、SSE-KMS、DSSE-KMS、SSE-C）](replication-config-for-kms-objects.md)。 

**先决条件**  
在将存储桶配置为使用 S3 存储桶密钥之前，请查看 [启用 S3 存储桶密钥之前需要注意的更改](bucket-key.md#bucket-key-changes)。

**Topics**

## 使用 S3 控制台
<a name="enable-bucket-key"></a>

在 S3 控制台中，您可以为新存储桶或现有存储桶启用或禁用 S3 存储桶密钥。S3 控制台中的对象从存储桶配置中继承其 S3 存储桶密钥设置。当您为存储桶启用 S3 存储桶密钥时，您上传到存储桶的新对象将利用 S3 存储桶密钥进行 SSE-KMS 加密。

**在启用了 S3 存储桶密钥的存储桶中上传，复制或修改对象**  
如果您在启用了 S3 存储桶密钥的存储桶中上传、修改或复制对象，则该对象的 S3 存储桶密钥设置可能会更新以与存储桶配置保持一致。

如果对象已启用 S3 存储桶密钥，则在复制或修改对象时，该对象的 S3 存储桶密钥设置不会更改。但是，如果您修改或复制未启用 S3 存储桶密钥的对象，并且目标存储桶具有 S3 存储桶密钥配置，则该对象将继承目标存储桶的 S3 存储桶密钥设置。例如，如果源对象尚未启用 S3 存储桶密钥，但目标存储桶已启用 S3 存储桶密钥，则为该对象启用 S3 存储桶密钥。

**在创建新存储桶时启用 S3 存储桶密钥**

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

1. 在左侧导航窗格中，选择**存储桶**。

1. 请选择 **Create bucket（创建存储桶）**。

1. 输入存储桶名称，然后选择您的 AWS 区域。

1. 在**默认加密**下，对于**加密密钥类型**，选择 **AWS Key Management Service 密钥（SSE-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)。

1. 在 **Bucket Key（存储桶密钥）**下，请选择 **Enable（启用）**。

1. 请选择 **Create bucket（创建存储桶）**。

   Amazon S3 创建启用了 S3 存储桶密钥的存储桶。您上传到存储桶的新对象将使用 S3 存储桶密钥。 

   要禁用 S3 存储桶密钥，请按照前面的步骤操作，然后选择 **Disable（禁用）**。

**为现有存储桶启用 S3 存储桶密钥**

1. 通过以下网址打开 Amazon S3 控制台：[https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/)。

1. 在左侧导航窗格中，选择**存储桶**。

1. 在 **Buckets（存储桶）**列表中，请选择要为其启用 S3 存储桶密钥的存储桶。

1. 选择**属性**选项卡。

1. 在**默认加密**下，选择**编辑**。

1. 在**默认加密**下，对于**加密密钥类型**，选择 **AWS Key Management Service 密钥（SSE-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)。

1. 在 **Bucket Key（存储桶密钥）**下，请选择 **Enable（启用）**。

1. 选择 **Save Changes**（保存更改）。

   Amazon S3 为添加到存储桶中的新对象启用 S3 存储桶密钥。现有对象未使用 S3 存储桶密钥。要为现有对象配置 S3 存储桶密钥，可以使用 `CopyObject` 操作。有关更多信息，请参阅 [在对象级别配置 S3 存储桶密钥](configuring-bucket-key-object.md)。

   要禁用 S3 存储桶密钥，请按照前面的步骤操作，然后选择 **Disable（禁用）**。

## 使用 REST API
<a name="enable-bucket-key-rest"></a>

您可以使用 [PutBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) 为存储桶启用或禁用 S3 存储桶密钥。要使用 `PutBucketEncryption` 配置 S3 存储桶密钥，请使用 [ServerSideEncryptionRule](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ServerSideEncryptionRule.html) 数据类型，其中包括使用 SSE-KMS 进行的默认加密。您还可以通过客户托管密钥的 KMS 密钥 ID 来选择使用客户托管密钥。  

有关更多信息和示例语法，请参阅 [ putbucKetenCryption ](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html)。

## 使用适用于 Java 的 AWS 软件开发工具包
<a name="enable-bucket-key-sdk"></a>

以下示例使用 适用于 Java 的 AWS SDK，通过 SSE-KMS 和 S3 存储桶密钥启用默认存储桶加密。

------
#### [ Java ]

```
AmazonS3 s3client = AmazonS3ClientBuilder.standard()
    .withRegion(Regions.DEFAULT_REGION)
    .build();
    
ServerSideEncryptionByDefault serverSideEncryptionByDefault = new ServerSideEncryptionByDefault()
    .withSSEAlgorithm(SSEAlgorithm.KMS);
ServerSideEncryptionRule rule = new ServerSideEncryptionRule()
    .withApplyServerSideEncryptionByDefault(serverSideEncryptionByDefault)
    .withBucketKeyEnabled(true);
ServerSideEncryptionConfiguration serverSideEncryptionConfiguration =
    new ServerSideEncryptionConfiguration().withRules(Collections.singleton(rule));

SetBucketEncryptionRequest setBucketEncryptionRequest = new SetBucketEncryptionRequest()
    .withServerSideEncryptionConfiguration(serverSideEncryptionConfiguration)
    .withBucketName(bucketName);
            
s3client.setBucketEncryption(setBucketEncryptionRequest);
```

------

## 使用 AWS CLI
<a name="enable-bucket-key-cli"></a>

以下示例使用 AWS CLI，通过 SSE-KMS 和 S3 存储桶密钥启用默认存储桶加密。将 `user input placeholders` 替换为您自己的信息。

```
aws s3api put-bucket-encryption --bucket amzn-s3-demo-bucket --server-side-encryption-configuration '{
        "Rules": [
            {
                "ApplyServerSideEncryptionByDefault": {
                    "SSEAlgorithm": "aws:kms",
                    "KMSMasterKeyID": "KMS-Key-ARN"
                },
                "BucketKeyEnabled": true
            }
        ]
    }'
```

## 使用 CloudFormation
<a name="enable-bucket-key-cloudformation"></a>

有关使用 CloudFormation 配置 S3 存储桶密钥的更多信息，请参阅《AWS CloudFormation 用户指南》**中的 [AWS::S3::Bucket ServerSideEncryptionRule](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-s3-bucket-serversideencryptionrule.html)。

# 在对象级别配置 S3 存储桶密钥
<a name="configuring-bucket-key-object"></a>

当您使用 REST API、AWS SDK 或 AWS CLI 执行 PUT 或 COPY 操作时，您可以通过添加带有 `true` 或 `false` 值的 `x-amz-server-side-encryption-bucket-key-enabled` 请求标头在对象级别启用或禁用 S3 存储桶密钥。S3 存储桶密钥通过减少从 Amazon S3 到 AWS KMS 的请求流量，降低了使用 AWS Key Management Service（AWS KMS）（SSE-KMS）进行服务器端加密的成本。有关更多信息，请参阅 [使用 Amazon S3 存储桶密钥降低 SSE-KMS 的成本](bucket-key.md)。

当您使用 PUT 或 COPY 操作为对象配置 S3 存储桶密钥时，Amazon S3 仅更新该对象的设置。目标存储桶的 S3 存储桶密钥设置不会更改。如果您在启用了 S3 存储桶密钥的存储桶中提交对于 KMS 加密对象的 PUT 或 COPY 请求，则除非您禁用了请求标头中的密钥，否则您的对象级操作将自动使用 S3 存储桶密钥。如果您未为对象指定 S3 存储桶密钥，则 Amazon S3 会将目标存储桶的 S3 存储桶密钥设置应用于该对象。

**先决条件：**  
在将对象配置为使用 S3 存储桶密钥之前，请查看 [启用 S3 存储桶密钥之前需要注意的更改](bucket-key.md#bucket-key-changes)。

**Topics**
+ [Amazon S3 批量操作](#bucket-key-object-bops)
+ [使用 REST API](#bucket-key-object-rest)
+ [使用适用于 Java 的 AWS SDK（PutObject）](#bucket-key-object-sdk)
+ [使用 AWS CLI (PutObject)](#bucket-key-object-cli)

## Amazon S3 批量操作
<a name="bucket-key-object-bops"></a>

要加密现有 Amazon S3 对象，可以使用 Amazon S3 批量操作。您为 S3 批量操作提供了要操作的对象列表，而批量操作调用相应的 API 来执行指定的操作。

您可以使用 [S3 批量操作复制操作](https://docs.aws.amazon.com/AmazonS3/latest/userguide/batch-ops-copy-object.html)复制现有的未加密对象，并将其作为加密对象写回同一存储桶。单个批量操作作业可对数十亿个对象执行指定操作。有关更多信息，请参阅 [使用批量操作批量执行对象操作](batch-ops.md) 和 [使用 Amazon S3 批量操作加密对象](https://aws.amazon.com/blogs/storage/encrypting-objects-with-amazon-s3-batch-operations/)。

## 使用 REST API
<a name="bucket-key-object-rest"></a>

使用 SSE-KMS 时，您可以使用以下 API 操作为对象启用 S3 存储桶密钥：
+ [PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html) – 上传对象时，您可以指定 `x-amz-server-side-encryption-bucket-key-enabled` 请求标头以在对象级别启用或禁用 S3 存储桶密钥。
+ [CopyObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html) – 当您复制对象并配置 SSE-KMS 时，您可以指定 `x-amz-server-side-encryption-bucket-key-enabled` 请求标头以为对象启用或禁用 S3 存储桶密钥。
+ [POST 对象](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) – 当您使用 `POST` 操作上传对象并配置 SSE-KMS 时，您可以使用 `x-amz-server-side-encryption-bucket-key-enabled` 表单字段为对象启用或禁用 S3 存储桶密钥。
+ [CreateMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html) – 当您使用 `CreateMultipartUpload` API 操作上传大型对象并配置 SSE-KMS 时，您可以使用 `x-amz-server-side-encryption-bucket-key-enabled` 请求标头为对象启用或禁用 S3 存储桶密钥。

要在对象级别启用 S3 存储桶密钥，请包含 `x-amz-server-side-encryption-bucket-key-enabled` 请求标头。有关 SSE-KMS 和 REST API 的更多信息，请参阅 [使用 REST API](specifying-kms-encryption.md#KMSUsingRESTAPI)。

## 使用适用于 Java 的 AWS SDK（PutObject）
<a name="bucket-key-object-sdk"></a>

您可以使用以下示例通过 适用于 Java 的 AWS SDK 在对象级别配置 S3 存储桶密钥。

------
#### [ Java ]

```
AmazonS3 s3client = AmazonS3ClientBuilder.standard()
    .withRegion(Regions.DEFAULT_REGION)
    .build();

String bucketName = "amzn-s3-demo-bucket1";
String keyName = "key name for object";
String contents = "file contents";

PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, keyName, contents)
    .withBucketKeyEnabled(true);
    
s3client.putObject(putObjectRequest);
```

------

## 使用 AWS CLI (PutObject)
<a name="bucket-key-object-cli"></a>

您可以使用以下 AWS CLI 示例作为 `PutObject` 请求的一部分在对象级别配置 S3 存储桶密钥。

```
aws s3api put-object --bucket amzn-s3-demo-bucket --key object key name --server-side-encryption aws:kms --bucket-key-enabled --body filepath
```

# 查看 S3 存储桶密钥的设置
<a name="viewing-bucket-key-settings"></a>

您可以使用 Amazon S3 控制台、REST API、AWS Command Line Interface（AWS CLI）或 AWS SDK 在存储桶或对象级别查看 S3 存储桶密钥的设置。

S3 存储桶密钥减少了从 Amazon S3 到 AWS KMS 的请求流量，从而降低了使用 AWS Key Management Service（SSE-KMS）进行服务器端加密的成本。有关更多信息，请参阅 [使用 Amazon S3 存储桶密钥降低 SSE-KMS 的成本](bucket-key.md)。

要查看存储桶或已从存储桶配置继承了 S3 存储桶密钥设置的对象的 S3 存储桶密钥设置，您需要获得执行 `s3:GetEncryptionConfiguration` 操作的权限。有关更多信息，请参阅 *Amazon Simple Storage Service API 参考*中的 [GetBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketEncryption.html)。

## 使用 S3 控制台
<a name="bucket-key-settings"></a>

在 S3 控制台中，您可以查看存储桶或对象的 S3 存储桶密钥设置。S3 存储桶密钥设置继承自存储桶配置，除非源对象已配置 S3 存储桶密钥。

同一存储桶中的对象和文件夹可以具有不同的 S3 存储桶密钥设置。例如，如果您使用 REST API 上传对象并为该对象启用了 S3 存储桶密钥，则即使在目标存储桶中禁用了 S3 存储桶密钥，该对象仍会在目标存储桶中保留其 S3 存储桶密钥设置。另一个示例是，如果您为现有存储桶启用 S3 存储桶密钥，则存储桶中已存在的对象将不使用 S3 存储桶密钥。但是，新对象已启用 S3 存储桶密钥。

**查看存储桶的 S3 存储桶密钥设置**

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

1. 在左侧导航窗格中，选择**存储桶**。

1. 在 **Buckets（存储桶）**列表中，请选择要为其启用 S3 存储桶密钥的存储桶。

1. 选择 **Properties (属性)**。

1. 在**默认加密**部分的**存储桶密钥**下，您可以看到存储桶的 S3 存储桶密钥设置。

   如果您看不到 S3 存储桶密钥设置，则可能没有执行 `s3:GetEncryptionConfiguration` 操作的权限。有关更多信息，请参阅 *Amazon Simple Storage Service API 参考* 中的 [GetBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketEncryption.html)。

**查看对象的 S3 存储桶密钥设置**

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

1. 在 **Buckets（存储桶）**列表中，请选择要为其启用 S3 存储桶密钥的存储桶。

1. 在 **Objects（对象）**列表中，请选择对象名称。

1. 在 **Details (详细信息)** 选项卡上，**Server-side encryption settings (服务器端加密设置)** 下，请选择 **Edit (编辑)**。

   在**存储桶密钥**下，您可以看到对象的 S3 存储桶密钥设置。您无法编辑此设置。

## 使用 AWS CLI
<a name="bucket-key-settings-cli"></a>

**返回存储桶级别 S3 存储桶密钥设置**  
要使用此示例，请将每个 `user input placeholder` 替换为您自己的信息。

```
aws s3api get-bucket-encryption --bucket amzn-s3-demo-bucket1
```

有关更多信息，请参阅《AWS CLI 命令参考》**中的 [get-bucket-encryption](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/get-bucket-encryption.html)。

**返回对象级别 S3 存储桶密钥设置**  
要使用此示例，请将每个 `user input placeholder` 替换为您自己的信息。

```
aws s3api head-object --bucket amzn-s3-demo-bucket1 --key my_images.tar.bz2
```

有关更多信息，请参阅《AWS CLI 命令参考》**中的 [head-object](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/head-object.html)。

## 使用 REST API
<a name="bucket-key-settings-rest"></a>

**返回存储桶级别 S3 存储桶密钥设置**  
要返回存储桶的加密信息，包括 S3 存储桶密钥的设置，请使用 `GetBucketEncryption` 操作。S3 存储桶密钥设置将在 `ServerSideEncryptionConfiguration` 元素中的响应正文中与 `BucketKeyEnabled` 设置一起返回。有关更多信息，请参阅 *Amazon S3 API 参考*中的 [GetBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketEncryption.html)。

**返回 S3 存储桶密钥的对象级别设置**  
要返回对象的 S3 存储桶密钥状态，请使用 `HeadObject` 操作。`HeadObject` 返回 `x-amz-server-side-encryption-bucket-key-enabled` 响应标头，以显示是否为对象启用或禁用了 S3 存储桶密钥。有关更多信息，请参阅 *Amazon S3 API 参考*中的 [HeadObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html)。

如果为对象配置了 S3 存储桶密钥，则以下 API 操作还会返回 `x-amz-server-side-encryption-bucket-key-enabled` 响应标头：
+ [PutObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html) 
+ [PostObject](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html) 
+ [CopyObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html) 
+ [CreateMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html) 
+ [UploadPartCopy](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html) 
+ [UploadPart](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html) 
+ [CompleteMultipartUpload](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html) 
+ [GetObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html) 

# 使用具有 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
```

# 使用具有客户提供的密钥的服务器端加密（SSE-C）
<a name="ServerSideEncryptionCustomerKeys"></a>

服务器端加密是为了保护静态数据。服务器端加密仅加密对象数据而非加密对象元数据。您可以在通用存储桶中使用具有客户提供密钥的服务器端加密（SSE-C），通过自己的加密密钥来加密数据。使用您作为请求的一部分提供的加密密钥，Amazon S3 在其写入磁盘时管理数据加密，并在您访问对象时管理数据解密。因此，您不需要维护任何代码来执行数据加密和解密。您只需管理您提供的加密密钥。

Amazon S3 中的大多数现代化使用案例不再使用 SSE-C，因为相比具有 Amazon S3 托管式密钥的服务器端加密（SSE-S3）或具有 AWS KMS 密钥的服务器端加密（SSE-KMS），这种方法欠缺灵活性。SSE-C 要求您在每次与 SSE-C 加密数据交互时提供加密密钥，因此您无法通过与其他用户、角色或 AWS 服务共享 SSE-C 密钥来允许对方从您的 S3 存储桶读取数据以便操作数据。由于 AWS 广泛支持 SSE-KMS，大多数现代化工作负载都不使用 SSE-C 加密，因为此方法欠缺 SSE-KMS 的灵活性。要了解有关 SSE-KMS 的更多信息，请参阅[使用具有 AWS KMS 密钥的服务器端加密（SSE-KMS）](UsingKMSEncryption.md)。

如果您想阻止对写入存储桶的对象使用 SSE-C 加密，则可以在更改存储桶的默认加密配置时阻止 SSE-C 加密。为通用存储桶阻止了 SSE-C 之后，任何指定 SSE-C 加密的 `PutObject`、`CopyObject`、`PostObject`、分段上传或复制请求都将被拒绝，并返回 `HTTP 403 AccessDenied` 错误。要了解有关阻止 SSE-C 的更多信息，请参阅[对通用存储桶阻止或取消阻止 SSE-C](blocking-unblocking-s3-c-encryption-gpb.md)。

使用 SSE-C 没有额外费用。但是，配置和使用 SSE-C 的请求会产生标准的 Amazon S3 请求费用。有关定价的信息，请参阅 [Amazon S3 定价](https://aws.amazon.com/s3/pricing/)。

**重要**  
从 2026 年 4 月开始，AWS 将对所有新存储桶禁用具有客户提供密钥的服务器端加密（SSE-C）。此外，对于 AWS 账户中没有任何 SSE-C 加密数据的所有现有存储桶，都将禁用 SSE-C 加密。通过这些更改，少数需要 SSE-C 加密的应用程序必须在创建存储桶后，专门通过 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) API 启用 SSE-C。在这些情况下，您可能需要更新自动化脚本、CloudFormation 模板或其他基础设施配置工具来配置这些设置。有关更多信息，请参阅 [AWS Storage 博客文章](https://aws.amazon.com/blogs/storage/advanced-notice-amazon-s3-to-disable-the-use-of-sse-c-encryption-by-default-for-all-new-buckets-and-select-existing-buckets-in-april-2026/)。

## 使用 SSE-C 之前的注意事项
<a name="considerations-before-using-sse-c"></a>
+ 当您使用 SSE-C 时，S3 从不存储加密密钥。每次您要让任何人从 S3 下载您的 SSE-C 加密数据时，都必须提供加密密钥。
  + 您管理哪个加密密钥用于加密哪个对象的映射。您负责跟踪为哪个对象提供了哪个加密密钥。这还意味着，如果您丢失加密密钥，则会失去该对象。
  + 因为您在客户端管理加密密钥，所以也要在客户端管理所有额外的保护措施，例如密钥轮换。
  + 这种设计使您难以与其他用户、角色或 AWS 服务共享 SSE-C 密钥来操作您的数据。由于 AWS 广泛支持 SSE-KMS，大多数现代化工作负载都不使用 SSE-C，因为此方法欠缺 SSE-KMS 的灵活性。要了解有关 SSE-KMS 的更多信息，请参阅[使用具有 AWS KMS 密钥的服务器端加密（SSE-KMS）](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingKMSEncryption.html)。
  + 这意味着 AWS 托管服务无法对使用 SSE-C 加密的对象进行本地解密。
+ 在请求中指定 SSE-C 标头时，必须使用 HTTPS。
  + 在使用 SSE-C 时，Amazon S3 会拒绝通过 HTTP 发出的所有请求。出于安全原因，我们建议您考虑您错误地通过 HTTP 发送的任何密钥都会遭泄露。丢弃该密钥，并根据需要轮换密钥。
+ 如果您的存储桶启用了版本控制，则您上传的每个对象版本可能都具有自己的加密密钥。您负责跟踪哪个加密密钥用于哪个对象版本。
+ Amazon S3 控制台中不支持 SSE-C。您不能使用 Amazon S3 控制台上传对象和指定 SSE-C 加密。也不能使用控制台来更新使用 SSE-C 存储的现有对象（例如，更改存储类别或添加元数据）。

**Topics**
+ [使用 SSE-C 之前的注意事项](#considerations-before-using-sse-c)
+ [指定使用客户提供的密钥的服务器端加密 (SSE-C)。](specifying-s3-c-encryption.md)
+ [对通用存储桶阻止或取消阻止 SSE-C](blocking-unblocking-s3-c-encryption-gpb.md)
+ [新存储桶的默认 SSE-C 设置常见问题解答](default-s3-c-encryption-setting-faq.md)

# 指定使用客户提供的密钥的服务器端加密 (SSE-C)。
<a name="specifying-s3-c-encryption"></a>

要使用具有客户提供密钥的服务器端加密（SSE-C），请先确保在您的 Amazon S3 通用存储桶默认加密配置中，没有阻止 SSE-C 加密类型。如果此加密类型被阻止，您可以通过更新存储桶的默认加密配置来启用它。然后，您可以通过在上传请求中传递所需的标头来使用 SSE-C。请参阅[支持使用 SSE-C 写入数据的 Amazon S3 操作](#amazon-s3-actions-that-support-writing-data-with-sse-c)，并确保包含 [SSE-C 对象加密和解密请求所需的 S3 API 标头](#s3-api-headers-required-for-sse-c-object-encryption-and-decryption-requests)。

如果您在上传对象时指定了 SSE-C，Amazon S3 将使用您提供的加密密钥对数据应用 AES-256 加密。然后，Amazon S3 从内存中删除此加密密钥。在检索对象时，必须提供相同的加密密钥作为您请求的一部分。Amazon S3 在将对象数据返回给您之前，会首先验证您提供的加密密钥是否匹配，然后再解密对象。

使用 SSE-C 之前，请确保您已查看[使用 SSE-C 之前的注意事项](ServerSideEncryptionCustomerKeys.md#considerations-before-using-sse-c)。

**注意**  
Amazon S3 不存储您提供的加密密钥，而是存储加密密钥的添加了随机数据的 HMAC 散列消息认证码（HMAC）值，以验证将来的请求。无法使用添加了随机数据的 HMAC 值来推导出加密密钥的值或解密加密对象的内容。这意味着，如果您丢失加密密钥，则会失去该对象。

**Topics**
+ [SSE-C 操作和必需表头](#sse-c-actions-and-required-headers)
+ [强制 SSE-C 加密的存储桶策略示例](#example-bucket-policy-to-enforce-sse-c-encryption)
+ [预签名 URL 和 SSE-C](#ssec-and-presignedurl)
+ [使用 SSE-C 发出请求](#making-requests-with-sse-c)
+ [使用 REST API](#using-rest-api-sse-c)
+ [使用 AWS SDK 为 PUT、GET、Head 和 Copy 操作指定 SSE-C](#sse-c-using-sdks)
+ [使用 AWS SDK 为分段上传指定 SSE-C](#sse-c-using-sdks-multipart-uploads)

## SSE-C 操作和必需表头
<a name="sse-c-actions-and-required-headers"></a>

在支持的 S3 API 上指定 SSE-C 需要传递特定请求参数。

**注意**  
Amazon S3 中的 `PutBucketEncryption` API 用于为存储桶配置默认的服务器端加密。但是，`PutBucketEncryption` 不支持启用 SSE-C 作为存储桶的默认加密方法。SSE-C 是对象级加密方法，您可以随对象上传或下载的每个请求向 Amazon S3 提供加密密钥。Amazon S3 在请求处理期间使用此密钥加密或解密对象，然后丢弃密钥。这意味着 SSE-C 是按对象启用的，而不是作为默认的存储桶设置。

### 支持使用 SSE-C 写入数据的 Amazon S3 操作
<a name="amazon-s3-actions-that-support-writing-data-with-sse-c"></a>

您可以使用以下 API 操作，在向通用存储桶写入对象时，请求使用具有客户提供密钥的服务器端加密（SSE-C）：
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.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_CompleteMultipartUpload.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html)
+ [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_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)

**注意**  
S3 复制支持使用 SSE-C 加密的对象。有关复制加密对象的更多信息，请参阅[复制加密对象（SSE-S3、SSE-KMS、DSSE-KMS、SSE-C）](replication-config-for-kms-objects.md)。

### SSE-C 对象加密和解密请求所需的 S3 API 标头
<a name="s3-api-headers-required-for-sse-c-object-encryption-and-decryption-requests"></a>

要使用 SSE-C 加密或解密对象，您必须提供以下三个 API 标头：
+ `x-amz-server-side-encryption-customer-algorithm`：使用此标头来指定加密算法。标头值必须为 AES256。
+ `x-amz-server-side-encryption-customer-key`：使用此标头来提供 256 位的 base64 编码的加密密钥，供 Amazon S3 用于加密或解密您的数据。
+ `x-amz-server-side-encryption-customer-key-MD5`：使用此标头来根据 RFC 1321，提供加密密钥的 base64 编码的 128 位 MD5 摘要。Amazon S3 使用此标头进行消息完整性检查以确保加密密钥的传输无误。

### 请求复制使用 SSE-C 加密的源对象时需要的 S3 API 标头
<a name="s3-api-headers-required-for-requests-to-copy-source-objects-encrypted-with-sse-c"></a>

要复制使用 SSE-C 加密的源对象，您必须提供以下三个 API 标头：
+ `x-amz-copy-source-server-side-encryption-customer-algorithm`：包括此标头以指定 Amazon S3 用于解密源对象的算法。此值必须为 AES256。
+ `x-amz-copy-source-server-side-encryption-customer-key`：包括此标头以提供 base64 编码的加密密钥，供 Amazon S3 用于解密源对象。此加密密钥必须是您在创建源对象时为 Amazon S3 提供的加密密钥。否则，Amazon S3 无法解密对象。
+ `x-amz-copy-source-server-side-encryption-customer-key-MD5`：包括此标头来根据 RFC 1321，提供加密密钥的 base64 编码的 128 位 MD5 摘要。

## 强制 SSE-C 加密的存储桶策略示例
<a name="example-bucket-policy-to-enforce-sse-c-encryption"></a>

如果要对写入 Amazon S3 存储桶中的所有对象要求使用 SSE-C 加密，您可以使用存储桶策略。例如，如果请求不包括用于请求 SSE-C 的 `x-amz-server-side-encryption-customer-algorithm` 标头，以下存储桶策略将拒绝针对所有此类请求的上传对象（`s3:PutObject`）权限。

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

**重要**  
如果您使用存储桶策略在 `s3:PutObject` 上请求 SSE-C，则必须在所有分段上传请求中（CreateMultipartUpload、UploadPart 和 CompleteMultipartUpload）包括 `x-amz-server-side-encryption-customer-algorithm` 标头。

## 预签名 URL 和 SSE-C
<a name="ssec-and-presignedurl"></a>

您可以生成可用于上传新对象、检索现有对象或检索对象元数据等操作的预签名 URL。预签名 URL 支持 SSE-C，如下所示：
+ 在创建预签名 URL 时，您必须在签名计算中使用 `x-amz-server-side-encryption-customer-algorithm` 标头指定算法。
+ 在使用预签名 URL 上传新对象、检索现有对象或仅检索对象元数据时，您必须在您的客户端应用程序的请求中提供所有加密标头。
**注意**  
对于非 SSE-C 对象，您可以生成预签名 URL，并将该 URL 直接复制到浏览器中以访问数据。  
但是，不能对 SSE-C 对象执行此操作，因为除了预签名 URL 外，还必须包含 SSE-C 对象特定的 HTTP 标头。因此，您只能以编程方式将预签名 URL 用于 SSE-C 对象。

有关预签名 URL 的更多信息，请参阅 [使用预签名 URL 下载和上传对象](using-presigned-url.md)。

## 使用 SSE-C 发出请求
<a name="making-requests-with-sse-c"></a>

 在使用 REST API 创建对象时，您可以使用客户提供的密钥（SSE-C）指定服务器端加密。使用 SSE-C 时，必须使用[请求复制使用 SSE-C 加密的源对象时需要的 S3 API 标头](#s3-api-headers-required-for-requests-to-copy-source-objects-encrypted-with-sse-c)提供加密密钥信息。您可以使用 AWS SDK 包装库将这些标头添加到您的请求中。如果需要，您可以直接在应用程序中调用 Amazon S3 REST API。

**重要**  
在指定具有客户提供密钥的服务器端加密（SSE-C）之前，请确保通用存储桶未阻止 SSE-C 加密。有关更多信息，请参阅 [对通用存储桶阻止或取消阻止 SSE-C](blocking-unblocking-s3-c-encryption-gpb.md)。

**注意**  
您不能使用 Amazon S3 控制台上传对象并请求 SSE-C，也不能使用控制台来更新使用 SSE-C 存储的现有对象（例如，更改存储类别或添加元数据）。有关更多信息，请参阅[SSE-C 对象加密和解密请求所需的 S3 API 标头](#s3-api-headers-required-for-sse-c-object-encryption-and-decryption-requests)。

## 使用 REST API
<a name="using-rest-api-sse-c"></a>

### 支持 SSE-C 的 Amazon S3 REST API
<a name="sse-c-supported-apis"></a>

以下 Amazon S3 API 支持使用客户提供的加密密钥进行服务器端加密 (SSE-C)。
+ **GET 操作** – 在使用 GET API 检索对象（请参阅 [GET Object](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectGET.html)）时，您可以指定请求标头。
+ **HEAD 操作** – 要使用 HEAD API 检索对象元数据（请参阅 [HEAD Object](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectHEAD.html)），可以指定这些请求标头。
+ **PUT 操作** – 使用 PUT Object API 上传数据（请参阅 [PUT Object](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html)）时，可以指定这些请求标头。
+ **分段上传** – 在使用分段上传 API 上传大对象时，可以指定这些标头。您可以在以下请求中指定这些标头：启动请求（请参阅[启动分段上传](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadInitiate.html)），以及每个后续分段上传请求（请参阅[上传分段](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPart.html)或 [UploadPartCopy](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPartCopy.html)）。对于每个分段上传请求，加密信息必须与您在启动分段上传请求中提供的信息相同。
+ **POST 操作** – 使用 POST 操作上传对象（请参阅 [POST 对象](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html)）时，可在表单字段而不是请求标头中提供相同的信息。
+ **复制操作**：复制对象（请参阅 [CopyObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html)）时，您同时具有源对象和目标对象：
  + 如果要指定目标对象的加密类型，您必须提供 `x-amz-server-side-encryption `请求标头。
  + 如果您希望使用 SSE-C 加密目标对象，则必须使用[SSE-C 对象加密和解密请求所需的 S3 API 标头](#s3-api-headers-required-for-sse-c-object-encryption-and-decryption-requests)提供加密信息。
  + 如果源对象使用 SSE-C 加密，则您必须使用[请求复制使用 SSE-C 加密的源对象时需要的 S3 API 标头](#s3-api-headers-required-for-requests-to-copy-source-objects-encrypted-with-sse-c)提供加密密钥信息。

## 使用 AWS SDK 为 PUT、GET、Head 和 Copy 操作指定 SSE-C
<a name="sse-c-using-sdks"></a>

以下示例演示如何为对象请求使用客户提供的密钥的服务器端加密 (SSE-C)。这些示例执行以下操作。每个操作均演示了如何在请求中指定 SSE-C 相关标头：
+ **放置对象** – 上传对象，并请求使用客户提供的加密密钥的服务器端加密。
+ **获取对象** – 下载上一步中上传的对象。在请求中，应提供上传对象时提供的同一加密信息。Amazon S3 需要此信息来解密对象，以便将对象返回给您。
+ **获取对象元数据** – 检索对象的元数据。提供创建对象时使用的同一加密信息。
+ **复制对象** – 复制之前上传的对象的副本。因为源对象是使用 SSE-C 存储的，因此必须在复制请求中提供其加密信息。默认情况下，仅当您显式请求加密时，Amazon S3 才会为对象的副本加密。此示例指示 Amazon S3 存储对象的加密副本。

------
#### [ Java ]

**注意**  
本示例显示如何在单个操作中上传对象。当使用分段上传 API 上传大型对象时，应按照此示例中所示的方式提供加密信息。有关使用 适用于 Java 的 AWS SDK 的分段上传的示例，请参阅 [使用分段上传操作上传对象](mpu-upload-object.md)。

要添加必需的加密信息，请在请求中包含 `SSECustomerKey`。有关该 `SSECustomerKey` 课程的更多信息，请参阅 REST API 部分。

有关创建和测试有效示例的说明，请参阅《适用于 Java 的 AWS SDK 开发人员指南》中的[入门](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/getting-started.html)。

**Example**  

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;

import javax.crypto.KeyGenerator;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

public class ServerSideEncryptionUsingClientSideEncryptionKey {
    private static SSECustomerKey SSE_KEY;
    private static AmazonS3 S3_CLIENT;
    private static KeyGenerator KEY_GENERATOR;

    public static void main(String[] args) throws IOException, NoSuchAlgorithmException {
        Regions clientRegion = Regions.DEFAULT_REGION;
        String bucketName = "*** Bucket name ***";
        String keyName = "*** Key name ***";
        String uploadFileName = "*** File path ***";
        String targetKeyName = "*** Target key name ***";

        // Create an encryption key.
        KEY_GENERATOR = KeyGenerator.getInstance("AES");
        KEY_GENERATOR.init(256, new SecureRandom());
        SSE_KEY = new SSECustomerKey(KEY_GENERATOR.generateKey());

        try {
            S3_CLIENT = AmazonS3ClientBuilder.standard()
                    .withCredentials(new ProfileCredentialsProvider())
                    .withRegion(clientRegion)
                    .build();

            // Upload an object.
            uploadObject(bucketName, keyName, new File(uploadFileName));

            // Download the object.
            downloadObject(bucketName, keyName);

            // Verify that the object is properly encrypted by attempting to retrieve it
            // using the encryption key.
            retrieveObjectMetadata(bucketName, keyName);

            // Copy the object into a new object that also uses SSE-C.
            copyObject(bucketName, keyName, targetKeyName);
        } catch (AmazonServiceException e) {
            // The call was transmitted successfully, but Amazon S3 couldn't process
            // it, so it returned an error response.
            e.printStackTrace();
        } catch (SdkClientException e) {
            // Amazon S3 couldn't be contacted for a response, or the client
            // couldn't parse the response from Amazon S3.
            e.printStackTrace();
        }
    }

    private static void uploadObject(String bucketName, String keyName, File file) {
        PutObjectRequest putRequest = new PutObjectRequest(bucketName, keyName, file).withSSECustomerKey(SSE_KEY);
        S3_CLIENT.putObject(putRequest);
        System.out.println("Object uploaded");
    }

    private static void downloadObject(String bucketName, String keyName) throws IOException {
        GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, keyName).withSSECustomerKey(SSE_KEY);
        S3Object object = S3_CLIENT.getObject(getObjectRequest);

        System.out.println("Object content: ");
        displayTextInputStream(object.getObjectContent());
    }

    private static void retrieveObjectMetadata(String bucketName, String keyName) {
        GetObjectMetadataRequest getMetadataRequest = new GetObjectMetadataRequest(bucketName, keyName)
                .withSSECustomerKey(SSE_KEY);
        ObjectMetadata objectMetadata = S3_CLIENT.getObjectMetadata(getMetadataRequest);
        System.out.println("Metadata retrieved. Object size: " + objectMetadata.getContentLength());
    }

    private static void copyObject(String bucketName, String keyName, String targetKeyName)
            throws NoSuchAlgorithmException {
        // Create a new encryption key for target so that the target is saved using
        // SSE-C.
        SSECustomerKey newSSEKey = new SSECustomerKey(KEY_GENERATOR.generateKey());

        CopyObjectRequest copyRequest = new CopyObjectRequest(bucketName, keyName, bucketName, targetKeyName)
                .withSourceSSECustomerKey(SSE_KEY)
                .withDestinationSSECustomerKey(newSSEKey);

        S3_CLIENT.copyObject(copyRequest);
        System.out.println("Object copied");
    }

    private static void displayTextInputStream(S3ObjectInputStream input) throws IOException {
        // Read one line at a time from the input stream and display each line.
        BufferedReader reader = new BufferedReader(new InputStreamReader(input));
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
        System.out.println();
    }
}
```

------
#### [ .NET ]

**注意**  
有关使用分段上传 API 上传大型对象的示例，请参阅 [使用分段上传操作上传对象](mpu-upload-object.md) 和 [使用 AWS SDK（低级别 API）](mpu-upload-object.md#mpu-upload-low-level)。

有关设置和运行代码示例的信息，请参阅《适用于 .NET 的 AWS SDK 开发人员指南》**中的[适用于 .NET 的 AWS SDK 入门](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html)。

**Example**  

```
using Amazon;
using Amazon.S3;
using Amazon.S3.Model;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Threading.Tasks;

namespace Amazon.DocSamples.S3
{
    class SSEClientEncryptionKeyObjectOperationsTest
    {
        private const string bucketName = "*** bucket name ***"; 
        private const string keyName = "*** key name for new object created ***"; 
        private const string copyTargetKeyName = "*** key name for object copy ***";
        // Specify your bucket region (an example region is shown).
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2;
        private static IAmazonS3 client;

        public static void Main()
        {
            client = new AmazonS3Client(bucketRegion);
            ObjectOpsUsingClientEncryptionKeyAsync().Wait();
        }
        private static async Task ObjectOpsUsingClientEncryptionKeyAsync()
        {
            try
            {
                // Create an encryption key.
                Aes aesEncryption = Aes.Create();
                aesEncryption.KeySize = 256;
                aesEncryption.GenerateKey();
                string base64Key = Convert.ToBase64String(aesEncryption.Key);

                // 1. Upload the object.
                PutObjectRequest putObjectRequest = await UploadObjectAsync(base64Key);
                // 2. Download the object and verify that its contents matches what you uploaded.
                await DownloadObjectAsync(base64Key, putObjectRequest);
                // 3. Get object metadata and verify that the object uses AES-256 encryption.
                await GetObjectMetadataAsync(base64Key);
                // 4. Copy both the source and target objects using server-side encryption with 
                //    a customer-provided encryption key.
                await CopyObjectAsync(aesEncryption, base64Key);
            }
            catch (AmazonS3Exception e)
            {
                Console.WriteLine("Error encountered ***. Message:'{0}' when writing an object", e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
            }
        }

        private static async Task<PutObjectRequest> UploadObjectAsync(string base64Key)
        {
            PutObjectRequest putObjectRequest = new PutObjectRequest
            {
                BucketName = bucketName,
                Key = keyName,
                ContentBody = "sample text",
                ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                ServerSideEncryptionCustomerProvidedKey = base64Key
            };
            PutObjectResponse putObjectResponse = await client.PutObjectAsync(putObjectRequest);
            return putObjectRequest;
        }
        private static async Task DownloadObjectAsync(string base64Key, PutObjectRequest putObjectRequest)
        {
            GetObjectRequest getObjectRequest = new GetObjectRequest
            {
                BucketName = bucketName,
                Key = keyName,
                // Provide encryption information for the object stored in Amazon S3.
                ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                ServerSideEncryptionCustomerProvidedKey = base64Key
            };

            using (GetObjectResponse getResponse = await client.GetObjectAsync(getObjectRequest))
            using (StreamReader reader = new StreamReader(getResponse.ResponseStream))
            {
                string content = reader.ReadToEnd();
                if (String.Compare(putObjectRequest.ContentBody, content) == 0)
                    Console.WriteLine("Object content is same as we uploaded");
                else
                    Console.WriteLine("Error...Object content is not same.");

                if (getResponse.ServerSideEncryptionCustomerMethod == ServerSideEncryptionCustomerMethod.AES256)
                    Console.WriteLine("Object encryption method is AES256, same as we set");
                else
                    Console.WriteLine("Error...Object encryption method is not the same as AES256 we set");

                // Assert.AreEqual(putObjectRequest.ContentBody, content);
                // Assert.AreEqual(ServerSideEncryptionCustomerMethod.AES256, getResponse.ServerSideEncryptionCustomerMethod);
            }
        }
        private static async Task GetObjectMetadataAsync(string base64Key)
        {
            GetObjectMetadataRequest getObjectMetadataRequest = new GetObjectMetadataRequest
            {
                BucketName = bucketName,
                Key = keyName,

                // The object stored in Amazon S3 is encrypted, so provide the necessary encryption information.
                ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                ServerSideEncryptionCustomerProvidedKey = base64Key
            };

            GetObjectMetadataResponse getObjectMetadataResponse = await client.GetObjectMetadataAsync(getObjectMetadataRequest);
            Console.WriteLine("The object metadata show encryption method used is: {0}", getObjectMetadataResponse.ServerSideEncryptionCustomerMethod);
            // Assert.AreEqual(ServerSideEncryptionCustomerMethod.AES256, getObjectMetadataResponse.ServerSideEncryptionCustomerMethod);
        }
        private static async Task CopyObjectAsync(Aes aesEncryption, string base64Key)
        {
            aesEncryption.GenerateKey();
            string copyBase64Key = Convert.ToBase64String(aesEncryption.Key);

            CopyObjectRequest copyRequest = new CopyObjectRequest
            {
                SourceBucket = bucketName,
                SourceKey = keyName,
                DestinationBucket = bucketName,
                DestinationKey = copyTargetKeyName,
                // Information about the source object's encryption.
                CopySourceServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                CopySourceServerSideEncryptionCustomerProvidedKey = base64Key,
                // Information about the target object's encryption.
                ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                ServerSideEncryptionCustomerProvidedKey = copyBase64Key
            };
            await client.CopyObjectAsync(copyRequest);
        }
    }
}
```

------

## 使用 AWS SDK 为分段上传指定 SSE-C
<a name="sse-c-using-sdks-multipart-uploads"></a>

上一部分中的示例显示了如何在 PUT、GET、Head 和 Copy 操作中请求使用客户提供的密钥的服务器端加密 (SSE-C)。本节介绍支持 SSE-C 的其他 Amazon S3 API。

------
#### [ Java ]

要上传大型对象，您可以使用分段上传 API。有关更多信息，请参阅 [在 Amazon S3 中使用分段上传来上传和复制对象](mpuoverview.md)。可以使用高级或低级 API 上传大型对象。这些 API 支持在请求中使用与加密相关的标头。
+ 使用高级别 `TransferManager` API 时，应在 `PutObjectRequest` 中提供特定于加密的标头。有关更多信息，请参阅 [使用分段上传操作上传对象](mpu-upload-object.md)。
+ 当使用低级别 API 时，应提供 `InitiateMultipartUploadRequest` 中的加密相关信息，后跟每个 `UploadPartRequest` 中的相同加密信息。不需要在 `CompleteMultipartUploadRequest` 中提供任何特定于加密的标头。有关示例，请参阅 [使用 AWS SDK（低级别 API）](mpu-upload-object.md#mpu-upload-low-level)。

以下示例使用 `TransferManager` 创建对象并显示如何提供 SSE-C 相关信息。本示例执行以下操作：
+ 使用 `TransferManager.upload()` 方法创建对象。在 `PutObjectRequest` 实例中，应在请求中提供加密密钥信息。Amazon S3 将使用客户提供的密钥对于对象进行加密。
+ 通过调用 `TransferManager.copy()` 方法创建对象的副本。该示例指示 Amazon S3 使用新的 `SSECustomerKey` 对对象副本进行加密。由于源对象使用 SSE-C 加密，因此 `CopyObjectRequest` 还提供了源对象的加密密钥，以便 Amazon S3 可以在复制对象之前解密对象。

**Example**  

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.CopyObjectRequest;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.SSECustomerKey;
import com.amazonaws.services.s3.transfer.Copy;
import com.amazonaws.services.s3.transfer.TransferManager;
import com.amazonaws.services.s3.transfer.TransferManagerBuilder;
import com.amazonaws.services.s3.transfer.Upload;

import javax.crypto.KeyGenerator;
import java.io.File;
import java.security.SecureRandom;

public class ServerSideEncryptionCopyObjectUsingHLwithSSEC {

    public static void main(String[] args) throws Exception {
        Regions clientRegion = Regions.DEFAULT_REGION;
        String bucketName = "*** Bucket name ***";
        String fileToUpload = "*** File path ***";
        String keyName = "*** New object key name ***";
        String targetKeyName = "*** Key name for object copy ***";

        try {
            AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                    .withRegion(clientRegion)
                    .withCredentials(new ProfileCredentialsProvider())
                    .build();
            TransferManager tm = TransferManagerBuilder.standard()
                    .withS3Client(s3Client)
                    .build();

            // Create an object from a file.
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, keyName, new File(fileToUpload));

            // Create an encryption key.
            KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
            keyGenerator.init(256, new SecureRandom());
            SSECustomerKey sseCustomerEncryptionKey = new SSECustomerKey(keyGenerator.generateKey());

            // Upload the object. TransferManager uploads asynchronously, so this call
            // returns immediately.
            putObjectRequest.setSSECustomerKey(sseCustomerEncryptionKey);
            Upload upload = tm.upload(putObjectRequest);

            // Optionally, wait for the upload to finish before continuing.
            upload.waitForCompletion();
            System.out.println("Object created.");

            // Copy the object and store the copy using SSE-C with a new key.
            CopyObjectRequest copyObjectRequest = new CopyObjectRequest(bucketName, keyName, bucketName, targetKeyName);
            SSECustomerKey sseTargetObjectEncryptionKey = new SSECustomerKey(keyGenerator.generateKey());
            copyObjectRequest.setSourceSSECustomerKey(sseCustomerEncryptionKey);
            copyObjectRequest.setDestinationSSECustomerKey(sseTargetObjectEncryptionKey);

            // Copy the object. TransferManager copies asynchronously, so this call returns
            // immediately.
            Copy copy = tm.copy(copyObjectRequest);

            // Optionally, wait for the upload to finish before continuing.
            copy.waitForCompletion();
            System.out.println("Copy complete.");
        } catch (AmazonServiceException e) {
            // The call was transmitted successfully, but Amazon S3 couldn't process
            // it, so it returned an error response.
            e.printStackTrace();
        } catch (SdkClientException e) {
            // Amazon S3 couldn't be contacted for a response, or the client
            // couldn't parse the response from Amazon S3.
            e.printStackTrace();
        }
    }
}
```

------
#### [ .NET ]

要上传大型对象，您可以使用分段上传 API（请参阅[在 Amazon S3 中使用分段上传来上传和复制对象](mpuoverview.md)）。AWS适用于 .NET 的 SDK 提供了高级或低级 API 来上传大型对象。这些 API 支持在请求中使用与加密相关的标头。
+ 当使用高级 `Transfer-Utility ` API 时，可以在 `TransferUtilityUploadRequest` 中提供特定于加密的标头，如下所示。有关代码示例，请参阅 [使用分段上传操作上传对象](mpu-upload-object.md)。

  ```
  TransferUtilityUploadRequest request = new TransferUtilityUploadRequest()
  {
      FilePath = filePath,
      BucketName = existingBucketName,
      Key = keyName,
      // Provide encryption information.
      ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
      ServerSideEncryptionCustomerProvidedKey = base64Key,
  };
  ```
+ 当使用低级 API 时，可以在启动分段上传请求中提供加密相关的信息，并在后续的分段上传请求中提供相同加密信息。不需要在完成的分段上传请求中提供任何特定于加密的标头。有关示例，请参阅 [使用 AWS SDK（低级别 API）](mpu-upload-object.md#mpu-upload-low-level)。

  下面是一个低级分段上传示例，该示例复制一个现有大型对象。在本示例中，要复制的对象使用 SSE-C 存储在 Amazon S3 中，并且您希望使用 SSE-C 保存目标对象。在本例中，您可以执行以下操作：
  + 通过提供加密密钥和相关信息启动分段上传请求。
  + 在 `CopyPartRequest` 中提供源和目标对象加密密钥及相关信息。
  + 通过检索对象元数据获取要复制的源对象的大小。
  + 以 5 MB 大小的分段上传对象。  
**Example**  

  ```
  using Amazon;
  using Amazon.S3;
  using Amazon.S3.Model;
  using System;
  using System.Collections.Generic;
  using System.IO;
  using System.Security.Cryptography;
  using System.Threading.Tasks;
  
  namespace Amazon.DocSamples.S3
  {
      class SSECLowLevelMPUcopyObjectTest
      {
          private const string existingBucketName = "*** bucket name ***";
          private const string sourceKeyName      = "*** source object key name ***"; 
          private const string targetKeyName      = "*** key name for the target object ***";
          private const string filePath           = @"*** file path ***";
          // Specify your bucket region (an example region is shown).
          private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2;
          private static IAmazonS3 s3Client;
          static void Main()
          {
              s3Client = new AmazonS3Client(bucketRegion);
              CopyObjClientEncryptionKeyAsync().Wait();
          }
  
          private static async Task CopyObjClientEncryptionKeyAsync()
          {
              Aes aesEncryption = Aes.Create();
              aesEncryption.KeySize = 256;
              aesEncryption.GenerateKey();
              string base64Key = Convert.ToBase64String(aesEncryption.Key);
  
              await CreateSampleObjUsingClientEncryptionKeyAsync(base64Key, s3Client);
  
              await CopyObjectAsync(s3Client, base64Key);
          }
          private static async Task CopyObjectAsync(IAmazonS3 s3Client, string base64Key)
          {
              List<CopyPartResponse> uploadResponses = new List<CopyPartResponse>();
  
              // 1. Initialize.
              InitiateMultipartUploadRequest initiateRequest = new InitiateMultipartUploadRequest
              {
                  BucketName = existingBucketName,
                  Key = targetKeyName,
                  ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                  ServerSideEncryptionCustomerProvidedKey = base64Key,
              };
  
              InitiateMultipartUploadResponse initResponse =
                  await s3Client.InitiateMultipartUploadAsync(initiateRequest);
  
              // 2. Upload Parts.
              long partSize = 5 * (long)Math.Pow(2, 20); // 5 MB
              long firstByte = 0;
              long lastByte = partSize;
  
              try
              {
                  // First find source object size. Because object is stored encrypted with
                  // customer provided key you need to provide encryption information in your request.
                  GetObjectMetadataRequest getObjectMetadataRequest = new GetObjectMetadataRequest()
                  {
                      BucketName = existingBucketName,
                      Key = sourceKeyName,
                      ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                      ServerSideEncryptionCustomerProvidedKey = base64Key // " * **source object encryption key ***"
                  };
  
                  GetObjectMetadataResponse getObjectMetadataResponse = await s3Client.GetObjectMetadataAsync(getObjectMetadataRequest);
  
                  long filePosition = 0;
                  for (int i = 1; filePosition < getObjectMetadataResponse.ContentLength; i++)
                  {
                      CopyPartRequest copyPartRequest = new CopyPartRequest
                      {
                          UploadId = initResponse.UploadId,
                          // Source.
                          SourceBucket = existingBucketName,
                          SourceKey = sourceKeyName,
                          // Source object is stored using SSE-C. Provide encryption information.
                          CopySourceServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                          CopySourceServerSideEncryptionCustomerProvidedKey = base64Key, //"***source object encryption key ***",
                          FirstByte = firstByte,
                          // If the last part is smaller then our normal part size then use the remaining size.
                          LastByte = lastByte > getObjectMetadataResponse.ContentLength ?
                              getObjectMetadataResponse.ContentLength - 1 : lastByte,
  
                          // Target.
                          DestinationBucket = existingBucketName,
                          DestinationKey = targetKeyName,
                          PartNumber = i,
                          // Encryption information for the target object.
                          ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                          ServerSideEncryptionCustomerProvidedKey = base64Key
                      };
                      uploadResponses.Add(await s3Client.CopyPartAsync(copyPartRequest));
                      filePosition += partSize;
                      firstByte += partSize;
                      lastByte += partSize;
                  }
  
                  // Step 3: complete.
                  CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest
                  {
                      BucketName = existingBucketName,
                      Key = targetKeyName,
                      UploadId = initResponse.UploadId,
                  };
                  completeRequest.AddPartETags(uploadResponses);
  
                  CompleteMultipartUploadResponse completeUploadResponse =
                      await s3Client.CompleteMultipartUploadAsync(completeRequest);
              }
              catch (Exception exception)
              {
                  Console.WriteLine("Exception occurred: {0}", exception.Message);
                  AbortMultipartUploadRequest abortMPURequest = new AbortMultipartUploadRequest
                  {
                      BucketName = existingBucketName,
                      Key = targetKeyName,
                      UploadId = initResponse.UploadId
                  };
                  s3Client.AbortMultipartUpload(abortMPURequest);
              }
          }
          private static async Task CreateSampleObjUsingClientEncryptionKeyAsync(string base64Key, IAmazonS3 s3Client)
          {
              // List to store upload part responses.
              List<UploadPartResponse> uploadResponses = new List<UploadPartResponse>();
  
              // 1. Initialize.
              InitiateMultipartUploadRequest initiateRequest = new InitiateMultipartUploadRequest
              {
                  BucketName = existingBucketName,
                  Key = sourceKeyName,
                  ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                  ServerSideEncryptionCustomerProvidedKey = base64Key
              };
  
              InitiateMultipartUploadResponse initResponse =
                 await s3Client.InitiateMultipartUploadAsync(initiateRequest);
  
              // 2. Upload Parts.
              long contentLength = new FileInfo(filePath).Length;
              long partSize = 5 * (long)Math.Pow(2, 20); // 5 MB
  
              try
              {
                  long filePosition = 0;
                  for (int i = 1; filePosition < contentLength; i++)
                  {
                      UploadPartRequest uploadRequest = new UploadPartRequest
                      {
                          BucketName = existingBucketName,
                          Key = sourceKeyName,
                          UploadId = initResponse.UploadId,
                          PartNumber = i,
                          PartSize = partSize,
                          FilePosition = filePosition,
                          FilePath = filePath,
                          ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256,
                          ServerSideEncryptionCustomerProvidedKey = base64Key
                      };
  
                      // Upload part and add response to our list.
                      uploadResponses.Add(await s3Client.UploadPartAsync(uploadRequest));
  
                      filePosition += partSize;
                  }
  
                  // Step 3: complete.
                  CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest
                  {
                      BucketName = existingBucketName,
                      Key = sourceKeyName,
                      UploadId = initResponse.UploadId,
                      //PartETags = new List<PartETag>(uploadResponses)
  
                  };
                  completeRequest.AddPartETags(uploadResponses);
  
                  CompleteMultipartUploadResponse completeUploadResponse =
                      await s3Client.CompleteMultipartUploadAsync(completeRequest);
  
              }
              catch (Exception exception)
              {
                  Console.WriteLine("Exception occurred: {0}", exception.Message);
                  AbortMultipartUploadRequest abortMPURequest = new AbortMultipartUploadRequest
                  {
                      BucketName = existingBucketName,
                      Key = sourceKeyName,
                      UploadId = initResponse.UploadId
                  };
                  await s3Client.AbortMultipartUploadAsync(abortMPURequest);
              }
          }
      }
  }
  ```

------

# 对通用存储桶阻止或取消阻止 SSE-C
<a name="blocking-unblocking-s3-c-encryption-gpb"></a>

Amazon S3 中的大多数现代化使用案例不再使用具有客户提供密钥的服务器端加密（SSE-C），因为相比具有 Amazon S3 托管式密钥的服务器端加密（SSE-S3）或具有 AWS KMS 密钥的服务器端加密（SSE-KMS），这种方法欠缺灵活性。SSE-C 要求您在每次与 SSE-C 加密数据交互时提供加密密钥，因此您无法通过与其他用户、角色或 AWS 服务共享 SSE-C 密钥来允许对方从您的 S3 存储桶读取数据以便操作数据。

要限制可在通用存储桶中使用的服务器端加密类型，您可以选择更新存储桶的默认加密配置，以此来阻止 SSE-C 写入请求。此存储桶级别的配置将阻止请求上传指定了 SSE-C 的对象。当存储桶阻止 SSE-C 时，任何指定了 SSE-C 加密的 `PutObject`、`CopyObject`、`PostObject`、分段上传或复制请求都将被拒绝，并返回 HTTP 403 `AccessDenied` 错误。

此设置是 `PutBucketEncryption` API 上的一个参数，如果您有 `s3:PutEncryptionConfiguration` 权限，也可以使用 S3 控制台、AWS CLI 和AWS SDK 更新此设置。

有效值为 `SSE-C`（在通用存储桶上阻止 SSE-C 加密）和 `NONE`（允许在写入存储桶时使用 SSE-C）。

**重要**  
从 2026 年 4 月开始，AWS 将对所有新存储桶禁用具有客户提供密钥的服务器端加密（SSE-C）。此外，对于 AWS 账户中没有任何 SSE-C 加密数据的所有现有存储桶，都将禁用 SSE-C 加密。通过这些更改，少数需要 SSE-C 加密的应用程序必须在创建存储桶后，专门通过 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) API 启用 SSE-C。在这些情况下，您可能需要更新自动化脚本、CloudFormation 模板或其他基础设施配置工具来配置这些设置。有关更多信息，请参阅 [AWS Storage 博客文章](https://aws.amazon.com/blogs/storage/advanced-notice-amazon-s3-to-disable-the-use-of-sse-c-encryption-by-default-for-all-new-buckets-and-select-existing-buckets-in-april-2026/)。

## 权限
<a name="bucket-encryption-permissions"></a>

对于通用存储桶，使用 `PutBucketEncryption` API、S3 控制台、AWS SDK 或 AWS CLI 来阻止或取消阻止加密类型。您必须拥有以下权限：
+ `s3:PutEncryptionConfiguration`

对于通用存储桶，使用 `GetBucketEncryption` API、S3 控制台、AWS SDK 或 AWS CLI 来查看阻止的加密类型。您必须拥有以下权限：
+ `s3:GetEncryptionConfiguration`

## 阻止 SSE-C 加密之前的注意事项
<a name="considerations-before-blocking-sse-c"></a>

在为所有存储桶阻止 SSE-C 后，将应用以下加密行为：
+ 对于在您阻止 SSE-C 加密之前存储桶中已有的对象，其加密没有变化。
+ 阻止 SSE-C 加密后，只要您在请求中提供所需的 SSE-C 标头，就可以继续对之前已有的 SSE-C 加密对象发出 GetObject 和 HeadObject 请求。
+ 为存储桶阻止 SSE-C 之后，任何指定 SSE-C 加密的 `PutObject`、`CopyObject`、`PostObject` 或分段上传请求都将被拒绝，并返回 HTTP 403 `AccessDenied` 错误。
+ 如果用于复制的目标存储桶已阻止 SSE-C，并且所复制的源对象使用 SSE-C 加密，则复制将失败并返回 HTTP 403 `AccessDenied` 错误。

如果您要在阻止 SSE-C 加密类型之前检查是否有任何存储桶使用了此加密类型，可以使用 [AWS CloudTrail](https://aws.amazon.com/cloudtrail/) 等工具来监控对数据的访问权限。这篇[博客文章](https://aws.amazon.com/blogs/storage/auditing-amazon-s3-server-side-encryption-methods-for-object-uploads/)说明如何实时审计对象上传的加密方法。您也可以参考这篇 [re:Post 文章](https://repost.aws/articles/ARhGC12rOiTBCKHcAe9GZXCA/how-to-detect-existing-use-of-sse-c-in-your-amazon-s3-buckets)，文中指导您通过查询 S3 清单报告来查看是否有任何 SSE-C 加密对象。

### Steps
<a name="block-sse-c-gpb-steps"></a>

对于通用存储桶，您可以使用 Amazon S3 控制台、AWS Command Line Interface（AWS CLI）、Amazon S3 REST API 和 AWS SDK，阻止或取消阻止具有客户提供密钥的服务器端加密（SSE-C）。

### 使用 S3 控制台
<a name="block-sse-c-gpb-console"></a>

要使用 Amazon S3 控制台为存储桶阻止或取消阻止 SSE-C 加密，请执行以下操作：

1. 登录 AWS 管理控制台并在 https://console.aws.amazon.com/s3/ 中打开 Amazon S3 控制台。

1. 在左侧导航窗格中，选择**通用存储桶**。

1. 选择您要阻止 SSE-C 加密的存储桶。

1. 选择存储桶的**属性**选项卡。

1. 导航到存储桶的**默认加密**属性面板，然后选择**编辑**。

1. 在**阻止的加密类型**部分中，选中**具有客户提供密钥的服务器端加密（SSE-C）**旁边的复选框可阻止 SSE-C 加密，取消选中此框则表示允许 SSE-C。

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

### 使用 AWS CLI
<a name="block-sse-c-gpb-cli"></a>

要安装 AWS CLI，请参阅《AWS Command Line Interface 用户指南》**中的[安装 AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)。

以下 CLI 示例说明如何使用 AWS CLI，为通用存储桶阻止或取消阻止 SSE-C 加密。要使用该命令，请将*用户输入占位符* 替换为您自己的信息。

**请求为通用存储桶阻止 SSE-C 加密：**

```
aws s3api put-bucket-encryption \
  --bucket amzn-s3-demo-bucket \
  --server-side-encryption-configuration '{
    "Rules": [{
      "BlockEncryptionTypes": {
        "EncryptionType": "SSE-C"
      }
    }]
  }'
```

**请求在通用存储桶上启用 SSE-C 加密：**

```
aws s3api put-bucket-encryption \
  --bucket amzn-s3-demo-bucket \
  --server-side-encryption-configuration '{
    "Rules": [{
      "BlockEncryptionTypes": {
        "EncryptionType": "NONE"
      }
    }]
  }'
```

## 使用 AWS SDK
<a name="block-sse-c-gpb-sdks"></a>

------
#### [ SDK for Java 2.x ]

以下示例说明如何使用 AWS SDK，为通用存储桶阻止或取消阻止 SSE-C 加密写入。

**示例：PutBucketEncryption 请求将默认加密配置设置为 SSE-S3 并阻止 SSE-C**

```
S3Client s3Client = ...;
ServerSideEncryptionByDefault defaultSse = ServerSideEncryptionByDefault
        .builder()
        .sseAlgorithm(ServerSideEncryption.AES256)
        .build();
BlockedEncryptionTypes blockedEncryptionTypes = BlockedEncryptionTypes
        .builder()
        .encryptionType(EncryptionType.SSE_C)
        .build();
ServerSideEncryptionRule rule = ServerSideEncryptionRule.builder()
        .applyServerSideEncryptionByDefault(defaultSse)
        .blockedEncryptionTypes(blockedEncryptionTypes)
        .build();
s3Client.putBucketEncryption(be -> be
        .bucket(bucketName)
        .serverSideEncryptionConfiguration(c -> c.rules(rule)));
```

**示例：PutBucketEncryption 请求将默认加密配置设置为 SSE-S3 并取消阻止 SSE-C**

```
S3Client s3Client = ...;
ServerSideEncryptionByDefault defaultSse = ServerSideEncryptionByDefault
        .builder()
        .sseAlgorithm(ServerSideEncryption.AES256)
        .build();
BlockedEncryptionTypes blockedEncryptionTypes = BlockedEncryptionTypes
        .builder()
        .encryptionType(EncryptionType.NONE)
        .build();
ServerSideEncryptionRule rule = ServerSideEncryptionRule.builder()
        .applyServerSideEncryptionByDefault(defaultSse)
        .blockedEncryptionTypes(blockedEncryptionTypes)
        .build();
s3Client.putBucketEncryption(be -> be
        .bucket(bucketName)
        .serverSideEncryptionConfiguration(c -> c.rules(rule)));
```

------
#### [ SDK for Python Boto3 ]

**示例：PutBucketEncryption 请求将默认加密配置设置为 SSE-S3 并阻止 SSE-C**

```
s3 = boto3.client("s3")
s3.put_bucket_encryption(
    Bucket="amzn-s3-demo-bucket",
    ServerSideEncryptionConfiguration={
        "Rules":[{
            "ApplyServerSideEncryptionByDefault": {
                "SSEAlgorithm": "AES256"
            },
            "BlockedEncryptionTypes": {
                "EncryptionType": ["SSE-C"]
            }
        }]
    }
)
```

**示例：PutBucketEncryption 请求将默认加密配置设置为 SSE-S3 并取消阻止 SSE-C**

```
s3 = boto3.client("s3")
s3.put_bucket_encryption(
    Bucket="amzn-s3-demo-bucket",
    ServerSideEncryptionConfiguration={
        "Rules":[{
            "ApplyServerSideEncryptionByDefault": {
                "SSEAlgorithm": "AES256"
            },
            "BlockedEncryptionTypes": {
                "EncryptionType": ["NONE"]
            }
        }]
    }
)
```

------

## 使用 REST API
<a name="bucket-tag-add-api"></a>

有关 Amazon S3 REST API 支持为通用存储桶阻止或取消阻止 SSE-C 加密的相关信息，请参阅《Amazon Simple Storage Service API 参考》**中的以下部分：
+ [BlockedEncryptionTypes](https://docs.aws.amazon.com/AmazonS3/latest/API/API_BlockedEncryptionTypes.html) 数据类型用于 [PutBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) 和 [GetBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketEncryption.html) API 操作的 [ServerSideEncryptionRule](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ServerSideEncryptionRule.html) 数据类型中。

# 新存储桶的默认 SSE-C 设置常见问题解答
<a name="default-s3-c-encryption-setting-faq"></a>

**重要**  
从 2026 年 4 月开始，AWS 将对所有新存储桶禁用具有客户提供密钥的服务器端加密（SSE-C）。此外，对于 AWS 账户中没有任何 SSE-C 加密数据的所有现有存储桶，都将禁用 SSE-C 加密。通过这些更改，少数需要 SSE-C 加密的应用程序必须在创建存储桶后，专门通过 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) API 启用 SSE-C。在这些情况下，您可能需要更新自动化脚本、CloudFormation 模板或其他基础设施配置工具来配置这些设置。有关更多信息，请参阅 [AWS Storage 博客文章](https://aws.amazon.com/blogs/storage/advanced-notice-amazon-s3-to-disable-the-use-of-sse-c-encryption-by-default-for-all-new-buckets-and-select-existing-buckets-in-april-2026/)。

以下各部分回答了有关此更新的问题。

**1. 2026 年 4 月，新的 SSE-C 设置是否会对所有新创建的存储桶生效？**

可以。在 2026 年 4 月期间，新的默认设置将逐步在所有 AWS 区域推出。

**2. 这次推出需要多长时间才能涵盖所有 AWS 区域？**

此更新将需要数周时间才能推出。当我们开始部署此更新时，我们将发布一篇“新增内容”帖子。

**3. 我怎么知道更新已完成？**

您可以创建新的存储桶，然后调用 [GetBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketEncryption.html) API 操作来确定是否已禁用 SSE-C 加密，从而轻松地确定您所在的 AWS 区域是否已完成更改。更新完成后，默认情况下，所有新的通用存储桶都将自动禁用 SSE-C 加密。您可以在创建 S3 存储桶后，通过调用 [PutBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) API 操作调整这些设置。

**4. Amazon S3 会更新我现有的桶配置吗？**

如果您的 AWS 账户中没有任何 SSE-C 加密对象，则 AWS 将在所有现有存储桶上禁用 SSE-C 加密。如果您的 AWS 账户中的所有存储桶都包含 SSE-C 加密对象，则 AWS 不会更改该账户中任何存储桶的存储桶配置。您所在 AWS 区域的 `CreateBucket` 更改完成后，新的默认设置将应用于所有新的通用存储桶。

 **5. 我能否在更新完成之前对存储桶禁用 SSE-C 加密？** 

可以。您可以调用 [PutBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) API 操作并指定新的 `BlockedEncryptionTypes` 标头，为所有存储桶禁用 SSE-C 加密。

**6. 我能否使用 SSE-C 对新存储桶中的数据进行加密？**

可以。Amazon S3 中的大多数现代化使用案例不再使用 SSE-C，因为相比具有 Amazon S3 托管式密钥的服务器端加密（SSE-S3）或具有 AWS KMS 密钥的服务器端加密（SSE-KMS），这种方法欠缺灵活性。如果您需要在新存储桶中使用 SSE-C 加密，则可以创建新的存储桶，然后在单独的 `PutBucketEncryption` 请求中启用 SSE-C 加密。

 **示例**

```
aws s3api create-bucket \  
bucket amzn-s3-demo-bucket \ 
region us-east-1 \ 
  
aws s3api put-bucket-encryption \  
-- bucket amzn-s3-demo-bucket \
-- server-side-encryption-configuration \
'{ \Rules\: [{   
   {   
   \ApplyServerSideEncryptionByDefault\: {   
     \SSEAlgorithm\: \AES256\,  
    },   
   \BlockedEncryptionTypes\: [  
     \EncryptionType\:\NONE\]   
   }   
   }]   
}'
```

**注意**  
您必须拥有调用 `PutBucketEncryption` API 的 `s3:PutEncryptionConfiguration` 权限。

**7. 阻止 SSE-C 会如何影响对我的存储桶的请求？**

为存储桶阻止了 SSE-C 之后，任何指定 SSE-C 加密的 `PutObject`、`CopyObject`、`PostObject` 或者分段上传或复制请求都将被拒绝，并返回 HTTP 403 `AccessDenied` 错误。