Amazon Simple Storage Service
开发人员指南 (API Version 2006-03-01)
AWS 服务或AWS文档中描述的功能,可能因地区/位置而异。点 击 Getting Started with Amazon AWS to see specific differences applicable to the China (Beijing) Region.

使用 .NET 开发工具包指定具有客户提供的加密密钥的服务器端加密

以下 C# 代码示例演示了使用客户提供的密钥的服务器端加密 (SSE-C) (请参阅通过使用客户提供的加密密钥的服务器端加密 (SSE-C) 保护数据)。本示例执行以下操作,每个操作都显示您如何在请求中指定 SSE-C 相关标头:

  • 放置对象 – 上传对象,该对象请求使用客户提供的加密密钥的服务器端加密。

  • 获取对象 – 下载上一步中上传的对象。它表明,请求必须提供相同的加密信息,以便 Amazon S3 在将对象返回给您之前将其解密。

  • 获取对象元数据 – 该请求表明,必须提供您在创建对象时指定的相同加密信息才能检索对象的元数据。

  • 复制对象 – 本示例复制之前上传的对象。因为源对象是使用 SSE-C 存储的,因此在复制请求中必须提供加密信息。默认情况下,对象副本不会加密。但是在本示例中,您请求 Amazon S3 存储使用 SSE-C 加密的对象副本,因此也为目标提供了加密相关信息。

注意

如下例所示,在使用分段上传 API 上传大型对象时,需要提供您在请求中提供的相同加密信息。有关分段上传 .NET 开发工具包示例,请参阅使用适用于分段上传的 AWS .NET 开发工具包 (高级别 API) 使用适用于分段上传的 AWS .NET 开发工具包 (低级别 API)

有关如何创建和测试有效示例的信息,请参阅 运行 Amazon S3 .NET 代码示例

Copy
using System; using System.IO; using System.Security.Cryptography; using Amazon.S3; using Amazon.S3.Model; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace s3.amazon.com.docsamples { class SSEClientEncryptionKeyObjectOperations { static string bucketName = "*** bucket name ***"; static string keyName = "*** object key name for new object ***"; static string copyTargetKeyName = "*** copy operation target object key name ***"; static IAmazonS3 client; public static void Main(string[] args) { using (client = new AmazonS3Client(Amazon.RegionEndpoint.USWest2)) { try { // Create encryption key. Aes aesEncryption = Aes.Create(); aesEncryption.KeySize = 256; aesEncryption.GenerateKey(); string base64Key = Convert.ToBase64String(aesEncryption.Key); // 1. Upload object. PutObjectRequest putObjectRequest = UploadObject(base64Key); // 2. Download object (and also verify content is same as what you uploaded). DownloadObject(base64Key, putObjectRequest); // 3. Get object metadata (and also verify AES256 encryption). GetObjectMetadata(base64Key); // 4. Copy object (both source and target objects use server-side encryption with // customer-provided encryption key. CopyObject(aesEncryption, base64Key); } catch (AmazonS3Exception amazonS3Exception) { if (amazonS3Exception.ErrorCode != null && (amazonS3Exception.ErrorCode.Equals("InvalidAccessKeyId") || amazonS3Exception.ErrorCode.Equals("InvalidSecurity"))) { Console.WriteLine("Check the provided AWS Credentials."); Console.WriteLine( "For service sign up go to http://aws.amazon.com/s3"); } else { Console.WriteLine( "Error occurred. Message:'{0}' when writing an object" , amazonS3Exception.Message); } } } Console.WriteLine("Press any key to continue..."); Console.ReadKey(); } private static void CopyObject(Aes aesEncryption, string base64Key) { aesEncryption.GenerateKey(); string copyBase64Key = Convert.ToBase64String(aesEncryption.Key); CopyObjectRequest copyRequest = new CopyObjectRequest { SourceBucket = bucketName, SourceKey = keyName, DestinationBucket = bucketName, DestinationKey = copyTargetKeyName, // Source object encryption information. CopySourceServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256, CopySourceServerSideEncryptionCustomerProvidedKey = base64Key, // Target object encryption information. ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256, ServerSideEncryptionCustomerProvidedKey = copyBase64Key }; client.CopyObject(copyRequest); } private static void DownloadObject(string base64Key, PutObjectRequest putObjectRequest) { GetObjectRequest getObjectRequest = new GetObjectRequest { BucketName = bucketName, Key = keyName, // Provide encryption information of the object stored in S3. ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256, ServerSideEncryptionCustomerProvidedKey = base64Key }; using (GetObjectResponse getResponse = client.GetObject(getObjectRequest)) using (StreamReader reader = new StreamReader(getResponse.ResponseStream)) { string content = reader.ReadToEnd(); Assert.AreEqual(putObjectRequest.ContentBody, content); Assert.AreEqual(ServerSideEncryptionCustomerMethod.AES256, getResponse.ServerSideEncryptionCustomerMethod); } } private static void GetObjectMetadata(string base64Key) { GetObjectMetadataRequest getObjectMetadataRequest = new GetObjectMetadataRequest { BucketName = bucketName, Key = keyName, // Object stored in S3 is encrypted. So provide necessary encryption information. ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256, ServerSideEncryptionCustomerProvidedKey = base64Key }; GetObjectMetadataResponse getObjectMetadataResponse = client.GetObjectMetadata(getObjectMetadataRequest); Assert.AreEqual(ServerSideEncryptionCustomerMethod.AES256, getObjectMetadataResponse.ServerSideEncryptionCustomerMethod); } private static PutObjectRequest UploadObject(string base64Key) { PutObjectRequest putObjectRequest = new PutObjectRequest { BucketName = bucketName, Key = keyName, ContentBody = "sample text", ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256, ServerSideEncryptionCustomerProvidedKey = base64Key }; PutObjectResponse putObjectResponse = client.PutObject(putObjectRequest); return putObjectRequest; } } }

其他 Amazon S3 操作和 SSE-C

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

要上传大型对象,您可以使用分段上传 API (请参阅使用分段上传 API 上传对象)。可以使用高级或低级 API 上传大型对象。这些 API 支持在请求中使用与加密相关的标头。

  • 当使用高级 Transfer-Utility API 时,可以在 TransferUtilityUploadRequest 中提供加密特定的标头,如下所示。有关代码示例,请参阅使用适用于分段上传的 AWS .NET 开发工具包 (高级别 API)

    Copy
    TransferUtilityUploadRequest request = new TransferUtilityUploadRequest() { FilePath = filePath, BucketName = existingBucketName, Key = keyName, // Provide encryption information. ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256, ServerSideEncryptionCustomerProvidedKey = base64Key, };
  • 当使用低级 API 时,可以在启动分段上传请求中提供加密相关的信息,并在后续的分段上传请求中提供相同加密信息。您不需要在完成的分段上传请求中提供任何加密特定的标头。有关示例,请参阅 使用适用于分段上传的 AWS .NET 开发工具包 (低级别 API)

    下面是一个低级分段上传示例,该示例复制一个现有大型对象。在本示例中,要复制的对象使用 SSE-C 存储在 Amazon S3,并且您希望使用 SSE-C 保存目标对象。因此,您执行以下操作:

    • 通过提供加密密钥和相关信息启动分段上传请求。

    • CopyPartRequest 中提供源和目标对象加密密钥及相关信息。

    • 通过检索对象元数据获取要复制的源对象的大小。

    • 以 5 MB 大小的分段上传对象。

    Copy
    using System; using System.Collections.Generic; using System.Security.Cryptography; using Amazon.S3; using Amazon.S3.Model; namespace s3.amazon.com.docsamples { class SSECLowLevelMPUcopyObject { static string existingBucketName = "*** bucket name ***"; static string sourceKeyName = "*** key name ***"; static string targetKeyName = "*** key name ***"; static void Main(string[] args) { IAmazonS3 s3Client = new AmazonS3Client(Amazon.RegionEndpoint.USEast1); List<CopyPartResponse> uploadResponses = new List<CopyPartResponse>(); Aes aesEncryption = Aes.Create(); aesEncryption.KeySize = 256; aesEncryption.GenerateKey(); string base64Key = Convert.ToBase64String(aesEncryption.Key); // 1. Initialize. InitiateMultipartUploadRequest initiateRequest = new InitiateMultipartUploadRequest { BucketName = existingBucketName, Key = targetKeyName, ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256, ServerSideEncryptionCustomerProvidedKey = base64Key, }; InitiateMultipartUploadResponse initResponse = s3Client.InitiateMultipartUpload(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 = "***source object encryption key ***" }; GetObjectMetadataResponse getObjectMetadataResponse = s3Client.GetObjectMetadata(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 = "***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, // Ecnryption information for the target object. ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256, ServerSideEncryptionCustomerProvidedKey = base64Key }; uploadResponses.Add(s3Client.CopyPart(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 = s3Client.CompleteMultipartUpload(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); } } } }