The Wayback Machine - https://web.archive.org/web/20210616214008/https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/configure.html
Configuring the AWS Encryption SDK - AWS Encryption SDK

Configuring the AWS Encryption SDK

The AWS Encryption SDK is designed to be easy to use. Although the AWS Encryption SDK has several configuration options, the default values are carefully chosen to be practical and secure for most applications. However, you might need to adjust your configuration to improve performance or include a custom feature in your design.

When configuring your implementation, review the AWS Encryption SDK best practices and implement as many as you can.

Select a programming language

The AWS Encryption SDK is available in multiple programming languages. The language implementations are designed to be fully interoperable and to offer the same features, although they might be implemented in different ways. Typically, you use the library that is compatible with your application. However, you might select a programming language for a particular implementation. For example, if you prefer to work with keyrings, you might choose the AWS Encryption SDK for C or the AWS Encryption SDK for JavaScript.

Select wrapping keys

The AWS Encryption SDK generates a unique symmetric data key to encrypt each message. Unless you are using data key caching, you don't need to configure, manage, or use the data keys. The AWS Encryption SDK does it for you.

However, you must select one or more wrapping keys to encrypt each data key. The AWS Encryption SDK supports AES symmetric keys and RSA asymmetric keys in different sizes. It also supports AWS Key Management Service (AWS KMS) symmetric customer master keys. You are responsible for the safety and durability of your wrapping keys, so we recommend that you use an encryption key in a hardware security module or a key infrastructure service, such as AWS KMS.

To specify your wrapping keys for encryption and decryption, you use a keyring (C and JavaScript) or a master key provider (Java and Python). You can specify one wrapping key or multiple wrapping keys of the same or different types. If you use multiple wrapping keys to wrap a data key, each wrapping key will encrypt a copy of the same data key. The encrypted data keys (one per wrapping key) are stored with the encrypted data in the encrypted message that the AWS Encryption SDK returns. To decrypt the data, the AWS Encryption SDK must first use one of your wrapping keys to decrypt an encrypted data key.

Using multi-Region KMS keys

You can use AWS Key Management Service (AWS KMS) multi-Region keys as wrapping keys in the AWS Encryption SDK. If you encrypt with a multi-Region key in one AWS Region, you can decrypt using a related multi-Region key in a different AWS Region. Support for multi-Region keys is introduced in version 2.3.x of the AWS Encryption SDK and version 3.0.x of the AWS Encryption CLI.

AWS KMS multi-Region keys are a set of AWS KMS customer master keys (CMKs) in different AWS Regions that have the same key material and key ID. You can use these related keys as though they were the same key in different Regions. Multi-Region keys support common disaster recovery and backup scenarios that require encrypting in one Region and decrypting in a different Region without making a cross-Region call to AWS KMS. For information about multi-Region keys, see Using multi-Region keys in the AWS Key Management Service Developer Guide.

To support multi-Region keys, the AWS Encryption SDK includes AWS KMS multi-Region-aware keyrings and master key providers.

The new multi-Region-aware symbol in each programming language supports both single-Region and multi-Region keys.

  • For single-Region keys, the multi-Region-aware symbol behaves just like the single-Region AWS KMS keyring and master key provider. It attempts to decrypt ciphertext only with the single-Region key that encrypted the data.

  • For multi-Region keys, the multi-Region-aware symbol attempts to decrypt ciphertext with the same multi-Region key that encrypted the data or any related multi-Region key.

    For example, suppose you encrypt with a multi-Region key in the Europe (Frankfurt) Region. Then you move your data to Asia Pacific (Singapore) and construct a multi-Region-aware symbol that specifies the related multi-Region key in the Asia Pacific (Singapore) Region. The multi-Region-aware symbol recognizes that the keys in Europe (Frankfurt) and Asia Pacific (Singapore) are related multi-Region keys. It uses the key in Asia Pacific (Singapore) to decrypt.

You can specify multiple wrapping keys in the multi-Region-aware keyrings and master key providers. However, you can specify only one key from each set of related multi-Region keys. If you specify more than one key identifier with the same key ID, the constructor call fails.

You can also use a multi-Region key with the standard, single-Region AWS KMS keyrings and master key providers. However, you must use the same multi-Region key in the same Region to encrypt and decrypt. The single-Region keyrings and master key providers attempt to decrypt ciphertext only with the keys that encrypted the data.

The following examples show how to encrypt and decrypt data using multi-Region keys and the new multi-Region-aware keyrings and master key providers. For example, to encrypt data in the us-east-1 Region with a multi-Region key, instantiate the multi-Region-aware symbol and specify a multi-Region key in us-east-1.

Before running these examples, replace the example multi-Region key ARN with a valid value from your AWS account.

C

To encrypt with a multi-Region key, use the Aws::Cryptosdk::KmsMrkAwareSymmetricKeyring::Builder() method to instantiate the keyring. Specify a multi-Region key.

This simple example does not include an encryption context. For an example that uses an encryption context in C, see Encrypting and decrypting strings.

For a complete example, see kms_multi_region_keys.cpp in the AWS Encryption SDK for C repository on GitHub.

/* Initialize a multi-Region keyring */ const char *mrk_us_east_1 = "arn:aws:kms:us-east-1:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab"; struct aws_cryptosdk_keyring *mrk_keyring = Aws::Cryptosdk::KmsMrkAwareSymmetricKeyring::Builder().Build(mrk_us_east_1); /* Create a session; release the keyring */ struct aws_cryptosdk_session *session = aws_cryptosdk_session_new_from_keyring_2(aws_default_allocator(), AWS_CRYPTOSDK_ENCRYPT, mrk_keyring); aws_cryptosdk_session_set_commitment_policy(session, COMMITMENT_POLICY_REQUIRE_ENCRYPT_REQUIRE_DECRYPT); aws_cryptosdk_keyring_release(mrk_keyring); /* Encrypt the data * aws_cryptosdk_session_process_full is designed for non-streaming data */ aws_cryptosdk_session_process_full( session, ciphertext, ciphertext_buf_sz, &ciphertext_len, plaintext, plaintext_len)); /* Clean up the session */ aws_cryptosdk_session_destroy(session);
AWS Encryption CLI

This example encrypts the hello.txt file under a multi-Region key in the us-east-1 Region. Because the example specifies a key ARN with a Region element, this example doesn't use the region attribute of the --wrapping-keys parameter.

When the key ID of the wrapping key doesn't specify a Region, you can use the region attribute of the --wrapping-keys to specify the region, such as --wrapping-keys key=$keyID region=us-east-1.

# To run this example, replace the fictitious key ARN with a valid value. $ mrkUSEast1=arn:aws:kms:us-east-1:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab $ aws-encryption-cli --encrypt \ --input hello.txt \ --wrapping-keys key=$mrkUSEast1 \ --metadata-output ~/metadata \ --encryption-context purpose=test \ --commitment-policy require-encrypt-require-decrypt \ --output .
Java

To encrypt with a multi-Region key, instantiate an AwsKmsMrkAwareMasterKeyProvider and specify a multi-Region key.

For a complete example, see BasicMultiRegionKeyEncryptionExample.java in the AWS Encryption SDK for Java repository on GitHub.

//Encrypt in us-east-1 Region // Instantiate the client final AwsCrypto crypto = AwsCrypto.builder() .withCommitmentPolicy(CommitmentPolicy.RequireEncryptRequireDecrypt) .build(); // Multi-Region keys have a distinctive key ID that begins with 'mrk' // Specify a multi-Region key in us-east-1 final String mrkUSEast1 = "arn:aws:kms:us-east-1:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab"; // Instantiate an AWS KMS master key provider in strict mode for multi-Region keys // Configure it to encrypt with the multi-Region key in us-east-1 final AwsKmsMrkAwareMasterKeyProvider kmsMrkProvider = AwsKmsMrkAwareMasterKeyProvider .builder() .buildStrict(mrkUSEast1); // Create an encryption context final Map<String, String> encryptionContext = Collections.singletonMap("Purpose", "Test"); // Encrypt your plaintext data final CryptoResult<byte[], AwsKmsMrkAwareMasterKey> encryptResult = crypto.encryptData( kmsMrkProvider, encryptionContext, sourcePlaintext); byte[] ciphertext = encryptResult.getResult();
JavaScript Browser

To encrypt with a multi-Region key, use the buildAwsKmsMrkAwareStrictMultiKeyringBrowser() method to create the keyring and specify a multi-Region key.

For a complete example, see kms_multi_region_simple.ts in the AWS Encryption SDK for JavaScript repository on GitHub.

import { buildAwsKmsMrkAwareStrictMultiKeyringBrowser, buildClient, CommitmentPolicy, KMS, } from '@aws-crypto/client-browser' /* Instantiate an AWS Encryption SDK client */ const { encrypt } = buildClient( CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) declare const credentials: { accessKeyId: string secretAccessKey: string sessionToken: string } /* Instantiate an AWS KMS client * The AWS Encryption SDK for JavaScript gets the Region from the key ARN */ const clientProvider = (region: string) => new KMS({ region, credentials }) /* Specify a multi-Region key in us-east-1 */ const multiRegionUsEastKey = 'arn:aws:kms:us-east-1:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab' /* Instantiate the keyring */ const encryptKeyring = buildAwsKmsMrkAwareStrictMultiKeyringBrowser({ generatorKeyId: multiRegionUsEastKey, clientProvider, }) /* Set the encryption context */ const context = { purpose: 'test', } /* Test data to encrypt */ const cleartext = new Uint8Array([1, 2, 3, 4, 5]) /* Encrypt the data */ const { result } = await encrypt(encryptKeyring, cleartext, { encryptionContext: context, })
JavaScript Node.js

To encrypt with a multi-Region key, use the buildAwsKmsMrkAwareStrictMultiKeyringNode() method to create the keyring and specify a multi-Region key.

For a complete example, see kms_multi_region_simple.ts in the AWS Encryption SDK for JavaScript repository on GitHub.

import { buildClient } from '@aws-crypto/client-node' /* Instantiate the AWS Encryption SDK client const { encrypt } = buildClient( CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) /* Test string to encrypt */ const cleartext = 'asdf' /* Multi-Region keys have a distinctive key ID that begins with 'mrk' * Specify a multi-Region key in us-east-1 */ const multiRegionUsEastKey = 'arn:aws:kms:us-east-1:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab' /* Create an AWS KMS keyring */ const mrkEncryptKeyring = buildAwsKmsMrkAwareStrictMultiKeyringNode({ generatorKeyId: multiRegionUsEastKey, }) /* Specify an encryption context */ const context = { purpose: 'test', } /* Create an encryption keyring */ const { result } = await encrypt(mrkEncryptKeyring, cleartext, { encryptionContext: context, })
Python

To encrypt with an AWS KMS multi-Region key, use the MRKAwareStrictAwsKmsMasterKeyProvider() method and specify a multi-Region key.

For a complete example, see mrk_aware_kms_provider.py in the AWS Encryption SDK for Python repository on GitHub.

# Instantiate the client client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) # Specify a multi-Region key in us-east-1 mrk_us_east_1 = "arn:aws:kms:us-east-1:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab" # Use the multi-Region method to create the master key provider # in strict mode strict_mrk_key_provider = MRKAwareStrictAwsKmsMasterKeyProvider( key_ids=[mrk_us_east_1] ) # Set the encryption context encryption_context = { "purpose": "test" } # Encrypt your plaintext data ciphertext, encrypt_header = client.encrypt( source=source_plaintext, encryption_context=encryption_context, key_provider=strict_mrk_key_provider )

Next, move your ciphertext to the us-west-2 Region. You don't need to re-encrypt the ciphertext.

To decrypt the ciphertext in strict mode in the us-west-2 Region, instantiate the multi-Region-aware symbol with the key ARN of the related multi-Region key in the us-west-2 Region. If you specify the key ARN of a related multi-Region key in a different Region (including us-east-1, where it was encrypted), the multi-Region-aware symbol will make a cross-Region call for that CMK.

When decrypting in strict mode, the multi-Region-aware symbol requires a key ARN. It accepts only one key ARN from each set of related multi-Region keys.

Before running these examples, replace the example multi-Region key ARN with a valid value from your AWS account.

C

To decrypt in strict mode with a multi-Region key, use the Aws::Cryptosdk::KmsMrkAwareSymmetricKeyring::Builder() method to instantiate the keyring. Specify the related multi-Region key in the local (us-west-2) Region.

For a complete example, see kms_multi_region_keys.cpp in the AWS Encryption SDK for C repository on GitHub.

/* Initialize a multi-Region keyring */ const char *mrk_us_west_2 = "arn:aws:kms:us-west-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab"; struct aws_cryptosdk_keyring *mrk_keyring = Aws::Cryptosdk::KmsMrkAwareSymmetricKeyring::Builder().Build(mrk_us_west_2); /* Create a session; release the keyring */ struct aws_cryptosdk_session *session = aws_cryptosdk_session_new_from_keyring_2(aws_default_allocator(), AWS_CRYPTOSDK_ENCRYPT, mrk_keyring); aws_cryptosdk_session_set_commitment_policy(session, COMMITMENT_POLICY_REQUIRE_ENCRYPT_REQUIRE_DECRYPT); aws_cryptosdk_keyring_release(mrk_keyring); /* Decrypt the ciphertext * aws_cryptosdk_session_process_full is designed for non-streaming data */ aws_cryptosdk_session_process_full( session, plaintext, plaintext_buf_sz, &plaintext_len, ciphertext, ciphertext_len)); /* Clean up the session */ aws_cryptosdk_session_destroy(session);
AWS Encryption CLI

To decrypt with the related multi-Region key in the us-west-2 Region, use the key attribute of the --wrapping-keys parameter to specify its key ARN.

# To run this example, replace the fictitious key ARN with a valid value. $ mrkUSWest2=arn:aws:kms:us-west-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab $ aws-encryption-cli --decrypt \ --input hello.txt.encrypted \ --wrapping-keys key=$mrkUSWest2 \ --commitment-policy require-encrypt-require-decrypt \ --encryption-context purpose=test \ --metadata-output ~/metadata \ --max-encrypted-data-keys 1 \ --buffer \ --output .
Java

To decrypt in strict mode, instantiate an AwsKmsMrkAwareMasterKeyProvider and specify the related multi-Region key in the local (us-west-2) Region.

For a complete example, see BasicMultiRegionKeyEncryptionExample.java in the AWS Encryption SDK for Java repository on GitHub.

// Decrypt in us-west-2 Region // Instantiate the client final AwsCrypto crypto = AwsCrypto.builder() .withCommitmentPolicy(CommitmentPolicy.RequireEncryptRequireDecrypt) .build(); // Related multi-Region keys have the same key ID. Their key ARNs differs only in the Region field. String mrkUSWest2 = "arn:aws:kms:us-west-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab"; // Use the multi-Region method to create the master key provider // in strict mode AwsKmsMrkAwareMasterKeyProvider kmsMrkProvider = AwsKmsMrkAwareMasterKeyProvider.builder() .buildStrict(mrkUSWest2); // Decrypt your ciphertext CryptoResult<byte[], AwsKmsMrkAwareMasterKey> decryptResult = crypto.decryptData( kmsMrkProvider, ciphertext); byte[] decrypted = decryptResult.getResult();
JavaScript Browser

To decrypt in strict mode, use the buildAwsKmsMrkAwareStrictMultiKeyringBrowser() method to create the keyring and specify the related multi-Region key in the local (us-west-2) Region.

For a complete example, see kms_multi_region_simple.ts in the AWS Encryption SDK for JavaScript repository on GitHub.

import { buildAwsKmsMrkAwareStrictMultiKeyringBrowser, buildClient, CommitmentPolicy, KMS, } from '@aws-crypto/client-browser' /* Instantiate an AWS Encryption SDK client */ const { decrypt } = buildClient( CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) declare const credentials: { accessKeyId: string secretAccessKey: string sessionToken: string } /* Instantiate an AWS KMS client * The AWS Encryption SDK for JavaScript gets the Region from the key ARN */ const clientProvider = (region: string) => new KMS({ region, credentials }) /* Specify a multi-Region key in us-west-2 */ const multiRegionUsWestKey = 'arn:aws:kms:us-west-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab' /* Instantiate the keyring */ const mrkDecryptKeyring = buildAwsKmsMrkAwareStrictMultiKeyringBrowser({ generatorKeyId: multiRegionUsWestKey, clientProvider, }) /* Decrypt the data */ const { plaintext, messageHeader } = await decrypt(mrkDecryptKeyring, result)
JavaScript Node.js

To decrypt in strict mode, use the buildAwsKmsMrkAwareStrictMultiKeyringNode() method to create the keyring and specify the related multi-Region key in the local (us-west-2) Region.

For a complete example, see kms_multi_region_simple.ts in the AWS Encryption SDK for JavaScript repository on GitHub.

import { buildClient } from '@aws-crypto/client-node' /* Instantiate the client const { decrypt } = buildClient( CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) /* Multi-Region keys have a distinctive key ID that begins with 'mrk' * Specify a multi-Region key in us-east-1 */ const multiRegionUsWestKey = 'arn:aws:kms:us-west-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab' /* Create an AWS KMS keyring */ const mrkDecryptKeyring = buildAwsKmsMrkAwareStrictMultiKeyringNode({ generatorKeyId: multiRegionUsWestKey, }) /* Decrypt your ciphertext */ const { plaintext, messageHeader } = await decrypt(decryptKeyring, result)
Python

To decrypt in strict mode, use the MRKAwareStrictAwsKmsMasterKeyProvider() method to create the master key provider. Specify the related multi-Region key in the local (us-west-2) Region.

For a complete example, see mrk_aware_kms_provider.py in the AWS Encryption SDK for Python repository on GitHub.

# Instantiate the client client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) # Related multi-Region keys have the same key ID. Their key ARNs differs only in the Region field mrk_us_west_2 = "arn:aws:kms:us-west-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab" # Use the multi-Region method to create the master key provider # in strict mode strict_mrk_key_provider = MRKAwareStrictAwsKmsMasterKeyProvider( key_ids=[mrk_us_west_2] ) # Decrypt your ciphertext plaintext, _ = client.decrypt( source=ciphertext, key_provider=strict_mrk_key_provider )

You can also decrypt in discovery mode with multi-Region keys. When decrypting in discovery mode, you don't specify any CMKs.

If you encrypted with a multi-Region key, the multi-Region-aware symbol in discovery mode will try to decrypt by using a related multi-Region key in the local Region. If none exists; the call fails. In discovery mode, the AWS Encryption SDK will not attempt a cross-Region call for the multi-Region key used for encryption.

The following example shows how to decrypt with the multi-Region-aware symbol in discovery mode. Because you don't specify a CMK, the AWS Encryption SDK must get the Region from a different source. When possible, specify the local Region explicitly. Otherwise, the AWS Encryption SDK gets the local Region from the Region configured in the AWS SDK for your programming language.

Before running these examples, replace the example account ID and multi-Region key ARN with valid values from your AWS account.

C

To decrypt in discovery mode with a multi-Region key, use the Aws::Cryptosdk::KmsKeyring::DiscoveryFilter::Builder() method. To specify the local Region, define a ClientConfiguration and specify it in the AWS KMS client.

For a complete example, see kms_multi_region_keys.cpp in the AWS Encryption SDK for C repository on GitHub.

/* Construct a discovery filter for the account and partition. The * filter is optional, but it's a best practice that we recommend. */ const char *account_id = "111122223333"; const char *partition = "aws"; const std::shared_ptr<Aws::Cryptosdk::KmsKeyring::DiscoveryFilter> discovery_filter = Aws::Cryptosdk::KmsKeyring::DiscoveryFilter::Builder(partition).AddAccount(account_id).Build(); /* Create an AWS KMS client in the desired region. */ const char *region = "us-west-2"; Aws::Client::ClientConfiguration client_config; client_config.region = region; const std::shared_ptr<Aws::KMS::KMSClient> kms_client = Aws::MakeShared<Aws::KMS::KMSClient>("AWS_SAMPLE_CODE", client_config); /* Initialize a multi-Region keyring */ const char *mrk_us_west_2 = "arn:aws:kms:us-west-2:111122223333:key/mrk-1234abcd12ab34cd56ef1234567890ab"; struct aws_cryptosdk_keyring *mrk_keyring = Aws::Cryptosdk::KmsMrkAwareSymmetricKeyring::Builder() .WithKmsClient(kms_client) .BuildDiscovery(region, discovery_filter); /* Create a session; release the keyring */ struct aws_cryptosdk_session *session = aws_cryptosdk_session_new_from_keyring_2(aws_default_allocator(), AWS_CRYPTOSDK_DECRYPT, mrk_keyring); aws_cryptosdk_session_set_commitment_policy(session, COMMITMENT_POLICY_REQUIRE_ENCRYPT_REQUIRE_DECRYPT); aws_cryptosdk_keyring_release(mrk_keyring); /* Decrypt the ciphertext * aws_cryptosdk_session_process_full is designed for non-streaming data */ aws_cryptosdk_session_process_full( session, plaintext, plaintext_buf_sz, &plaintext_len, ciphertext, ciphertext_len)); /* Clean up the session */ aws_cryptosdk_session_destroy(session);
AWS Encryption CLI

To decrypt in discovery mode, use the discovery attribute of the --wrapping-keys parameter. The discovery-account and discovery-partition attributes create a discovery filter that is optional, but recommended.

To specify the Region, this command includes the region attribute of the --wrapping-keys parameter.

$ aws-encryption-cli --decrypt \ --input hello.txt.encrypted \ --wrapping-keys discovery=true \ discovery-account=111122223333 \ discovery-partition=aws \ region=us-west-2 \ --commitment-policy require-encrypt-require-decrypt \ --encryption-context purpose=test \ --metadata-output ~/metadata \ --max-encrypted-data-keys 1 \ --buffer \ --output .
Java

To specify the local Region, use the builder().withDiscoveryMrkRegion parameter. Otherwise, the AWS Encryption SDK gets the local Region from the Region configured in the AWS SDK for Java.

For a complete example, see DiscoveryMultiRegionKeyEncryptionExample.java in the AWS Encryption SDK for Java repository on GitHub.

// Decrypt in discovery mode in us-west-2 Region // Instantiate the client final AwsCrypto crypto = AwsCrypto.builder() .withCommitmentPolicy(CommitmentPolicy.RequireEncryptRequireDecrypt) .build(); DiscoveryFilter discoveryFilter = new DiscoveryFilter("aws", 111122223333); AwsKmsMrkAwareMasterKeyProvider mrkDiscoveryProvider = AwsKmsMrkAwareMasterKeyProvider .builder() .withDiscoveryMrkRegion("us-west-2") .buildDiscovery(discoveryFilter); // Decrypt your ciphertext final CryptoResult<byte[], AwsKmsMrkAwareMasterKey> decryptResult = crypto .decryptData(mrkDiscoveryProvider, ciphertext);
JavaScript Browser

To decrypt in discovery mode with a symmetric multi-Region key, use the AwsKmsMrkAwareSymmetricDiscoveryKeyringBrowser() method.

For a complete example, see kms_multi_region_discovery.ts in the AWS Encryption SDK for JavaScript repository on GitHub.

import { AwsKmsMrkAwareSymmetricDiscoveryKeyringBrowser, buildClient, CommitmentPolicy, KMS, } from '@aws-crypto/client-browser' /* Instantiate an AWS Encryption SDK client */ const { decrypt } = buildClient( CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) declare const credentials: { accessKeyId: string secretAccessKey: string sessionToken: string } /* Instantiate the KMS client with an explicit Region */ const client = new KMS({ region: 'us-west-2', credentials }) /* Create a discovery filter */ const discoveryFilter = { partition: 'aws', accountIDs: ['111122223333'] } /* Create an AWS KMS discovery keyring */ const mrkDiscoveryKeyring = new AwsKmsMrkAwareSymmetricDiscoveryKeyringBrowser({ client, discoveryFilter, }) /* Decrypt the data */ const { plaintext, messageHeader } = await decrypt(mrkDiscoveryKeyring, ciphertext)
JavaScript Node.js

To decrypt in discovery mode with a symmetric multi-Region key, use the AwsKmsMrkAwareSymmetricDiscoveryKeyringNode() method.

For a complete example, see kms_multi_region_discovery.ts in the AWS Encryption SDK for JavaScript repository on GitHub.

import { AwsKmsMrkAwareSymmetricDiscoveryKeyringNode, buildClient, CommitmentPolicy, KMS, } from '@aws-crypto/client-node' /* Instantiate the Encryption SDK client const { decrypt } = buildClient( CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT ) /* Instantiate the KMS client with an explicit Region */ const client = new KMS({ region: 'us-west-2' }) /* Create a discovery filter */ const discoveryFilter = { partition: 'aws', accountIDs: ['111122223333'] } /* Create an AWS KMS discovery keyring */ const mrkDiscoveryKeyring = new AwsKmsMrkAwareSymmetricDiscoveryKeyringNode({ client, discoveryFilter, }) /* Decrypt your ciphertext */ const { plaintext, messageHeader } = await decrypt(mrkDiscoveryKeyring, result)
Python

To decrypt in discovery mode with a multi-Region key, use the MRKAwareDiscoveryAwsKmsMasterKeyProvider() method.

For a complete example, see mrk_aware_kms_provider.py in the AWS Encryption SDK for Python repository on GitHub.

# Instantiate the client client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT) # Create the discovery filter and specify the region decrypt_kwargs = dict( discovery_filter=DiscoveryFilter(account_ids="111122223333", partition="aws"), discovery_region="us-west-2", ) # Use the multi-Region method to create the master key provider # in discovery mode mrk_discovery_key_provider = MRKAwareDiscoveryAwsKmsMasterKeyProvider(**decrypt_kwargs) # Decrypt your ciphertext plaintext, _ = client.decrypt( source=ciphertext, key_provider=mrk_discovery_key_provider )

Examine the security features

The AWS Encryption SDK supports the following security features. Although they aren't required, we recommend that you use them whenever it's practical.

Choosing an algorithm suite

The AWS Encryption SDK supports several symmetric and asymmetric encryption algorithms for encrypting your data keys under the wrapping keys you specify. However, when it uses those data keys to encrypt your data, the AWS Encryption SDK defaults to a recommended algorithm suite that uses the AES-GCM algorithm with key derivation, digital signatures, and key commitment. Although this algorithm suite is likely to be suitable for most applications, you can choose an alternate algorithm suite. For example, some trust models would be satisfied by an algorithm suite without digital signatures.

For information about the algorithm suites that the AWS Encryption SDK supports, see Supported algorithm suites in the AWS Encryption SDK.

Limiting encrypted data keys

You can limit the number of encrypted data keys in an encrypted message. This best practice feature can help you detect a misconfigured keyring when encrypting or a malicious ciphertext when decrypting. It also prevents unnecessary, expensive, and potentially exhaustive calls to your key infrastructure. Limiting encrypted data keys is most valuable when you are decrypting messages from an untrusted source.

Although most encrypted messages have one encrypted data key for each wrapping key used in the encryption, an encrypted message can contain up to 65,535 encrypted data keys. A malicious actor might construct an encrypted message with thousands of encrypted data keys, none of which can be decrypted. As a result, the AWS Encryption SDK would attempt to decrypt each encrypted data key until it exhausted the encrypted data keys in the message.

To limit encrypted data keys, use the MaxEncryptedDataKeys parameter. This parameter is available for all supported programming languages beginning in versions 1.9.x and 2.2.x of the AWS Encryption SDK. It is optional and valid when encrypting and decrypting. The following examples decrypt data that was encrypted under three different wrapping keys. The MaxEncryptedDataKeys value is set to 3.

C
/* Construct an AWS KMS keyring */ struct aws_cryptosdk_keyring *kms_keyring = Aws::Cryptosdk::KmsKeyring::Builder().Build(key_arn1, { key_arn2, key_arn3 }); /* Create a session */ struct aws_cryptosdk_session *session = aws_cryptosdk_session_new_from_keyring_2(alloc, AWS_CRYPTOSDK_DECRYPT, kms_keyring); aws_cryptosdk_keyring_release(kms_keyring); /* Limit encrypted data keys */ aws_cryptosdk_session_set_max_encrypted_data_keys(session, 3); /* Decrypt */ size_t ciphertext_consumed_output; aws_cryptosdk_session_process(session, plaintext_output, plaintext_buf_sz_output, &plaintext_len_output, ciphertext_input, ciphertext_len_input, &ciphertext_consumed_output); assert(aws_cryptosdk_session_is_done(session)); assert(ciphertext_consumed == ciphertext_len);
AWS Encryption CLI
# Decrypt with limited encrypted data keys $ aws-encryption-cli --decrypt \ --input hello.txt.encrypted \ --wrapping-keys key=$key_arn1 key=$key_arn2 key=$key_arn3 \ --buffer \ --max-encrypted-data-keys 3 \ --encryption-context purpose=test \ --metadata-output ~/metadata \ --output .
Java
// Construct a client with limited encrypted data keys final AwsCrypto crypto = AwsCrypto.builder() .withMaxEncryptedDataKeys(3) .build(); // Create an AWS KMS master key provider final KmsMasterKeyProvider keyProvider = KmsMasterKeyProvider.builder() .buildStrict(keyArn1, keyArn2, keyArn3); // Decrypt final CryptoResult<byte[], KmsMasterKey> decryptResult = crypto.decryptData(keyProvider, ciphertext)
JavaScript Browser
// Construct a client with limited encrypted data keys const { encrypt, decrypt } = buildClient({ maxEncryptedDataKeys: 3 }) declare const credentials: { accessKeyId: string secretAccessKey: string sessionToken: string } const clientProvider = getClient(KMS, { credentials: { accessKeyId, secretAccessKey, sessionToken } }) // Create an AWS KMS keyring const keyring = new KmsKeyringBrowser({ clientProvider, keyIds: [keyArn1, keyArn2, keyArn3], }) // Decrypt const { plaintext, messageHeader } = await decrypt(keyring, ciphertext)
JavaScript Node.js
// Construct a client with limited encrypted data keys const { encrypt, decrypt } = buildClient({ maxEncryptedDataKeys: 3 }) // Create an AWS KMS keyring const keyring = new KmsKeyringBrowser({ keyIds: [keyArn1, keyArn2, keyArn3], }) // Decrypt const { plaintext, messageHeader } = await decrypt(keyring, ciphertext)
Python
# Instantiate a client with limited encrypted data keys client = aws_encryption_sdk.EncryptionSDKClient(max_encrypted_data_keys=3) # Create an AWS KMS master key provider master_key_provider = aws_encryption_sdk.StrictAwsKmsMasterKeyProvider( key_ids=[key_arn1, key_arn2, key_arn3]) # Decrypt plaintext, header = client.decrypt(source=ciphertext, key_provider=master_key_provider)

Working with streaming data

When you stream data for decryption, be aware that the AWS Encryption SDK returns decrypted plaintext after the integrity checks are complete, but before the digital signature is verified. To ensure that you don't return or use plaintext until the signature is verified, we recommend that you buffer the streamed plaintext until the entire decryption process is complete.

This issue arises only when you are streaming ciphertext for decryption, and only when you are using an algorithm suite, such as the default algorithm suite, that includes digital signatures.

To make the buffering easier, some AWS Encryption SDK language implementations, such as AWS Encryption SDK for JavaScript in Node.js, include a buffering feature as part of the decrypt method. The AWS Encryption CLI, which always streams input and output introduced a --buffer parameter in versions 1.9.x and 2.2.x. In other language implementations, you can use existing buffering features.

If you are using an algorithm suite without digital signatures, be sure to use the decrypt-unsigned feature in each language implementation. This feature decrypts ciphertext but fails if it encounters signed ciphertext. For details, see Choosing an algorithm suite.

Review other options

The AWS Encryption SDK supports following configuration options. Before using these options, consider the risks and benefits and determine whether the option is right for your application.

Data key caching

In general, reusing data keys is discouraged, but the AWS Encryption SDK offers a data key caching option that provides limited reuse of data keys. Data key caching can improve the performance of some applications and reduce calls to your key infrastructure. Before using data key caching in production, adjust the security thresholds, and test to make sure that the benefits outweigh the disadvantages of reusing data keys.