

# Migrating your AWS Encryption SDK
<a name="migration"></a>

The AWS Encryption SDK supports multiple interoperable [programming language implementations](programming-languages.md), each of which is developed in an open-source repository on GitHub. As a [best practice](best-practices.md), we recommend that you use the latest version of the AWS Encryption SDK for each language. 

You can safely upgrade from version 2.0.*x* or later of AWS Encryption SDK to the latest version. However, the 2.0.*x* version of the AWS Encryption SDK introduces significant new security features, some of which are breaking changes. To upgrade from versions earlier than 1.7.*x* to versions 2.0.*x* and later, you must first upgrade to the latest 1.*x* version. The topics in this section are designed to help you understand the changes, select the correct version for your application, and migrate safely and successfully to the newest versions of the AWS Encryption SDK.

For information about significant versions of the AWS Encryption SDK, see [Versions of the AWS Encryption SDK](about-versions.md).

**Important**  
Do not upgrade directly from a version earlier than 1.7.*x* to version 2.0.*x* or later without first upgrading to the latest 1.*x* version. If you upgrade directly to version 2.0.*x* or later and enable all new features immediately, the AWS Encryption SDK won't be able to decrypt ciphertext encrypted under older versions of the AWS Encryption SDK.

**Note**  
The earliest version of the AWS Encryption SDK for .NET is version 3.0.*x*. All versions of the AWS Encryption SDK for .NET support the security best practices introduced in 2.0.*x* of the AWS Encryption SDK. You can safely upgrade to the latest version without any code or data changes.  
AWS Encryption CLI: When reading this migration guide, use the 1.7.*x* migration instructions for AWS Encryption CLI 1.8.*x* and use the 2.0.*x* migration instructions for AWS Encryption CLI 2.1.*x*. For details, see [Versions of the AWS Encryption CLI](crypto-cli-versions.md).  
New security features were originally released in AWS Encryption CLI versions 1.7.*x* and 2.0.*x*. However, AWS Encryption CLI version 1.8.*x* replaces version 1.7.*x* and AWS Encryption CLI 2.1.*x* replaces 2.0.*x*. For details, see the relevant [security advisory](https://github.com/aws/aws-encryption-sdk-cli/security/advisories/GHSA-2xwp-m7mq-7q3r) in the [aws-encryption-sdk-cli](https://github.com/aws/aws-encryption-sdk-cli/) repository on GitHub.

**New users**  
If you're new to the AWS Encryption SDK, install the latest version of the AWS Encryption SDK for your programming language. The default values enable all security features of the AWS Encryption SDK, including encryption with signing, key derivation, and [key commitment](concepts.md#key-commitment). of the AWS Encryption SDK

**Current users**  
We recommend that you upgrade from your current version to the latest available version as soon as possible. All 1.*x* versions of the AWS Encryption SDK are in the [end-of-support phase](https://docs.aws.amazon.com/sdkref/latest/guide/maint-policy.html#version-life-cycle), as are later versions in some programming languages. For details about the support and maintenance status of the AWS Encryption SDK in your programming language, see [Support and maintenance](introduction.md#support).  
AWS Encryption SDK versions 2.0.*x* and later provide new security features to help protect your data. However, AWS Encryption SDK version 2.0.*x* includes breaking changes that are not backwards compatible. To assure a safe transition, begin by migrating from your current version to the latest 1.*x* in your programming language. When your latest 1.*x* version is fully deployed and operating successfully, you can safely migrate to versions 2.0.*x* and later. This [two-step process](migration-guide.md) is critical especially for distributed applications.

For more information about the AWS Encryption SDK security features that underlie these changes, see [Improved client-side encryption: Explicit KeyIds and key commitment](https://aws.amazon.com/blogs/security/improved-client-side-encryption-explicit-keyids-and-key-commitment/) in the *AWS Security Blog*.

Looking for help with using the AWS Encryption SDK for Java with the AWS SDK for Java 2.x? See [Prerequisites](java.md#java-prerequisites).

**Topics**
+ [

# How to migrate and deploy the AWS Encryption SDK
](migration-guide.md)
+ [

# Updating AWS KMS master key providers
](migrate-mkps-v2.md)
+ [

# Updating AWS KMS keyrings
](migrate-keyrings-v2.md)
+ [

# Setting your commitment policy
](migrate-commitment-policy.md)
+ [

# Troubleshooting migration to the latest versions
](troubleshooting-migration.md)

# How to migrate and deploy the AWS Encryption SDK
<a name="migration-guide"></a>

When migrating from an AWS Encryption SDK version earlier than 1.7.*x* to version 2.0.*x* or later, you must transition safely to encrypting with [key commitment](concepts.md#key-commitment). Otherwise, your application will encounter ciphertexts that it cannot decrypt. If you are using AWS KMS master key providers, you must update to new constructors that create master key providers in strict mode or discovery mode.

**Note**  
This topic is designed for users migrating from earlier versions of the AWS Encryption SDK to version 2.0.*x* or later. If you are new to the AWS Encryption SDK, you can begin using the latest available version immediately with the default settings.

To avoid a critical situation in which you cannot decrypt ciphertext that you need to read, we recommend that you migrate and deploy in multiple distinct stages. Verify that each stage is complete and fully deployed before starting the next stage. This is particularly important for distributed applications with multiple hosts.

## Stage 1: Update your application to the latest 1.*x* version
<a name="migrate-stage1"></a>

Update to the latest 1.*x* version for your programming language. Test carefully, deploy your changes, and confirm that the update has propagated to all destination hosts before starting stage 2.

**Important**  
Verify that your latest 1.*x* version is version 1.7.*x* or later of the AWS Encryption SDK.

The latest 1.*x* versions of the AWS Encryption SDK are backward compatible with legacy versions of the AWS Encryption SDK and forward compatible with versions 2.0.*x* and later. They include the new features that are present in version 2.0.*x*, but include safe defaults designed for this migration. They allow you to upgrade your AWS KMS master key providers, if necessary, and to fully deploy with algorithm suites that can decrypt ciphertext with key commitment.
+ Replace deprecated elements, including constructors for legacy AWS KMS master key providers. In [Python](https://docs.python.org/3/library/warnings.html), be sure to turn on deprecation warnings. Code elements that are deprecated in the latest 1.*x* versions are removed from versions 2.0.*x* and later. 
+ Explicitly set your commitment policy to `ForbidEncryptAllowDecrypt`. Although this is the only valid value in the latest 1.*x* versions, this setting is required when you use the APIs introduced in this release. It prevents your application from rejecting ciphertext encrypted without key commitment when you migrate to version 2.0.*x* and later. For details, see [Setting your commitment policy](migrate-commitment-policy.md).
+ If you use AWS KMS master key providers, you must update your legacy master key providers to master key providers that support *strict mode* and *discovery mode*. This update is required for the AWS Encryption SDK for Java, AWS Encryption SDK for Python, and the AWS Encryption CLI. If you use master key providers in discovery mode, we recommend that you implement the discovery filter that limits the wrapping keys used to those in particular AWS accounts. This update is optional, but it's a [best practice](best-practices.md) that we recommend. For details, see [Updating AWS KMS master key providers](migrate-mkps-v2.md). 
+ If you use [AWS KMS discovery keyrings](use-kms-keyring.md#kms-keyring-discovery), we recommend that you include a discovery filter that limits the wrapping keys used in decryption to those in particular AWS accounts. This update is optional, but it's a [best practice](best-practices.md) that we recommend. For details, see [Updating AWS KMS keyrings](migrate-keyrings-v2.md).

## Stage 2: Update your application to the latest version
<a name="migrate-stage2"></a>

After deploying the latest 1.*x* version successfully to all hosts, you can upgrade to versions 2.0.*x* and later. Version 2.0.*x* includes breaking changes for all earlier versions of the AWS Encryption SDK. However, if you make the code changes recommended in Stage 1, you can avoid errors when you migrate to the latest version.

Before you update to the latest version, verify that your commitment policy is consistently set to `ForbidEncryptAllowDecrypt`. Then, depending on your data configuration, you can migrate at your own pace to `RequireEncryptAllowDecrypt` and then to the default setting, `RequireEncryptRequireDecrypt`. We recommend a series of transition steps like the following pattern.

1. Begin with your [commitment policy](migrate-commitment-policy.md) set to `ForbidEncryptAllowDecrypt`. The AWS Encryption SDK can decrypt messages with key commitment, but it doesn't yet encrypt with key commitment.

1. When you are ready, update your commitment policy to `RequireEncryptAllowDecrypt`. The AWS Encryption SDK begins to encrypt your data with [key commitment](concepts.md#key-commitment). It can decrypt ciphertext with and without key commitment. 

   Before updating your commitment policy to `RequireEncryptAllowDecrypt`, verify that your latest 1.*x* version is deployed to all hosts, including hosts of any applications that decrypt the ciphertext you produce. Versions of the AWS Encryption SDK prior to version 1.7.*x* cannot decrypt messages encrypted with key commitment.

   This is also a good time to add metrics to your application to measure whether you are still processing ciphertext without key commitment. This will help you determine when it's safe to update your commitment policy setting to `RequireEncryptRequireDecrypt`. For some applications, such as those that encrypt messages in an Amazon SQS queue, this might mean waiting long enough that all ciphertext encrypted under old versions have been re-encrypted or deleted. For other applications, such as encrypted S3 objects, you might need to download, re-encrypt, and re-upload all objects.

1. When you are certain that you don't have any messages encrypted without key commitment, you can update your commitment policy to `RequireEncryptRequireDecrypt`. This value assures that your data is always encrypted and decrypted with key commitment. This setting is the default, so you aren't required to set it explicitly, but we recommend it. An explicit setting will [aid debugging](troubleshooting-migration.md) and any potential rollbacks that might be required if your application encounters ciphertext encrypted without key commitment. 

# Updating AWS KMS master key providers
<a name="migrate-mkps-v2"></a>

To migrate to the latest 1.*x* version of the AWS Encryption SDK, and then to version 2.0.*x* or later, you must replace legacy AWS KMS master key providers with master key providers created explicitly in [*strict mode* or *discovery mode*](about-versions.md#changes-to-mkps). Legacy master key providers are deprecated in version 1.7.*x* and removed in version 2.0.*x*. This change is required for applications and scripts that use the [AWS Encryption SDK for Java](java.md), [AWS Encryption SDK for Python](python.md), and the [AWS Encryption CLI](crypto-cli.md). The examples in this section will show you how to update your code. 

**Note**  
In Python, [turn on deprecation warnings](https://docs.python.org/3/library/warnings.html). This will help you identify the parts of your code that you need to update.

If you are using an AWS KMS master key (not a master key provider), you can skip this step. AWS KMS master keys are not deprecated or removed. They encrypt and decrypt only with the wrapping keys that you specify.

The examples in this section focus on the elements of your code that you need to change. For a complete example of the updated code, see the Examples section of the GitHub repository for your [programming language](programming-languages.md). Also, these examples typically use key ARNs to represent AWS KMS keys. When you create a master key provider for encrypting, you can use any valid AWS KMS [key identifier](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id) to represent an AWS KMS key . When you create a master key provider for decrypting, you must use a key ARN.

**Learn more about migration**

For all AWS Encryption SDK users, learn about setting your commitment policy in [Setting your commitment policy](migrate-commitment-policy.md).

For AWS Encryption SDK for C and AWS Encryption SDK for JavaScript users, learn about an optional update to keyrings in [Updating AWS KMS keyrings](migrate-keyrings-v2.md).

**Topics**
+ [

## Migrating to strict mode
](#migrate-mkp-strict-mode)
+ [

## Migrating to discovery mode
](#migrate-mkp-discovery-mode)

## Migrating to strict mode
<a name="migrate-mkp-strict-mode"></a>

After updating to the latest 1.*x* version of the AWS Encryption SDK, replace your legacy master key providers with master key providers in strict mode. In strict mode, you must specify the wrapping keys to use when encrypting and decrypting. The AWS Encryption SDK uses only the wrapping keys you specify. Deprecated master key providers can decrypt data using any AWS KMS key that encrypted a data key, including AWS KMS keys in different AWS accounts and Regions.

Master key providers in strict mode are introduced in the AWS Encryption SDK version 1.7.*x*. They replace legacy master key providers, which are deprecated in 1.7.*x* and removed in 2.0.*x*. Using master key providers in strict mode is an AWS Encryption SDK [ best practice](best-practices.md).

The following code creates a master key provider in strict mode that you can use for encrypting and decrypting. 

------
#### [ Java ]

This example represents code in an application that uses the version 1.6.2 or earlier of the AWS Encryption SDK for Java.

This code uses the `KmsMasterKeyProvider.builder()` method to instantiate an AWS KMS master key provider that uses one AWS KMS key as a wrapping key. 

```
// Create a master key provider
// Replace the example key ARN with a valid one
String awsKmsKey = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab";

KmsMasterKeyProvider masterKeyProvider = KmsMasterKeyProvider.builder()
    .withKeysForEncryption(awsKmsKey)
    .build();
```

This example represents code in an application that uses version 1.7.*x* or later of the AWS Encryption SDK for Java . For a complete example, see [BasicEncryptionExample.java](https://github.com/aws/aws-encryption-sdk-java/blob/master/src/examples/java/com/amazonaws/crypto/examples/v2/BasicEncryptionExample.java).

The `Builder.build()` and `Builder.withKeysForEncryption()` methods used in the previous example are deprecated in version 1.7.*x* and are removed from version 2.0.*x*.

To update to a strict mode master key provider, this code replaces calls to deprecated methods with a call to the new `Builder.buildStrict()` method. This example specifies one AWS KMS key as the wrapping key, but the `Builder.buildStrict()` method can take a list of multiple AWS KMS keys.

```
// Create a master key provider in strict mode
// Replace the example key ARN with a valid one from your AWS account.
String awsKmsKey = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab";

KmsMasterKeyProvider masterKeyProvider = KmsMasterKeyProvider.builder()
    .buildStrict(awsKmsKey);
```

------
#### [ Python ]

This example represents code in an application that uses version 1.4.1 of the AWS Encryption SDK for Python. This code uses `KMSMasterKeyProvider`, which is deprecated in version 1.7.*x* and removed from version 2.0.*x*. When decrypting, it uses any AWS KMS key that encrypted a data key without regard to the AWS KMS keys you specify. 

Note that `KMSMasterKey` is not deprecated or removed. When encrypting and decrypting, it uses only the AWS KMS key you specify.

```
# Create a master key provider
# Replace the example key ARN with a valid one
key_1 = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"
key_2 = "arn:aws:kms:us-west-2:111122223333:key/0987dcba-09fe-87dc-65ba-ab0987654321"

aws_kms_master_key_provider = KMSMasterKeyProvider(
   key_ids=[key_1, key_2]
)
```

This example represents code in an application that uses version 1.7.*x* of the AWS Encryption SDK for Python. For a complete example, see [basic\$1encryption.py](https://github.com/aws/aws-encryption-sdk-python/blob/master/examples/src/legacy/basic_encryption.py).

To update to a strict mode master key provider, this code replaces the call to `KMSMasterKeyProvider()` with a call to `StrictAwsKmsMasterKeyProvider()`. 

```
# Create a master key provider in strict mode
# Replace the example key ARNs with valid values from your AWS account
key_1 = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"
key_2 = "arn:aws:kms:us-west-2:111122223333:key/0987dcba-09fe-87dc-65ba-ab0987654321"

aws_kms_master_key_provider = StrictAwsKmsMasterKeyProvider(
    key_ids=[key_1, key_2]
)
```

------
#### [ AWS Encryption CLI ]

This example shows how to encrypt and decrypt using the AWS Encryption CLI version 1.1.7 or earlier.

In version 1.1.7 and earlier, when encrypting, you specify one or more master keys (or *wrapping keys*), such as an AWS KMS key. When decrypting, you can't specify any wrapping keys unless you are using a custom master key provider. The AWS Encryption CLI can use any wrapping key that encrypted a data key.

```
\\ Replace the example key ARN with a valid one
$ keyArn=arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab

\\ Encrypt your plaintext data
$ aws-encryption-cli --encrypt \
                     --input hello.txt \
                     --master-keys key=$keyArn \
                     --metadata-output ~/metadata \
                     --encryption-context purpose=test \
                     --output .

\\ Decrypt your ciphertext               
$ aws-encryption-cli --decrypt \
                     --input hello.txt.encrypted \
                     --encryption-context purpose=test \
                     --metadata-output ~/metadata \
                     --output .
```

This example shows how to encrypt and decrypt using the AWS Encryption CLI version 1.7.*x* or later. For complete examples, see [Examples of the AWS Encryption CLI](crypto-cli-examples.md).

The `--master-keys` parameter is deprecated in version 1.7.*x* and removed in version 2.0.*x*. It's replaced the by `--wrapping-keys` parameter, which is required in encrypt and decrypt commands. This parameter supports strict mode and discovery mode. Strict mode is an AWS Encryption SDK best practice that assures that you use the wrapping key that you intend. 

To upgrade to *strict mode*, use the **key** attribute of the `--wrapping-keys` parameter to specify a wrapping key when encrypting and decrypting. 

```
\\ Replace the example key ARN with a valid value
$ keyArn=arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab

\\ Encrypt your plaintext data
$ aws-encryption-cli --encrypt \
                     --input hello.txt \
                     --wrapping-keys key=$keyArn \
                     --metadata-output ~/metadata \
                     --encryption-context purpose=test \
                     --output .

\\ Decrypt your ciphertext               
$ aws-encryption-cli --decrypt \
                     --input hello.txt.encrypted \
                     --wrapping-keys key=$keyArn \
                     --encryption-context purpose=test \
                     --metadata-output ~/metadata \
                     --output .
```

------

## Migrating to discovery mode
<a name="migrate-mkp-discovery-mode"></a>

Beginning in version 1.7.*x*, it's an AWS Encryption SDK [best practice](best-practices.md) to use *strict mode* for AWS KMS master key providers, that is, to specify wrapping keys when encrypting and decrypting. You must always specify wrapping keys when encrypting. But there are situations in which specifying the key ARNs of AWS KMS keys for decrypting is impractical. For example, if you're using aliases to identify AWS KMS keys when encrypting, you lose the benefit of aliases if you have to list key ARNs when decrypting. Also, because master key providers in discovery mode behave like the original master key providers, you might use them temporarily as part of your migration strategy, and then upgrade to master key providers in strict mode later.

In cases like this, you can use master key providers in *discovery mode*. These master key providers don't let you specify wrapping keys, so you cannot use them for encrypting. When decrypting, they can use any wrapping key that encrypted a data key. But unlike legacy master key providers, which behave the same way, you create them in discovery mode explicitly. When using master key providers in discovery mode, you can limit the wrapping keys that can be used to those in particular AWS accounts. This discovery filter is optional, but it's a best practice that we recommend. For information about AWS partitions and accounts, see [Amazon Resource Names](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#arns-syntax) in the *AWS General Reference*.

The following examples create an AWS KMS master key provider in strict mode for encrypting and an AWS KMS master key provider in discovery mode for decrypting. The master key provider in discovery mode uses a discovery filter to limit the wrapping keys used for decrypting to the `aws` partition and to particular example AWS accounts. Although the account filter is not necessary in this very simple example, it's a best practice that is very beneficial when one application encrypts data and a different application decrypts the data.

------
#### [ Java ]

This example represents code in an application that uses version 1.7.*x* or later of the AWS Encryption SDK for Java. For a complete example, see [DiscoveryDecryptionExample.java](https://github.com/aws/aws-encryption-sdk-java/blob/master/src/examples/java/com/amazonaws/crypto/examples/).

To instantiate a master key provider in strict mode for encrypting, this example uses the `Builder.buildStrict()` method. To instantiate a master key provider in discovery mode for decrypting, it uses the `Builder.buildDiscovery()` method. The `Builder.buildDiscovery()` method takes a `DiscoveryFilter` that limits the AWS Encryption SDK to AWS KMS keys in the specified AWS partition and accounts. 

```
// Create a master key provider in strict mode for encrypting
// Replace the example alias ARN with a valid one from your AWS account.
String awsKmsKey = "arn:aws:kms:us-west-2:111122223333:alias/ExampleAlias";

KmsMasterKeyProvider encryptingKeyProvider = KmsMasterKeyProvider.builder()
    .buildStrict(awsKmsKey);

// Create a master key provider in discovery mode for decrypting
// Replace the example account IDs with valid values.
DiscoveryFilter accounts = new DiscoveryFilter("aws", Arrays.asList("111122223333", "444455556666"));

KmsMasterKeyProvider decryptingKeyProvider = KmsMasterKeyProvider.builder()
    .buildDiscovery(accounts);
```

------
#### [ Python ]

 This example represents code in an application that uses version 1.7.*x* or later of the AWS Encryption SDK for Python . For a complete example, see [discovery\$1kms\$1provider.py](https://github.com/aws/aws-encryption-sdk-python/blob/master/examples/src/legacy/discovery_kms_provider.py).

To create a master key provider in strict mode for encrypting, this example uses `StrictAwsKmsMasterKeyProvider`. To create a master key provider in discovery mode for decrypting, it uses `DiscoveryAwsKmsMasterKeyProvider` with a `DiscoveryFilter` that limits the AWS Encryption SDK to AWS KMS keys in the specified AWS partition and accounts. 

```
# Create a master key provider in strict mode
# Replace the example key ARN and alias ARNs with valid values from your AWS account.
key_1 = "arn:aws:kms:us-west-2:111122223333:alias/ExampleAlias"
key_2 = "arn:aws:kms:us-west-2:444455556666:key/1a2b3c4d-5e6f-1a2b-3c4d-5e6f1a2b3c4d"

aws_kms_master_key_provider = StrictAwsKmsMasterKeyProvider(
    key_ids=[key_1, key_2]
)

# Create a master key provider in discovery mode for decrypting
# Replace the example account IDs with valid values
accounts = DiscoveryFilter(
    partition="aws",
    account_ids=["111122223333", "444455556666"]
)
aws_kms_master_key_provider = DiscoveryAwsKmsMasterKeyProvider(
        discovery_filter=accounts
)
```

------
#### [ AWS Encryption CLI ]

This example shows how to encrypt and decrypt using the AWS Encryption CLI version 1.7.*x* or later. Beginning in version 1.7.*x*, the `--wrapping-keys` parameter is required when encrypting and decrypting. The `--wrapping-keys` parameter supports strict mode and discovery mode. For complete examples, see [Examples of the AWS Encryption CLI](crypto-cli-examples.md).

When encrypting, this example specifies a wrapping key, which is required. When decrypting, it explicitly chooses *discovery mode* by using the `discovery` attribute of the `--wrapping-keys` parameter with a value of `true`. 

To limit the wrapping keys that the AWS Encryption SDK can use in discovery mode to those in particular AWS accounts, this example uses the `discovery-partition` and `discovery-account` attributes of the `--wrapping-keys` parameter. These optional attributes are valid only when the `discovery` attribute is set to `true`. You must use the `discovery-partition` and `discovery-account` attributes together; neither is valid alone.

```
\\ Replace the example key ARN with a valid value
$ keyAlias=arn:aws:kms:us-west-2:111122223333:alias/ExampleAlias

\\ Encrypt your plaintext data
$ aws-encryption-cli --encrypt \
                     --input hello.txt \
                     --wrapping-keys key=$keyAlias \
                     --metadata-output ~/metadata \
                     --encryption-context purpose=test \
                     --output .

\\ Decrypt your ciphertext
\\ Replace the example account IDs with valid values           
$ aws-encryption-cli --decrypt \
                     --input hello.txt.encrypted \
                     --wrapping-keys discovery=true \
                                     discovery-partition=aws \
                                     discovery-account=111122223333 \
                                     discovery-account=444455556666 \
                     --encryption-context purpose=test \
                     --metadata-output ~/metadata \
                     --output .
```

------

# Updating AWS KMS keyrings
<a name="migrate-keyrings-v2"></a>

The AWS KMS keyrings in the [AWS Encryption SDK for C](c-language.md), the [AWS Encryption SDK for .NET](dot-net.md), and the [AWS Encryption SDK for JavaScript](javascript.md) support [best practices](best-practices.md) by allowing you to specify wrapping keys when encrypting and decrypting. If you create an [AWS KMS discovery keyring](use-kms-keyring.md#kms-keyring-discovery), you do so explicitly. 

**Note**  
The earliest version of the AWS Encryption SDK for .NET is version 3.0.*x*. All versions of the AWS Encryption SDK for .NET support the security best practices introduced in 2.0.*x* of the AWS Encryption SDK. You can safely upgrade to the latest version without any code or data changes.

When you update to the latest 1.*x* version of the AWS Encryption SDK, you can use a [discovery filter](use-kms-keyring.md#kms-keyring-discovery) to limit the wrapping keys that an [AWS KMS discovery keyring](use-kms-keyring.md#kms-keyring-discovery) or [AWS KMS regional discovery keyring](use-kms-keyring.md#kms-keyring-regional) uses when decrypting to those in particular AWS accounts. Filtering a discovery keyring is an AWS Encryption SDK [best practice](best-practices.md).

The examples in this section will show you how to add the discovery filter to an AWS KMS regional discovery keyring.

**Learn more about migration**

For all AWS Encryption SDK users, learn about setting your commitment policy in [Setting your commitment policy](migrate-commitment-policy.md).

For AWS Encryption SDK for Java, AWS Encryption SDK for Python, and AWS Encryption CLI users, learn about a required update to master key providers in [Updating AWS KMS master key providers](migrate-mkps-v2.md).

 

You might have code like the following in your application. This example creates an AWS KMS regional discovery keyring that can only use wrapping keys in the US West (Oregon) (us-west-2) Region. This example represents code in AWS Encryption SDK versions earlier than 1.7.*x*. However, it is still valid in versions 1.7.*x* and later. 

------
#### [ C ]

```
struct aws_cryptosdk_keyring *kms_regional_keyring = Aws::Cryptosdk::KmsKeyring::Builder()
       .WithKmsClient(create_kms_client(Aws::Region::US_WEST_2)).BuildDiscovery());
```

------
#### [ JavaScript Browser ]

```
const clientProvider = getClient(KMS, { credentials })

const discovery = true
const clientProvider = limitRegions(['us-west-2'], getKmsClient)
const keyring = new KmsKeyringBrowser({ clientProvider, discovery })
```

------
#### [ JavaScript Node.js ]

```
const discovery = true
const clientProvider = limitRegions(['us-west-2'], getKmsClient)
const keyring = new KmsKeyringNode({ clientProvider, discovery })
```

------

Beginning in version 1.7.*x*, you can add a discovery filter to any AWS KMS discovery keyring. This discovery filter limits the AWS KMS keys that the AWS Encryption SDK can use for decryption to those in the specified partition and accounts. Before using this code, change the partition, if necessary, and replace the example account IDs with valid ones.

------
#### [ C ]

For a complete example, see [kms\$1discovery.cpp](https://github.com/aws/aws-encryption-sdk-c/blob/master/examples/kms_discovery.cpp).

```
std::shared_ptr<KmsKeyring::DiscoveryFilter> discovery_filter(
    KmsKeyring::DiscoveryFilter::Builder("aws")
        .AddAccount("111122223333")
        .AddAccount("444455556666")
        .Build());

struct aws_cryptosdk_keyring *kms_regional_keyring = Aws::Cryptosdk::KmsKeyring::Builder()
       .WithKmsClient(create_kms_client(Aws::Region::US_WEST_2)).BuildDiscovery(discovery_filter));
```

------
#### [ JavaScript Browser ]

```
const clientProvider = getClient(KMS, { credentials })

const discovery = true
const clientProvider = limitRegions(['us-west-2'], getKmsClient)
const keyring = new KmsKeyringBrowser(clientProvider, {
    discovery,
    discoveryFilter: { accountIDs: ['111122223333', '444455556666'], partition: 'aws' }
})
```

------
#### [ JavaScript Node.js ]

For a complete example, see [kms\$1filtered\$1discovery.ts](https://github.com/aws/aws-encryption-sdk-javascript/blob/master/modules/example-node/src/kms_filtered_discovery.ts).

```
const discovery = true
const clientProvider = limitRegions(['us-west-2'], getKmsClient)
const keyring = new KmsKeyringNode({
    clientProvider,
    discovery,
    discoveryFilter: { accountIDs: ['111122223333', '444455556666'], partition: 'aws' }
})
```

------

# Setting your commitment policy
<a name="migrate-commitment-policy"></a>

[Key commitment](concepts.md#key-commitment) assures that your encrypted data always decrypts to the same plaintext. To provide this security property, beginning in version 1.7.*x*, the AWS Encryption SDK uses new [algorithm suites](supported-algorithms.md) with key commitment. To determine whether your data is encrypted and decrypted with key commitment, use the [commitment policy](concepts.md#commitment-policy) configuration setting. Encrypting and decrypting data with key commitment is an [AWS Encryption SDK best practice](best-practices.md).

Setting a commitment policy is an important part of the second step in the migration process — migrating from the latest 1.*x* versions of the AWS Encryption SDK to versions 2.0.*x* and later. After setting and changing your commitment policy, be sure to test your application thoroughly before deploying it in production. For migration guidance, see [How to migrate and deploy the AWS Encryption SDK](migration-guide.md).

The commitment policy setting has three valid values in versions 2.0.*x* and later. In the latest 1.*x* versions (beginning with version 1.7.*x*), only `ForbidEncryptAllowDecrypt` is valid.
+ `ForbidEncryptAllowDecrypt` — The AWS Encryption SDK cannot encrypt with key commitment. It can decrypt ciphertexts encrypted with or without key commitment. 

  In the latest 1.*x* versions, this is the only valid value. It ensures that you don't encrypt with key commitment until you are fully prepared to decrypt with key commitment. Setting the value explicitly prevents your commitment policy from changing automatically to `require-encrypt-require-decrypt` when you upgrade to versions 2.0.*x* or later. Instead, you can [migrate your commitment policy](#migrate-commitment-policy) in stages.
+ `RequireEncryptAllowDecrypt` — The AWS Encryption SDK always encrypts with key commitment. It can decrypt ciphertexts encrypted with or without key commitment. This value is added in version 2.0.*x*.
+ `RequireEncryptRequireDecrypt` — The AWS Encryption SDK always encrypts and decrypts with key commitment. This value is added in version 2.0.*x*. It is the default value in versions 2.0.*x* and later.

In the latest 1.*x* versions, the only valid commitment policy value is `ForbidEncryptAllowDecrypt`. After you migrate to version 2.0.*x* or later, you can [change your commitment policy in stages](migration-guide.md) as you are ready. Don't update your commitment policy to `RequireEncryptRequireDecrypt` until you are certain that you don't have any messages encrypted without key commitment. 

These examples show you how to set your commitment policy in the latest 1.*x* versions and in versions 2.0.*x* and later. The technique depends on your programming language. 

**Learn more about migration**

For AWS Encryption SDK for Java, AWS Encryption SDK for Python, and the AWS Encryption CLI, learn about required changes to master key providers in [Updating AWS KMS master key providers](migrate-mkps-v2.md).

For AWS Encryption SDK for C and AWS Encryption SDK for JavaScript, learn about an optional update to keyrings in [Updating AWS KMS keyrings](migrate-keyrings-v2.md).

## How to set your commitment policy
<a name="migrate-commitment-step1"></a>

The technique that you use to set your commitment policy differs slightly with each language implementation. These examples show you how to do it. Before changing your commitment policy, review the multi-stage approach in [How to migrate and deploy](migration-guide.md). 

------
#### [ C ]

Beginning in version 1.7.*x* of the AWS Encryption SDK for C, you use the `aws_cryptosdk_session_set_commitment_policy` function to set the commitment policy on your encrypt and decrypt sessions. The commitment policy that you set applies to all encrypt and decrypt operations called on that session.

The `aws_cryptosdk_session_new_from_keyring` and `aws_cryptosdk_session_new_from_cmm` functions are deprecated in version 1.7.*x* and removed in version 2.0.*x*. These functions are replaced by `aws_cryptosdk_session_new_from_keyring_2` and `aws_cryptosdk_session_new_from_cmm_2` functions that return a session.

When you use the `aws_cryptosdk_session_new_from_keyring_2` and `aws_cryptosdk_session_new_from_cmm_2` in the latest 1.*x* versions, you are required to call the `aws_cryptosdk_session_set_commitment_policy` function with the `COMMITMENT_POLICY_FORBID_ENCRYPT_ALLOW_DECRYPT` commitment policy value. In versions 2.0.*x* and later, calling this function is optional and it takes all valid values. The default commitment policy for versions 2.0.*x* and later is `COMMITMENT_POLICY_REQUIRE_ENCRYPT_REQUIRE_DECRYPT`.

For a complete example, see [string.cpp](https://github.com/aws/aws-encryption-sdk-c/blob/master/examples/string.cpp).

```
/* Load error strings for debugging */
aws_cryptosdk_load_error_strings();

/* Create an AWS KMS keyring */
const char * key_arn = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab";
struct aws_cryptosdk_keyring *kms_keyring = Aws::Cryptosdk::KmsKeyring::Builder().Build(key_arn);

/* Create an encrypt session with a CommitmentPolicy setting */
struct aws_cryptosdk_session *encrypt_session = aws_cryptosdk_session_new_from_keyring_2(
    alloc, AWS_CRYPTOSDK_ENCRYPT, kms_keyring);

aws_cryptosdk_keyring_release(kms_keyring);
aws_cryptosdk_session_set_commitment_policy(encrypt_session,
    COMMITMENT_POLICY_FORBID_ENCRYPT_ALLOW_DECRYPT);

...
/* Encrypt your data */

size_t plaintext_consumed_output;
aws_cryptosdk_session_process(encrypt_session,
                              ciphertext_output,
                              ciphertext_buf_sz_output,
                              ciphertext_len_output,
                              plaintext_input,
                              plaintext_len_input,
                              &plaintext_consumed_output)
...

/* Create a decrypt session with a CommitmentPolicy setting */

struct aws_cryptosdk_keyring *kms_keyring = Aws::Cryptosdk::KmsKeyring::Builder().Build(key_arn);
struct aws_cryptosdk_session *decrypt_session = *aws_cryptosdk_session_new_from_keyring_2(
        alloc, AWS_CRYPTOSDK_DECRYPT, kms_keyring);
aws_cryptosdk_keyring_release(kms_keyring);
aws_cryptosdk_session_set_commitment_policy(decrypt_session,
        COMMITMENT_POLICY_FORBID_ENCRYPT_ALLOW_DECRYPT);

/* Decrypt your ciphertext */
size_t ciphertext_consumed_output;
aws_cryptosdk_session_process(decrypt_session,
                              plaintext_output,
                              plaintext_buf_sz_output,
                              plaintext_len_output,
                              ciphertext_input,
                              ciphertext_len_input,
                              &ciphertext_consumed_output)
```

------
#### [ C\$1 / .NET ]

The `require-encrypt-require-decrypt` value is the default commitment policy in all versions of the AWS Encryption SDK for .NET. You can set it explicitly as a best practice, but it's not required. However, if you are using the AWS Encryption SDK for .NET to decrypt ciphertext that was encrypted by another language implementation of the AWS Encryption SDK without key commitment, you need to change the commitment policy value to `REQUIRE_ENCRYPT_ALLOW_DECRYPT` or `FORBID_ENCRYPT_ALLOW_DECRYPT`. Otherwise, attempts to decrypt the ciphertext will fail.

In the AWS Encryption SDK for .NET, you set the commitment policy on an instance of the AWS Encryption SDK. Instantiate an `AwsEncryptionSdkConfig` object with a `CommitmentPolicy` parameter, and use the configuration object to create the AWS Encryption SDK instance. Then, call the `Encrypt()` and `Decrypt()` methods of the configured AWS Encryption SDK instance. 

This example sets the commitment policy to `require-encrypt-allow-decrypt`.

```
// Instantiate the material providers
var materialProviders =
    AwsCryptographicMaterialProvidersFactory.CreateDefaultAwsCryptographicMaterialProviders();

// Configure the commitment policy on the AWS Encryption SDK instance
var config = new AwsEncryptionSdkConfig
{
    CommitmentPolicy = CommitmentPolicy.REQUIRE_ENCRYPT_ALLOW_DECRYPT
};
var encryptionSdk = AwsEncryptionSdkFactory.CreateAwsEncryptionSdk(config);

string keyArn = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab";

var encryptionContext = new Dictionary<string, string>()
{
    {"purpose", "test"}encryptionSdk
};

var createKeyringInput = new CreateAwsKmsKeyringInput
{
    KmsClient = new AmazonKeyManagementServiceClient(),
    KmsKeyId = keyArn
};
var keyring = materialProviders.CreateAwsKmsKeyring(createKeyringInput);

// Encrypt your plaintext data
var encryptInput = new EncryptInput
{
    Plaintext = plaintext,
    Keyring = keyring,
    EncryptionContext = encryptionContext
};
var encryptOutput = encryptionSdk.Encrypt(encryptInput);

// Decrypt your ciphertext
var decryptInput = new DecryptInput
{
    Ciphertext = ciphertext,
    Keyring = keyring
};
var decryptOutput = encryptionSdk.Decrypt(decryptInput);
```

------
#### [ AWS Encryption CLI ]

To set a commitment policy in the AWS Encryption CLI, use the `--commitment-policy` parameter. This parameter is introduced in version 1.8.*x*. 

In the latest 1.*x* version, when you use the `--wrapping-keys` parameter in an `--encrypt` or `--decrypt` command, a `--commitment-policy` parameter with the `forbid-encrypt-allow-decrypt` value is required. Otherwise, the `--commitment-policy` parameter is invalid.

In versions 2.1.*x* and later, the `--commitment-policy` parameter is optional and defaults to the `require-encrypt-require-decrypt` value, which won't encrypt or decrypt any ciphertext encrypted without key commitment. However, we recommend that you set the commitment policy explicitly in all encrypt and decrypt calls to help with maintenance and troubleshooting.

This example sets the commitment policy. It also uses the `--wrapping-keys` parameter that replaces the `--master-keys` parameter beginning in version 1.8.*x*. For details, see [Updating AWS KMS master key providers](migrate-mkps-v2.md). For complete examples, see [Examples of the AWS Encryption CLI](crypto-cli-examples.md).

```
\\ To run this example, replace the fictitious key ARN with a valid value. 
$ keyArn=arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab

\\ Encrypt your plaintext data - no change to algorithm suite used
$ aws-encryption-cli --encrypt \
                     --input hello.txt \
                     --wrapping-keys key=$keyArn \
                     --commitment-policy forbid-encrypt-allow-decrypt \
                     --metadata-output ~/metadata \
                     --encryption-context purpose=test \
                     --output .

\\ Decrypt your ciphertext - supports key commitment on 1.7 and later
$ aws-encryption-cli --decrypt \
                     --input hello.txt.encrypted \
                     --wrapping-keys key=$keyArn \
                     --commitment-policy forbid-encrypt-allow-decrypt \
                     --encryption-context purpose=test \
                     --metadata-output ~/metadata \
                     --output .
```

------
#### [ Java ]

Beginning in version 1.7.*x* of the AWS Encryption SDK for Java, you set the commitment policy on your instance of `AwsCrypto`, the object that represents the AWS Encryption SDK client. This commitment policy setting applies to all encrypt and decrypt operations called on that client.

The `AwsCrypto()` constructor is deprecated in the latest 1.*x* versions of the AWS Encryption SDK for Java and is removed in version 2.0.*x*. It's replaced by a new `Builder` class, a `Builder.withCommitmentPolicy()` method, and the `CommitmentPolicy` enumerated type. 

In the latest 1.*x* versions, the `Builder` class requires the `Builder.withCommitmentPolicy()` method and the `CommitmentPolicy.ForbidEncryptAllowDecrypt` argument. Beginning in version 2.0.*x*, the `Builder.withCommitmentPolicy()` method is optional; the default value is `CommitmentPolicy.RequireEncryptRequireDecrypt`.

For a complete example, see [SetCommitmentPolicyExample.java](https://github.com/aws/aws-encryption-sdk-java/blob/master/src/examples/java/com/amazonaws/crypto/examples/v2/SetCommitmentPolicyExample.java).

```
// Instantiate the client
final AwsCrypto crypto = AwsCrypto.builder()
    .withCommitmentPolicy(CommitmentPolicy.ForbidEncryptAllowDecrypt)
    .build();

// Create a master key provider in strict mode
String awsKmsKey = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab";

KmsMasterKeyProvider masterKeyProvider = KmsMasterKeyProvider.builder()
    .buildStrict(awsKmsKey);

// Encrypt your plaintext data
CryptoResult<byte[], KmsMasterKey> encryptResult = crypto.encryptData(
    masterKeyProvider,
    sourcePlaintext,
    encryptionContext);
byte[] ciphertext = encryptResult.getResult();

// Decrypt your ciphertext
CryptoResult<byte[], KmsMasterKey> decryptResult = crypto.decryptData(
        masterKeyProvider,
        ciphertext);
byte[] decrypted = decryptResult.getResult();
```

------
#### [ JavaScript ]

Beginning in version 1.7.*x* of the AWS Encryption SDK for JavaScript, you can set the commitment policy when you call the new `buildClient` function that instantiates an AWS Encryption SDK client. The `buildClient` function takes an enumerated value that represents your commitment policy. It returns updated `encrypt` and `decrypt` functions that enforce your commitment policy when you encrypt and decrypt.

In the latest 1.*x* versions, the `buildClient` function requires the `CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT` argument. Beginning in version 2.0.*x*, the commitment policy argument is optional and the default value is `CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT`.

The code for Node.js and the browser are identical for this purpose, except that browser needs a statement to set credentials. 

The following example encrypts data with an AWS KMS keyring. The new `buildClient` function sets the commitment policy to `FORBID_ENCRYPT_ALLOW_DECRYPT`, the default value in the latest 1.*x* versins. The upgraded `encrypt` and `decrypt` functions that `buildClient` returns enforce the commitment policy you set. 

```
import { buildClient } from '@aws-crypto/client-node'
const { encrypt, decrypt } = buildClient(CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT)

// Create an AWS KMS keyring
const generatorKeyId = 'arn:aws:kms:us-west-2:111122223333:alias/ExampleAlias'
const keyIds = ['arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab']
const keyring = new KmsKeyringNode({ generatorKeyId, keyIds })

// Encrypt your plaintext data
const { ciphertext } = await encrypt(keyring, plaintext, { encryptionContext: context })

// Decrypt your ciphertext
const { decrypted, messageHeader } = await decrypt(keyring, ciphertext)
```

------
#### [ Python ]

Beginning in version 1.7.*x* of the AWS Encryption SDK for Python, you set the commitment policy on your instance of `EncryptionSDKClient`, a new object that represents the AWS Encryption SDK client. The commitment policy that you set applies to all `encrypt` and `decrypt` calls that use that instance of the client.

In the latest 1.*x* versions, the `EncryptionSDKClient` constructor requires the `CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT` enumerated value. Beginning in version 2.0.*x*, the commitment policy argument is optional and the default value is `CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT`.

This example uses the new `EncryptionSDKClient` constructor and sets the commitment policy to the 1.7.*x* default value. The constructor instantiates a client that represents the AWS Encryption SDK. When you call the `encrypt`, `decrypt`, or `stream` methods on this client, they enforce the commitment policy that you set. This example also uses the new constructor for the `StrictAwsKmsMasterKeyProvider` class, which specifies AWS KMS keys when encrypting and decrypting. 

For a complete example, see [set\$1commitment.py](https://github.com/aws/aws-encryption-sdk-python/blob/master/examples/src/legacy/set_commitment.py).

```
# Instantiate the client
client = aws_encryption_sdk.EncryptionSDKClient(commitment_policy=CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT)

// Create a master key provider in strict mode
aws_kms_key = "arn:aws:kms:us-west-2:111122223333:key/1234abcd-12ab-34cd-56ef-1234567890ab"
aws_kms_strict_master_key_provider = StrictAwsKmsMasterKeyProvider(
        key_ids=[aws_kms_key]
)

# Encrypt your plaintext data
ciphertext, encrypt_header = client.encrypt(
        source=source_plaintext,
        encryption_context=encryption_context,
        master_key_provider=aws_kms_strict_master_key_provider
)

# Decrypt your ciphertext
decrypted, decrypt_header = client.decrypt(
        source=ciphertext,
        master_key_provider=aws_kms_strict_master_key_provider
)
```

------
#### [ Rust ]

The `require-encrypt-require-decrypt` value is the default commitment policy in all versions of the AWS Encryption SDK for Rust. You can set it explicitly as a best practice, but it's not required. However, if you are using the AWS Encryption SDK for Rust to decrypt ciphertext that was encrypted by another language implementation of the AWS Encryption SDK without key commitment, you need to change the commitment policy value to `REQUIRE_ENCRYPT_ALLOW_DECRYPT` or `FORBID_ENCRYPT_ALLOW_DECRYPT`. Otherwise, attempts to decrypt the ciphertext will fail.

In the AWS Encryption SDK for Rust, you set the commitment policy on an instance of the AWS Encryption SDK. Instantiate an `AwsEncryptionSdkConfig` object with a `comitment_policy` parameter, and use the configuration object to create the AWS Encryption SDK instance. Then, call the `Encrypt()` and `Decrypt()` methods of the configured AWS Encryption SDK instance. 

This example sets the commitment policy to `forbid-encrypt-allow-decrypt`.

```
// Configure the commitment policy on the AWS Encryption SDK instance
let esdk_config = AwsEncryptionSdkConfig::builder()
                    .commitment_policy(ForbidEncryptAllowDecrypt)
                    .build()?;
let esdk_client = esdk_client::Client::from_conf(esdk_config)?;

// Create an AWS KMS client
let sdk_config = aws_config::load_defaults(aws_config::BehaviorVersion::latest()).await;
let kms_client = aws_sdk_kms::Client::new(&sdk_config);

// Create your encryption context
let encryption_context = HashMap::from([
    ("encryption".to_string(), "context".to_string()),
    ("is not".to_string(), "secret".to_string()),
    ("but adds".to_string(), "useful metadata".to_string()),
    ("that can help you".to_string(), "be confident that".to_string()),
    ("the data you are handling".to_string(), "is what you think it is".to_string()),
]);

// Instantiate the material providers library
let mpl_config = MaterialProvidersConfig::builder().build()?;
let mpl = mpl_client::Client::from_conf(mpl_config)?;

// Create an AWS KMS keyring
let kms_keyring = mpl
    .create_aws_kms_keyring()
    .kms_key_id(kms_key_id)
    .kms_client(kms_client)
    .send()
    .await?;

// Encrypt your plaintext data
let plaintext = example_data.as_bytes();

let encryption_response = esdk_client.encrypt()
    .plaintext(plaintext)
    .keyring(kms_keyring.clone())
    .encryption_context(encryption_context.clone())
    .send()
    .await?;

// Decrypt your ciphertext
let decryption_response = esdk_client.decrypt()
    .ciphertext(ciphertext)
    .keyring(kms_keyring)
    // Provide the encryption context that was supplied to the encrypt method
    .encryption_context(encryption_context)
    .send()
    .await?;
```

------
#### [ Go ]

```
import (
    "context"
    
	mpl "aws/aws-cryptographic-material-providers-library/releases/go/mpl/awscryptographymaterialproviderssmithygenerated"
	mpltypes "aws/aws-cryptographic-material-providers-library/releases/go/mpl/awscryptographymaterialproviderssmithygeneratedtypes"
	client "github.com/aws/aws-encryption-sdk/awscryptographyencryptionsdksmithygenerated"
	esdktypes "github.com/aws/aws-encryption-sdk/awscryptographyencryptionsdksmithygeneratedtypes"
    "github.com/aws/aws-sdk-go-v2/config"
    "github.com/aws/aws-sdk-go-v2/service/kms"
)

// Instantiate the AWS Encryption SDK client
commitPolicyForbidEncryptAllowDecrypt := mpltypes.ESDKCommitmentPolicyForbidEncryptAllowDecrypt
encryptionClient, err := client.NewClient(esdktypes.AwsEncryptionSdkConfig{CommitmentPolicy: &commitPolicyForbidEncryptAllowDecrypt})
if err != nil {
    panic(err)
}

// Create an AWS KMS client
cfg, err := config.LoadDefaultConfig(context.TODO())
if err != nil {
    panic(err)
}
kmsClient := kms.NewFromConfig(cfg, func(o *kms.Options) {
    o.Region = KmsKeyRegion
})

// Optional: Create an encryption context
encryptionContext := map[string]string{
    "encryption":                "context",
    "is not":                    "secret",
    "but adds":                  "useful metadata",
    "that can help you":         "be confident that",
    "the data you are handling": "is what you think it is",
}

// Instantiate the material providers library
matProv, err := mpl.NewClient(mpltypes.MaterialProvidersConfig{})
if err != nil {
    panic(err)
}

// Create an AWS KMS keyring
awsKmsKeyringInput := mpltypes.CreateAwsKmsKeyringInput{
    KmsClient: kmsClient,
    KmsKeyId:  kmsKeyId,
}
awsKmsKeyring, err := matProv.CreateAwsKmsKeyring(context.Background(), awsKmsKeyringInput)
if err != nil {
    panic(err)
}

// Encrypt your plaintext data
res, err := forbidEncryptClient.Encrypt(context.Background(), esdktypes.EncryptInput{
    Plaintext:         []byte(exampleText),
    EncryptionContext: encryptionContext,
    Keyring:           awsKmsKeyring,
})
if err != nil {
    panic(err)
}

// Decrypt your ciphertext
decryptOutput, err := forbidEncryptClient.Decrypt(context.Background(), esdktypes.DecryptInput{
    Ciphertext:        res.Ciphertext,
    EncryptionContext: encryptionContext,
    Keyring:           awsKmsKeyring,
})
if err != nil {
    panic(err)
}
```

------

# Troubleshooting migration to the latest versions
<a name="troubleshooting-migration"></a>

Before updating your application to version 2.0.*x* or later of the AWS Encryption SDK, update to the latest 1.*x* version of the AWS Encryption SDK and deploy it completely. That will help you avoid most errors you might encounter when updating to versions 2.0.*x* and later. For detailed guidance, including examples, see [Migrating your AWS Encryption SDK](migration.md).

**Important**  
Verify that your latest 1.*x* version is version 1.7.*x* or later of the AWS Encryption SDK.

**Note**  
**AWS Encryption CLI**: References in this guide to version 1.7.*x* of the AWS Encryption SDK apply to version 1.8.*x* of the AWS Encryption CLI. References in this guide to version 2.0.*x* of the AWS Encryption SDK apply to 2.1.*x* of the AWS Encryption CLI.  
New security features were originally released in AWS Encryption CLI versions 1.7.*x* and 2.0.*x*. However, AWS Encryption CLI version 1.8.*x* replaces version 1.7.*x* and AWS Encryption CLI 2.1.*x* replaces 2.0.*x*. For details, see the relevant [security advisory](https://github.com/aws/aws-encryption-sdk-cli/security/advisories/GHSA-2xwp-m7mq-7q3r) in the [aws-encryption-sdk-cli](https://github.com/aws/aws-encryption-sdk-cli/) repository on GitHub.

This topic is designed to help you recognize and resolve the most common errors you might encounter.

**Topics**
+ [

## Deprecated or removed objects
](#deprecated-removed)
+ [

## Configuration conflict: Commitment policy and algorithm suite
](#configuration-conflict_1)
+ [

## Configuration conflict: Commitment policy and ciphertext
](#configuration-conflict_2)
+ [

## Key commitment validation failed
](#commitment-failed)
+ [

## Other encryption failures
](#encrypt-failed)
+ [

## Other decryption failures
](#decrypt-failed)
+ [

## Rollback considerations
](#migration-rollback)

## Deprecated or removed objects
<a name="deprecated-removed"></a>

Version 2.0.*x* includes several breaking changes, including removing legacy constructors, methods, functions, and classes that were deprecated in version 1.7.*x*. To avoid compiler errors, import errors, syntax errors, and symbol not found errors (depending on your programming language), upgrade first to the latest 1.*x* version of the AWS Encryption SDK for your programming language. (This must be version 1.7.*x* or later.) While using the latest 1.*x* version, you can begin using the replacement elements before the original symbols are removed.

If you need to upgrade to version 2.0.*x* or later immediately, [consult the changelog](about-versions.md) for your programming language, and replace the legacy symbols with the symbols the changelog recommends.

## Configuration conflict: Commitment policy and algorithm suite
<a name="configuration-conflict_1"></a>

If you specify an algorithm suite that conflicts with your [commitment policy](concepts.md#commitment-policy), the call to encrypt fails with a *Configuration conflict* error.

To avoid this type of error, don't specify an algorithm suite. By default, the AWS Encryption SDK chooses the most secure algorithm that is compatible with your commitment policy. However, if you must specify an algorithm suite, such as one without signing, be sure to choose an algorithm suite that is compatible with your commitment policy.


| Commitment policy | Compatible algorithm suites | 
| --- | --- | 
| ForbidEncryptAllowDecrypt | Any algorithm suite *without* key commitment, such as:AES\$1256\$1GCM\$1IV12\$1TAG16\$1HKDF\$1SHA384\$1ECDSA\$1P384 ([03 78](algorithms-reference.md)) (with signing) `AES_256_GCM_IV12_TAG16_HKDF_SHA256` ([01 78](algorithms-reference.md)) (without signing) | 
| RequireEncryptAllowDecryptRequireEncryptRequireDecrypt | Any algorithm suite *with* key commitment, such as:AES\$1256\$1GCM\$1HKDF\$1SHA512\$1COMMIT\$1KEY\$1ECDSA\$1P384 ([05 78](algorithms-reference.md)) (with signing) `AES_256_GCM_HKDF_SHA512_COMMIT_KEY` ([04 78](algorithms-reference.md)) (without signing) | 

If you encounter this error when you have not specified an algorithm suite, the conflicting algorithm suite might have been chosen by your [cryptographic materials manager](concepts.md#crypt-materials-manager) (CMM). The Default CMM won't select a conflicting algorithm suite, but a custom CMM might. For help, consult the documentation for your custom CMM.

## Configuration conflict: Commitment policy and ciphertext
<a name="configuration-conflict_2"></a>

The `RequireEncryptRequireDecrypt` [commitment policy](concepts.md#commitment-policy) does not permit the AWS Encryption SDK to decrypt a message that was encrypted without [key commitment](concepts.md#key-commitment). If you ask the AWS Encryption SDK to decrypt a message without key commitment, it returns a *Configuration conflict* error.

To avoid this error, before setting the `RequireEncryptRequireDecrypt` commitment policy, be sure that all ciphertexts encrypted without key commitment are decrypted and re-encrypted with key commitment, or handled by a different application. If you encounter this error, you can return an error for the conflicting ciphertext or change your commitment policy temporarily to `RequireEncryptAllowDecrypt`.

If you are encountering this error because you upgraded to version 2.0.*x* or later from a version earlier than 1.7.*x* without first upgrading to the latest 1.*x* version (version 1.7.*x* or later), consider [rolling back](#migration-rollback) to the latest 1.*x* version and deploying that version to all hosts before upgrading to version 2.0.*x* or later. For help, see [How to migrate and deploy the AWS Encryption SDK](migration-guide.md).

## Key commitment validation failed
<a name="commitment-failed"></a>

When you decrypt messages that are encrypted with key commitment, you might get a *Key commitment validation failed* error message. This indicates that the decrypt call failed because a data key in an [encrypted message](concepts.md#DEK) is not identical to the unique data key for the message. By validating the data key during decryption, [key commitment](concepts.md#key-commitment) protects you from decrypting a message that might result in more than one plaintext. 

This error indicates that the encrypted message that you were trying to decrypt was not returned by the AWS Encryption SDK. It might be a manually crafted message or the result of data corruption. If you encounter this error, your application can reject the message and continue, or stop processing new messages.

## Other encryption failures
<a name="encrypt-failed"></a>

Encryption can fail for multiple reasons. You cannot use an [AWS KMS discovery keyring](use-kms-keyring.md#kms-keyring-discovery) or a [master key provider in discovery mode](migrate-mkps-v2.md) to encrypt a message. 

Be sure that you specify a keyring or master key provider with wrapping keys that you have [permission to use](use-kms-keyring.md#kms-keyring-permissions) for encryption. For help with permissions on AWS KMS keys, see [Viewing a key policy](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-viewing.html) and [Determining access to an AWS KMS key](https://docs.aws.amazon.com/kms/latest/developerguide/determining-access.html) in the *AWS Key Management Service Developer Guide*.

## Other decryption failures
<a name="decrypt-failed"></a>

If your attempt to decrypt an encrypted message fails, it means that the AWS Encryption SDK could not (or would not) decrypt any of the encrypted data keys in the message. 

If you used a keyring or master key provider that specifies wrapping keys, the AWS Encryption SDK uses only the wrapping keys you specify. Verify that you are using the wrapping keys that you intend and that you have `kms:Decrypt` permission on at least one of the wrapping keys. If you are using AWS KMS keys, as a fallback, you can try decrypting the message with an [AWS KMS discovery keyring](use-kms-keyring.md#kms-keyring-discovery) or a [master key provider in discovery mode](migrate-mkps-v2.md). If the operation succeeds, before returning the plaintext, verify that the key used to decrypt the message is one that you trust. 

## Rollback considerations
<a name="migration-rollback"></a>

If your application is failing to encrypt or decrypt data, you can usually resolve the problem by updating the code symbols, keyrings, master key providers, or [commitment policy](concepts.md#commitment-policy). However, in some cases, you might decide that it's best to roll back your application to a previous version of the AWS Encryption SDK.

If you must roll back, do so with caution. Versions of the AWS Encryption SDK prior to 1.7.*x* cannot decrypt ciphertext encrypted with [key commitment](concepts.md#key-commitment).
+ Rolling back from the latest 1.*x* version to a previous version of the AWS Encryption SDK is generally safe. You might have to undo changes you made to your code to use symbols and objects that are not supported in previous versions. 
+ Once you have begun encrypting with key commitment (setting your commitment policy to `RequireEncryptAllowDecrypt`) in version 2.0.*x* or later, you can roll back to version 1.7.*x*, but not to any earlier version. Versions of the AWS Encryption SDK prior to 1.7.*x* cannot decrypt ciphertext encrypted with [key commitment](concepts.md#key-commitment).

If you accidentally enable encrypting with key commitment before all hosts can decrypt with key commitment, it might be best to continue with the roll out rather than to roll back. If messages are transient or can be safely dropped, then you might consider a rollback with loss of messages. If a rollback is required, you might consider writing a tool that decrypts and re-encrypts all messages.