指定 Amazon S3 加密 - Amazon Simple Storage Service
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

欢迎使用新的 Amazon S3 用户指南! Amazon S3 用户指南结合了以下三个已停用的指南中的信息和说明:Amazon S3 开发人员指南Amazon S3 控制台用户指南Amazon S3 入门指南

指定 Amazon S3 加密

创建对象时,您可以指定使用具有 Amazon S3 托管加密密钥的服务器端加密来加密您的数据。当您要上传新对象或复制现有对象时,也是这种情况。这种加密称为 SSE-S3。

您可以使用 S3 控制台、REST API、AWS 开发工具包和 AWS CLI 指定 SSE-S3。有关更多信息,请参阅以下主题。

本主题描述如何使用 AWS 管理控制台设置或更改对象的加密类型。使用控制台复制对象时,控制台将按原样复制对象。如果源被加密,则目标对象也会被加密。控制台还允许您添加或更改对象的加密。

注意

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

添加或更改对象的加密

  1. 登录 AWS 管理控制台,并通过以下网址打开 Amazon S3 控制台:https://console.aws.amazon.com/s3/

  2. Bucket (存储桶) 列表中,选择包含对象的存储桶的名称。

  3. Objects (对象) 列表中,选择要为其添加或更改加密的对象的名称。

    Object overview (对象概述) 随即打开,其中显示对象的属性。

  4. Server-side encryption settings (服务器端加密设置) 下,选择 Edit (编辑)

    Edit server-side encryption (编辑服务器端加密) 页面随即打开。

  5. 要为对象启用服务器端加密,请在 Server-side encryption (服务器端加密) 下选择 Enable (启用)

  6. 要使用 Amazon S3 托管密钥启用服务器端加密,请在 Encryption key type (加密密钥类型) 下,选择 Amazon S3 key (SSE-S3) (Amazon S3 密钥 (SSE-S3))

    有关使用 Amazon S3 服务器端加密对数据进行加密的更多信息,请参阅 使用具有 Amazon S3 托管加密密钥的服务器端加密 (SSE-S3) 保护数据

  7. 选择保存更改

注意

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

创建对象时(即,上传新对象或复制现有对象时),您可以通过为请求添加 x-amz-server-side-encryption 标头来指定您是否希望 Amazon S3 加密您的数据。将标头的值是设置为 Amazon S3 支持的加密算法 AES256。通过返回响应标头 x-amz-server-side-encryption,Amazon S3 确认已使用服务器端加密存储了您的数据元。

以下 REST 上传 API 接受 x-amz-server-side-encryption 请求标题。

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

使用服务器端加密存储对象后,以下 REST API 的响应标头将返回 x-amz-server-side-encryption 标头。

注意

如果对象使用 SSE-S3,则不应对 GET 请求和 HEAD 请求发送加密请求标头,否则将出现 HTTP 400 BadRequest 错误。

使用 AWS 开发工具包时,您可以请求 Amazon S3 使用 Amazon S3 托管的加密密钥。本节提供了以多种语言使用 AWS 开发工具包的示例。有关其他软件开发工具包的信息,请转到示例代码和库

Java

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

当使用分段上传 API 上传对象时,还可以请求服务器端加密:

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

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

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

例 示例

以下示例演示如何使用适用于 Java 的 AWS 开发工具包设置服务器端加密。它展示了如何执行以下任务:

  • 使用服务器端加密上传新对象。

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

  • 检查对象的加密状态。

有关服务器端加密的更多信息,请参阅使用 REST API。有关创建和测试有效示例的说明,请参阅测试 Amazon S3 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 中指定服务器端加密,请添加以下命令:

ServerSideEncryptionMethod = ServerSideEncryptionMethod.AES256

有关如何复制对象的有效示例,请参阅 使用 AWS 开发工具包

以下示例将上传对象。在请求中,该示例指示 Amazon S3 加密对象。该示例随后检索对象元数据并验证使用的加密方法。有关创建和测试有效示例的信息,请参阅 运行 Amazon S3 .NET 代码示例

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 开发工具包版本 3 中的类来将服务器端加密添加到您上传到 Amazon Simple Storage Service (Amazon S3) 的对象。此部分假定您已按照使用适用于 PHP 的 AWS 开发工具包和运行 PHP 示例 中的说明执行操作,并正确安装了适用于 PHP 的 AWS 开发工具包。

要将对象上传到 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 上传大型对象时,您可以为正在上传的对象指定服务器端加密,如下所示:

要确定现有对象的加密状态,请通过调用 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() 不会加密目标,除非您通过将值 ServerSideEncryption 用于 AES256 参数,显式请求对目标对象进行服务器端加密。以下 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

在使用适用于 Ruby 的 AWS 开发工具包上传对象时,您可以指定使用服务器端加密 (SSE) 对存储的对象进行静态加密。在您读回对象时,它将自动解密。

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

require 'aws-sdk-s3' # Uploads a file to an Amazon S3 bucket and then encrypts the file server-side # by using the 256-bit Advanced Encryption Standard (AES-256) block cipher. # # Prerequisites: # # - An Amazon S3 bucket. # # @param s3_client [Aws::S3::Client] An initialized Amazon S3 client. # @param bucket_name [String] The name of the bucket. # @param object_key [String] The name for the uploaded object. # @param object_content [String] The content to upload into the object. # @return [Boolean] true if the file was successfully uploaded and then # encrypted; otherwise, false. # @example # exit 1 unless upload_file_encrypted_aes256_at_rest?( # Aws::S3::Client.new(region: 'us-east-1'), # 'doc-example-bucket', # 'my-file.txt', # 'This is the content of my-file.txt.' # ) def upload_file_encrypted_aes256_at_rest?( s3_client, bucket_name, object_key, object_content ) s3_client.put_object( bucket: bucket_name, key: object_key, body: object_content, server_side_encryption: 'AES256' ) return true rescue StandardError => e puts "Error uploading object: #{e.message}" return false end

有关演示在不使用 SSE 的情况下上传对象的示例,请参阅上传对象

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

require 'aws-sdk-s3' # Gets the server-side encryption state of an object in an Amazon S3 bucket. # # Prerequisites: # # - An Amazon S3 bucket. # - An object within that bucket. # # @param s3_client [Aws::S3::Client] An initialized Amazon S3 client. # @param bucket_name [String] The bucket's name. # @param object_key [String] The object's key. # @return [String] The server-side encryption state. # @example # s3_client = Aws::S3::Client.new(region: 'us-east-1') # puts get_server_side_encryption_state( # s3_client, # 'doc-example-bucket', # 'my-file.txt' # ) def get_server_side_encryption_state(s3_client, bucket_name, object_key) response = s3_client.get_object( bucket: bucket_name, key: object_key ) encryption_state = response.server_side_encryption encryption_state.nil? ? 'not set' : encryption_state rescue StandardError => e "unknown or error: #{e.message}" end

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

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

require 'aws-sdk-s3' # Copies an object from one Amazon S3 bucket to another, # changing the object's server-side encryption state during # the copy operation. # # Prerequisites: # # - A bucket containing an object to be copied. # - A separate bucket to copy the object into. # # @param s3_client [Aws::S3::Client] An initialized Amazon S3 client. # @param source_bucket_name [String] The source bucket's name. # @param source_object_key [String] The name of the object to be copied. # @param target_bucket_name [String] The target bucket's name. # @param target_object_key [String] The name of the copied object. # @param encryption_type [String] The server-side encryption type for # the copied object. # @return [Boolean] true if the object was copied with the specified # server-side encryption; otherwise, false. # @example # s3_client = Aws::S3::Client.new(region: 'us-east-1') # if object_copied_with_encryption?( # s3_client, # 'doc-example-bucket1', # 'my-source-file.txt', # 'doc-example-bucket2', # 'my-target-file.txt', # 'AES256' # ) # puts 'Copied.' # else # puts 'Not copied.' # end def object_copied_with_encryption?( s3_client, source_bucket_name, source_object_key, target_bucket_name, target_object_key, encryption_type ) response = s3_client.copy_object( bucket: target_bucket_name, copy_source: source_bucket_name + '/' + source_object_key, key: target_object_key, server_side_encryption: encryption_type ) return true if response.copy_object_result rescue StandardError => e puts "Error while copying object: #{e.message}" end

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

有关如何复制未加密对象的示例,请参阅 复制对象