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
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 Download Bouncy Castle for Java
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 theKmsClient
interfacein 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 thekms
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
toaws-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
tosoftware.amazon.awssdk
and theartifactId
tokms
.
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 supported by the following versions:
-
Version 3.x of the AWS Encryption SDK for Java
-
Version 4.x of the AWS Encryption SDK for .NET
-
Version 4.x of the AWS Encryption SDK for Python, when used with the optional Cryptographic Material Providers Library
(MPL) dependency.
If you encrypt data using the required encryption context CMM, you can only decrypt it with one of these supported versions.
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() );