Especificación del cifrado del lado del servidor con claves proporcionadas por el cliente (SSE-C) - Amazon Simple Storage Service

Especificación del cifrado del lado del servidor con claves proporcionadas por el cliente (SSE-C)

Para utilizar el cifrado del servidor con claves proporcionadas por el cliente (SSE-C), primero asegúrese de que SSE-C no sea un tipo de cifrado bloqueado en la configuración de cifrado predeterminada del bucket de uso general de Amazon S3. Si está bloqueado, puede habilitar este tipo de cifrado actualizando la configuración de cifrado predeterminada del bucket. Luego, puede usar SSE-C en las solicitudes de carga pasando los encabezados necesarios. Consulte Acciones de Amazon S3 que admiten la escritura de datos con SSE-C y asegúrese de incluir Los encabezados de la API de S3 son necesarios para las solicitudes de cifrado y descifrado de objetos con SSE-C.

Cuando carga un objeto especificando SSE-C, Amazon S3 usa la clave de cifrado facilitada para aplicar un cifrado AES-256 a los datos. A continuación, Amazon S3 elimina la clave de cifrado de la memoria. Al recuperar un objeto, debe facilitar la misma clave de cifrado como parte de la solicitud. En primer lugar, Amazon S3 comprueba que la clave de cifrado proporcionada coincida, y a continuación descifra el objeto antes de devolverle los datos del mismo.

Antes de usar SSE-C, asegúrese de haber revisado Consideraciones antes de usar SSE-C.

nota

Amazon S3 no almacena la clave de cifrado que facilite. En su lugar, almacena un valor de código de autenticación de mensajes basado en hash (HMAC) discontinuo aleatorio de la clave de cifrado para validar las solicitudes futuras. El valor HMAC "salted" no se puede usar para derivar el valor de la clave de cifrado ni para descifrar los contenidos del objeto cifrado. Esto implica que, si pierde la clave de cifrado, habrá perdido el objeto.

Acciones de SSE-C y encabezados obligatorios

Para especificar SSE-C en las API de S3 compatibles, es necesario pasar parámetros de solicitud específicos.

nota

La API de PutBucketEncryption de Amazon S3 se usa para configurar el cifrado predeterminado del servidor para un bucket. Sin embargo, PutBucketEncryption no admite la habilitación de SSE-C como método de cifrado predeterminado para un bucket. SSE-C es un método de cifrado por objeto en el que se proporciona la clave de cifrado a Amazon S3 con cada solicitud de carga o descarga de objetos. Amazon S3 utiliza esta clave para cifrar o descifrar el objeto durante la solicitud y, a continuación, descarta la clave. Esto significa que SSE-C se habilita para cada objeto, no como una configuración de bucket predeterminada.

Acciones de Amazon S3 que admiten la escritura de datos con SSE-C

Puede solicitar el cifrado del servidor con claves proporcionadas por el cliente (SSE-C) al escribir objetos en un bucket de uso general mediante las siguientes operaciones o acciones de la API:

nota

La replicación de S3 admite objetos cifrados con SSE-C. Para obtener más información sobre la replicación de objetos cifrados, consulte Replicación de objetos cifrados (SSE-S3, SSE-KMS, DSSE-KMS, SSE-C).

Los encabezados de la API de S3 son necesarios para las solicitudes de cifrado y descifrado de objetos con SSE-C

Debe proporcionar los tres encabezados de API siguientes para cifrar o descifrar objetos con SSE-C:

  • x-amz-server-side-encryption-customer-algorithm Use este encabezado para especificar el algoritmo de cifrado. El valor del encabezado ha de ser AES256.

  • x-amz-server-side-encryption-customer-key Use este encabezado para facilitar la clave de cifrado de 256 bits con codificación base64 para que Amazon S3 pueda usarla para cifrar o descifrar los datos.

  • x-amz-server-side-encryption-customer-key-MD5 Use este encabezado para facilitar el resumen MD5 de 128 bits con codificación en base64 de la clave de cifrado, según la RFC 1321. Amazon S3 usa este encabezado para comprobar la integridad del mensaje y garantizar que la clave de cifrado se haya transmitido sin errores.

Los encabezados de la API de S3 son necesarios para copiar objetos de origen cifrados con SSE-C

Debe proporcionar los tres encabezados de API siguientes para copiar objetos de origen cifrados con SSE-C:

  • x-amz-copy-source-server-side-encryption-customer-algorithm Incluya este encabezado para especificar el algoritmo que debe usar Amazon S3 para descifrar el objeto de origen. Este valor debe ser AES256.

  • x-amz-copy-source-server-side-encryption-customer-key Incluya este encabezado para facilitar la clave de cifrado con codificación base64 para que Amazon S3 la utilice para descifrar el objeto de origen. Esta clave de cifrado debe ser la que proporcionó a Amazon S3 al crear el objeto de origen. De lo contrario, Amazon S3 no puede descifrar el objeto.

  • x-amz-copy-source-server-side-encryption-customer-key-MD5 Incluya este encabezado para facilitar el resumen MD5 de 128 bits con codificación en base64 de la clave de cifrado, según la RFC 1321.

Ejemplo de política de bucket para aplicar el cifrado SSE-C

Para requerir SSE-C para todos los objetos escritos en un bucket de Amazon S3, puede usar una política de bucket. Por ejemplo, la siguiente política de bucket deniega la carga de objetos (s3:PutObject) para todas las solicitudes que no incluyan el encabezado x-amz-server-side-encryption-customer-algorithm que solicita SSE-C.

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

Si utiliza una política de bucket para exigir SSE-C en s3:PutObject, debe incluir el encabezado x-amz-server-side-encryption-customer-algorithm en todas las solicitudes de carga multiparte (CreateMultipartUpload, UploadPart y CompleteMultipartUpload).

URL prefirmadas y SSE-C

Puede generar una URL prefirmada, que podrá utilizar para operaciones como la carga de un nuevo objeto, la recuperación de un objeto existente o la recuperación de metadatos de objetos. Las URL prefirmadas se usan con el SSE-C de la siguiente forma:

  • Al crear una URL prefirmada, debe especificar el algoritmo utilizando el encabezado x-amz-server-side-encryption-customer-algorithm en el cálculo de la firma.

  • Al usar la URL prefirmada para cargar un objeto nuevo, recuperar un objeto existente o recuperar solo metadatos de objetos, debe facilitar todos los encabezados de cifrado en su solicitud de aplicación cliente.

    nota

    Para objetos no SSE-C, puede generar una URL prefirmada y pegar dicha URL directamente en un navegador para acceder a los datos.

    No obstante, no puede hacer esto en objetos SSE-C porque además de la URL prefirmada también debe incluir encabezamientos de HTTP específicos de objetos SSE-C Por tanto, puede usar las URL prefirmadas para objetos SSE-C solo mediante programación.

Para obtener más información acerca de las URL prefirmadas, consulte Descarga y carga de objetos con URL prefirmadas.

Realización de solicitudes con SSE-C

En el momento de la creación de objetos con la API de REST, puede especificar el cifrado del lado del servidor con claves proporcionadas por el cliente (SSE-C). Cuando utilice SSE-C, deberá proporcionar información sobre la clave de cifrado mediante Los encabezados de la API de S3 son necesarios para copiar objetos de origen cifrados con SSE-C. Puede usar las bibliotecas de encapsulamiento del SDK de AWS para agregar estos encabezados a su solicitud. Si lo necesita, también puede realizar las llamadas a la API de REST de Amazon S3 directamente en su aplicación.

importante

Antes de especificar el cifrado del servidor con claves proporcionadas por el cliente (SSE-C), asegúrese de que el cifrado SSE-C no esté bloqueado para el bucket de uso general. Para obtener más información, consulte Bloqueo o desbloqueo de SSE-C para un bucket de uso general.

nota

No puede usar la consola de Amazon S3 para cargar un objeto y solicitar SSE-C. Tampoco puede usar la consola para actualizar (por ejemplo, cambiar la clase de almacenamiento o agregar metadatos) un objeto existente almacenado con SSE-C. Para obtener más información, consulte Los encabezados de la API de S3 son necesarios para las solicitudes de cifrado y descifrado de objetos con SSE-C.

Uso de la API de REST

API de REST de Amazon S3 que admiten SSE-C

Las siguientes API de Amazon S3 admiten el cifrado del lado del servidor con claves de cifrado (SSE-C) proporcionadas por el cliente.

  • Operación GET: cuando recupera datos con la API GET (consulte GET Object), puede especificar los encabezados de solicitud.

  • Operación HEAD: para recuperar metadatos de objetos con la API HEAD (consulte HEAD Object), puede especificar estos encabezados de solicitud.

  • Operación PUT: cuando carga datos con la API de PUT Object (consulte PUT Object), puede especificar estos encabezados de solicitud.

  • Carga multiparte: al cargar objetos grandes mediante la API de carga multiparte, puede especificar estos encabezados. Debe especificar estos encabezados en la solicitud inicial (consulte Iniciar carga multiparte) y en cada solicitud de carga de partes subsiguiente (consulte Cargar parte o UploadPartCopy). Para cada solicitud de carga de parte, la información de cifrado ha de ser la misma que la facilitada en la solicitud inicial de la carga multiparte.

  • Operación POST: cuando utiliza una operación POST para cargar un objeto (consulte POST Object), en vez de proporcionar los encabezados de solicitud, debe proporcionar la misma información en los campos del formulario.

  • Operación copia: cuando copia un objeto (consulte CopyObject), tiene un objeto de origen y uno de destino:

Uso de los SDK de AWS para especificar SSE-C en las operaciones PUT, GET, Head y Copy

En el siguiente ejemplo se muestra cómo solicitar el cifrado del lado del servidor con claves proporcionadas por el cliente (SSE-C) para objetos. En los ejemplos se realizan las siguientes operaciones. Cada operación muestra cómo especificar encabezados relacionados con el SSE-C en la solicitud:

  • Put object: carga un objeto y solicita el cifrado del lado del servidor mediante una clave de cifrado proporcionada por un cliente.

  • Get object: descarga el objeto que se cargó en el paso anterior. En la solicitud, proporciona la misma información de cifrado que proporcionó al cargar el objeto. Amazon S3 necesita esta información para descifrar el objeto de modo que pueda devolvérselo.

  • Get object metadata: recupera los metadatos del objeto. Proporciona la misma información de cifrado usada al crear el objeto.

  • Copy object: realiza una copia del objeto cargado previamente. Dado que el objeto de origen se almacena mediante SSE-C, usted debe proporcionar la información de cifrado en su solicitud de copia. De forma predeterminada, Amazon S3 cifra la copia del objeto solo si lo solicita explícitamente. En este ejemplo se indica a Amazon S3 que almacene una copia cifrada del objeto.

Java
nota

Este ejemplo muestra cómo cargar un objeto en una operación única. Cuando utiliza la API de carga multiparte para cargar objetos grandes, brinda información de cifrado como se muestra en el siguiente ejemplo. Para ver ejemplos de cargas multiparte que utilizan AWS SDK para Java, consulte Carga de un objeto con la carga multiparte.

Para añadir la información de cifrado necesaria, incluya una SSECustomerKey en su solicitud. Para obtener más información sobre la clase SSECustomerKey , consulte la sección REST API (API de REST).

Para obtener instrucciones sobre cómo crear y probar una muestra funcional, consulte Introducción en la Guía para desarrolladores de AWS SDK para Java.

import com.amazonaws.AmazonServiceException; import com.amazonaws.SdkClientException; import com.amazonaws.auth.profile.ProfileCredentialsProvider; import com.amazonaws.regions.Regions; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; import com.amazonaws.services.s3.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
nota

Para ver ejemplos de cómo cargar objetos grandes con la API de carga multiparte, consulte Carga de un objeto con la carga multiparte y Uso de los SDK de AWS (API de bajo nivel).

Para obtener información acerca de cómo configurar y ejecutar ejemplos de código, consulte Introducción al SDK de AWS para .NET en la Guía para desarrolladores del SDK de AWS para .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); } } }

Uso de los SDK de AWS para especificar SSE-C en las cargas multiparte

En el ejemplo de la sección anterior se muestra cómo solicitar cifrado del lado del servidor con claves proporcionadas por el cliente (SSE-C) en operaciones PUT, GET, Head y Copy. En esta sección se describen otras API de Amazon S3 que admiten SSE-C.

Java

Para cargar objetos grandes, puede utilizar las API de carga multiparte. Para obtener más información, consulte Carga y copia de objetos con la carga multiparte en Amazon S3. Puede usar API de nivel alto o de nivel bajo para cargar objetos grandes. Estas API admiten los encabezados relacionados con el cifrado en la solicitud.

  • Cuando utiliza la API de TransferManager de alto nivel, proporciona los encabezados específicos del cifrado en la PutObjectRequest. Para obtener más información, consulte Carga de un objeto con la carga multiparte.

  • Al usar la API de bajo nivel, proporcionará información relacionada con el cifrado en la InitiateMultipartUploadRequest, seguida por información de cifrado idéntica en cada UploadPartRequest. No necesita proporcionar encabezados específicos de cifrado en su CompleteMultipartUploadRequest. Para ver ejemplos, consulte Uso de los SDK de AWS (API de bajo nivel).

En el siguiente ejemplo se usa TransferManager para crear objetos y se muestra cómo facilitar la información relacionada con SSE-C. En el ejemplo se realiza lo siguiente:

  • Crea un objeto mediante el método TransferManager.upload(). En la instancia de PutObjectRequest, proporciona la información de la clave de cifrado en la solicitud. Amazon S3 cifre el objeto utilizando la clave de facilitada por el cliente.

  • Realiza una copia del objeto llamando al método TransferManager.copy(). El ejemplo indica a Amazon S3 que cifre la copia del objeto con una nueva SSECustomerKey. Dado que el objeto de origen está cifrado con SSE-C, la CopyObjectRequest también facilita la clave de cifrado del objeto de origen, de modo que Amazon S3 puede descifrar el objeto antes de copiarlo.

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

Para cargar objetos grandes, puede utilizar la API de carga multiparte (consulte Carga y copia de objetos con la carga multiparte en Amazon S3).AWS SDK para .NET proporciona API de nivel alto o bajo para cargar objetos de gran tamaño. Estas API admiten los encabezados relacionados con el cifrado en la solicitud.

  • Cuando utiliza la API de Transfer-Utility de alto nivel, usted proporciona los encabezados específicos del cifrado en TransferUtilityUploadRequest como se muestra. Para ver ejemplos de código, consulte Carga de un objeto con la carga multiparte.

    TransferUtilityUploadRequest request = new TransferUtilityUploadRequest() { FilePath = filePath, BucketName = existingBucketName, Key = keyName, // Provide encryption information. ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.AES256, ServerSideEncryptionCustomerProvidedKey = base64Key, };
  • Al usar la API de bajo nivel, proporcionará información relacionada con el cifrado en la solicitud de inicio de la carga multiparte, seguida por información de cifrado idéntica en las solicitudes de carga de partes subsiguientes. No necesita proporcionar encabezados específicos de cifrado en su solicitud de carga multiparte completa. Para ver ejemplos, consulte Uso de los SDK de AWS (API de bajo nivel).

    A continuación se muestra un ejemplo de carga multiparte de bajo nivel que hace una copia de un objeto grande existente. En el ejemplo, el objeto que se copiará se guarda en Amazon S3 mediante el SSE-C y usted también desea usar el SSE-C para guardar el objeto de destino. En el ejemplo, hará lo siguiente:

    • Inicie una solicitud de carga multiparte proporcionando una clave de cifrado y la información relacionada.

    • Proporcione las claves de cifrado del objeto de origen y de destino, y la información relacionada en CopyPartRequest.

    • Recupere los metadatos del objeto para obtener el tamaño del objeto de origen que se copiará.

    • Cargue los objetos en partes de 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); } } } }