Menggunakan enkripsi di sisi server dengan kunci yang disediakan pelanggan (SSE-C) - Amazon Simple Storage Service

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Menggunakan enkripsi di sisi server dengan kunci yang disediakan pelanggan (SSE-C)

Enkripsi sisi-server adalah tentang melindungi data diam. Enkripsi di sisi server hanya mengenkripsi data objek, bukan metadata objek. Dengan menggunakan enkripsi di sisi server dengan kunci yang disediakan pelanggan (SSE-C), Anda dapat menyimpan kunci enkripsi Anda sendiri. Dengan kunci enkripsi yang Anda sediakan sebagai bagian dari permintaan Anda, Amazon S3 mengelola enkripsi data saat menulis ke disk dan dekripsi data saat Anda mengakses objek Anda. Oleh karena itu, Anda tidak perlu menyimpan kode apa pun untuk melakukan enkripsi dan dekripsi data. Satu-satunya hal yang perlu Anda lakukan adalah mengelola kunci enkripsi yang Anda berikan.

Saat Anda mengunggah objek, Amazon S3 menggunakan kunci enkripsi yang Anda berikan untuk menerapkan enkripsi AES-256 ke data Anda. Amazon S3 kemudian menghapus kunci enkripsi dari memori. Saat mengambil sebuah objek, Anda harus memberikan kunci enkripsi yang sama sebagai bagian dari permintaan Anda. Amazon S3 pertama-tama memverifikasi bahwa kunci enkripsi yang Anda berikan cocok, lalu mendekripsi objek sebelum mengembalikan data objek kepada Anda.

Tidak ada biaya tambahan untuk penggunaan SSE-C. Namun, permintaan untuk mengonfigurasi dan menggunakan SSE-C dikenakan biaya permintaan Amazon S3 standar. Untuk informasi tentang harga, lihat Harga Amazon S3.

catatan

Amazon S3 tidak menyimpan kunci enkripsi yang Anda sediakan. Sebaliknya, ia menyimpan nilai Kode Autentikasi Pesan Berbasis Hash (HMAC) salted secara acak dari kunci enkripsi untuk memvalidasi permintaan di masa mendatang. Nilai HMAC salted tidak dapat digunakan untuk mendapatkan nilai kunci enkripsi atau untuk mendekripsi konten objek terenkripsi. Artinya, jika Anda kehilangan kunci enkripsi, Anda akan kehilangan objek.

S3 Replication mendukung objek yang dienkripsi dengan SSE-C. Untuk informasi selengkapnya tentang mereplikasi objek terenkripsi, lihat Mereplikasi objek yang dibuat dengan enkripsi di sisi server (SSE-C, SSE-S3, SSE-KMS, DSSE-KMS).

Untuk informasi selengkapnya tentang SSE-C, lihat topik berikut.

Gambaran umum SSE-C

Bagian ini memberikan gambaran umum SSE-C. Saat menggunakan SSE-C, perhatikan pertimbangan berikut ini.

  • Anda harus menggunakan HTTPS.

    penting

    Amazon S3 menolak permintaan apa pun yang dibuat melalui HTTP saat menggunakan SSE-C. Untuk pertimbangan keamanan, kami menyarankan Anda mempertimbangkan kunci apa pun yang salah Anda kirimkan melalui HTTP telah disusupi. Buang kuncinya dan putar seperlunya.

  • Tag entitas (ETag) dalam respons bukanlah hash MD5 dari data objek.

  • Anda mengelola pemetaan kunci enkripsi mana yang digunakan untuk mengenkripsi objek yang ingin dituju. Amazon S3 tidak menyimpan kunci enkripsi. Anda bertanggung jawab untuk melacak kunci enkripsi yang Anda berikan untuk objek yang ingin dituju.

    • Jika versi bucket Anda diaktifkan dengan Penentuan Versi, setiap versi objek yang Anda unggah menggunakan fitur ini dapat memiliki kunci enkripsinya sendiri. Anda bertanggung jawab untuk melacak kunci enkripsi yang Anda berikan untuk objek yang ingin dituju.

    • Karena Anda mengelola kunci enkripsi di sisi klien, Anda mengelola perlindungan tambahan, seperti rotasi utama, di sisi klien.

    Awas

    Jika Anda kehilangan kunci enkripsi, setiap permintaan GET untuk objek tanpa kunci enkripsi akan gagal, dan Anda kehilangan objek tersebut.

Membutuhkan dan membatasi SSE-C

Untuk mewajibkan SSE-C bagi semua objek dalam bucket Amazon S3 tertentu, Anda dapat menggunakan kebijakan bucket.

Misalnya, kebijakan bucket berikut menolak izin unggah objek (s3:PutObject) untuk semua permintaan yang tidak menyertakan header x-amz-server-side-encryption-customer-algorithm yang meminta SSE-C.

{ "Version": "2012-10-17", "Id": "PutObjectPolicy", "Statement": [ { "Sid": "RequireSSECObjectUploads", "Effect": "Deny", "Principal": "*", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*", "Condition": { "Null": { "s3:x-amz-server-side-encryption-customer-algorithm": "true" } } } ] }

Anda juga dapat menggunakan kebijakan untuk membatasi enkripsi di sisi server pada semua objek di bucket Amazon S3 tertentu. Misalnya, kebijakan bucket berikut menolak izin unggah objek (s3:PutObject) untuk semua permintaan yang tidak menyertakan header x-amz-server-side-encryption-customer-algorithm yang meminta SSE-C.

{ "Version": "2012-10-17", "Id": "PutObjectPolicy", "Statement": [ { "Sid": "RestrictSSECObjectUploads", "Effect": "Deny", "Principal": "*", "Action": "s3:PutObject", "Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*", "Condition": { "Null": { "s3:x-amz-server-side-encryption-customer-algorithm": "false" } } } ] }
penting

Jika Anda menggunakan kebijakan bucket untuk mengharuskan SSE-C aktifs3:PutObject, Anda harus menyertakan x-amz-server-side-encryption-customer-algorithm header di semua permintaan unggahan multibagian (CreateMultipartUpload, UploadPart, dan). CompleteMultipartUpload

URL dan SSE-C yang ditandatangani sebelumnya

Anda dapat membuat URL yang telah ditandatangani sebelumnya yang dapat digunakan untuk operasi seperti mengunggah objek baru, mengambil objek yang sudah ada, atau mengambil metadata objek. URL yang ditandatangani sebelumnya mendukung SSE-C sebagai berikut:

  • Saat membuat URL yang telah ditandatangani, Anda harus menentukan algoritma dengan menggunakan header x-amz-server-side​-encryption​-customer-algorithm dalam perhitungan tanda tangan.

  • Saat menggunakan URL yang ditandatangani sebelumnya untuk mengunggah objek baru, mengambil objek yang sudah ada, atau mengambil metadata objek saja, Anda harus memberikan semua header enkripsi dalam permintaan aplikasi klien.

    catatan

    Untuk objek non-SSE-C, Anda dapat membuat URL yang telah ditandatangani sebelumnya dan secara langsung merekatkan URL tersebut ke browser untuk mengakses data.

    Namun, Anda tidak dapat melakukan ini untuk objek SSE-C, karena selain URL yang ditandatangani sebelumnya, Anda juga harus menyertakan header HTTP yang kustom untuk objek SSE-C. Oleh karena itu, Anda hanya dapat menggunakan URL yang telah ditentukan sebelumnya untuk objek SSE-C secara terprogram.

Untuk informasi selengkapnya tentang URL yang telah ditandatangani, lihat Bekerja dengan URL yang telah ditandatangani.

Menentukan enkripsi di sisi server dengan kunci yang disediakan pelanggan (SSE-C)

Pada saat pembuatan objek dengan API REST, Anda dapat menentukan enkripsi di sisi server dengan kunci yang disediakan pelanggan (SSE-C). Saat Anda menggunakan SSE-C, Anda harus memberikan informasi kunci enkripsi menggunakan header permintaan berikut.

Nama Deskripsi
x-amz-server-side​-encryption​-customer-algorithm

Gunakan header ini untuk menentukan algoritma enkripsi. Nilai header harus berupa AES256.

x-amz-server-side​-encryption​-customer-key

Gunakan header ini untuk menyediakan kunci enkripsi 256 bit, berkode base64 agar Amazon S3 dapat digunakan untuk mengenkripsi atau mendekripsi data Anda.

x-amz-server-side​-encryption​-customer-key-MD5

Gunakan header ini untuk menyediakan intisari kunci enkripsi MD5 128-bit yang dikodekan base64 menurut RFC 1321. Amazon S3 menggunakan header ini untuk pemeriksaan integritas pesan guna memastikan bahwa kunci enkripsi dikirimkan tanpa kesalahan.

Anda dapat menggunakan pustaka pembungkus AWS SDK untuk menambahkan header ini ke permintaan Anda. Jika perlu, Anda dapat melakukan panggilan API REST Amazon S3 secara langsung di aplikasi Anda.

catatan

Anda tidak dapat menggunakan konsol Amazon S3 untuk mengunggah objek dan meminta SSE-C. Anda juga tidak dapat menggunakan konsol untuk memperbarui (misalnya, mengubah kelas penyimpanan atau menambahkan metadata) objek yang sudah ada yang disimpan menggunakan SSE-C.

Amazon S3 mendiamkan API rest yang mendukung SSE-C

API Amazon S3 berikut mendukung enkripsi di sisi server dengan kunci enkripsi yang disediakan pelanggan (SSE-C).

  • GET operation–Saat mengambil objek menggunakan API GET (lihat GET Object), Anda dapat menentukan header permintaan.

  • HEAD operation–Untuk mengambil metadata objek menggunakan API HEAD (lihat HEAD Object), Anda dapat menentukan header permintaan ini.

  • PUT operation–Saat Anda mengunggah data dengan menggunakan API PUT Objek (lihat PUT Objek), Anda dapat menentukan header permintaan ini.

  • Unggahan Multibagian–Saat mengunggah objek yang berukuran besar menggunakan API unggahan multibagian, Anda dapat menentukan header ini. Anda menentukan header ini dalam permintaan inisiasi (lihat Mulai Pengunggahan Multibagian) dan setiap permintaan pengunggahan bagian berikutnya (lihat Unggah Bagian atau Unggah Bagian-Salin). Untuk setiap permintaan unggahan bagian, informasi enkripsi harus sama dengan yang Anda berikan dalam permintaan unggahan multibagian.

  • POST operation–Saat menggunakan POST operation untuk mengunggah objek (lihat Objek POST), alih-alih dengan header permintaan, Anda memberikan informasi yang sama di dalam bidang formulir.

  • Copy operation–Saat Anda menyalin objek (lihat PUT Objek-Salin), Anda memiliki objek sumber dan objek target:

    • Jika Anda ingin objek target dienkripsi menggunakan enkripsi sisi server dengan kunci AWS terkelola, Anda harus memberikan header permintaan. x-amz-server-side​-encryption

    • Jika Anda ingin objek target dienkripsi menggunakan SSE-C, Anda harus memberikan informasi enkripsi menggunakan tiga header yang dijelaskan dalam tabel sebelumnya.

    • Jika objek sumber dienkripsi menggunakan SSE-C, Anda harus memberikan informasi kunci enkripsi menggunakan header berikut sehingga Amazon S3 dapat mendekripsi objek untuk disalin.

      Nama Deskripsi
      x-amz-copy-source​-server-side​-encryption​-customer-algorithm

      Sertakan header ini untuk menentukan algoritma yang harus digunakan Amazon S3 untuk mendekripsi objek sumber. Nilai ini harus berupa AES256.

      x-amz-copy-source​-server-side​-encryption​-customer-key

      Sertakan header ini untuk menyediakan kunci enkripsi berenkode base64 untuk Amazon S3 untuk digunakan untuk mendekripsi objek sumber. Kunci enkripsi ini harus berupa kunci yang Anda berikan kepada Amazon S3 saat membuat objek sumber. Jika tidak, Amazon S3 tidak dapat mendekripsi objeknya.

      x-amz-copy-source-​server-side​-encryption​-customer-key-MD5

      Sertakan header ini untuk menyediakan intisari kunci enkripsi MD5 128-bit yang dikodekan base64 menurut RFC 1321.

Contoh berikut ini menunjukkan cara untuk meminta enkripsi di sisi server dengan kunci yang disediakan pelanggan (SSE-C) untuk objek. Contoh melakukan operasi berikut. Setiap operasi menunjukkan cara untuk menetapkan header terkait SSE-C pada permintaan:

  • Put objek–Mengunggah objek dan meminta enkripsi di sisi server menggunakan kunci enkripsi yang disediakan pelanggan.

  • Get object–Mengunduh objek yang diunggah dalam langkah sebelumnya. Dalam permintaan tersebut, Anda memberikan informasi enkripsi yang sama dengan yang Anda berikan saat unggah objek tersebut. Amazon S3 memerlukan informasi ini untuk mendekripsi objek sehingga dapat mengembalikannya kepada Anda.

  • Get object metadata–Mengambil metadata objek. Anda memberikan informasi enkripsi yang sama, yang digunakan saat objek tersebut dibuat.

  • Copy object–Membuat salinan dari objek yang diunggah sebelumnya. Karena objek sumber disimpan menggunakan SSE-C, Anda harus memberikan informasi enkripsinya dalam permintaan salinan Anda. Secara default, Amazon S3 mengenkripsi salinan objek hanya jika Anda secara eksplisit memintanya. Contoh ini mengarahkan Amazon S3 untuk menyimpan salinan objek yang dienkripsi.

Java
catatan

Contoh ini menunjukkan cara untuk mengunggah objek dalam satu operasi. Saat menggunakan API Unggahan Multibagian untuk mengunggah objek besar, Anda memberikan informasi enkripsi dengan cara yang sama seperti yang ditunjukkan dalam contoh ini. Untuk contoh unggahan multipart yang menggunakan file AWS SDK for Java, lihat. Pengunggahan objek menggunakan unggahan multibagian

Untuk menambahkan informasi enkripsi yang diperlukan, Anda menyertakan SSECustomerKey dalam permintaan Anda. Untuk informasi selengkapnya tentang kelas SSECustomerKey, lihat bagian API REST.

Untuk informasi tentang SSE-C, lihat Menggunakan enkripsi di sisi server dengan kunci yang disediakan pelanggan (SSE-C). Untuk instruksi tentang membuat dan menguji sampel kerja, lihat Menguji Contoh Kode Java Amazon S3.

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
catatan

Untuk contoh pengunggahan objek besar menggunakan API unggahan multibagian, lihat Pengunggahan objek menggunakan unggahan multibagian dan Menggunakan AWS SDK (API tingkat rendah).

Untuk informasi tentang SSE-C, lihat Menggunakan enkripsi di sisi server dengan kunci yang disediakan pelanggan (SSE-C). Untuk informasi tentang membuat dan menguji sampel kerja, lihat Menjalankan Contoh Kode Amazon S3 .NET.

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); } } }

Contoh di bagian sebelumnya menunjukkan cara meminta enkripsi di sisi server dengan kunci yang disediakan pelanggan (SSE-C) dalam operasi PUT, GET, Head, dan Copy. Bagian ini menjelaskan API Amazon S3 lainnya yang mendukung SSE-C.

Java

Untuk mengunggah objek besar, Anda dapat menggunakan API unggahan multibagian (lihat Mengunggah dan menyalin objek menggunakan unggahan multibagian). Anda dapat menggunakan API tingkat tinggi atau tingkat rendah untuk mengunggah objek besar. API ini mendukung header terkait enkripsi dalam permintaan.

  • Saat menggunakan API TransferManager tingkat tinggi, Anda menyediakan header kustom enkripsi di PutObjectRequest (lihat Pengunggahan objek menggunakan unggahan multibagian).

  • Saat menggunakan API tingkat rendah, Anda memberikan informasi terkait enkripsi pada InitiateMultipartUploadRequest, diikuti dengan informasi enkripsi identik pada setiap UploadPartRequest. Anda tidak perlu memberikan header kustom enkripsi apa pun dalam CompleteMultipartUploadRequest Anda. Sebagai contoh, lihat Menggunakan AWS SDK (API tingkat rendah).

Contoh berikut menggunakan TransferManager untuk membuat objek dan menunjukkan cara memberikan informasi terkait SSE-C. Contoh ini melakukan hal berikut:

  • Membuat objek menggunakan metode TransferManager.upload(). Di dalam instans PutObjectRequest, Anda memberikan informasi kunci enkripsi untuk meminta. Amazon S3 mengenkripsi objek menggunakan kunci yang disediakan pelanggan.

  • Membuat salinan objek dengan memanggil metode TransferManager.copy(). Contoh tersebut mengarahkan Amazon S3 untuk mengenkripsi salinan objek menggunakan SSECustomerKey yang baru. Karena objek sumber dienkripsi menggunakan SSE-C, CopyObjectRequest juga menyediakan kunci enkripsi objek sumber sehingga Amazon S3 dapat mendekripsi objek tersebut sebelum menyalinnya.

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

Untuk mengunggah objek besar, Anda dapat menggunakan API unggahan multibagian (lihatMengunggah dan menyalin objek menggunakan unggahan multibagian). AWS SDK for .NET menyediakan API tingkat tinggi atau tingkat rendah untuk mengunggah objek besar. API ini mendukung header terkait enkripsi dalam permintaan.

  • Saat menggunakan API Transfer-Utility tingkat tinggi, Anda menyediakan header kustom enkripsi di TransferUtilityUploadRequest seperti yang ditunjukkan. Untuk contoh kode, lihat Pengunggahan objek menggunakan unggahan multibagian.

    TransferUtilityUploadRequest request = new TransferUtilityUploadRequest() { FilePath = filePath, BucketName = existingBucketName, Key = keyName, // Provide encryption information. ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256, ServerSideEncryptionCustomerProvidedKey = base64Key, };
  • Saat menggunakan API tingkat rendah, Anda memberikan informasi terkait enkripsi dalam memulai permintaan unggahan multibagian, diikuti dengan informasi enkripsi yang sama dalam permintaan bagian unggahan berikutnya. Anda tidak perlu memberikan header kustom enkripsi apa pun dalam permintaan pengunggahan multibagian lengkap Anda. Sebagai contoh, lihat Menggunakan AWS SDK (API tingkat rendah).

    Berikut ini adalah contoh pengunggahan multibagian tingkat rendah yang membuat salinan objek besar yang sudah ada. Pada contoh, objek yang akan disalin disimpan di Amazon S3 menggunakan SSE-C, dan Anda ingin menyimpan objek target juga menggunakan SSE-C. Dalam contoh ini, Anda melakukan hal berikut:

    • Mulai permintaan pengunggahan multibagian dengan memberikan kunci enkripsi dan informasi terkait.

    • Menyediakan kunci enkripsi objek sumber dan sasaran serta informasi terkait dalam CopyPartRequest.

    • Dapatkan ukuran objek sumber yang akan disalin dengan mengambil metadata objek.

    • Unggah objek ke dalam bagian 5 MB.

    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); } } } }