

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

# Kit SDK de chiffrement AWS pour Java
<a name="java"></a>

Cette rubrique explique comment installer et utiliser le kit Kit SDK de chiffrement AWS pour Java. Pour plus de détails sur la programmation avec le Kit SDK de chiffrement AWS pour Java, consultez le [aws-encryption-sdk-java](https://github.com/aws/aws-encryption-sdk-java/)référentiel sur GitHub. Pour la documentation de l'API, consultez le [Javadoc](https://aws.github.io/aws-encryption-sdk-java/) pour le Kit SDK de chiffrement AWS pour Java.

**Topics**
+ [

## Conditions préalables
](#java-prerequisites)
+ [

## Installation
](#java-installation)
+ [Exemples](java-example-code.md)

## Conditions préalables
<a name="java-prerequisites"></a>

Avant d'installer le Kit SDK de chiffrement AWS pour Java, assurez-vous de remplir les conditions préalables suivantes.

**Environnement de développement Java**  
Vous aurez besoin de Java 8 ou version ultérieure. Sur le site web d'Oracle, consultez la page [Téléchargements Java SE](https://www.oracle.com/java/technologies/downloads/), puis téléchargez et installez le kit Java SE Development (JDK).  
Si vous utilisez le kit JDK Oracle, vous devez également télécharger et installer les [fichiers Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy](http://www.oracle.com/java/technologies/javase-jce8-downloads.html).

**Bouncy Castle**  
 Kit SDK de chiffrement AWS pour Java Cela nécessite [Bouncy Castle](https://www.bouncycastle.org/download/bouncy-castle-java/).   
+ Kit SDK de chiffrement AWS pour Java les versions 1.6.1 et ultérieures utilisent Bouncy Castle pour sérialiser et désérialiser des objets cryptographiques. Vous pouvez utiliser Bouncy Castle ou [Bouncy Castle FIPS](https://www.bouncycastle.org/about/bouncy-castle-fips-faq/) pour répondre à cette exigence. **Pour obtenir de l'aide sur l'installation et la configuration de Bouncy Castle FIPS, consultez la [documentation BC FIPS](https://www.bouncycastle.org/documentation/), en particulier les **guides de l'utilisateur** et la politique de sécurité.** PDFs
+ Les versions antérieures Kit SDK de chiffrement AWS pour Java utilisent l'API de cryptographie de Bouncy Castle pour Java. Cette exigence n'est satisfaite que par les Bouncy Castle non FIPS.
Si vous n'avez pas Bouncy Castle, rendez-vous sur [Télécharger Bouncy Castle pour Java pour](https://bouncycastle.org/download/bouncy-castle-java/) télécharger le fichier fournisseur correspondant à votre JDK. [Vous pouvez également utiliser [Apache Maven](https://maven.apache.org/) pour obtenir l'artefact pour le fournisseur standard de Bouncy Castle ([bcprov-ext-jdk15on](https://mvnrepository.com/artifact/org.bouncycastle/bcprov-ext-jdk15on)) ou l'artefact pour Bouncy Castle FIPS (bc-fips).](https://mvnrepository.com/artifact/org.bouncycastle/bc-fips)

**AWS SDK pour Java**  
Version 3. *x* l' Kit SDK de chiffrement AWS pour Java exige AWS SDK for Java 2.x, même si vous n'utilisez pas de AWS KMS porte-clés.  
Version 2. *x* ou une version antérieure du Kit SDK de chiffrement AWS pour Java ne nécessite pas le AWS SDK pour Java. Cependant, AWS SDK pour Java il est nécessaire d'utiliser [AWS Key Management Service](https://aws.amazon.com/kms/)(AWS KMS) comme fournisseur de clé principale. À partir de la Kit SDK de chiffrement AWS pour Java version 2.4.0, il Kit SDK de chiffrement AWS pour Java prend en charge les versions 1.x et 2.x du. AWS SDK pour Java AWS Encryption SDK le code pour les versions AWS SDK pour Java 1.x et 2.x est interopérable. Par exemple, vous pouvez chiffrer des données avec un AWS Encryption SDK code compatible avec la version AWS SDK pour Java 1.x et les déchiffrer à l'aide d'un code compatible AWS SDK for Java 2.x (ou vice versa). Les versions antérieures à Kit SDK de chiffrement AWS pour Java 2.4.0 ne prennent en charge que la version AWS SDK pour Java 1.x. Pour plus d'informations sur la mise à jour de votre version du AWS Encryption SDK, consultez[Migration de votre AWS Encryption SDK](migration.md).  
Lorsque vous mettez à jour votre Kit SDK de chiffrement AWS pour Java code de la AWS SDK pour Java version 1.x à AWS SDK for Java 2.x, remplacez les références à l'[`AWSKMS`interface](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/kms/package-summary.html) de la version AWS SDK pour Java 1.x par des références à l'[`KmsClient`interface](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kms/package-summary.html) de. AWS SDK for Java 2.x Kit SDK de chiffrement AWS pour Java Ne prend pas en charge l'[`KmsAsyncClient`interface](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kms/KmsAsyncClient.html). Mettez également à jour votre code pour utiliser les objets AWS KMS associés dans l'espace de `kmssdkv2` noms, plutôt que dans l'espace de `kms` noms.   
Pour l'installer AWS SDK pour Java, utilisez Apache Maven.   
+ Pour [importer tout le AWS SDK pour Java](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-project-maven.html#build-the-entire-sdk-into-your-project) en tant que dépendance, déclarez-le dans votre fichier `pom.xml`.
+ Pour créer une dépendance uniquement pour le AWS KMS module dans la version AWS SDK pour Java 1.x, suivez les instructions pour [spécifier des modules particuliers](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/setup-project-maven.html#modules-dependencies) et définissez la valeur sur`artifactId`. `aws-java-sdk-kms`
+ Pour créer une dépendance uniquement pour le AWS KMS module dans la version AWS SDK pour Java 2.x, suivez les instructions pour [spécifier des modules particuliers](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-project-maven.html#modules-dependencies). Réglez le `groupId` to `software.amazon.awssdk` et le `artifactId` to`kms`.
Pour plus de modifications, consultez la section [Quelles sont les différences entre la version AWS SDK pour Java 1.x et la version 2.x](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/migration-whats-different.html) dans le manuel du AWS SDK for Java 2.x développeur.  
Les exemples de Java présentés dans le Guide du AWS Encryption SDK développeur utilisent le AWS SDK for Java 2.x.

## Installation
<a name="java-installation"></a>

Installez la dernière version de Kit SDK de chiffrement AWS pour Java.

**Note**  
Toutes les versions Kit SDK de chiffrement AWS pour Java antérieures à la version 2.0.0 sont en [end-of-supportphase](https://docs.aws.amazon.com/sdkref/latest/guide/maint-policy.html#version-life-cycle).  
Vous pouvez effectuer la mise à jour en toute sécurité à partir de la version 2.0. *x* et versions ultérieures vers la dernière version du Kit SDK de chiffrement AWS pour Java sans aucune modification du code ou des données. Cependant, de [nouvelles fonctionnalités de sécurité](about-versions.md#version-2) ont été introduites dans la version 2.0. *x* ne sont pas rétrocompatibles. Pour effectuer une mise à jour à partir de versions antérieures à 1.7. *x* vers la version 2.0. *x* et versions ultérieures, vous devez d'abord effectuer la mise à jour vers la dernière version 1. version *x* du AWS Encryption SDK. Pour en savoir plus, consultez [Migration de votre AWS Encryption SDK](migration.md).

Vous pouvez l'installer Kit SDK de chiffrement AWS pour Java de la manière suivante.

**Manuellement**  
Pour installer le [aws-encryption-sdk-java](https://github.com/aws/aws-encryption-sdk-java/) GitHubréférentiel Kit SDK de chiffrement AWS pour Java, le cloner ou le télécharger.

**Utilisation d'Apache Maven**  
 Kit SDK de chiffrement AWS pour Java Il est disponible via [Apache Maven](https://maven.apache.org/) avec la définition de dépendance suivante.  

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

Après avoir installé le SDK, commencez par consulter l'[exemple de code Java présenté](java-example-code.md) dans ce guide et le [Javadoc](https://aws.github.io/aws-encryption-sdk-java/) activé. GitHub

# Kit SDK de chiffrement AWS pour Java exemples
<a name="java-example-code"></a>

Les exemples suivants vous montrent comment utiliser le Kit SDK de chiffrement AWS pour Java pour chiffrer et déchiffrer des données. Ces exemples montrent comment utiliser la version 3. *x* et versions ultérieures du Kit SDK de chiffrement AWS pour Java. Version 3. *x* de Kit SDK de chiffrement AWS pour Java nécessite le AWS SDK for Java 2.x. Version 3. *x* of the Kit SDK de chiffrement AWS pour Java remplace les [fournisseurs de clés principales](concepts.md#master-key-provider) par des [porte-clés](concepts.md#keyring). Pour les exemples utilisant des versions antérieures, recherchez votre version dans la liste des [versions](https://github.com/aws/aws-encryption-sdk-java/releases) du [aws-encryption-sdk-java](https://github.com/aws/aws-encryption-sdk-java/)référentiel sur GitHub.

**Topics**
+ [Chaînes](#java-example-strings)
+ [Flux d'octets](#java-example-streams)
+ [Flux d'octets avec plusieurs fournisseurs de clés principales](#java-example-multiple-providers)

## Chiffrement et déchiffrement de chaînes
<a name="java-example-strings"></a>

L'exemple suivant montre comment utiliser la version 3. *x* de Kit SDK de chiffrement AWS pour Java pour chiffrer et déchiffrer des chaînes. Avant d'utiliser la chaîne, convertissez-la en un tableau d'octets.

Cet exemple utilise un [AWS KMS porte-clés.](use-kms-keyring.md) Lorsque vous chiffrez avec un AWS KMS trousseau de clés, vous pouvez utiliser un ID de clé, un ARN de clé, un nom d'alias ou un ARN d'alias pour identifier les clés KMS. Lors du déchiffrement, vous devez utiliser un ARN de clé pour identifier les clés KMS.

Lorsque vous appelez la méthode `encryptData()`, elle renvoie un [message chiffré](concepts.md#message) (`CryptoResult`) qui inclut le texte chiffré, les clés de données chiffrées et le contexte de chiffrement. Lorsque vous appelez `getResult` sur l'objet `CryptoResult`, il renvoie une version de chaîne codée en base 64 du [message chiffré](message-format.md) que vous pouvez transmettre à la méthode `decryptData()`.

De même, lorsque vous appelez`decryptData()`, l'`CryptoResult`objet renvoyé contient le message en texte brut et un AWS KMS key identifiant. Avant que votre application ne renvoie le texte en clair, vérifiez que l' AWS KMS key identifiant et le contexte de chiffrement du message chiffré correspondent à vos attentes.

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

## Chiffrement et déchiffrement de flux d'octets
<a name="java-example-streams"></a>

L'exemple suivant montre comment utiliser le AWS Encryption SDK pour chiffrer et déchiffrer des flux d'octets.

Cet exemple utilise un trousseau de [clés AES brut](use-raw-aes-keyring.md).

Lors du chiffrement, cet exemple utilise la `AwsCrypto.builder() .withEncryptionAlgorithm()` méthode pour spécifier une suite d'algorithmes sans [signatures numériques](concepts.md#digital-sigs). Lors du déchiffrement, pour garantir que le texte chiffré n'est pas signé, cet exemple utilise la méthode. `createUnsignedMessageDecryptingStream()` La `createUnsignedMessageDecryptingStream()` méthode échoue si elle rencontre un texte chiffré avec une signature numérique. 

Si vous chiffrez avec la suite d'algorithmes par défaut, qui inclut les signatures numériques, utilisez plutôt `createDecryptingStream()` cette méthode, comme indiqué dans l'exemple suivant.

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

## Chiffrer et déchiffrer des flux d'octets à l'aide d'un jeu de clés multiples
<a name="java-example-multiple-providers"></a>

L'exemple suivant montre comment utiliser le AWS Encryption SDK avec un [porte-clés multiple](use-multi-keyring.md). Lorsque vous utilisez un porte-clés multiple pour chiffrer des données, toutes les clés d'encapsulage de tous ses porte-clés sont capables de déchiffrer les données. Cet exemple utilise un [AWS KMS porte-clés et un porte-clés](use-kms-keyring.md) [RSA brut comme porte-clés](use-raw-rsa-keyring.md) enfants.

Cet exemple chiffre avec la [suite d'algorithmes par défaut](supported-algorithms.md), qui inclut une [signature numérique](concepts.md#digital-sigs). Lors du streaming, il AWS Encryption SDK publie du texte brut après des contrôles d'intégrité, mais avant que la signature numérique ne soit vérifiée. Pour éviter d'utiliser le texte en clair tant que la signature n'est pas vérifiée, cet exemple met le texte en clair en mémoire tampon et ne l'écrit sur le disque que lorsque le déchiffrement et la vérification sont terminés. 

```
// 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());

    }
}
```