

# 使用具有客户提供的密钥的服务器端加密（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` 错误。