

# Uso de cifrado en el lado del servidor con claves proporcionadas por el cliente (SSE-C)
<a name="ServerSideEncryptionCustomerKeys"></a>

El cifrado en el servidor consiste en proteger los datos en reposo. El cifrado en el servidor solo cifra los datos de objetos, no los metadatos de objetos. Puede usar el cifrado del servidor con claves proporcionadas por el cliente (SSE-C) en los buckets de propósito general para cifrar los datos con sus propias claves de cifrado. Con la clave de cifrado que proporcione como parte de su solicitud, Amazon S3 administra tanto el cifrado de datos, al escribir en los discos, como el descifrado de datos, al obtener acceso a los objetos. Por tanto, no ha de mantener ningún código para llevar a cabo el cifrado y el descifrado de los datos. Lo único que tiene que hacer es administrar las claves de cifrado que proporcione. 

En la mayoría de casos de uso modernos de Amazon S3 ya no se utiliza SSE-C porque no tiene la flexibilidad del cifrado del servidor con claves administradas por Amazon S3 (SSE-S3) o el cifrado del servidor con claves de AWS KMS (SSE-KMS). El requisito de SSE-C de proporcionar la clave de cifrado cada vez que interactúa con los datos cifrados de SSE-C hace que no sea práctico compartir la clave de SSE-C con otros usuarios, roles o servicios de AWS que leen datos de los buckets de S3 para poder operar en los datos. Debido a la amplia compatibilidad con SSE-KMS en todo AWS, la mayoría de las cargas de trabajo modernas no utilizan el cifrado SSE-C porque carece de la flexibilidad del SSE-KMS. Para obtener más información sobre SSE-KMS, consulte [Uso del cifrado del servidor con claves de AWS KMS (SSE-KMS)](UsingKMSEncryption.md).

Si quiere evitar que el cifrado SSE-C se utilice para los objetos escritos en el bucket, puede bloquear el cifrado SSE-C al cambiar la configuración de cifrado predeterminada del bucket. Cuando se bloquea SSE-C para un bucket de uso general, cualquier solicitud `PutObject`, `CopyObject`, `PostObject`, de carga o replicación multiparte que especifique el cifrado SSE-C se rechazará con un error `HTTP 403 AccessDenied`. Para obtener más información acerca de bloquear SSE-C, consulte [Bloqueo o desbloqueo de SSE-C para un bucket de uso general](blocking-unblocking-s3-c-encryption-gpb.md).

El uso de SSE-C no tiene costes adicionales. Sin embargo, las solicitudes de configuración y uso de SSE-C incurren en cargos estándar de solicitud de Amazon S3. Para obtener información acerca de los precios, consulte [Precios de Amazon S3](https://aws.amazon.com/s3/pricing/).

**importante**  
A partir de abril de 2026, AWS desactivará el cifrado del servidor con claves proporcionadas por el cliente (SSE-C) para todos los buckets nuevos. Además, el cifrado SSE-C se desactivará para todos los buckets existentes en Cuentas de AWS que no contengan datos cifrados con SSE-C. Con estos cambios, las pocas aplicaciones que necesitan el cifrado SSE-C deberán habilitar deliberadamente el uso de SSE-C a través de la API [https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) después de crear el bucket. En estos casos, es posible que deba actualizar los scripts de automatización, las plantillas de CloudFormation u otras herramientas de configuración de infraestructura para configurar estos ajustes. Para obtener más información, consulte la [publicación del Blog de almacenamiento de AWS](https://aws.amazon.com/blogs/storage/advanced-notice-amazon-s3-to-disable-the-use-of-sse-c-encryption-by-default-for-all-new-buckets-and-select-existing-buckets-in-april-2026/).

## Consideraciones antes de usar SSE-C
<a name="considerations-before-using-sse-c"></a>
+ S3 nunca almacena la clave de cifrado cuando se utiliza SSE-C. Debe proporcionar la clave de cifrado cada vez que desee que alguien descargue los datos cifrados con SSE-C de S3. 
  + Debe administrar el mapeo de qué clave de cifrado se utiliza para cifrar cada objeto. Usted debe responsabilizarse de realizar un seguimiento de qué clave de cifrado proporciona para cada objeto. Esto también implica que, si pierde la clave de cifrado, habrá perdido el objeto. 
  + Dado que es usted quien administra las claves de cifrado en el cliente, ha de administrar todas las garantías adicionales, como la rotación de claves, en el lado del cliente. 
  + Este diseño puede dificultar el intercambio de la clave de SSE-C con otros usuarios, roles o servicios de AWS que utilice con los datos. Debido a la amplia compatibilidad con SSE-KMS en todo AWS, la mayoría de las cargas de trabajo modernas no utilizan SSE-C porque carece de la flexibilidad del SSE-KMS. Para obtener más información sobre SSE-KMS, consulte [Uso del cifrado del servidor con claves de AWS KMS (SSE-KMS)](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingKMSEncryption.html). 
  + Esto significa que los objetos cifrados con SSE-C no se pueden descifrar de forma mediante servicios administrados por AWS. 
+ Debe usar HTTPS al especificar los encabezados de SSE-C en las solicitudes.
  + Amazon S3 rechaza cualquier solicitud que se realice por HTTP cuando use SSE-C. Por motivos de seguridad, le recomendamos que tenga en cuenta que cualquier clave que envíe por error sobre HTTP podría estar en peligro. Descarte la clave y practique la rotación apropiada. 
+ Si el bucket tiene habilitado el control de versiones, cada versión del objeto que cargue puede tener su propia clave de cifrado. Usted debe responsabilizarse de realizar un seguimiento de qué clave de cifrado se ha utilizado en cada versión del objeto. 
+ La consola de Amazon S3 no admite SSE-C. No es posible utilizar la consola de Amazon S3 para cargar un objeto y especificar el cifrado 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. 

**Topics**
+ [

## Consideraciones antes de usar SSE-C
](#considerations-before-using-sse-c)
+ [

# Especificación del cifrado del lado del servidor con claves proporcionadas por el cliente (SSE-C)
](specifying-s3-c-encryption.md)
+ [

# Bloqueo o desbloqueo de SSE-C para un bucket de uso general
](blocking-unblocking-s3-c-encryption-gpb.md)
+ [

# Configuración de SSE-C predeterminada para preguntas frecuentes de buckets nuevos
](default-s3-c-encryption-setting-faq.md)

# Especificación del cifrado del lado del servidor con claves proporcionadas por el cliente (SSE-C)
<a name="specifying-s3-c-encryption"></a>

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](#amazon-s3-actions-that-support-writing-data-with-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](#s3-api-headers-required-for-sse-c-object-encryption-and-decryption-requests). 

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](ServerSideEncryptionCustomerKeys.md#considerations-before-using-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.

**Topics**
+ [

## Acciones de SSE-C y encabezados obligatorios
](#sse-c-actions-and-required-headers)
+ [

## Ejemplo de política de bucket para aplicar el cifrado SSE-C
](#example-bucket-policy-to-enforce-sse-c-encryption)
+ [

## URL prefirmadas y SSE-C
](#ssec-and-presignedurl)
+ [

## Realización de solicitudes con SSE-C
](#making-requests-with-sse-c)
+ [

## Uso de la API de REST
](#using-rest-api-sse-c)
+ [

## Uso de los SDK de AWS para especificar SSE-C en las operaciones PUT, GET, Head y Copy
](#sse-c-using-sdks)
+ [

## Uso de los SDK de AWS para especificar SSE-C en las cargas multiparte
](#sse-c-using-sdks-multipart-uploads)

## Acciones de SSE-C y encabezados obligatorios
<a name="sse-c-actions-and-required-headers"></a>

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
<a name="amazon-s3-actions-that-support-writing-data-with-sse-c"></a>

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: 
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CreateMultipartUpload.html)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutObject.html)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPart.html)
+ [https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_UploadPartCopy.html)

**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)](replication-config-for-kms-objects.md). 

### Los encabezados de la API de S3 son necesarios para las solicitudes de cifrado y descifrado de objetos con SSE-C
<a name="s3-api-headers-required-for-sse-c-object-encryption-and-decryption-requests"></a>

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
<a name="s3-api-headers-required-for-requests-to-copy-source-objects-encrypted-with-sse-c"></a>

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
<a name="example-bucket-policy-to-enforce-sse-c-encryption"></a>

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
<a name="ssec-and-presignedurl"></a>

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](using-presigned-url.md).

## Realización de solicitudes con SSE-C
<a name="making-requests-with-sse-c"></a>

 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](#s3-api-headers-required-for-requests-to-copy-source-objects-encrypted-with-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](blocking-unblocking-s3-c-encryption-gpb.md).

**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](#s3-api-headers-required-for-sse-c-object-encryption-and-decryption-requests). 

## Uso de la API de REST
<a name="using-rest-api-sse-c"></a>

### API de REST de Amazon S3 que admiten SSE-C
<a name="sse-c-supported-apis"></a>

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](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectGET.html)), puede especificar los encabezados de solicitud.
+ **Operación HEAD**: para recuperar metadatos de objetos con la API HEAD (consulte [HEAD Object](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectHEAD.html)), puede especificar estos encabezados de solicitud.
+ **Operación PUT**: cuando carga datos con la API de PUT Object (consulte [PUT Object](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html)), 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](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadInitiate.html)) y en cada solicitud de carga de partes subsiguiente (consulte [Cargar parte](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPart.html) o [UploadPartCopy](https://docs.aws.amazon.com/AmazonS3/latest/API/mpUploadUploadPartCopy.html)). 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](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPOST.html)), 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](https://docs.aws.amazon.com/AmazonS3/latest/API/API_CopyObject.html)), tiene un objeto de origen y uno de destino:
  + Si desea especificar el tipo de cifrado del objeto de destino, debe proporcionar el encabezado de solicitud `x-amz-server-side-encryption `.
  + Si quiere que el objeto de destino se cifre mediante SSE-C, debe facilitar información de cifrado mediante la API de S3 [Los encabezados de la API de S3 son necesarios para las solicitudes de cifrado y descifrado de objetos con SSE-C](#s3-api-headers-required-for-sse-c-object-encryption-and-decryption-requests).
  + Si el objeto de origen se cifra mediante SSE-C, debe proporcionar información clave de cifrado mediante los encabezados de la API de S3 [Los encabezados de la API de S3 son necesarios para copiar objetos de origen cifrados con SSE-C](#s3-api-headers-required-for-requests-to-copy-source-objects-encrypted-with-sse-c).

## Uso de los SDK de AWS para especificar SSE-C en las operaciones PUT, GET, Head y Copy
<a name="sse-c-using-sdks"></a>

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](mpu-upload-object.md).

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](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/getting-started.html) en la Guía para desarrolladores de AWS SDK para Java.

**Example**  

```
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](mpu-upload-object.md) y [Uso de los SDK de AWS (API de bajo nivel)](mpu-upload-object.md#mpu-upload-low-level).

Para obtener información acerca de cómo configurar y ejecutar ejemplos de código, consulte [Introducción al SDK de AWS para .NET](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html) en la *Guía para desarrolladores del SDK de AWS para .NET*. 

**Example**  

```
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
<a name="sse-c-using-sdks-multipart-uploads"></a>

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](mpuoverview.md). 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](mpu-upload-object.md). 
+ 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)](mpu-upload-object.md#mpu-upload-low-level). 

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. 

**Example**  

```
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](mpuoverview.md)).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](mpu-upload-object.md).

  ```
  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)](mpu-upload-object.md#mpu-upload-low-level).

  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.  
**Example**  

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

------

# Bloqueo o desbloqueo de SSE-C para un bucket de uso general
<a name="blocking-unblocking-s3-c-encryption-gpb"></a>

En la mayoría de casos de uso modernos de Amazon S3 ya no se utiliza el cifrado del servidor con claves proporcionadas por el cliente (SSE-C) porque no tiene la flexibilidad del cifrado del servidor con claves administradas por Amazon S3 (SSE-S3) o el cifrado del servidor con claves de AWS KMS (SSE-KMS). El requisito de SSE-C de proporcionar la clave de cifrado cada vez que interactúa con los datos cifrados de SSE-C hace que no sea práctico compartir la clave de SSE-C con otros usuarios, roles o servicios de AWS que leen datos de los buckets de S3 para poder operar en los datos.

Para limitar los tipos de cifrado del servidor que puede utilizar en los buckets de uso general, tiene la opción de elegir bloquear las solicitudes de escritura de SSE-C actualizando la configuración de cifrado predeterminada de los buckets. Esta configuración por bucket bloquea las solicitudes de carga de objetos que especifican SSE-C. Cuando se bloquea SSE-C para un bucket, cualquier solicitud `PutObject`, `CopyObject`, `PostObject` o de replicación o carga multiparte que especifique el cifrado SSE-C se rechazará con un error HTTP 403 `AccessDenied`.

Esta configuración es un parámetro de la API de `PutBucketEncryption` y también se puede actualizar mediante la consola de S3, la AWS CLI y los AWS SDK, si tiene el permiso `s3:PutEncryptionConfiguration`.

Los valores válidos son `SSE-C`, que bloquea el cifrado SSE-C para el bucket de uso general y `NONE`, que permite usar SSE-C para escribir en el bucket.

**importante**  
A partir de abril de 2026, AWS desactivará el cifrado del servidor con claves proporcionadas por el cliente (SSE-C) para todos los buckets nuevos. Además, el cifrado SSE-C se desactivará para todos los buckets existentes en Cuentas de AWS que no contengan datos cifrados con SSE-C. Con estos cambios, las pocas aplicaciones que necesitan el cifrado SSE-C deberán habilitar deliberadamente el uso de SSE-C a través de la API [https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) después de crear el bucket. En estos casos, es posible que deba actualizar los scripts de automatización, las plantillas de CloudFormation u otras herramientas de configuración de infraestructura para configurar estos ajustes. Para obtener más información, consulte la [publicación del Blog de almacenamiento de AWS](https://aws.amazon.com/blogs/storage/advanced-notice-amazon-s3-to-disable-the-use-of-sse-c-encryption-by-default-for-all-new-buckets-and-select-existing-buckets-in-april-2026/).

## Permisos
<a name="bucket-encryption-permissions"></a>

Utilice la API de `PutBucketEncryption` o la consola de S3, los AWS SDK o la AWS CLI para bloquear o desbloquear los tipos de cifrado para un bucket de uso general. Debe tener el siguiente permiso:
+ `s3:PutEncryptionConfiguration`

Utilice la API de `GetBucketEncryption` o la consola de S3, los AWS SDK o la AWS CLI para ver los tipos de cifrado bloqueados para un bucket de uso general. Debe tener el siguiente permiso:
+ `s3:GetEncryptionConfiguration`

## Consideraciones antes de bloquear el cifrado SSE-C
<a name="considerations-before-blocking-sse-c"></a>

Después de bloquear SSE-C para cualquier bucket, se aplica el siguiente comportamiento de cifrado:
+ No hay ninguna variación en el cifrado de los objetos que existían en el bucket antes de que bloqueara el cifrado SSE-C.
+ Tras bloquear el cifrado SSE-C, puede seguir realizando solicitudes GetObject y HeadObject en objetos preexistentes cifrados con SSE-C siempre que proporcione los encabezados de SSE-C necesarios en las solicitudes.
+ Cuando se bloquea SSE-C para un bucket, cualquier solicitud `PutObject`, `CopyObject`, `PostObject` o de carga multiparte que especifique el cifrado SSE-C se rechazará con un error 403 `AccessDenied`.
+ Si un bucket de destino para la replicación tiene SSE-C bloqueado y los objetos de origen que se están replicando están cifrados con SSE-C, la replicación producirá un error HTTP 403 `AccessDenied`.

Si quiere comprobar si utiliza el cifrado SSE-C en alguno de los buckets antes de bloquear este tipo de cifrado, puede utilizar herramientas como [AWS CloudTrail](https://aws.amazon.com/cloudtrail/) para supervisar el acceso a los datos. En esta [entrada de blog](https://aws.amazon.com/blogs/storage/auditing-amazon-s3-server-side-encryption-methods-for-object-uploads/), se muestra cómo auditar los métodos de cifrado para la carga de objetos en tiempo real. También puede consultar este [artículo de re:Post](https://repost.aws/articles/ARhGC12rOiTBCKHcAe9GZXCA/how-to-detect-existing-use-of-sse-c-in-your-amazon-s3-buckets) como guía a la hora de consultar los informes de inventario de S3 para ver si tiene algún objeto cifrado con SSE-C.

### Steps
<a name="block-sse-c-gpb-steps"></a>

Puede bloquear o desbloquear el cifrado del servidor con claves proporcionadas por el cliente (SSE-C) para un bucket de uso general mediante la consola de Amazon S3, la AWS Command Line Interface (AWS CLI), la API de REST de Amazon S3 y los AWS SDK.

### Uso de la consola de S3
<a name="block-sse-c-gpb-console"></a>

Para bloquear o desbloquear el cifrado SSE-C de un bucket mediante la consola de Amazon S3:

1. Inicie sesión en la consola de administración de AWS y abra la consola de Amazon S3 en https://console.aws.amazon.com/s3/.

1. En el panel de navegación izquierdo, elija **Buckets de uso general**.

1. Seleccione el bucket para el que desea bloquear el cifrado SSE-C.

1. Seleccione la pestaña **Propiedades** del bucket.

1. Navegue hasta el panel de propiedades de **Cifrado predeterminado** del bucket y seleccione **Editar**.

1. En la sección **Tipos de cifrado bloqueados**, marque la casilla situada junto a **Cifrado del servidor con claves proporcionadas por el cliente (SSE-C)** para bloquear el cifrado SSE-C o desmarque esta casilla para permitir SSE-C.

1. Seleccione **Save Changes (Guardar cambios)**.

### Uso de AWS CLI
<a name="block-sse-c-gpb-cli"></a>

Para instalar la CLI de AWS, consulte [Instalación de la CLI de AWS](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) en la *Guía del usuario de AWS Command Line Interface*.

En el ejemplo de la CLI siguiente se muestra cómo bloquear o desbloquear el cifrado SSE-C para un bucket de uso general mediante la AWS CLI. Para usar el comando, sustituya los *marcadores de posición de entrada del usuario* con su propia información.

**Solicitud para bloquear el cifrado SSE-C para un bucket de uso general:**

```
aws s3api put-bucket-encryption \
  --bucket amzn-s3-demo-bucket \
  --server-side-encryption-configuration '{
    "Rules": [{
      "BlockEncryptionTypes": {
        "EncryptionType": "SSE-C"
      }
    }]
  }'
```

**Solicitud para habilitar el uso del cifrado SSE-C en un bucket de uso general:**

```
aws s3api put-bucket-encryption \
  --bucket amzn-s3-demo-bucket \
  --server-side-encryption-configuration '{
    "Rules": [{
      "BlockEncryptionTypes": {
        "EncryptionType": "NONE"
      }
    }]
  }'
```

## Uso de los AWS SDK
<a name="block-sse-c-gpb-sdks"></a>

------
#### [ SDK for Java 2.x ]

En los ejemplos siguientes, se muestra cómo bloquear o desbloquear las escrituras de cifrado SSE-C para los buckets de uso general mediante los AWS SDK.

**Ejemplo: solicitud PutBucketEncryption que establece la configuración de cifrado predeterminada en SSE-S3 y bloquea SSE-C**

```
S3Client s3Client = ...;
ServerSideEncryptionByDefault defaultSse = ServerSideEncryptionByDefault
        .builder()
        .sseAlgorithm(ServerSideEncryption.AES256)
        .build();
BlockedEncryptionTypes blockedEncryptionTypes = BlockedEncryptionTypes
        .builder()
        .encryptionType(EncryptionType.SSE_C)
        .build();
ServerSideEncryptionRule rule = ServerSideEncryptionRule.builder()
        .applyServerSideEncryptionByDefault(defaultSse)
        .blockedEncryptionTypes(blockedEncryptionTypes)
        .build();
s3Client.putBucketEncryption(be -> be
        .bucket(bucketName)
        .serverSideEncryptionConfiguration(c -> c.rules(rule)));
```

**Ejemplo: solicitud PutBucketEncryption que establece la configuración de cifrado predeterminada en SSE-S3 y desbloquea SSE-C**

```
S3Client s3Client = ...;
ServerSideEncryptionByDefault defaultSse = ServerSideEncryptionByDefault
        .builder()
        .sseAlgorithm(ServerSideEncryption.AES256)
        .build();
BlockedEncryptionTypes blockedEncryptionTypes = BlockedEncryptionTypes
        .builder()
        .encryptionType(EncryptionType.NONE)
        .build();
ServerSideEncryptionRule rule = ServerSideEncryptionRule.builder()
        .applyServerSideEncryptionByDefault(defaultSse)
        .blockedEncryptionTypes(blockedEncryptionTypes)
        .build();
s3Client.putBucketEncryption(be -> be
        .bucket(bucketName)
        .serverSideEncryptionConfiguration(c -> c.rules(rule)));
```

------
#### [ SDK for Python Boto3 ]

**Ejemplo: solicitud PutBucketEncryption que establece la configuración de cifrado predeterminada en SSE-S3 y bloquea SSE-C**

```
s3 = boto3.client("s3")
s3.put_bucket_encryption(
    Bucket="amzn-s3-demo-bucket",
    ServerSideEncryptionConfiguration={
        "Rules":[{
            "ApplyServerSideEncryptionByDefault": {
                "SSEAlgorithm": "AES256"
            },
            "BlockedEncryptionTypes": {
                "EncryptionType": ["SSE-C"]
            }
        }]
    }
)
```

**Ejemplo: solicitud PutBucketEncryption que establece la configuración de cifrado predeterminada en SSE-S3 y desbloquea SSE-C**

```
s3 = boto3.client("s3")
s3.put_bucket_encryption(
    Bucket="amzn-s3-demo-bucket",
    ServerSideEncryptionConfiguration={
        "Rules":[{
            "ApplyServerSideEncryptionByDefault": {
                "SSEAlgorithm": "AES256"
            },
            "BlockedEncryptionTypes": {
                "EncryptionType": ["NONE"]
            }
        }]
    }
)
```

------

## Uso de la API de REST
<a name="bucket-tag-add-api"></a>

Para obtener información sobre la compatibilidad con la API de REST de Amazon S3 para el bloqueo o desbloqueo del cifrado SSE-C para un bucket de uso general, consulte la siguiente sección en la *Referencia de la API de Amazon Simple Storage Service*:
+ Tipo de datos [BlockedEncryptionTypes](https://docs.aws.amazon.com/AmazonS3/latest/API/API_BlockedEncryptionTypes.html) usado en el tipo de datos [ServerSideEncryptionRule](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ServerSideEncryptionRule.html) de las operaciones de la API [PutBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) y [GetBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketEncryption.html).

# Configuración de SSE-C predeterminada para preguntas frecuentes de buckets nuevos
<a name="default-s3-c-encryption-setting-faq"></a>

**importante**  
A partir de abril de 2026, AWS desactivará el cifrado del servidor con claves proporcionadas por el cliente (SSE-C) para todos los buckets nuevos. Además, el cifrado SSE-C se desactivará para todos los buckets existentes en Cuentas de AWS que no contengan datos cifrados con SSE-C. Con estos cambios, las pocas aplicaciones que necesitan el cifrado SSE-C deberán habilitar deliberadamente el uso de SSE-C a través de la API [https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) después de crear el bucket. En estos casos, es posible que deba actualizar los scripts de automatización, las plantillas de CloudFormation u otras herramientas de configuración de infraestructura para configurar estos ajustes. Para obtener más información, consulte la [publicación del Blog de almacenamiento de AWS](https://aws.amazon.com/blogs/storage/advanced-notice-amazon-s3-to-disable-the-use-of-sse-c-encryption-by-default-for-all-new-buckets-and-select-existing-buckets-in-april-2026/).

Las siguientes secciones responden a las preguntas sobre esta actualización.

**1. En abril de 2026, ¿entrará en vigor la nueva configuración de SSE-C para todos los buckets recién creados?**

Sí. Durante el mes de abril de 2026, la nueva configuración predeterminada se implementará gradualmente en todas las regiones de AWS.

**2. ¿Cuánto tiempo pasará antes de que esta implementación cubra todas las regiones de AWS?**

Esta actualización tardará varias semanas en lanzarse. Realizaremos una publicación sobre las novedades cuando empecemos a implementar esta actualización.

**3. Cómo sabré que la actualización se ha completado?**

Para determinar fácilmente si el cambio se ha realizado en la región de AWS, cree un nuevo bucket y llame a la operación de la API [GetBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketEncryption.html) para determinar si el cifrado SSE-C está desactivado. Una vez finalizada la actualización, todos los buckets de uso general desactivarán automáticamente el cifrado SSE-C de forma predeterminada. Puede ajustar esta configuración después de crear el bucket de S3 mediante la operación de la API [PutBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html).

**4. Amazon S3 actualizará las configuraciones de mis bucket existentes?**

Si la cuenta de AWS no tiene ningún objeto con cifrado SSE-C, AWS desactivará el cifrado SSE-C en todos los buckets existentes. Si algún bucket de la cuenta de AWS tiene objetos con cifrado SSE-C, AWS no cambiará la configuración del bucket de ninguno de los buckets de esa cuenta. Cuando se complete el cambio `CreateBucket` en la región de AWS, la nueva configuración predeterminada se aplicará a todos los nuevos buckets de uso general. 

 **5. Puedo desactivar el cifrado SSE-C para mis buckets antes de que se complete la actualización?** 

Sí. Para desactivar el cifrado SSE-C en cualquier bucket, llame a la operación de la API [PutBucketEncryption](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html) y especifique el nuevo encabezado `BlockedEncryptionTypes`. 

**6. Puedo usar SSE-C para cifrar los datos de mis nuevos buckets?**

Sí. En la mayoría de casos de uso modernos de Amazon S3 ya no se utiliza SSE-C porque no tiene la flexibilidad del cifrado del servidor con claves administradas por Amazon S3 (SSE-S3) o el cifrado del servidor con claves de AWS KMS (SSE-KMS). Si necesita usar el cifrado SSE-C en un bucket nuevo, puede crear el nuevo bucket y, a continuación, habilitar el uso del cifrado SSE-C en una solicitud `PutBucketEncryption` independiente.

 **Ejemplo**

```
aws s3api create-bucket \  
bucket amzn-s3-demo-bucket \ 
region us-east-1 \ 
  
aws s3api put-bucket-encryption \  
-- bucket amzn-s3-demo-bucket \
-- server-side-encryption-configuration \
'{ \Rules\: [{   
   {   
   \ApplyServerSideEncryptionByDefault\: {   
     \SSEAlgorithm\: \AES256\,  
    },   
   \BlockedEncryptionTypes\: [  
     \EncryptionType\:\NONE\]   
   }   
   }]   
}'
```

**nota**  
Debe tener el permiso `s3:PutEncryptionConfiguration` para llamar a la API `PutBucketEncryption`. 

**7. Cómo afecta el bloqueo de SSE-C a las solicitudes a mi bucket?**

Cuando se bloquea SSE-C para un bucket, cualquier solicitud `PutObject`, `CopyObject`, `PostObject` o de replicación o carga multiparte que especifique el cifrado SSE-C se rechazará con un error HTTP 403 `AccessDenied`. 