Utilisation du chiffrement côté serveur avec les clés fournies par le client (SSE-C) - Amazon Simple Storage Service

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Utilisation du chiffrement côté serveur avec les clés fournies par le client (SSE-C)

Le chiffrement côté serveur consiste à protéger les données au repos. Un chiffrement côté serveur chiffre uniquement les données d'objet, pas les métadonnées d'objet. Dans le cadre du chiffrement côté serveur avec les clés de chiffrement fournies par le client (SSE-C), vous pouvez stocker vos propres clés de chiffrement. Avec la clé de chiffrement que vous fournissez dans la demande, Amazon S3 gère le chiffrement des données quand il écrit sur les disques et le déchiffrement des données quand vous accédez à vos objets. Par conséquent, vous n'avez pas besoin de conserver de code pour procéder au chiffrement et déchiffrement des données. Il ne vous reste qu'à gérer les clés de chiffrement que vous fournissez.

Quand vous chargez un objet, Amazon S3 utilise la clé de chiffrement que vous fournissez pour appliquer le chiffrement AES-256 à vos données. Amazon S3 supprime ensuite la clé de chiffrement de la mémoire. Lorsque vous récupérez un objet, vous devez fournir la même clé de chiffrement dans la demande. Amazon S3 vérifie tout d'abord que la clé de chiffrement que vous avez fournie correspond, puis il déchiffre l'objet avant de vous renvoyer les données de ce dernier.

Aucuns frais supplémentaires ne s'appliquent à l'utilisation du chiffrement SSE-C. Toutefois, les demandes de configuration et d'utilisation du chiffrement SSE-C entraînent des frais de demande Amazon S3 standard. Pour obtenir des informations sur la tarification, consultez Tarification Amazon S3.

Note

Amazon S3 ne stocke pas la clé de chiffrement que vous fournissez. À la place, il stocke un code d'authentification de message utilisant hash (HMAC) crypté de manière aléatoire de la clé de chiffrement pour valider les demandes futures. La valeur HMAC cryptée ne peut pas être utilisée pour retrouver la valeur de la clé de chiffrement ou pour déchiffrer les contenus de l'objet chiffré. Cela signifie que si vous perdez la clé de chiffrement, vous perdez l'objet.

S3 Replication prend en charge les objets chiffrés avec le SSE-C. Pour plus d'informations sur la réplication des objets chiffrés, consultez Réplication d'objets créés avec le chiffrement côté serveur (SSE-C, SSE-S3, SSE-KMS, DSSE-KMS).

Pour plus d'informations sur SSE-C, consultez les rubriques suivantes :

Présentation des SSE-C

Cette section fournit une présentation du chiffrement SSE-C. Dans le cadre du chiffrement SSE-C, gardez à l'esprit les considérations suivantes.

  • Vous devez utiliser HTTPS.

    Important

    Amazon S3 rejette toute demande faite via HTTP lors de l'utilisation du chiffrement SSE-C. Pour des raisons de sécurité, nous vous recommandons de considérer toute clé que vous envoyez par erreur via HTTP comme compromise. Écartez la clé et permutez comme il convient.

  • La balise d'entité (ETag) dans la réponse n'est pas le hachage MD5 des données de l'objet.

  • Vous gérez un mappage pour savoir quelle clé de chiffrement a été utilisée pour chiffrer quel objet. Amazon S3 ne stocke pas les clés de chiffrement. Vous devez assurer le suivi pour savoir quelle clé de chiffrement a été fournie pour quel objet.

    • Si votre compartiment prend en charge la gestion des versions, chaque version d'objet que vous chargez à l'aide de cette fonctionnalité peut avoir sa propre clé de chiffrement. Vous devez assurer le suivi pour savoir quelle clé de chiffrement a été utilisée pour quelle version d'objet.

    • Etant donné que vous gérez les clés de chiffrement du côté client, vous gérez toute sauvegarde supplémentaire, comme la rotation des clés, du côté client.

    Avertissement

    Si vous perdez la clé de chiffrement, toute requête GET d'un objet sans clé de chiffrement échoue et vous perdez l'objet.

Exigence et restriction des SSE-C

Pour exiger le chiffrement SSE-C de tous les objets figurant dans un compartiment Amazon S3 particulier, vous pouvez utiliser une politique de compartiment.

Par exemple, la stratégie de compartiment suivante refuse les autorisations de chargement d’objet (s3:PutObject) autorisations pour toutes les demandes qui n'incluent pas l'en-tête x-amz-server-side-encryption-customer-algorithm demandant 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" } } } ] }

Vous pouvez également utiliser une politique pour limiter le chiffrement côté serveur de tous les objets figurant dans un compartiment Amazon S3 particulier. Par exemple, la politique de compartiment suivante n'autorise pas le chargement d'objet (s3:PutObject) si la demande inclut l'en-tête x-amz-server-side-encryption-customer-algorithm demandant le chiffrement 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" } } } ] }
Important

Si vous utilisez une politique de compartiment pour activer SSE-Cs3:PutObject, vous devez inclure l'x-amz-server-side-encryption-customer-algorithmen-tête dans toutes les demandes de téléchargement partitionné (CreateMultipartUpload UploadPart, et). CompleteMultipartUpload

URL présignées et SSE-C

Vous pouvez générer une URL pré-signée qui peut être utilisée pour des opérations comme le chargement d'un nouvel objet, la récupération d'un objet existant ou la récupération des métadonnées d'objet. Les URL pré-signées prennent en charge le chiffrement SSE-C comme suit :

  • Lors de la création d'une URL pré-signée, vous devez spécifier l'algorithme en utilisant l'en-tête x-amz-server-side​-encryption​-customer-algorithm dans le calcul de la signature.

  • Lorsque vous utilisez l'URL pré-signée pour charger un nouvel objet, récupérer un objet existant ou récupérer uniquement des métadonnées d'objet, vous devez fournir tous les en-têtes de chiffrement dans la demande de votre application cliente.

    Note

    Pour des objets hors chiffrement SSE-C, vous pouvez générer une URL pré-signée et la coller directement dans un navigateur pour accéder aux données.

    Toutefois, vous ne pouvez pas procéder ainsi pour des objets SSE-C, car en plus de l'URL pré-signée, vous devez également inclure des en-têtes HTTP spécifiques aux objets SSE-C. Par conséquent, vous pouvez utiliser des URL pré-signées pour les objets SSE-C uniquement par programmation.

Pour en savoir plus sur les URL présignées, veuillez consulter Utilisation d'URL présignées.

Spécification du chiffrement côté serveur avec des clés fournies par le client (SSE-C)

Au moment de la création de l'objet avec l'API REST, vous pouvez spécifier un chiffrement côté serveur avec les clés fournies par le client (SSE-C). Lorsque vous utilisez SSE-C, vous devez fournir des informations de clé de chiffrement à l'aide des en-têtes de demande suivants.

Nom Description
x-amz-server-side​-encryption​-customer-algorithm

Utilisez cet en-tête pour spécifier l'algorithme du chiffrement. La valeur de l'en-tête doit être AES256.

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

Utilisez cet en-tête pour fournir la clé de chiffrement de 256 bits encodée en Base64 qu'Amazon S3 doit utiliser pour chiffrer ou déchiffrer les données.

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

Utilisez cet en-tête pour fournir la valeur de hachage MD5 128 bits encodée en Base64 de la clé de chiffrement conformément à la norme RFC 1321. Amazon S3 utilise cet en-tête pour vérifier l'intégrité du message et veiller à ce que la clé de chiffrement ait été transmise sans erreur.

Vous pouvez utiliser les bibliothèques d'encapsulation du AWS SDK pour ajouter ces en-têtes à votre demande. Si nécessaire, vous pouvez effectuer les appels à l'API REST Amazon S3 directement dans l'application.

Note

Vous ne pouvez pas utiliser la console Amazon S3 pour charger un objet et demander des clés SSE-C. Vous ne pouvez pas non plus utiliser la console pour mettre à jour (par exemple, modifier la classe de stockage ou ajouter des métadonnées) un objet existant stocké à l'aide de clés SSE-C.

API REST Amazon S3 prenant en charge SSE-C

Les API Amazon S3 suivantes prennent en charge le chiffrement côté serveur avec les clés de chiffrement fournies par le client (SSE-C).

  • Opération GET – Lorsque vous récupérez des objets via l'API GET (consultez GetObject), vous pouvez spécifier ces en-têtes de demande.

  • Opération HEAD – Pour récupérer les métadonnées d'objet via l'API HEAD (consultez HeadObject), vous pouvez spécifier ces en-têtes de demande.

  • Opération PUT – Lorsque vous chargez des données via l'API PutObject (consultez PutObject), vous pouvez spécifier ces en-têtes de demande.

  • Chargement partitionné – Lorsque vous chargez des objets volumineux via l'API de chargement partitionné, vous pouvez spécifier ces en-têtes. Vous spécifiez ces en-têtes dans la demande initiale (consultez Lancement du chargement partitionné (langue française non garantie)) et dans chaque demande de chargement de partie suivante (consultez Chargement d'une partie ou Chargement d'une partie (Copy) (langue française non garantie)). Pour chaque demande de chargement d'une partie, les informations de chiffrement doivent être les mêmes que celles fournies dans la demande de lancement du chargement partitionné.

  • Opération POST – Lorsque vous utilisez une opération POST pour charger un objet (consultez Objet POST), à la place des en-têtes de demande, fournissez les mêmes informations dans les champs du formulaire.

  • Opération Copy – Lorsque vous copiez un objet (consultez CopyObject), vous disposez d'un objet source et d'un objet cible :

    • Si vous souhaitez que l'objet cible soit chiffré à l'aide d'un chiffrement côté serveur avec des clés AWS gérées, vous devez fournir l'en-tête de x-amz-server-side​-encryption demande.

    • Si vous souhaitez chiffrer l'objet cible grâce aux SSE-C, vous devez fournir des informations de chiffrement grâce aux trois en-têtes décrits dans le tableau précédent.

    • Si l'objet source est chiffré grâce aux SSE-C, vous devez fournir les informations sur la clé de chiffrement grâce aux en-têtes suivants afin qu'Amazon S3 puisse déchiffrer l'objet pour le copier.

      Nom Description
      x-amz-copy-source​-server-side​-encryption​-customer-algorithm

      Incluez cet en-tête pour spécifier l'algorithme qu'Amazon S3 doit utiliser pour déchiffrer l'objet source. La valeur doit être AES256.

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

      Incluez cet en-tête pour fournir la clé de chiffrement encodée en Base64 qu'Amazon S3 doit utiliser pour déchiffrer l'objet source. La clé de chiffrement doit être celle fournie à Amazon S3 lorsque vous avez créé l'objet source. Sinon, Amazon S3 ne peut pas déchiffrer l'objet.

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

      Incluez cet en-tête pour fournir la valeur de hachage MD5 128 bits encodée en Base64 de la clé de chiffrement conformément à la norme RFC 1321.

Les exemples suivants illustrent la demande d'un chiffrement côté serveur avec les clés de chiffrement fournies par le client (SSE-C) pour les objets. Les exemples exécutent les opérations suivantes. Chaque opération montre comment spécifier les en-têtes SSE-C dans la demande :

  • Put object – Charge un objet et demande un chiffrement côté serveur avec une clé de chiffrement fournie par le client.

  • Get object – Télécharge l'objet chargé à l'étape précédente. Dans la demande, vous fournissez les mêmes informations de chiffrement que celles fournies lors du chargement de l'objet. Amazon S3 a besoin de ces informations pour déchiffrer l'objet afin de pouvoir vous le renvoyer.

  • Get object metadata – Récupère les métadonnées de l'objet. Vous fournissez les mêmes informations de chiffrement que celles utilisées quand l'objet a été chargé.

  • Copy object – Effectue une copie de l'objet précédemment chargé. Comme l'objet source est stocké via SSE-C, vous devez fournir ses informations de chiffrement dans votre demande de copie. Par défaut, Amazon S3 ne chiffre la copie de l'objet que si vous le demandez explicitement. Cet exemple demande à Amazon S3 de stocker une copie chiffrée de l'objet.

Java
Note

Cet exemple montre comment copier un objet en une seule opération. Lorsque vous utilisez l'API de chargement partitionné pour charger des objets volumineux, vous fournissez les informations de chiffrement comme illustré dans l'exemple suivant. Pour des exemples de téléchargements partitionnés utilisant le AWS SDK for Java, voir. Chargement d'un objet à l'aide du chargement partitionné

Pour ajouter les informations de chiffrement requises, vous incluez une clé SSECustomerKey dans votre demande. Pour plus d'informations sur la classe SSECustomerKey, consultez la section API REST.

Pour plus d'informations sur SSE-C, consultez Utilisation du chiffrement côté serveur avec les clés fournies par le client (SSE-C). Pour obtenir les instructions sur la création et le test d'un exemple pratique, consultez Test des exemples de code 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
Note

Pour obtenir des exemples de chargement d'objets volumineux à l'aide de l'API de chargement partitionné, consultez Chargement d'un objet à l'aide du chargement partitionné et Utilisation des AWS SDK (API de bas niveau).

Pour plus d'informations sur SSE-C, consultez Utilisation du chiffrement côté serveur avec les clés fournies par le client (SSE-C). Pour obtenir des informations sur la façon de créer et de tester un exemple pratique, consultez Exécution des exemples de code .NET 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); } } }

L'exemple de la section précédente montre comment demander le chiffrement côté serveur à l'aide d'une clé de chiffrement fournie par le client (SSE-C) dans les opérations PUT, GET, Head et Copy. Cette section décrit d'autres API Amazon S3 prenant en charge SSE-C.

Java

Pour charger des objets volumineux, vous pouvez utiliser l'API de chargement partitionné (consultez Chargement et copie d'objets à l'aide d'un chargement partitionné). Auquel cas, vous avez le choix entre l'API de haut niveau ou l'API de bas niveau. Ces API permettent l'utilisation d'en-têtes liés au chiffrement dans votre demande.

  • Lorsque vous utilisez l'API TransferManager de haut niveau , vous fournissez les en-têtes propres au chiffrement dans l'objet PutObjectRequest (voir Chargement d'un objet à l'aide du chargement partitionné).

  • Lorsque vous utilisez l'API de bas niveau, vous fournissez les informations de chiffrement dans l'objet InitiateMultipartUploadRequest, suivies des mêmes informations dans chaque UploadPartRequest. Il est inutile de fournir des en-têtes liés au chiffrement dans votre objet CompleteMultipartUploadRequest. Pour obtenir des exemples, consultez Utilisation des AWS SDK (API de bas niveau).

L'exemple ci-dessous utilise TransferManager pour créer des objets ; il explique également la marche à suivre pour fournir des informations SSE-C. Cet exemple effectue les opérations suivantes :

  • Crée un objet à l'aide de la méthode TransferManager.upload(). Dans l'instance PutObjectRequest, vous fournissez à la demande les informations de clé de chiffrement. Amazon S3 chiffre l'objet en utilisant la clé fournie par le client.

  • Effectue une copie de l'objet en appelant la méthode TransferManager.copy(). L'exemple demande à Amazon S3 de chiffrer la copie de l'objet à l'aide d'un nouvel objet SSECustomerKey. L'objet source étant chiffré au moyen de SSE-C, CopyObjectRequestfournit également la clé de chiffrement de l'objet source, afin qu'Amazon S3 puisse déchiffrer l'objet avant de le copier.

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

Pour télécharger des objets volumineux, vous pouvez utiliser l'API de téléchargement partitionné (voirChargement et copie d'objets à l'aide d'un chargement partitionné). AWS Le SDK for .NET fournit des API de haut niveau ou de bas niveau pour télécharger des objets volumineux. Ces API permettent l'utilisation d'en-têtes liés au chiffrement dans votre demande.

  • Lorsque vous utilisez l'API de haut niveau Transfer-Utility , vous fournissez les en-têtes propres au chiffrement dans l'objet TransferUtilityUploadRequest comme illustré. Pour des exemples de code, consultez Chargement d'un objet à l'aide du chargement partitionné.

    TransferUtilityUploadRequest request = new TransferUtilityUploadRequest() { FilePath = filePath, BucketName = existingBucketName, Key = keyName, // Provide encryption information. ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256, ServerSideEncryptionCustomerProvidedKey = base64Key, };
  • Lorsque vous utilisez l'API de bas niveau, vous fournissez des informations de chiffrement dans votre demande de lancement du chargement partitionné. Ces informations de chiffrement doivent être identiques dans les demandes de chargement partitionné qui suivent. Il est toutefois inutile de fournir des en-têtes liés au chiffrement dans votre demande de fin de chargement partitionné. Pour obtenir des exemples, consultez Utilisation des AWS SDK (API de bas niveau).

    L'exemple suivant concerne un chargement partitionné de niveau inférieur exécutant une copie d'un objet volumineux existant. Dans cet exemple, l'objet à copier est stocké dans Amazon S3 à l'aide d'une clé SSE-C, et vous souhaitez également enregistrer l'objet cible à l'aide d'une clé SSE-C. Dans l'exemple, vous procédez comme suit :

    • Initier une demande de chargement partitionné en fournissant une clé de chiffrement et les informations connexes.

    • Fournir les clés de chiffrement de l'objet source et cible et les informations relatives dans la CopyPartRequest.

    • Obtenir la taille de l'objet source à copier en récupérant les métadonnées de l'objet.

    • Charger les objets par lots de 5 Mo.

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