AWS Encryption SDK for Java - AWS Encryption SDK

AWS Encryption SDK for Java

This topic explains how to install and use the AWS Encryption SDK for Java. For details about programming with the AWS Encryption SDK for Java, see the aws-encryption-sdk-java repository on GitHub. For API documentation, see the Javadoc for the AWS Encryption SDK for Java.

Prerequisites

Before you install the AWS Encryption SDK for Java, be sure you have the following prerequisites.

A Java development environment

You will need Java 8 or later. On the Oracle website, go to Java SE Downloads, and then download and install the Java SE Development Kit (JDK).

If you use the Oracle JDK, you must also download and install the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files.

Bouncy Castle

The AWS Encryption SDK for Java requires Bouncy Castle.

  • AWS Encryption SDK for Java versions 1.6.1 and later use Bouncy Castle to serialize and deserialize cryptographic objects. You can use Bouncy Castle or Bouncy Castle FIPS to satisfy this requirement. For help installing and configuring Bouncy Castle FIPS, see BC FIPS Documentation, especially the User Guides and Security Policy PDFs.

  • Earlier versions of the AWS Encryption SDK for Java use Bouncy Castle's cryptography API for Java. This requirement is satisfied only by non-FIPS Bouncy Castle.

If you don't have Bouncy Castle, go to Bouncy Castle latest releases to download the provider file that corresponds to your JDK. You can also use Apache Maven to get the artifact for the standard Bouncy Castle provider (bcprov-ext-jdk15on) or the artifact for Bouncy Castle FIPS (bc-fips).

AWS SDK for Java

Version 3.x of the AWS Encryption SDK for Java requires the AWS SDK for Java 2.x, even if you don't use AWS KMS keyrings.

Version 2.x or earlier of the AWS Encryption SDK for Java does not require the AWS SDK for Java. However, the AWS SDK for Java is required to use AWS Key Management Service (AWS KMS) as a master key provider. Beginning in the AWS Encryption SDK for Java version 2.4.0, the AWS Encryption SDK for Java supports both version 1.x and 2.x of the AWS SDK for Java. AWS Encryption SDK code for the AWS SDK for Java 1.x and 2.x are interoperable. For example, you can encrypt data with AWS Encryption SDK code that supports AWS SDK for Java 1.x and decrypt it using code that supports AWS SDK for Java 2.x (or vice versa). Versions of the AWS Encryption SDK for Java earlier than 2.4.0 support only AWS SDK for Java 1.x. For information about updating your version of the AWS Encryption SDK, see Migrating your AWS Encryption SDK.

When updating your AWS Encryption SDK for Java code from the AWS SDK for Java 1.x to AWS SDK for Java 2.x, replace references to the AWSKMS interface in AWS SDK for Java 1.x with references to the KmsClient interface in AWS SDK for Java 2.x. The AWS Encryption SDK for Java does not support the KmsAsyncClient interface. Also, update your code to use the AWS KMS-related objects in the kmssdkv2 namespace, instead of the kms namespace.

To install the AWS SDK for Java, use Apache Maven.

  • To import the entire AWS SDK for Java as a dependency, declare it in your pom.xml file.

  • To create a dependency only for the AWS KMS module in AWS SDK for Java 1.x, follow the instructions for specifying particular modules, and set the artifactId to aws-java-sdk-kms.

  • To create a dependency only for the AWS KMS module in AWS SDK for Java 2.x, follow the instructions for specifying particular modules. Set the groupId to software.amazon.awssdk and the artifactId to kms.

For more changes, see What's different between the AWS SDK for Java 1.x and 2.x in the AWS SDK for Java 2.x Developer Guide.

Java examples in the AWS Encryption SDK Developer Guide use the AWS SDK for Java 2.x.

Installation

Install the latest version of the AWS Encryption SDK for Java.

Note

All versions of the AWS Encryption SDK for Java earlier than 2.0.0 are in the end-of-support phase.

You can safely update from version 2.0.x and later to the latest version of the AWS Encryption SDK for Java without any code or data changes. However, new security features introduced in version 2.0.x are not backward-compatible. To update from versions earlier than 1.7.x to version 2.0.x and later, you must first update to the latest 1.x version of the AWS Encryption SDK. For details, see Migrating your AWS Encryption SDK.

You can install the AWS Encryption SDK for Java in the following ways.

Manually

To install the AWS Encryption SDK for Java, clone or download the aws-encryption-sdk-java GitHub repository.

Using Apache Maven

The AWS Encryption SDK for Java is available through Apache Maven with the following dependency definition.

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

After you install the SDK, get started by looking at the example Java code in this guide and the Javadoc on GitHub.

AWS KMS keyrings in the AWS Encryption SDK for Java

Version 3.x of the AWS Encryption SDK for Java uses keyrings to perform envelope encryption. The basic AWS KMS keyrings in the AWS Encryption SDK for Java take only one KMS key. They also require an AWS KMS client, which gives you an opportunity to configure the client for the AWS Region of the KMS key.

To create a AWS KMS keyring with one or more wrapping keys, use a multi-keyring. The AWS Encryption SDK for Java has a special multi-keyring that takes one or more AWS KMS keys, and a standard multi-keyring that takes one or more keyrings of any supported type. Some programmers prefer to use a multi-keyring method to create all of their keyrings, and the AWS Encryption SDK for Java supports that strategy.

The AWS Encryption SDK for Java provides basic single-key keyrings and multi-keyrings for all typical use-cases, including AWS KMS multi-Region keys.

For example, to create a AWS KMS keyring with one AWS KMS key, you can use the CreateAwsKmsKeyring()] method.

// Instantiate the AWS Encryption SDK and material providers final AwsCrypto crypto = AwsCrypto.builder().build(); final MaterialProviders materialProviders = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); // Create the keyring CreateAwsKmsKeyringInput kmsKeyringInput = CreateAwsKmsKeyringInput.builder() .kmsKeyId(keyArn) .kmsClient(KmsClient.create()) .build(); IKeyring kmsKeyring = materialProviders.CreateAwsKmsKeyring(kmsKeyringInput);

To create a keyring with one or more AWS KMS keys, use the CreateAwsKmsMultiKeyring() method. This example uses two KMS keys. To specify one KMS key, use only the generator parameter. The msKeyIds parameter that specifies additional KMS keys is optional.

The input for this keyring doesn't take an AWS KMS client. Instead, the AWS Encryption SDK uses the default AWS KMS client for each Region represented by a KMS key in the keyring. For example, if the KMS key identified by the value of the Generator parameter is in the US West (Oregon) Region (us-west-2), the AWS Encryption SDK creates a default AWS KMS client for the us-west-2 Region. If you need to customize the AWS KMS client, use the CreateAwsKmsKeyring() method.

// Instantiate the AWS Encryption SDK and material providers final AwsCrypto crypto = AwsCrypto.builder().build(); final MaterialProviders materialProviders = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); String generatorKey = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"; List<String> additionalKey = Collections.singletonList("arn:aws:kms:us-west-2:111122223333:key/0987dcba-09fe-87dc-65ba-ab0987654321"); // Create the keyring final CreateAwsKmsMultiKeyringInput keyringInput = CreateAwsKmsMultiKeyringInput.builder() .generator(generatorKey) .kmsKeyIds(additionalKey) .build(); final IKeyring kmsKeyring = materialProviders.CreateAwsKmsMultiKeyring(keyringInput);

AWS Encryption SDK for Java supports AWS KMS keyrings that use symmetric encryption (SYMMETRIC_DEFAULT) or asymmetric RSA KMS keys. AWS KMS keyrings created with asymmetric RSA KMS keys can only contain one key pair.

To encrypt with an asymmetric RSA AWS KMS keyring, you do not need kms:GenerateDataKey or kms:Encrypt because you must specify the public key material that you want to use for encryption when you create the keyring. No AWS KMS calls are made when encrypting with this keyring. To decrypt with an asymmetric RSA AWS KMS keyring, you need kms:Decrypt permission.

To create an asymmetric RSA AWS KMS keyring, you must provide the public key and private key ARN from your asymmetric RSA KMS key. The public key must be PEM encoded. The following example creates an AWS KMS keyring with an asymmetric RSA key pair.

// Instantiate the AWS Encryption SDK and material providers final AwsCrypto crypto = AwsCrypto.builder() // Specify algorithmSuite without asymmetric signing here // // ALG_AES_128_GCM_IV12_TAG16_NO_KDF("0x0014"), // ALG_AES_192_GCM_IV12_TAG16_NO_KDF("0x0046"), // ALG_AES_256_GCM_IV12_TAG16_NO_KDF("0x0078"), // ALG_AES_128_GCM_IV12_TAG16_HKDF_SHA256("0x0114"), // ALG_AES_192_GCM_IV12_TAG16_HKDF_SHA256("0x0146"), // ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256("0x0178") .withEncryptionAlgorithm(CryptoAlgorithm.ALG_AES_256_GCM_IV12_TAG16_HKDF_SHA256) .build(); final MaterialProviders matProv = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); // Create a KMS RSA keyring. // This keyring takes in: // - kmsClient // - kmsKeyId: Must be an ARN representing an asymmetric RSA KMS key // - publicKey: A ByteBuffer of a UTF-8 encoded PEM file representing the public // key for the key passed into kmsKeyId // - encryptionAlgorithm: Must be either RSAES_OAEP_SHA_256 or RSAES_OAEP_SHA_1 final CreateAwsKmsRsaKeyringInput createAwsKmsRsaKeyringInput = CreateAwsKmsRsaKeyringInput.builder() .kmsClient(KmsClient.create()) .kmsKeyId(rsaKeyArn) .publicKey(publicKey) .encryptionAlgorithm(EncryptionAlgorithmSpec.RSAES_OAEP_SHA_256) .build(); IKeyring awsKmsRsaKeyring = matProv.CreateAwsKmsRsaKeyring(createAwsKmsRsaKeyringInput);

Required encryption contexts in version 3.x

With version 3.x of the AWS Encryption SDK for Java, you can use the required encryption context CMM to require encryption contexts in your cryptographic operations. An encryption context is a set of non-secret key–value pairs. The encryption context is cryptographically bound to the encrypted data so that the same encryption context is required to decrypt the field. When you use the required encryption context CMM, you can specify one or more required encryption context keys (required keys) that must be included in all encrypt and decrypt calls.

Note

The required encryption context CMM is only interoperable with version 4.x of the AWS Encryption SDK for .NET. It is not interoperable with any other programming language implementation. If you encrypt data using the required encryption context CMM, you can only decrypt it with version 3.x of the AWS Encryption SDK for Java or version 4.x of the AWS Encryption SDK for .NET.

On encrypt, the AWS Encryption SDK verifies that all required encryption context keys are included in the encryption context that you specified. The AWS Encryption SDK signs the encryption contexts that you specified. Only the key-value pairs that are not required keys are serialized and stored in plaintext in the header of the encrypted message that the encrypt operation returns.

On decrypt, you must provide an encryption context that contains all of the key-value pairs that represent the required keys. The AWS Encryption SDK uses this encryption context and the key-value pairs stored in the encrypted message’s header to reconstruct the original encryption context that you specified in the encrypt operation. If the AWS Encryption SDK cannot reconstruct the original encryption context, then the decrypt operation fails. If you provide a key-value pair that contains the required key with an incorrect value, the encrypted message cannot be decrypted. You must provide the same key-value pair that was specified on encrypt.

Important

Carefully consider which values you choose for the required keys in your encryption context. You must be able to provide the same keys and their corresponding values again on decrypt. If you're unable to reproduce the required keys, the encrypted message cannot be decrypted.

The following example initializes an AWS KMS keyring with the required encryption context CMM.

// Instantiate the AWS Encryption SDK final AwsCrypto crypto = AwsCrypto.builder() .withCommitmentPolicy(CommitmentPolicy.RequireEncryptRequireDecrypt) .build(); // Create your encryption context final Map<String, String> encryptionContext = new HashMap<>(); encryptionContext.put("encryption", "context"); encryptionContext.put("is not", "secret"); encryptionContext.put("but adds", "useful metadata"); encryptionContext.put("that can help you", "be confident that"); encryptionContext.put("the data you are handling", "is what you think it is"); // Create a list of required encryption contexts final List<String> requiredEncryptionContextKeys = Arrays.asList("encryption", "context"); // Create the keyring final MaterialProviders materialProviders = MaterialProviders.builder() .MaterialProvidersConfig(MaterialProvidersConfig.builder().build()) .build(); final CreateAwsKmsKeyringInput keyringInput = CreateAwsKmsKeyringInput.builder() .kmsKeyId(keyArn) .kmsClient(KmsClient.create()) .build(); IKeyring kmsKeyring = materialProviders.CreateAwsKmsKeyring(keyringInput); // Create the required encryption context CMM ICryptographicMaterialsManager cmm = materialProviders.CreateDefaultCryptographicMaterialsManager( CreateDefaultCryptographicMaterialsManagerInput.builder() .keyring(kmsKeyring) .build() ); ICryptographicMaterialsManager requiredCMM = materialProviders.CreateRequiredEncryptionContextCMM( CreateRequiredEncryptionContextCMMInput.builder() .requiredEncryptionContextKeys(requiredEncryptionContextKeys) .underlyingCMM(cmm) .build() );