

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# AWS Encryption SDK for Java
<a name="java"></a>

Topik ini menjelaskan cara menginstal dan menggunakan AWS Encryption SDK for Java. Untuk detail tentang pemrograman dengan AWS Encryption SDK for Java, lihat [aws-encryption-sdk-java](https://github.com/aws/aws-encryption-sdk-java/)repositori di. GitHub Untuk dokumentasi API, lihat [Javadoc](https://aws.github.io/aws-encryption-sdk-java/) untuk dokumen. AWS Encryption SDK for Java

**Topics**
+ [

## Prasyarat
](#java-prerequisites)
+ [

## Penginstalan
](#java-installation)
+ [Contoh](java-example-code.md)

## Prasyarat
<a name="java-prerequisites"></a>

Sebelum Anda menginstal AWS Encryption SDK for Java, pastikan Anda memiliki prasyarat berikut.

**Lingkungan pengembangan Java**  
Anda akan membutuhkan Java 8 atau yang lebih baru. Di situs web Oracle, buka [Unduhan Java SE](https://www.oracle.com/java/technologies/downloads/), kemudian unduh dan instal Java SE Development Kit (JDK).  
Jika Anda menggunakan Oracle JDK, Anda juga harus mengunduh dan menginstal [File Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy](http://www.oracle.com/java/technologies/javase-jce8-downloads.html).

**Kastil Goyang**  
 AWS Encryption SDK for Java Membutuhkan Kastil [Bouncy.](https://www.bouncycastle.org/download/bouncy-castle-java/)   
+ AWS Encryption SDK for Java versi 1.6.1 dan yang lebih baru menggunakan Bouncy Castle untuk membuat serial dan deserialisasi objek kriptografi. Anda dapat menggunakan Bouncy Castle atau [Bouncy Castle FIPS](https://www.bouncycastle.org/about/bouncy-castle-fips-faq/) untuk memenuhi persyaratan ini. **Untuk bantuan menginstal dan mengonfigurasi FIPS Bouncy Castle, lihat [Dokumentasi BC FIPS](https://www.bouncycastle.org/documentation/), terutama **Panduan Pengguna** dan Kebijakan Keamanan.** PDFs
+ Versi sebelumnya AWS Encryption SDK for Java menggunakan API kriptografi Bouncy Castle untuk Java. Persyaratan ini hanya dipenuhi oleh Kastil Bouncy non-FIPS.
Jika Anda tidak memiliki Bouncy Castle, buka [Unduh Bouncy Castle for Java untuk](https://bouncycastle.org/download/bouncy-castle-java/) mengunduh file penyedia yang sesuai dengan JDK Anda. [Anda juga dapat menggunakan [Apache Maven](https://maven.apache.org/) untuk mendapatkan artefak untuk penyedia Bouncy Castle standar ([bcprov-ext-jdk15on](https://mvnrepository.com/artifact/org.bouncycastle/bcprov-ext-jdk15on)) atau artefak untuk Bouncy Castle FIPS (bc-fips).](https://mvnrepository.com/artifact/org.bouncycastle/bc-fips)

**AWS SDK untuk Java**  
Versi 3. *x* dari AWS Encryption SDK for Java membutuhkan AWS SDK for Java 2.x, bahkan jika Anda tidak menggunakan AWS KMS gantungan kunci.  
Versi 2. *x* atau sebelumnya AWS Encryption SDK for Java tidak memerlukan AWS SDK untuk Java. Namun, AWS SDK untuk Java diperlukan untuk menggunakan [AWS Key Management Service](https://aws.amazon.com/kms/)(AWS KMS) sebagai penyedia kunci utama. Dimulai pada AWS Encryption SDK for Java versi 2.4.0, AWS Encryption SDK for Java mendukung versi 1.x dan 2.x dari versi. AWS SDK untuk Java AWS Encryption SDK kode untuk AWS SDK untuk Java 1.x dan 2.x dapat dioperasikan. Misalnya, Anda dapat mengenkripsi data dengan AWS Encryption SDK kode yang mendukung AWS SDK untuk Java 1.x dan mendekripsi menggunakan kode yang mendukung AWS SDK for Java 2.x (atau sebaliknya). Versi yang AWS Encryption SDK for Java lebih awal dari 2.4.0 hanya mendukung AWS SDK untuk Java 1.x. Untuk informasi tentang memperbarui versi Anda AWS Encryption SDK, lihat[Migrasi Anda AWS Encryption SDK](migration.md).  
Saat memperbarui AWS Encryption SDK for Java kode Anda dari AWS SDK untuk Java 1.x ke AWS SDK for Java 2.x, ganti referensi ke [`AWSKMS`antarmuka](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/kms/package-summary.html) di AWS SDK untuk Java 1.x dengan referensi ke [`KmsClient`antarmuka](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kms/package-summary.html) di. AWS SDK for Java 2.x AWS Encryption SDK for Java Tidak mendukung [`KmsAsyncClient`antarmuka](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kms/KmsAsyncClient.html). Juga, perbarui kode Anda untuk menggunakan objek AWS KMS-related di `kmssdkv2` namespace, bukan namespace. `kms`   
Untuk menginstal AWS SDK untuk Java, gunakan Apache Maven.   
+ Untuk [mengimpor keseluruhan AWS SDK untuk Java](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-project-maven.html#build-the-entire-sdk-into-your-project) sebagai dependensi, deklarasikan dalam file Anda. `pom.xml`
+ Untuk membuat dependensi hanya untuk AWS KMS modul di AWS SDK untuk Java 1.x, ikuti instruksi untuk [menentukan modul tertentu](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/setup-project-maven.html#modules-dependencies), dan atur ke. `artifactId` `aws-java-sdk-kms`
+ Untuk membuat dependensi hanya untuk AWS KMS modul di AWS SDK untuk Java 2.x, ikuti instruksi untuk [menentukan](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-project-maven.html#modules-dependencies) modul tertentu. Atur `groupId` ke `software.amazon.awssdk` dan `artifactId` ke`kms`.
Untuk perubahan lainnya, lihat [Apa yang berbeda antara AWS SDK untuk Java 1.x dan 2.x di Panduan](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/migration-whats-different.html) AWS SDK for Java 2.x Pengembang.  
Contoh Java dalam Panduan AWS Encryption SDK Pengembang menggunakan file AWS SDK for Java 2.x.

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

Instal versi terbaru dari file AWS Encryption SDK for Java.

**catatan**  
[Semua versi yang AWS Encryption SDK for Java lebih awal dari 2.0.0 sedang dalam fase. end-of-support](https://docs.aws.amazon.com/sdkref/latest/guide/maint-policy.html#version-life-cycle)  
Anda dapat memperbarui dengan aman dari versi 2.0. *x* dan yang lebih baru ke versi terbaru AWS Encryption SDK for Java tanpa kode atau perubahan data. Namun, [fitur keamanan baru](about-versions.md#version-2) diperkenalkan di versi 2.0. *x* tidak kompatibel ke belakang. Untuk memperbarui dari versi lebih awal dari 1.7. *x* ke versi 2.0. *x* dan yang lebih baru, Anda harus terlebih dahulu memperbarui ke yang terbaru 1. *x* versi AWS Encryption SDK. Lihat perinciannya di [Migrasi Anda AWS Encryption SDK](migration.md).

Anda dapat menginstal dengan cara berikut. AWS Encryption SDK for Java 

**Secara manual**  
Untuk menginstal AWS Encryption SDK for Java, kloning atau unduh [aws-encryption-sdk-java](https://github.com/aws/aws-encryption-sdk-java/) GitHubrepositori.

**Menggunakan Apache Maven**  
 AWS Encryption SDK for Java Ini tersedia melalui [Apache Maven dengan definisi ketergantungan](https://maven.apache.org/) berikut.  

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

Setelah Anda menginstal SDK, mulailah dengan melihat [contoh kode Java](java-example-code.md) dalam panduan ini dan [Javadoc](https://aws.github.io/aws-encryption-sdk-java/) aktif. GitHub

# AWS Encryption SDK for Java contoh
<a name="java-example-code"></a>

Contoh berikut menunjukkan cara menggunakan untuk mengenkripsi dan AWS Encryption SDK for Java mendekripsi data. Contoh-contoh ini menunjukkan cara menggunakan versi 3. *x* dan yang lebih baru AWS Encryption SDK for Java. Versi 3. *x* dari yang AWS Encryption SDK for Java membutuhkan AWS SDK for Java 2.x. Versi 3. *x* dari AWS Encryption SDK for Java menggantikan [penyedia kunci master](concepts.md#master-key-provider) dengan [keyrings](concepts.md#keyring). Untuk contoh yang menggunakan versi sebelumnya, temukan rilis Anda di daftar [Rilis [aws-encryption-sdk-java](https://github.com/aws/aws-encryption-sdk-java/)](https://github.com/aws/aws-encryption-sdk-java/releases)repositori di. GitHub

**Topics**
+ [String](#java-example-strings)
+ [Aliran byte](#java-example-streams)
+ [Aliran byte dengan beberapa penyedia kunci master](#java-example-multiple-providers)

## Mengenkripsi dan mendekripsi string
<a name="java-example-strings"></a>

Contoh berikut menunjukkan cara menggunakan versi 3. *x* dari AWS Encryption SDK for Java untuk mengenkripsi dan mendekripsi string. Sebelum menggunakan string, ubah menjadi array byte.

Contoh ini menggunakan [AWS KMS keyring](use-kms-keyring.md). Saat Anda mengenkripsi dengan AWS KMS keyring, Anda dapat menggunakan ID kunci, ARN kunci, nama alias, atau alias ARN untuk mengidentifikasi kunci KMS. Saat mendekripsi, Anda harus menggunakan ARN kunci untuk mengidentifikasi kunci KMS.

Ketika Anda memanggil `encryptData()` metode, ia mengembalikan [pesan terenkripsi](concepts.md#message) (`CryptoResult`) yang mencakup ciphertext, kunci data terenkripsi, dan konteks enkripsi. Ketika Anda memanggil `getResult` `CryptoResult` objek, ia mengembalikan versi string yang dikodekan basis-64 dari [pesan terenkripsi](message-format.md) yang dapat Anda teruskan ke metode. `decryptData()`

Demikian pula, ketika Anda memanggil`decryptData()`, `CryptoResult` objek yang dikembalikan berisi pesan teks biasa AWS KMS key dan ID. Sebelum aplikasi Anda mengembalikan plaintext, verifikasi bahwa AWS KMS key ID dan konteks enkripsi dalam pesan terenkripsi adalah yang Anda harapkan.

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

## Mengenkripsi dan mendekripsi aliran byte
<a name="java-example-streams"></a>

Contoh berikut menunjukkan cara menggunakan untuk mengenkripsi dan AWS Encryption SDK mendekripsi aliran byte.

Contoh ini menggunakan [keyring Raw AES](use-raw-aes-keyring.md).

Saat mengenkripsi, contoh ini menggunakan `AwsCrypto.builder() .withEncryptionAlgorithm()` metode untuk menentukan rangkaian algoritma tanpa tanda tangan [digital](concepts.md#digital-sigs). Saat mendekripsi, untuk memastikan bahwa ciphertext tidak ditandatangani, contoh ini menggunakan metode ini. `createUnsignedMessageDecryptingStream()` `createUnsignedMessageDecryptingStream()`Metode, gagal jika menemukan ciphertext dengan tanda tangan digital. 

Jika Anda mengenkripsi dengan rangkaian algoritme default, yang menyertakan tanda tangan digital, gunakan `createDecryptingStream()` metode ini sebagai gantinya, seperti yang ditunjukkan pada contoh berikutnya.

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

## Mengenkripsi dan mendekripsi aliran byte dengan multi-keyring
<a name="java-example-multiple-providers"></a>

Contoh berikut menunjukkan cara menggunakan AWS Encryption SDK dengan [multi-keyring](use-multi-keyring.md). Bila Anda menggunakan multi-keyring untuk mengenkripsi data, salah satu kunci pembungkus di salah satu keyrings nya dapat mendekripsi data tersebut. Contoh ini menggunakan [AWS KMS keyring dan keyring](use-kms-keyring.md) [Raw RSA sebagai keyring](use-raw-rsa-keyring.md) anak.

Contoh ini mengenkripsi dengan [rangkaian algoritme default](supported-algorithms.md), yang mencakup tanda tangan [digital](concepts.md#digital-sigs). Saat streaming, AWS Encryption SDK rilis plaintext setelah pemeriksaan integritas, tetapi sebelum memverifikasi tanda tangan digital. Untuk menghindari penggunaan plaintext sampai tanda tangan diverifikasi, contoh ini menyangga plaintext, dan menuliskannya ke disk hanya ketika dekripsi dan verifikasi selesai. 

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

    }
}
```