

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