

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

# SDK de cifrado de AWS para Java
<a name="java"></a>

En este tema se explica cómo instalar y utilizar el SDK de cifrado de AWS para Java. Para obtener detalles sobre la programación con SDK de cifrado de AWS para Java, consulte el [aws-encryption-sdk-java](https://github.com/aws/aws-encryption-sdk-java/)repositorio en GitHub. Para obtener documentación de la API, consulte la documentación de [Javadoc](https://aws.github.io/aws-encryption-sdk-java/) para SDK de cifrado de AWS para Java.

**Topics**
+ [Requisitos previos](#java-prerequisites)
+ [Instalación](#java-installation)
+ [Ejemplos](java-example-code.md)

## Requisitos previos
<a name="java-prerequisites"></a>

Antes de instalarlo SDK de cifrado de AWS para Java, asegúrese de cumplir los siguientes requisitos previos.

**Un entorno de desarrollo de Java**  
Necesitará Java 8 o una versión posterior. En el sitio web de Oracle, vaya a la página de [descargas de Java SE](https://www.oracle.com/java/technologies/downloads/) y, a continuación, descargue e instale el Java SE Development Kit (JDK).  
Si utiliza el JDK de Oracle, también debe descargar e instalar los [archivos de políticas de jurisdicción de seguridad ilimitada de la extensión de criptografía de Java (JCE)](http://www.oracle.com/java/technologies/javase-jce8-downloads.html).

**Bouncy Castle**  
 SDK de cifrado de AWS para Java Requiere [Bouncy Castle.](https://www.bouncycastle.org/download/bouncy-castle-java/)   
+ SDK de cifrado de AWS para Java las versiones 1.6.1 y posteriores utilizan Bouncy Castle para serializar y deserializar objetos criptográficos. Puede utilizar Bouncy Castle o [Bouncy Castle FIPS](https://www.bouncycastle.org/about/bouncy-castle-fips-faq/) para cumplir este requisito. ****Si necesita ayuda para instalar y configurar el FIPS de Bouncy Castle, consulte la [documentación del FIPS de BC](https://www.bouncycastle.org/documentation/), especialmente las guías de usuario y la política de seguridad.**** PDFs
+ Las versiones anteriores SDK de cifrado de AWS para Java utilizan la API de criptografía de Bouncy Castle para Java. Este requisito solo se cumple con el Bouncy Castle que no es de FIPS.
Si no tienes Bouncy Castle, ve a [Descargar Bouncy Castle para Java para](https://bouncycastle.org/download/bouncy-castle-java/) descargar el archivo del proveedor correspondiente a tu JDK. [También puedes usar [Apache Maven](https://maven.apache.org/) para obtener el artefacto para el proveedor estándar de Bouncy Castle ([bcprov-ext-jdk15on](https://mvnrepository.com/artifact/org.bouncycastle/bcprov-ext-jdk15on)) o el artefacto para Bouncy Castle FIPS (bc-fips).](https://mvnrepository.com/artifact/org.bouncycastle/bc-fips)

**AWS SDK para Java**  
Versión 3. *x* de los SDK de cifrado de AWS para Java requiere el AWS SDK for Java 2.x, incluso si no usas AWS KMS llaveros.  
Versión 2. *x* o una versión anterior de SDK de cifrado de AWS para Java no requiere la AWS SDK para Java. Sin embargo, AWS SDK para Java es necesario para usar [AWS Key Management Service](https://aws.amazon.com/kms/)(AWS KMS) como proveedor de claves maestras. A partir de la SDK de cifrado de AWS para Java versión 2.4.0, SDK de cifrado de AWS para Java es compatible con las versiones 1.x y 2.x de. AWS SDK para Java AWS Encryption SDK el código de la AWS SDK para Java 1.x y la 2.x es interoperable. Por ejemplo, puede cifrar los datos con un AWS Encryption SDK código compatible con la versión AWS SDK para Java 1.x y descifrarlos con un código compatible AWS SDK for Java 2.x (o viceversa). Las versiones anteriores a la 2.4.0 SDK de cifrado de AWS para Java solo admiten la versión 1.x. AWS SDK para Java Para obtener información sobre cómo actualizar su versión de AWS Encryption SDK, consulte. [Migración de su AWS Encryption SDK](migration.md)  
Al actualizar el SDK de cifrado de AWS para Java código de la versión AWS SDK para Java 1.x a AWS SDK for Java 2.x, sustituya las referencias a la [`AWSKMS`interfaz](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/kms/package-summary.html) de la versión AWS SDK para Java 1.x por las referencias a la [`KmsClient`interfaz](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kms/package-summary.html) de. AWS SDK for Java 2.x[No SDK de cifrado de AWS para Java es compatible con la `KmsAsyncClient` interfaz.](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kms/KmsAsyncClient.html) Además, actualice el código para usar los objetos relacionados al AWS KMS en el espacio de nombres de `kmssdkv2`, en lugar del espacio de nombres de `kms`.   
Para instalar AWS SDK para Java, utilice Apache Maven.   
+ Para [importar todo el AWS SDK para Java](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-project-maven.html#build-the-entire-sdk-into-your-project) como una dependencia declárelo en el archivo `pom.xml`.
+ Para crear una dependencia solo para el AWS KMS módulo de la AWS SDK para Java versión 1.x, siga las instrucciones para [especificar determinados módulos](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/setup-project-maven.html#modules-dependencies) y establezca el `artifactId` valor. `aws-java-sdk-kms`
+ Para crear una dependencia solo para el AWS KMS módulo de la versión AWS SDK para Java 2.x, siga las instrucciones para [especificar módulos concretos](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-project-maven.html#modules-dependencies). Establece el `groupId` en `software.amazon.awssdk` y el `artifactId` en `kms`.
Para ver más cambios, consulta las [diferencias entre la versión AWS SDK para Java 1.x y la 2.x](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/migration-whats-different.html) en la AWS SDK for Java 2.x Guía para desarrolladores.  
Los ejemplos de Java de la Guía AWS Encryption SDK para desarrolladores utilizan el. AWS SDK for Java 2.x

## Instalación
<a name="java-installation"></a>

Instale la versión más reciente de SDK de cifrado de AWS para Java.

**nota**  
Todas las versiones SDK de cifrado de AWS para Java anteriores a la 2.0.0 se encuentran en esta [end-of-supportfase](https://docs.aws.amazon.com/sdkref/latest/guide/maint-policy.html#version-life-cycle).  
Puede actualizar de forma segura desde la versión 2.0.*x* y versiones posteriores a la última versión de SDK de cifrado de AWS para Java sin cambios en el código ni en los datos. Sin embargo, [nuevas características de seguridad](about-versions.md#version-2) que se introdujeron en la versión 2.0.*x* no son compatibles con versiones anteriores. Para actualizar desde versiones anteriores a la 1.7.*x* a la versión 2.0.*x* y posteriores, primero debe actualizar a la última versión 1.*x* de AWS Encryption SDK. Para obtener más información, consulte [Migrando su AWS Encryption SDK](migration.md).

Puede instalarlo de SDK de cifrado de AWS para Java las siguientes maneras.

**Manualmente**  
Para instalarlo SDK de cifrado de AWS para Java, clone o descargue el [aws-encryption-sdk-java](https://github.com/aws/aws-encryption-sdk-java/) GitHubrepositorio.

**Con Apache Maven**  
 SDK de cifrado de AWS para Java Está disponible a través de [Apache Maven](https://maven.apache.org/) con la siguiente definición de dependencia.  

```
<dependency>
  <groupId>com.amazonaws</groupId>
  <artifactId>aws-encryption-sdk-java</artifactId>
  <version>3.0.0</version>
</dependency>
```

Después de instalar el SDK, comience consultando el [ejemplo de código Java](java-example-code.md) de esta guía y el [Javadoc](https://aws.github.io/aws-encryption-sdk-java/) que aparece en él. GitHub

# SDK de cifrado de AWS para Java ejemplos
<a name="java-example-code"></a>

Los siguientes ejemplos muestran cómo utilizarlos SDK de cifrado de AWS para Java para cifrar y descifrar datos. Estos ejemplos muestran cómo utilizar la versión 3. *x* y versiones posteriores de SDK de cifrado de AWS para Java. Versión 3. *x* de los SDK de cifrado de AWS para Java requiere el AWS SDK for Java 2.x. Versión 3. *x* de SDK de cifrado de AWS para Java reemplaza a los [proveedores de llaves maestras](concepts.md#master-key-provider) por [llaveros](concepts.md#keyring). Para ver ejemplos que utilizan versiones anteriores, busca tu versión en la lista de [versiones](https://github.com/aws/aws-encryption-sdk-java/releases) del [aws-encryption-sdk-java](https://github.com/aws/aws-encryption-sdk-java/)repositorio de GitHub.

**Topics**
+ [Cadenas](#java-example-strings)
+ [Secuencias de bytes](#java-example-streams)
+ [Secuencias de bytes con varios proveedores de claves maestras](#java-example-multiple-providers)

## Cifrado y descifrado de cadenas
<a name="java-example-strings"></a>

En el siguiente ejemplo, se muestra cómo utilizar la versión 3. *x* de SDK de cifrado de AWS para Java para cifrar y descifrar cadenas. Antes de usar la cadena, conviértala en una matriz de bytes.

[En este ejemplo se utiliza un AWS KMS anillo de claves.](use-kms-keyring.md) Al cifrar con un AWS KMS anillo de claves, puede usar un ID de clave, un ARN de clave, un nombre de alias o un ARN de alias para identificar las claves de KMS. Al descifrar, debe utilizar una clave ARN para identificar las claves de KMS.

Cuando se llama al método `encryptData()`, este devuelve un [mensaje cifrado](concepts.md#message) (`CryptoResult`) que incluye el texto cifrado, las claves de datos cifradas y el contexto de cifrado. Cuando llama a `getResult` en el objeto `CryptoResult`, se devuelve una versión de cadena codificada en base 64 del [mensaje cifrado](message-format.md) que puede pasar al método `decryptData()`.

Del mismo modo, cuando llamas`decryptData()`, el `CryptoResult` objeto que devuelve contiene el mensaje de texto sin formato y un identificador. AWS KMS key Antes de que la aplicación devuelva el texto sin formato, compruebe que el AWS KMS key identificador y el contexto de cifrado del mensaje cifrado son los esperados.

```
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package com.amazonaws.crypto.keyrings;

import com.amazonaws.encryptionsdk.AwsCrypto;
import com.amazonaws.encryptionsdk.CommitmentPolicy;
import com.amazonaws.encryptionsdk.CryptoResult;
import software.amazon.cryptography.materialproviders.IKeyring;
import software.amazon.cryptography.materialproviders.MaterialProviders;
import software.amazon.cryptography.materialproviders.model.CreateAwsKmsMultiKeyringInput;
import software.amazon.cryptography.materialproviders.model.MaterialProvidersConfig;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;

/**
 * Encrypts and then decrypts data using an AWS KMS Keyring.
 *
 * <p>Arguments:
 *
 * <ol>
 *   <li>Key ARN: For help finding the Amazon Resource Name (ARN) of your AWS KMS customer master
 *       key (CMK), see 'Viewing Keys' at
 *       http://docs.aws.amazon.com/kms/latest/developerguide/viewing-keys.html
 * </ol>
 */
public class BasicEncryptionKeyringExample {

  private static final byte[] EXAMPLE_DATA = "Hello World".getBytes(StandardCharsets.UTF_8);

  public static void main(final String[] args) {
    final String keyArn = args[0];

    encryptAndDecryptWithKeyring(keyArn);
  }

  public static void encryptAndDecryptWithKeyring(final String keyArn) {
    // 1. Instantiate the SDK
    // This builds the AwsCrypto client with the RequireEncryptRequireDecrypt commitment policy,
    // which means this client only encrypts using committing algorithm suites and enforces
    // that the client will only decrypt encrypted messages that were created with a committing
    // algorithm suite.
    // This is the default commitment policy if you build the client with
    // `AwsCrypto.builder().build()`
    // or `AwsCrypto.standard()`.
    final AwsCrypto crypto =
        AwsCrypto.builder()
            .withCommitmentPolicy(CommitmentPolicy.RequireEncryptRequireDecrypt)
            .build();

    // 2. Create the AWS KMS keyring.
    // This example creates a multi keyring, which automatically creates the KMS client.
    final MaterialProviders materialProviders =
        MaterialProviders.builder()
            .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
            .build();
    final CreateAwsKmsMultiKeyringInput keyringInput =
        CreateAwsKmsMultiKeyringInput.builder().generator(keyArn).build();
    final IKeyring kmsKeyring = materialProviders.CreateAwsKmsMultiKeyring(keyringInput);

    // 3. Create an encryption context
    // We recommend using an encryption context whenever possible
    // to protect integrity. This sample uses placeholder values.
    // For more information see:
    // blogs.aws.amazon.com/security/post/Tx2LZ6WBJJANTNW/How-to-Protect-the-Integrity-of-Your-Encrypted-Data-by-Using-AWS-Key-Management
    final Map<String, String> encryptionContext =
        Collections.singletonMap("ExampleContextKey", "ExampleContextValue");

    // 4. Encrypt the data
    final CryptoResult<byte[], ?> encryptResult =
        crypto.encryptData(kmsKeyring, EXAMPLE_DATA, encryptionContext);
    final byte[] ciphertext = encryptResult.getResult();

    // 5. Decrypt the data
    final CryptoResult<byte[], ?> decryptResult =
        crypto.decryptData(
            kmsKeyring,
            ciphertext,
            // Verify that the encryption context in the result contains the
            // encryption context supplied to the encryptData method
            encryptionContext);

    // 6. Verify that the decrypted plaintext matches the original plaintext
    assert Arrays.equals(decryptResult.getResult(), EXAMPLE_DATA);
  }
}
```

## Cifrado y descifrado de secuencias de bytes
<a name="java-example-streams"></a>

En el siguiente ejemplo, se muestra cómo utilizarlos AWS Encryption SDK para cifrar y descifrar secuencias de bytes.

En este ejemplo se utiliza un anillo de claves [AES sin procesar.](use-raw-aes-keyring.md)

Al cifrar, en este ejemplo se utiliza el método `AwsCrypto.builder() .withEncryptionAlgorithm()` para especificar un conjunto de algoritmos sin [firmas digitales.](concepts.md#digital-sigs) Al descifrar, para garantizar que el texto cifrado no esté firmado, en este ejemplo se utiliza el método `createUnsignedMessageDecryptingStream()`. El `createUnsignedMessageDecryptingStream()` método falla si encuentra un texto cifrado con una firma digital. 

Si está cifrando con el conjunto de algoritmos predeterminado, que incluye firmas digitales, utilice el método `createDecryptingStream()` en su lugar, como se muestra en el siguiente ejemplo.

```
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package com.amazonaws.crypto.keyrings;

import com.amazonaws.encryptionsdk.AwsCrypto;
import com.amazonaws.encryptionsdk.CommitmentPolicy;
import com.amazonaws.encryptionsdk.CryptoAlgorithm;
import com.amazonaws.encryptionsdk.CryptoInputStream;
import com.amazonaws.encryptionsdk.jce.JceMasterKey;
import com.amazonaws.util.IOUtils;
import software.amazon.cryptography.materialproviders.IKeyring;
import software.amazon.cryptography.materialproviders.MaterialProviders;
import software.amazon.cryptography.materialproviders.model.AesWrappingAlg;
import software.amazon.cryptography.materialproviders.model.CreateRawAesKeyringInput;
import software.amazon.cryptography.materialproviders.model.MaterialProvidersConfig;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.security.SecureRandom;
import java.util.Collections;
import java.util.Map;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;


/**
 * <p>
 * Encrypts and then decrypts a file under a random key.
 *
 * <p>
 * Arguments:
 * <ol>
 * <li>Name of file containing plaintext data to encrypt
 * </ol>
 *
 * <p>
 * This program demonstrates using a standard Java {@link SecretKey} object as a {@link IKeyring} to
 * encrypt and decrypt streaming data.
 */
public class FileStreamingKeyringExample {
    private static String srcFile;

    public static void main(String[] args) throws IOException {
        srcFile = args[0];

        // In this example, we generate a random key. In practice, 
        // you would get a key from an existing store
        SecretKey cryptoKey = retrieveEncryptionKey();

        // Create a Raw Aes Keyring using the random key and an AES-GCM encryption algorithm
        final MaterialProviders materialProviders = MaterialProviders.builder()
                .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
                .build();
        final CreateRawAesKeyringInput keyringInput = CreateRawAesKeyringInput.builder()
                .wrappingKey(ByteBuffer.wrap(cryptoKey.getEncoded()))
                .keyNamespace("Example")
                .keyName("RandomKey")
                .wrappingAlg(AesWrappingAlg.ALG_AES128_GCM_IV12_TAG16)
                .build();
        IKeyring keyring = materialProviders.CreateRawAesKeyring(keyringInput);

        // Instantiate the SDK.
        // This builds the AwsCrypto client with the RequireEncryptRequireDecrypt commitment policy,
        // which means this client only encrypts using committing algorithm suites and enforces
        // that the client will only decrypt encrypted messages that were created with a committing
        // algorithm suite.
        // This is the default commitment policy if you build the client with
        // `AwsCrypto.builder().build()`
        // or `AwsCrypto.standard()`.
        // This example encrypts with an algorithm suite that doesn't include signing for faster decryption,
        // since this use case assumes that the contexts that encrypt and decrypt are equally trusted.
        final AwsCrypto crypto = AwsCrypto.builder()
                .withCommitmentPolicy(CommitmentPolicy.RequireEncryptRequireDecrypt)
                .withEncryptionAlgorithm(CryptoAlgorithm.ALG_AES_256_GCM_HKDF_SHA512_COMMIT_KEY)
                .build();

        // Create an encryption context to identify the ciphertext
        Map<String, String> context = Collections.singletonMap("Example", "FileStreaming");

        // Because the file might be too large to load into memory, we stream the data, instead of 
        //loading it all at once.
        FileInputStream in = new FileInputStream(srcFile);
        CryptoInputStream<JceMasterKey> encryptingStream = crypto.createEncryptingStream(keyring, in, context);

        FileOutputStream out = new FileOutputStream(srcFile + ".encrypted");
        IOUtils.copy(encryptingStream, out);
        encryptingStream.close();
        out.close();

        // Decrypt the file. Verify the encryption context before returning the plaintext.
        // Since the data was encrypted using an unsigned algorithm suite, use the recommended
        // createUnsignedMessageDecryptingStream method, which only accepts unsigned messages.
        in = new FileInputStream(srcFile + ".encrypted");
        CryptoInputStream<JceMasterKey> decryptingStream = crypto.createUnsignedMessageDecryptingStream(keyring, in);
        // Does it contain the expected encryption context?
        if (!"FileStreaming".equals(decryptingStream.getCryptoResult().getEncryptionContext().get("Example"))) {
            throw new IllegalStateException("Bad encryption context");
        }

        // Write the plaintext data to disk.
        out = new FileOutputStream(srcFile + ".decrypted");
        IOUtils.copy(decryptingStream, out);
        decryptingStream.close();
        out.close();
    }

    /**
     * In practice, this key would be saved in a secure location.
     * For this demo, we generate a new random key for each operation.
     */
    private static SecretKey retrieveEncryptionKey() {
        SecureRandom rnd = new SecureRandom();
        byte[] rawKey = new byte[16]; // 128 bits
        rnd.nextBytes(rawKey);
        return new SecretKeySpec(rawKey, "AES");
    }
}
```

## Cifrar y descifrar secuencias de bytes con un conjunto de claves múltiples
<a name="java-example-multiple-providers"></a>

[En el siguiente ejemplo, se muestra cómo utilizarla con un conjunto de claves múltiples. AWS Encryption SDK](use-multi-keyring.md) Cuando se utiliza un conjunto de claves múltiple para cifrar datos, cualquiera de las claves de encapsulamiento en cualquiera de los conjuntos de claves puede descifrar dichos datos. En este ejemplo, se utiliza un [AWS KMS llavero](use-kms-keyring.md) y un llavero [RSA sin procesar como llaveros secundarios.](use-raw-rsa-keyring.md)

En este ejemplo, se cifra con el [conjunto de algoritmos predeterminado](supported-algorithms.md), que incluye una [firma digital](concepts.md#digital-sigs). Al transmitir, AWS Encryption SDK publica el texto sin formato después de las comprobaciones de integridad, pero antes de comprobar la firma digital. Para evitar utilizar el texto no cifrado hasta que se compruebe la firma, en este ejemplo se almacena el texto no cifrado en búfer y se graba en el disco únicamente cuando se han completado el descifrado y la verificación. 

```
// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package com.amazonaws.crypto.keyrings;

import com.amazonaws.encryptionsdk.AwsCrypto;
import com.amazonaws.encryptionsdk.CommitmentPolicy;
import com.amazonaws.encryptionsdk.CryptoOutputStream;
import com.amazonaws.util.IOUtils;
import software.amazon.cryptography.materialproviders.IKeyring;
import software.amazon.cryptography.materialproviders.MaterialProviders;
import software.amazon.cryptography.materialproviders.model.CreateAwsKmsMultiKeyringInput;
import software.amazon.cryptography.materialproviders.model.CreateMultiKeyringInput;
import software.amazon.cryptography.materialproviders.model.CreateRawRsaKeyringInput;
import software.amazon.cryptography.materialproviders.model.MaterialProvidersConfig;
import software.amazon.cryptography.materialproviders.model.PaddingScheme;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.util.Collections;

/**
 * <p>
 * Encrypts a file using both AWS KMS Key and an asymmetric key pair.
 *
 * <p>
 * Arguments:
 * <ol>
 * <li>Key ARN: For help finding the Amazon Resource Name (ARN) of your AWS KMS key,
 *   see 'Viewing Keys' at http://docs.aws.amazon.com/kms/latest/developerguide/viewing-keys.html
 *
 * <li>Name of file containing plaintext data to encrypt
 * </ol>
 * <p>
 * You might use AWS Key Management Service (AWS KMS) for most encryption and decryption operations, but
 * still want the option of decrypting your data offline independently of AWS KMS. This sample
 * demonstrates one way to do this.
 * <p>
 * The sample encrypts data under both an AWS KMS key and an "escrowed" RSA key pair
 * so that either key alone can decrypt it. You might commonly use the AWS KMS key for decryption. However,
 * at any time, you can use the private RSA key to decrypt the ciphertext independent of AWS KMS.
 * <p>
 * This sample uses the RawRsaKeyring to generate a RSA public-private key pair
 * and saves the key pair in memory. In practice, you would store the private key in a secure offline
 * location, such as an offline HSM, and distribute the public key to your development team.
 */
public class EscrowedEncryptKeyringExample {
    private static ByteBuffer publicEscrowKey;
    private static ByteBuffer privateEscrowKey;

    public static void main(final String[] args) throws Exception {
        // This sample generates a new random key for each operation.
        // In practice, you would distribute the public key and save the private key in secure
        // storage.
        generateEscrowKeyPair();

        final String kmsArn = args[0];
        final String fileName = args[1];

        standardEncrypt(kmsArn, fileName);
        standardDecrypt(kmsArn, fileName);

        escrowDecrypt(fileName);
    }

    private static void standardEncrypt(final String kmsArn, final String fileName) throws Exception {
        // Encrypt with the KMS key and the escrowed public key
        // 1. Instantiate the SDK
        // This builds the AwsCrypto client with the RequireEncryptRequireDecrypt commitment policy,
        // which means this client only encrypts using committing algorithm suites and enforces
        // that the client will only decrypt encrypted messages that were created with a committing
        // algorithm suite.
        // This is the default commitment policy if you build the client with
        // `AwsCrypto.builder().build()`
        // or `AwsCrypto.standard()`.
        final AwsCrypto crypto = AwsCrypto.builder()
                .withCommitmentPolicy(CommitmentPolicy.RequireEncryptRequireDecrypt)
                .build();

        // 2. Create the AWS KMS keyring.
        // This example creates a multi keyring, which automatically creates the KMS client.
        final MaterialProviders matProv = MaterialProviders.builder()
                .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
                .build();
        final CreateAwsKmsMultiKeyringInput keyringInput = CreateAwsKmsMultiKeyringInput.builder()
                .generator(kmsArn)
                .build();
        IKeyring kmsKeyring = matProv.CreateAwsKmsMultiKeyring(keyringInput);

        // 3. Create the Raw Rsa Keyring with Public Key.
        final CreateRawRsaKeyringInput encryptingKeyringInput = CreateRawRsaKeyringInput.builder()
                .keyName("Escrow")
                .keyNamespace("Escrow")
                .paddingScheme(PaddingScheme.OAEP_SHA512_MGF1)
                .publicKey(publicEscrowKey)
                .build();
        IKeyring rsaPublicKeyring = matProv.CreateRawRsaKeyring(encryptingKeyringInput);

        // 4. Create the multi-keyring.
        final CreateMultiKeyringInput createMultiKeyringInput = CreateMultiKeyringInput.builder()
                .generator(kmsKeyring)
                .childKeyrings(Collections.singletonList(rsaPublicKeyring))
                .build();
        IKeyring multiKeyring = matProv.CreateMultiKeyring(createMultiKeyringInput);

        // 5. Encrypt the file
        // To simplify this code example, we omit the encryption context. Production code should always 
        // use an encryption context. 
        final FileInputStream in = new FileInputStream(fileName);
        final FileOutputStream out = new FileOutputStream(fileName + ".encrypted");
        final CryptoOutputStream<?> encryptingStream = crypto.createEncryptingStream(multiKeyring, out);

        IOUtils.copy(in, encryptingStream);
        in.close();
        encryptingStream.close();
    }

    private static void standardDecrypt(final String kmsArn, final String fileName) throws Exception {
        // Decrypt with the AWS KMS key and the escrow public key. 

        // 1. Instantiate the SDK.
        // This builds the AwsCrypto client with the RequireEncryptRequireDecrypt commitment policy,
        // which means this client only encrypts using committing algorithm suites and enforces
        // that the client will only decrypt encrypted messages that were created with a committing
        // algorithm suite.
        // This is the default commitment policy if you build the client with
        // `AwsCrypto.builder().build()`
        // or `AwsCrypto.standard()`.
        final AwsCrypto crypto = AwsCrypto.builder()
                .withCommitmentPolicy(CommitmentPolicy.RequireEncryptRequireDecrypt)
                .build();

        // 2. Create the AWS KMS keyring.
        // This example creates a multi keyring, which automatically creates the KMS client.
        final MaterialProviders matProv = MaterialProviders.builder()
                .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
                .build();
        final CreateAwsKmsMultiKeyringInput keyringInput = CreateAwsKmsMultiKeyringInput.builder()
                .generator(kmsArn)
                .build();
        IKeyring kmsKeyring = matProv.CreateAwsKmsMultiKeyring(keyringInput);

        // 3. Create the Raw Rsa Keyring with Public Key.
        final CreateRawRsaKeyringInput encryptingKeyringInput = CreateRawRsaKeyringInput.builder()
                .keyName("Escrow")
                .keyNamespace("Escrow")
                .paddingScheme(PaddingScheme.OAEP_SHA512_MGF1)
                .publicKey(publicEscrowKey)
                .build();
        IKeyring rsaPublicKeyring = matProv.CreateRawRsaKeyring(encryptingKeyringInput);

        // 4. Create the multi-keyring.
        final CreateMultiKeyringInput createMultiKeyringInput = CreateMultiKeyringInput.builder()
                .generator(kmsKeyring)
                .childKeyrings(Collections.singletonList(rsaPublicKeyring))
                .build();
        IKeyring multiKeyring = matProv.CreateMultiKeyring(createMultiKeyringInput);

        // 5. Decrypt the file
        // To simplify this code example, we omit the encryption context. Production code should always 
        // use an encryption context. 
        final FileInputStream in = new FileInputStream(fileName + ".encrypted");
        final FileOutputStream out = new FileOutputStream(fileName + ".decrypted");
        // Since we are using a signing algorithm suite, we avoid streaming decryption directly to the output file,
        // to ensure that the trailing signature is verified before writing any untrusted plaintext to disk.
        final ByteArrayOutputStream plaintextBuffer = new ByteArrayOutputStream();
        final CryptoOutputStream<?> decryptingStream = crypto.createDecryptingStream(multiKeyring, plaintextBuffer);
        IOUtils.copy(in, decryptingStream);
        in.close();
        decryptingStream.close();
        final ByteArrayInputStream plaintextReader = new ByteArrayInputStream(plaintextBuffer.toByteArray());
        IOUtils.copy(plaintextReader, out);
        out.close();
    }

    private static void escrowDecrypt(final String fileName) throws Exception {
        // You can decrypt the stream using only the private key.
        // This method does not call AWS KMS.

        // 1. Instantiate the SDK
        final AwsCrypto crypto = AwsCrypto.standard();

        // 2. Create the Raw Rsa Keyring with Private Key.
        final MaterialProviders matProv = MaterialProviders.builder()
                .MaterialProvidersConfig(MaterialProvidersConfig.builder().build())
                .build();
        final CreateRawRsaKeyringInput encryptingKeyringInput = CreateRawRsaKeyringInput.builder()
                .keyName("Escrow")
                .keyNamespace("Escrow")
                .paddingScheme(PaddingScheme.OAEP_SHA512_MGF1)
                .publicKey(publicEscrowKey)
                .privateKey(privateEscrowKey)
                .build();
        IKeyring escrowPrivateKeyring = matProv.CreateRawRsaKeyring(encryptingKeyringInput);


        // 3. Decrypt the file
        // To simplify this code example, we omit the encryption context. Production code should always 
        // use an encryption context. 
        final FileInputStream in = new FileInputStream(fileName + ".encrypted");
        final FileOutputStream out = new FileOutputStream(fileName + ".deescrowed");
        final CryptoOutputStream<?> decryptingStream = crypto.createDecryptingStream(escrowPrivateKeyring, out);
        IOUtils.copy(in, decryptingStream);
        in.close();
        decryptingStream.close();

    }

    private static void generateEscrowKeyPair() throws GeneralSecurityException {
        final KeyPairGenerator kg = KeyPairGenerator.getInstance("RSA");
        kg.initialize(4096); // Escrow keys should be very strong
        final KeyPair keyPair = kg.generateKeyPair();
        publicEscrowKey = RawRsaKeyringExample.getPEMPublicKey(keyPair.getPublic());
        privateEscrowKey = RawRsaKeyringExample.getPEMPrivateKey(keyPair.getPrivate());

    }
}
```