Verwenden von serverseitiger Verschlüsselung mit vom Kunden bereitgestellten Schlüsseln (SSE-C) - Amazon Simple Storage Service

Verwenden von serverseitiger Verschlüsselung mit vom Kunden bereitgestellten Schlüsseln (SSE-C)

Die serverseitige Verschlüsselung dient zum Schutz ruhender Daten. Die serverseitige Verschlüsselung verschlüsselt nur die Objektdaten, nicht die Metadaten des Objekts. Die serverseitige Verschlüsselung mit vom Kunden bereitgestellten Schlüsseln (SSE-C) gestattet Ihnen, eigene Verschlüsselungsschlüssel zu speichern. Mit dem Verschlüsselungsschlüssel, den Sie als Teil Ihrer Anforderung bereitstellen, verwaltet Amazon S3 die Datenverschlüsselung, wenn es auf Datenträger schreibt, und die Entschlüsselung, wenn Sie auf Ihre Objekte zugreifen. Sie müssen also für die Datenverschlüsselung und -entschlüsselung keinen Code mehr verwalten. Sie müssen nur noch die von Ihnen bereitgestellten Verschlüsselungsschlüssel verwalten.

Wenn Sie ein Objekt hochladen, verwendet Amazon S3 den von Ihnen bereitgestellten Verschlüsselungsschlüssel, um eine AES-256-Verschlüsselung auf Ihre Daten anzuwenden. Amazon S3 entfernt dann den Verschlüsselungsschlüssel aus dem Speicher. Wenn Sie ein Objekt abrufen, müssen Sie denselben Verschlüsselungsschlüssel als Teil Ihrer Anfrage angeben. Amazon S3 überprüft zuerst, ob der von Ihnen bereitgestellte Verschlüsselungsschlüssel übereinstimmt, und entschlüsselt das Objekt, bevor Objektdaten zurückgegeben werden.

Für die Nutzung von SSE-C fallen keine zusätzlichen Gebühren an. Für Anforderungen zum Konfigurieren und Verwenden von SSE-C werden jedoch Standardgebühren für Amazon-S3-Anforderungen berechnet. Informationen zu Preisen finden Sie unter Amazon S3 – Preise.

Anmerkung

Amazon S3 speichert den von Ihnen bereitgestellten Verschlüsselungsschlüssel nicht. Stattdessen wird ein zufällig mit einem Salt versehener Hash-basierter Nachrichtenauthentifizierungscode (HMAC) des Verschlüsselungsschlüssels gespeichert, um zukünftige Anfragen zu überprüfen. Der mit einem Salt versehene HMAC-Wert kann nicht verwendet werden, um den Wert des Verschlüsselungsschlüssels abzuleiten oder den Inhalt des verschlüsselten Objekts zu entschlüsseln. Das bedeutet, wenn Sie den Verschlüsselungsschlüssel verlieren, verlieren Sie das Objekt.

Die S3-Replikation unterstützt Objekte, die mit SSE-C verschlüsselt sind. Weitere Informationen zum Replizieren verschlüsselter Objekte finden Sie unter Replizieren von mit serverseitiger Verschlüsselung (SSE-C, SSE-S3, SSE-KMS) erstellten Objekten mithilfe von KMS-Schlüsseln.

Weitere Informationen zu SSE-C finden Sie in den folgenden Themen.

Übersicht über SSE-C

Dieser Abschnitt bietet eine Übersicht über SSE-C. Bei der Verwendung von SSE-C sind die folgenden Punkte zu beachten.

  • Sie müssen HTTPS verwenden.

    Wichtig

    Amazon S3 weist Anfragen über HTTP zurück, wenn SSE-C verwendet wird. Aus Sicherheitsgründen sollten Sie jeden Schlüssel, den Sie versehentlich mittels HTTP senden, als nicht vertrauenswürdig betrachten. Verwerfen Sie den Schlüssel und rotieren Sie ihn wie erforderlich.

  • Das Entity-Tag (ETag) in der Antwort ist nicht der MD5-Hash der Objektdaten.

  • Sie Verwalten ein Mapping, welcher Verschlüsselungsschlüssel für die Verschlüsselung welches Objekts verwendet wurde. Amazon S3 speichert keine Verschlüsselungsschlüssel. Sie sind dafür verantwortlich, zu verwalten, welchen Verschlüsselungsschlüssel Sie für welches Objekt angegeben haben.

    • Wenn für Ihren Bucket Versioning aktiviert ist, kann jede Objektversion, die Sie mit dieser Funktion hochladen, einen eigenen Verschlüsselungsschlüssel haben. Sie sind dafür verantwortlich, zu verwalten, welcher Verschlüsselungsschlüssel für welche Objektversion verwendet wurde.

    • Sie verwalten die Verschlüsselungsschlüssel auf der Clientseite, deshalb verwalten Sie auch alle zusätzlichen Sicherungsmechanismen auf der Clientseite, wie beispielsweise die Schlüsselrotation.

    Warnung

    Wenn Sie den Verschlüsselungsschlüssel verlieren, schlagen alle GET-Anfragen für ein Objekt ohne seinen Verschlüsselungsschlüssel fehl und Sie verlieren das Objekt.

Anfordern und Einschränken von SSE-C

Um SSE-C für alle Objekte in einem bestimmten Amazon-S3-Bucket anzufordern, können Sie eine Bucket-Richtlinie verwenden.

Die folgende Bucket-Richtlinie verweigert beispielsweise die Berechtigung zum Hochladen von Objekten (s3:PutObject) für alle Anfragen, die nicht den Header x-amz-server-side-encryption-customer-algorithm enthalten, der SSE-C anfordert.

{ "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" } } } ] }

Sie können auch eine Richtlinie verwenden, um die serverseitige Verschlüsselung aller Objekte in einem bestimmten Amazon-S3-Bucket einzuschränken. Beispielsweise verweigert die folgende Bucket-Richtlinie jedem die s3:PutObject-Berechtigung zum Hochladen von Objekten, wenn die Anfrage nicht den x-amz-server-side-encryption-customer-algorithm-Header enthält, der SSE-C anfordert.

{ "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" } } } ] }

Vorsignierte URLs und SSE-C

Sie können eine vorsignierte URL erstellen, die für Vorgänge wie das Hochladen eines neuen Objekts, das Abrufen eines vorhandenen Objekts oder von Objekt-Metadaten verwendet werden kann. Vorsignierte URLs unterstützen die SSE-C wie folgt:

  • Beim Erstellen einer vorsignierten URL müssen Sie den Algorithmus unter Verwendung des x-amz-server-side​-encryption​-customer-algorithm-Headers in der Signaturberechnung angeben.

  • Wenn Sie die vorsignierte URL verwenden, um ein neues Objekt hochzuladen, ein vorhandenes Objekt abzurufen oder nur Objekt-Metadaten abzurufen, müssen Sie in der Anforderung Ihrer Client-Anwendung alle Verschlüsselungs-Header angeben.

    Anmerkung

    Für andere Objekte als SSE-C-Objekte können Sie eine vorsignierte URL generieren und diese URL direkt in einen Browser kopieren, um beispielsweise auf die Daten zuzugreifen.

    Dies ist für SSE-C-Objekte jedoch nicht möglich, da Sie zusätzlich zur vorsignierten URL auch HTTP-Header einfügen müssen, die für SSE-C-Objekte spezifisch sind. Daher können Sie vorsignierte URLs für SSE-C-Objekte ausschließlich programmgesteuert verwenden.

Weitere Informationen zu vorsignierten URLs finden Sie unter Verwenden vorsignierter URLs.

Angeben der serverseitigen Verschlüsselung mit vom Kunden bereitgestellten Schlüsseln (SSE-C)

Zum Zeitpunkt der Objekterstellung über die REST-API können Sie die serverseitige Verschlüsselung mit vom Kunden bereitgestellten Schlüsseln (SSE-C) angeben. Wenn Sie SSE-C verwenden, müssen Sie mithilfe der folgenden Anforderungs-Header Informationen zum Verschlüsselungsschlüssel bereitstellen.

Name Beschreibung
x-amz-server-side​-encryption​-customer-algorithm

Verwenden Sie diesen Header, um den Verschlüsselungsalgorithmus anzugeben. Der Header-Wert muss AES256 sein.

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

Verwenden Sie diesen Header, um den base64-codierten 256-bit-Verschlüsselungsschlüssel für Amazon S3 bereitzustellen, mit dem Ihre Daten verschlüsselt und entschlüsselt werden.

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

Verwenden Sie diesen Header, um den base64-codierten 128-bit-Verschlüsselungsschlüssel für Amazon S3 bereitzustellen, mit dem Ihre Daten gemäß RFC 1321 verschlüsselt und entschlüsselt werden. Amazon S3 verwendet diesen Header für eine Überprüfung der Nachrichtenintegrität, um sicherzustellen, dass der Verschlüsselungsschlüssel fehlerfrei übertragen wurde.

Sie können AWS-SDK-Wrapper-Bibliotheken verwenden, um Ihrer Anfrage diese Header hinzuzufügen. Falls nötig, können Sie auch die REST-API-Aufrufe in Amazon S3 direkt von Ihrer Anwendung aus durchführen.

Anmerkung

Sie können die Amazon-S3-Konsole nicht zum Hochladen eines Objekts und zum Anfordern von SSE-C verwenden. Sie können die Konsole auch nicht verwenden, um ein vorhandenes Objekt zu aktualisieren (beispielsweise durch Ändern der Speicherklasse oder Hinzufügen von Metadaten), das mittels SSE-C gespeichert wurde.

Amazon-S3-Rest-APIs, die SSE-C unterstützen

Die folgenden Amazon-S3-APIs unterstützen die serverseitige Verschlüsselung mit vom Kunden bereitgestellten Verschlüsselungsschlüsseln (SSE-C).

  • GET-Operation – Sie können beim Abrufen von Objekten über die GET-API (siehe GET Object) die Anforderungs-Header angeben.

  • HEAD-Operation – Um Objektmetadaten über die HEAD-API abzurufen (siehe HEAD Object), können Sie diese Anforderungs-Header angeben.

  • Operation PUT: Sie können beim Hochladen von Daten über die PUT Object API (siehe PUT Object) diese Anforderungs-Header angeben.

  • Multipart Upload – Sie können beim Hochladen großer Objekte über die Multipart Upload-API diese Header angeben. Sie geben diese Header in der Initiierungsanforderung (siehe Initiieren mehrteiliger Uploads) und in jeder nachfolgenden Anforderung für einen Teil-Upload an (siehe Hochladen von Teilen oder Hochladen von Teilen – Kopieren). Für jede teilweise Upload-Anfrage muss dieselbe Verschlüsslungsinformation angegeben werden, wie diejenige, die Sie in der Initiierungsanfrage für den mehrteiligen Upload angegeben haben.

  • POST-Operation – Bei Verwendung einer POST-Operation zum Hochladen eines Objekts (siehe POST Object) geben Sie die Informationen in den Formularfeldern und nicht in den Anforderungs-Headern an.

  • Copy-Operation – Wenn Sie ein Objekt kopieren (siehe PUT Object – Copy), erhalten Sie ein Quell- und ein Zielobjekt:

    • Wenn das Zielobjekt unter Verwendung von serverseitiger Verschlüsselung mit AWS-verwalteten Schlüsseln verschlüsselt werden soll, müssen Sie den Anfrage-Header x-amz-server-side​-encryption bereitstellen.

    • Wenn das Zielobjekt unter Verwendung von SSE-C verschlüsselt werden soll, müssen Sie die Verschlüsselungs-Informationen unter Verwendung der drei Header angeben, die in der obigen Tabelle beschrieben sind.

    • Wenn das Quellobjekt unter Verwendung von SSE-C verschlüsselt ist, müssen Sie die Verschlüsselungsschlüsselinformationen unter Verwendung der folgenden Header angeben, sodass Amazon S3 das Objekt zum Kopieren entschlüsseln kann.

      Name Beschreibung
      x-amz-copy-source​-server-side​-encryption​-customer-algorithm

      Verwenden Sie diesen Header, um den Verschlüsselungsalgorithmus anzugeben, den Amazon S3 für die Entschlüsselung des Quellobjekts verwenden soll. Dieser Wert muss AES256 lauten.

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

      Verwenden Sie diesen Header, um den base64-codierten 256-bit-Verschlüsselungsschlüssel für Amazon S3 bereitzustellen, mit dem das Quellobjekt entschlüsselt werden soll. Dieser Verschlüsselungsschlüssel muss derjenige sein, den Sie Amazon S3 beim Erstellen des Quellobjekts bereitgestellt haben. Andernfalls kann Amazon S3 das Objekt nicht entschlüsseln.

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

      Verwenden Sie diesen Header, um den base64-codierten 128-bit-MD5-Digest des Verschlüsselungsschlüssels gemäß RFC 1321 bereitzustellen.

In den folgenden Beispielen wird gezeigt, wie Sie für Objekte die serverseitige Verschlüsselung mit vom Kunden bereitgestellten Schlüsseln (SSE-C) anfordern. Dabei werden folgende Vorgänge ausgeführt. Jede Operation zeigt, wie SSE-C-bezogene Header in der Anfrage angegeben werden:

  • Put object – Lädt ein Objekt hoch und fordert die serverseitige Verschlüsselung mit einem vom Kunden bereitgestellten Verschlüsselungsschlüssel an.

  • Get object – Lädt das im vorigen Schritt hochgeladene Objekt herunter. Sie stellen in der Anforderung dieselben Verschlüsselungs-Informationen bereit, die Sie beim Hochladen des Objekts angegeben haben. Amazon S3 benötigt diese Informationen, um das Objekt zu entschlüsseln und an Sie zurückzugeben.

  • Get object metadata – Ruft die Metadaten des Objekts ab. Sie stellen dieselben Verschlüsselungs-Informationen bereit, die beim Erstellen des Objekts verwendet wurden.

  • Copy object – Erstellt eine Kopie des zuvor hochgeladenen Objekts. Da das Quellobjekt mit SSE-C gespeichert wurde, müssen Sie seine Verschlüsselungs-Informationen in Ihrer Kopieranfrage bereitstellen. Standardmäßig verschlüsselt Amazon S3 die Kopie des Objekts nur, wenn Sie dies ausdrücklich anfordern. In diesem Beispiel wird Amazon S3 dazu angewiesen, eine verschlüsselte Kopie des Objekts zu speichern.

Java
Anmerkung

Dieses Beispiel zeigt, wie ein Objekt in einer einzigen Operation hochgeladen wird. Wenn Sie die API für mehrteilige Uploads verwenden, um große Objekte hochzuladen, geben Sie Verschlüsslungsinformationen genauso wie in diesem Beispiel veranschaulicht ein. Beispiele für mehrteilige Uploads mit AWS SDK for Java finden Sie unter Hochladen eines Objekts mit Multipart-Upload.

Um die erforderlichen Verschlüsselungsinformationen hinzuzufügen, schließen Sie in Ihre Anfrage einen SSECustomerKey ein. Weitere Informationen zur Klasse SSECustomerKey finden Sie im Abschnitt "REST API".

Weitere Informationen über SSE-C finden Sie unter Verwenden von serverseitiger Verschlüsselung mit vom Kunden bereitgestellten Schlüsseln (SSE-C). Anweisungen zum Erstellen und Testen eines funktionierenden Beispiels finden Sie unter Testen der Java-Codebeispiele für 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
Anmerkung

Beispiele für das Hochladen großer Objekte mithilfe der API für mehrteilige Uploads finden Sie unter Hochladen eines Objekts mit Multipart-Upload und Verwenden der AWS-SDKs (Low-Level-API).

Weitere Informationen über SSE-C finden Sie unter Verwenden von serverseitiger Verschlüsselung mit vom Kunden bereitgestellten Schlüsseln (SSE-C). Weitere Informationen zum Erstellen und Testen eines funktionierenden Beispiels finden Sie unter Ausführen der .NET-Codebeispiele für Amazon S3.

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

Das Beispiel im obigen Abschnitt zeigt, wie Sie eine serverseitige Verschlüsselung mit einem vom Kunden bereitgestellten Schlüssel (SSE-C) in den PUT-, GET-, Head- und Copy-Vorgänge anfordern. In diesem Abschnitt werden andere Amazon-S3-APIs beschrieben, die SSE-C unterstützen.

Java

Um große Objekte hochzuladen, können Sie die API für mehrteilige Uploads verwenden (siehe Hochladen und Kopieren von Objekten mit mehrteiligen Uploads). Sie können entweder High-Level- und Low-Level-APIs zum Hochladen großer Objekte verwenden. Diese APIs unterstützen verschlüsselungsbezogene Header in der Anforderung.

  • Wenn Sie die High-Level-TransferManager-API verwenden, geben Sie die verschlüsselungsspezifischen Header in der PutObjectRequest an (siehe Hochladen eines Objekts mit Multipart-Upload).

  • Beim Verwenden der Low-Level-API geben Sie verschlüsselungsbezogene Informationen in der InitiateMultipartUploadRequest gefolgt von identischen Verschlüsselungsinformationen in jeder UploadPartRequest an. In Ihrer CompleteMultipartUploadRequest müssen Sie keine verschlüsselungsspezifischen Header angeben. Beispiele finden Sie unter Verwenden der AWS-SDKs (Low-Level-API).

Der folgende Beispiel verwendet den TransferManager, um Objekte zu erstellen, und zeigt, wie Sie SSE-C-bezogene Informationen bereitstellen. Das Beispiel erledigt Folgendes:

  • Erstellt ein Objekts mit der Methode TransferManager.upload(). In der Instance PutObjectRequest geben Sie anzufordernde Verschlüsselungsschlüssel-Informationen an. Amazon S3 verschlüsselt das Objekt mit dem vom Kunden bereitgestellten Schüssel.

  • Erstellt eine Kopie des Objekts durch Aufrufen der TransferManager.copy()-Methode. Das Beispiel weist Amazon S3 dazu an, eine Objektkopie unter Verwendung eines neuen SSECustomerKey zu verschlüsseln. Da das Quellobjekt mittels SSE-C verschlüsselt ist, stellt die CopyObjectRequest auch den Verschlüsselungsschlüssel des Quellobjekts bereit. Auf diese Weise kann Amazon S3 das Objekt vor dem Kopieren entschlüsseln.

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

Zum Hochladen großer Objekte können Sie die API für mehrteilige Uploads verwenden (siehe Hochladen und Kopieren von Objekten mit mehrteiligen Uploads). AWS SDK für .NET bietet sowohl High-Level- als auch Low-Level-APIs zum Hochladen großer Objekte. Diese APIs unterstützen verschlüsselungsbezogene Header in der Anforderung.

  • Bei Verwendung der High-Level-Transfer-Utility -API stellen Sie wie im Folgenden dargestellt verschlüsselungsspezifische Header in der TransferUtilityUploadRequest bereit. Codebeispiele finden Sie unter Hochladen eines Objekts mit Multipart-Upload.

    TransferUtilityUploadRequest request = new TransferUtilityUploadRequest() { FilePath = filePath, BucketName = existingBucketName, Key = keyName, // Provide encryption information. ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256, ServerSideEncryptionCustomerProvidedKey = base64Key, };
  • Beim Verwenden der Low-Level-API geben Sie verschlüsselungsbezogene Informationen in der Anforderung zum Starten des mehrteiligen Uploads gefolgt von identischen Verschlüsselungs-Informationen in den nachfolgenden Anforderungen zum mehrteiligen Upload an. In der vollständigen Anforderung zum mehrteiligen Upload müssen Sie keine verschlüsselungsspezifischen Header angeben. Beispiele finden Sie unter Verwenden der AWS-SDKs (Low-Level-API).

    Nachfolgend finden Sie ein Beispiel für einen mehrteiligen Low-Level-Upload, der eine Kopie eines vorhandenen großen Objekts erstellt. Im Beispiel wird das zu kopierende Objekt in Amazon S3 mittels SSE-C gespeichert und Sie möchten das Zielobjekt ebenfalls mittels SSE-C speichern. Im Beispiel machen Sie folgendes:

    • Initiieren Sie eine mehrteilige Upload-Anfrage, indem Sie einen Verschlüsselungsschlüssel und zugehörige Informationen bereitstellen.

    • Stellen Sie Verschlüsselungsschlüssel für das Quell- und das Zielobjekt sowie die zugehörigen Informationen in der CopyPartRequest bereit.

    • Ermitteln Sie die Größe des zu kopierenden Quellobjekts, indem Sie die Objekt-Metadaten abrufen.

    • Laden Sie die Objekte in Teilen mit je 5 MB hoch.

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