指定具有 Amazon S3 托管式密钥的服务器端加密(SSE-S3) - Amazon Simple Storage Service

指定具有 Amazon S3 托管式密钥的服务器端加密(SSE-S3)

默认情况下,所有 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。

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

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

注意
  • 如果对象小于 5 GB,则可以更改对象的加密。如果对象大于 5GB,必须使用 AWS CLIAWS SDK 来更改对象的加密。

  • 有关更改对象的加密所需的其它权限的列表,请参阅 Amazon S3 API 操作所需的权限。有关授予此权限的示例策略,请参阅Amazon S3 基于身份的策略示例

  • 如果更改对象的加密,则会创建一个新对象来替换旧对象。如果启用 S3 版本控制,则会创建对象的新版本,而现有对象将变为旧版本。更改属性的角色也会成为新对象(或对象版本)的拥有者。

更改对象的加密
  1. 登录到AWS Management Console,然后通过以下网址打开 Amazon S3 控制台:https://console.aws.amazon.com/s3/

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

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

  4. 操作菜单上,从显示的选项列表中选择编辑服务器端加密

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

  6. 加密设置下,选择使用默认加密的存储桶设置覆盖默认加密的存储桶设置

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

    1. 加密类型下,选择具有 Amazon S3 托管式密钥的服务器端加密(SSE-S3)。SSE-S3 使用最强的数据块密码之一 [即 256 位高级加密标准(AES-256)] 来加密每个对象。有关更多信息,请参阅 使用具有 Amazon S3 托管式密钥的服务器端加密(SSE-S3)

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

  9. 选择 Save Changes(保存更改)。

注意

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

创建对象时(即,上传新对象或复制现有对象时),您可以通过向请求添加 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 请求标头。

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

使用 SSE-S3 加密存储对象后,以下 REST API 操作的响应标头将返回 x-amz-server-side-encryption 标头。

注意

如果您的对象使用 SSE-S3,请不要发送 GET 请求和 HEAD 请求的加密请求标头,否则会收到 HTTP 状态代码 400(错误请求)错误。

使用 AWS SDK 时,您可以请求 Amazon S3 使用具有 Amazon S3 托管式加密密钥的服务器端加密(SSE-S3)。这部分提供了以多种语言使用 AWS SDK 的示例。有关其他 SDK 的信息,请转到示例代码和库

Java

当您使用 AWS SDK for Java 上传对象时,可以使用 SSE-S3 为对象加密。要请求服务器端加密,请使用 ObjectMetadataPutObjectRequest 属性设置 x-amz-server-side-encryption 请求标头。当您调用 AmazonS3ClientputObject() 方法时,Amazon S3 将加密并保存数据。

当使用分段上传 API 操作上传对象时,还可以请求 SSE-S3 加密:

  • 使用高级别分段上传 API 操作时,请在上传对象时使用 TransferManager 方法将服务器端加密应用于对象。可以使用将 ObjectMetadata 视为参数的任一上传方法。有关更多信息,请参阅 使用分段上传操作上传对象

  • 当使用低级别分段上传 API 操作时,应在启动分段上传时指定服务器端加密。您通过调用 ObjectMetadata 方法添加 InitiateMultipartUploadRequest.setObjectMetadata() 属性。有关更多信息,请参阅 使用 AWS SDK(低级别 API)

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

例 示例

以下示例演示如何使用 AWS SDK for Java 设置服务器端加密。它展示了如何执行以下任务:

  • 使用 SSE-S3 上传新对象。

  • 通过为对象创建副本来更改对象的加密状态 (本示例中为加密之前未加密的对象)。

  • 检查对象的加密状态。

有关服务器端加密的更多信息,请参阅 使用 REST API。有关创建和测试有效示例的说明,请参阅《AWS SDK for Java 开发人员指南》中的入门

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

以下示例将上传对象。在请求中,该示例指示 Amazon S3 加密对象。该示例随后检索对象元数据并验证使用的加密方法。有关设置和运行代码示例的信息,请参阅《适用于 .NET 的 AWS SDK 开发人员指南》中的适用于 .NET 的 AWS SDK 入门

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

本主题介绍如何使用 AWS SDK for PHP 版本 3 中的类来将 SSE-S3 添加到您上传到 Amazon S3 的对象。有关适用于 Ruby 的 AWS 开发工具包 API 的更多信息,请转到适用于 Ruby 的 AWS 开发工具包 – 版本 2

要将对象上传到 Amazon S3,请使用 Aws\S3\S3Client::putObject() 方法。要将 x-amz-server-side-encryption 请求标头添加到您的上传请求,请使用值 ServerSideEncryption 指定 AES256 参数,如以下代码示例中所示。有关服务器端加密请求的信息,请参阅 使用 REST API

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\S3\S3Client::createMultipartUpload() 方法时指定服务器端加密。要向请求添加 x-amz-server-side-encryption 请求标头,请使用值 array 指定 ServerSideEncryption 参数的 AES256 密钥。有关低级别分段上传 API 操作的更多信息,请参阅使用 AWS SDK(低级别 API)

  • 当使用高级别分段上传 API 操作时,请使用 CreateMultipartUpload API 操作的 ServerSideEncryption 参数来指定服务器端加密。有关将 setOption() 方法与高级别分段上传 API 操作结合使用的示例,请参阅使用分段上传操作上传对象

要确定现有对象的加密状态,请通过调用 Aws\S3\S3Client::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\S3\S3Client::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', ]);

有关更多信息,请参阅以下主题:

Ruby

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

下面的 AWS SDK for Ruby 版本 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 上传对象时指定 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。要在使用 AWS CLI 复制对象时指定 SSE-S3,请参阅 copy-object

有关使用 AWS CloudFormation 设置加密的示例,请参阅《AWS CloudFormation 用户指南》AWS::S3::Bucket ServerSideEncryptionRule 主题中的使用默认加密创建存储桶通过 AWS KMS 服务器端加密使用 S3 存储桶密钥创建存储桶示例。