

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

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

本主题介绍了如何安装和使用 AWS Encryption SDK for Java。有关使用编程的详细信息 AWS Encryption SDK for Java，请参阅上的[aws-encryption-sdk-java](https://github.com/aws/aws-encryption-sdk-java/)存储库 GitHub。有关 API 文档，请参阅适用于 AWS Encryption SDK for Java的 [Javadoc](https://aws.github.io/aws-encryption-sdk-java/)。

**Topics**
+ [

## 先决条件
](#java-prerequisites)
+ [

## 安装
](#java-installation)
+ [示例](java-example-code.md)

## 先决条件
<a name="java-prerequisites"></a>

在安装之前 AWS Encryption SDK for Java，请确保满足以下先决条件。

**Java 开发环境**  
您需要使用 Java 8 或更高版本。在 Oracle 网站上，转到 [Java SE 下载](https://www.oracle.com/java/technologies/downloads/)，然后下载并安装 Java SE Development Kit (JDK)。  
如果使用 Oracle JDK，您还必须下载并安装 [Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files](http://www.oracle.com/java/technologies/javase-jce8-downloads.html)。

**Bouncy Castle**  
 AWS Encryption SDK for Java 需要[充气城堡](https://www.bouncycastle.org/download/bouncy-castle-java/)。  
+ AWS Encryption SDK for Java 1.6.1 及更高版本使用 Bouncy Castle 对加密对象进行序列化和反序列化。您可以使用 Bouncy Castle 或 [Bouncy Castle FIPS](https://www.bouncycastle.org/about/bouncy-castle-fips-faq/) 以满足该要求。**有关安装和配置 Bouncy Castle FIPS 的帮助，请参阅 [BC FIPS 文档](https://www.bouncycastle.org/documentation/)，尤其是**用户指南和安全**政策。** PDFs
+ 早期版本 AWS Encryption SDK for Java 使用 Bouncy Castle 的 Java 加密 API。仅非 FIPS Bouncy Castle 满足该要求。
如果你没有 Bouncy Castle，请前往[下载 Java 版 Bouncy Castle](https://bouncycastle.org/download/bouncy-castle-java/) 下载与你的 JDK 对应的提供程序文件。[你也可以使用 [Apache Mav](https://maven.apache.org/) en 获取标准 Bouncy Castle 提供者（[bcprov-ext-jdk15 on](https://mvnrepository.com/artifact/org.bouncycastle/bcprov-ext-jdk15on)）的神器或 Bouncy Castle FIPS 的神器（bc-fips）。](https://mvnrepository.com/artifact/org.bouncycastle/bc-fips)

**适用于 Java 的 AWS SDK**  
版本 3。 *其中 x* AWS Encryption SDK for Java 需要 AWS SDK for Java 2.x，即使你不使用 AWS KMS 钥匙圈。  
版本 2。 *x* 或更早版本 AWS Encryption SDK for Java 不需要 适用于 Java 的 AWS SDK。但是 适用于 Java 的 AWS SDK ，必须使用 [AWS Key Management Service](https://aws.amazon.com/kms/)(AWS KMS) 作为主密钥提供程序。从 2.4.0 AWS Encryption SDK for Java 版本开始，同时 AWS Encryption SDK for Java 支持 1.x 和 2.x 版本的。 适用于 Java 的 AWS SDK AWS Encryption SDK 适用于 Java 的 AWS SDK 1.x 和 2.x 的代码是可互操作的。例如，您可以使用支持 适用于 Java 的 AWS SDK 1.x 的 AWS Encryption SDK 代码加密数据，然后使用支持的代码对其进行解密 AWS SDK for Java 2.x （反之亦然）。2.4.0 AWS Encryption SDK for Java 之前的版本仅支持 适用于 Java 的 AWS SDK 1.x。有关更新版本的信息 AWS Encryption SDK，请参阅[迁移你的 AWS Encryption SDK](migration.md)。  
将 AWS Encryption SDK for Java 代码从 1.x 更新到时 AWS SDK for Java 2.x，请将 适用于 Java 的 AWS SDK 1.x 中对[`AWSKMS`接口](https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/kms/package-summary.html)的引用替换为中 适用于 Java 的 AWS SDK 对[`KmsClient`接口](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kms/package-summary.html)的引用。 AWS SDK for Java 2.x AWS Encryption SDK for Java 不支持该[`KmsAsyncClient`接口](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/kms/KmsAsyncClient.html)。此外，更新代码即可使用 `kmssdkv2` 命名空间中的 AWS KMS相关对象，而不是 `kms` 命名空间。  
要安装，请使用 Apache Maven。 适用于 Java 的 AWS SDK  
+ 要[导入整个 适用于 Java 的 AWS SDK](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-project-maven.html#build-the-entire-sdk-into-your-project)以作为依赖项，请在 `pom.xml` 文件中对其进行声明。
+ 要在 适用于 Java 的 AWS SDK 1.x 中仅为 AWS KMS 模块创建依赖关系，请按照[指定特定模块](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/setup-project-maven.html#modules-dependencies)的说明进行操作，并将设置为。`artifactId` `aws-java-sdk-kms`
+ 要在 适用于 Java 的 AWS SDK 2.x 中仅为 AWS KMS 模块创建依赖关系，请按照[指定特定模块](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/setup-project-maven.html#modules-dependencies)的说明进行操作。将 `groupId` 设置为 `software.amazon.awssdk`，并将 `artifactId` 设置为 `kms`。
有关更多更改，请参阅[《 AWS SDK for Java 2.x 开发者指南》中的 适用于 Java 的 AWS SDK 1.x 和 2.x 有什么区别](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/migration-whats-different.html)。  
《 AWS Encryption SDK 开发人员指南》中的 Java 示例使用 AWS SDK for Java 2.x。

## 安装
<a name="java-installation"></a>

安装最新版本的 AWS Encryption SDK for Java。

**注意**  
[2.0.0 AWS Encryption SDK for Java 之前的所有版本都处于该阶段。end-of-support](https://docs.aws.amazon.com/sdkref/latest/guide/maint-policy.html#version-life-cycle)  
您可以安全地从 AWS Encryption SDK for Java 版本 2.0.*x* 及更高版本更新为最新版本，无需更改任何代码或数据。但是，版本 2.0.*x* 中引入了[新的安全功能](about-versions.md#version-2)，不向后兼容。要从 1.7.*x* 之前的版本更新到 2.0.*x* 及更高版本，必须先更新到 AWS Encryption SDK最新版本 1.*x*。有关更多信息，请参阅 [迁移你的 AWS Encryption SDK](migration.md)。

您可以通过以下 AWS Encryption SDK for Java 方式安装。

**手动方式**  
要安装 AWS Encryption SDK for Java，请克隆或下载[aws-encryption-sdk-java](https://github.com/aws/aws-encryption-sdk-java/) GitHub存储库。

**使用 Apache Maven**  
可通过 [Apache Maven](https://maven.apache.org/) 获得，依赖关系定义如下。 AWS Encryption SDK for Java   

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

安装完软件开发工具包后，请先查看本指南中的[示例 Java 代码](java-example-code.md)，然后打开 J [avadoc](https://aws.github.io/aws-encryption-sdk-java/)。 GitHub

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

以下示例向您展示了如何使用 AWS Encryption SDK for Java 来加密和解密数据。这些示例说明了如何使用版本 3。 *x* 及更高版本的 AWS Encryption SDK for Java. 版本 3。 其中的 *x* AWS Encryption SDK for Java 需要 AWS SDK for Java 2.x。版本 3。 *其中 x* AWS Encryption SDK for Java 将[主密钥提供程序](concepts.md#master-key-provider)替换为密[钥环](concepts.md#keyring)。有关使用早期版本的示例，请在上[aws-encryption-sdk-java](https://github.com/aws/aws-encryption-sdk-java/)存储库的[版本](https://github.com/aws/aws-encryption-sdk-java/releases)列表中找到您的版本 GitHub。

**Topics**
+ [字符串](#java-example-strings)
+ [字节流](#java-example-streams)
+ [具有多个主密钥提供程序的字节流](#java-example-multiple-providers)

## 加密和解密字符串
<a name="java-example-strings"></a>

以下示例向您展示了如何使用版本 3。 用于加密和解密字符串的 *x*。 AWS Encryption SDK for Java 在使用字符串之前，请将其转换为字节数组。

此示例使用密[AWS KMS 钥环](use-kms-keyring.md)。使用密 AWS KMS 钥环加密时，您可以使用密钥 ID、密钥 ARN、别名或别名 ARN 来识别 KMS 密钥。解密时，必须使用密钥 ARN 来识别 KMS 密钥。

在调用 `encryptData()` 方法时，它返回[加密的消息](concepts.md#message) (`CryptoResult`)，其中包括密文、加密的数据密钥以及加密上下文。在对 `CryptoResult` 对象调用 `getResult` 时，它返回[加密的消息](message-format.md)的 base-64 编码的字符串版本，您可以将其传递给 `decryptData()` 方法。

同样，当您调用时`decryptData()`，它返回的`CryptoResult`对象包含纯文本消息和一个 AWS KMS key ID。在您的应用程序返回纯文本之前，请验证加密消息中的 AWS KMS key ID 和加密上下文是否符合您的期望。

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

## 加密和解密字节流
<a name="java-example-streams"></a>

以下示例说明如何使用 AWS Encryption SDK 来加密和解密字节流。

此示例使用[原始的 AES 密钥环](use-raw-aes-keyring.md)。

加密时，此示例使用 `AwsCrypto.builder() .withEncryptionAlgorithm()` 方法指定不带[数字签名](concepts.md#digital-sigs)的算法套件。解密时，为确保加密文字未签名，此示例使用 `createUnsignedMessageDecryptingStream()` 方法。如果遇到带有数字签名的密文，则该`createUnsignedMessageDecryptingStream()`方法将失败。

如果您使用默认算法套件（包括数字签名）进行加密，请改用 `createDecryptingStream()` 方法，如下一个示例所示。

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

## 使用多密钥环加密和解密字节流
<a name="java-example-multiple-providers"></a>

以下示例向您展示了如何将与[多密钥 AWS Encryption SDK](use-multi-keyring.md)环一起使用。在使用多重密钥环加密数据时，其任意密钥环中的任意包装密钥都可以对数据进行解密。此示例使用[AWS KMS 密钥环](use-kms-keyring.md)和 Ra [w RSA 密钥环作为子密钥环](use-raw-rsa-keyring.md)。

此示例使用包含[数字签名](concepts.md#digital-sigs)的[默认算法套件](supported-algorithms.md)进行加密。直播时，会在完整性检查后但在验证数字签名之前 AWS Encryption SDK 发布纯文本。为了避免在签名验证之前使用明文，此示例会缓冲明文，并且仅在解密和验证完成后才将其写入磁盘。

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

    }
}
```