

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

# 迁移你的 AWS Encryption SDK
<a name="migration"></a>

 AWS Encryption SDK 支持多种可互操作的[编程语言实现](programming-languages.md)，每种实现都是在上的开源存储库中开发的。 GitHub作为[最佳实践](best-practices.md)，我们建议您对每种语言使用最新版本 AWS Encryption SDK 的。

您可以安全地从 2.0 版本升级。 *x* 或更高版本 AWS Encryption SDK 到最新版本。但是，2.0。 *x* 版本 AWS Encryption SDK 引入了重要的新安全功能，其中一些是重大更改。要从 1.7.*x* 之前的版本更新到版本 2.0.*x* 及更高版本，必须先更新到最新版本 1.*x*。本节中的主题旨在帮助您了解更改，为应用程序选择正确的版本，并成功安全迁移到 AWS Encryption SDK最新版本。

有关重要版本的信息 AWS Encryption SDK，请参见[的版本 AWS Encryption SDK](about-versions.md)。

**重要**  
若未升级到最新版本 1.*x*，请勿直接从 1.7.*x* 之前的版本升级到版本 2.0.*x* 或更高版本。如果您直接升级到 2.0 版。 *x* 或更高版本并立即启用所有新功能，则 AWS Encryption SDK 无法解密在旧版本下加密的密文。 AWS Encryption SDK

**注意**  
.NET AWS Encryption SDK 的最早版本是 3.0 版。 *x*。 AWS Encryption SDK 适用于.NET 的所有版本都支持 2.0 中引入的安全最佳实践。 *的 x 个* AWS Encryption SDK。无需更改任何代码或数据即可安全升级到最新版本。  
AWS 加密 CLI：阅读本迁移指南时，请使用 1.7。 *x* AWS 加密 CLI 1.8 的迁移说明。 *x* 然后使用 2.0。 *x* AWS 加密 CLI 2.1 的迁移说明。 *x*。有关更多信息，请参阅 [AWS 加密 CLI 的版本](crypto-cli-versions.md)。  
新的安全功能最初是在 AWS 加密 CLI 版本 1.7 中发布的。 *x* 和 2.0。 *x*。但是， AWS 加密 CLI 版本为 1.8。 *x* 取代了 1.7 版。 *x* 和 AWS 加密 CLI 2.1。 *x* 取代 2.0。 *x*。有关详细信息，请参阅[aws-encryption-sdk-cli](https://github.com/aws/aws-encryption-sdk-cli/)存储库中的相关[安全公告](https://github.com/aws/aws-encryption-sdk-cli/security/advisories/GHSA-2xwp-m7mq-7q3r) GitHub。

**新用户**  
如果您不熟悉 AWS Encryption SDK，请安装 AWS Encryption SDK 适用于您的编程语言的最新版本的。默认值启用的所有安全功能 AWS Encryption SDK，包括带签名的加密、密钥派生和[密钥承诺](concepts.md#key-commitment)。 AWS Encryption SDK

**当前用户**  
我们建议您尽快从当前版本升级到最新可用版本。全部 1. AWS Encryption SDK 的 *x* 版本正[end-of-support 处于阶段](https://docs.aws.amazon.com/sdkref/latest/guide/maint-policy.html#version-life-cycle)，某些编程语言的更高版本也是如此。有关您的编程语言中 AWS Encryption SDK 的支持和维护状态的详细信息，请参阅 [支持和维护](introduction.md#support)。  
AWS Encryption SDK 版本 2.0。 *x* 及更高版本提供了新的安全功能来帮助保护您的数据。但是， AWS Encryption SDK 版本为 2.0。 *x* 包括不向后兼容的重大更改。为确保安全过渡，请首先在你的编程语言中从当前版本迁移到最新版本 1.*x*。如果最新版本 1.*x* 已全面部署并成功运行，您可以安全迁移到版本 2.0.*x* 及更高版本。这个[两步过程](migration-guide.md)至关重要，对于分布式应用程序尤其如此。

有关这些更改所依据 AWS Encryption SDK 的安全功能的更多信息，请参阅*AWS 安全*博客中的[改进客户端加密：显式 KeyIds 和密钥承诺](https://aws.amazon.com/blogs/security/improved-client-side-encryption-explicit-keyids-and-key-commitment/)。

在使用时正在寻求帮助 AWS SDK for Java 2.x？ AWS Encryption SDK for Java 请参阅[先决条件](java.md#java-prerequisites)。

**Topics**
+ [如何迁移和部署 AWS Encryption SDK](migration-guide.md)
+ [更新 AWS KMS 主密钥提供程序](migrate-mkps-v2.md)
+ [更新 AWS KMS 钥匙圈](migrate-keyrings-v2.md)
+ [设置您的承诺策略](migrate-commitment-policy.md)
+ [对迁移到至最新版本进行故障排除](troubleshooting-migration.md)

# 如何迁移和部署 AWS Encryption SDK
<a name="migration-guide"></a>

从 1.7 之前的 AWS Encryption SDK 版本迁移时。 *x* 到 2.0 版。 *x* 或更高版本，您必须安全地过渡到使用密[钥承诺](concepts.md#key-commitment)进行加密。否则，您的应用程序将遇到无法解密的加密文字。如果您使用的是 AWS KMS 主密钥提供程序，则必须更新到在严格模式或发现模式下创建主密钥提供程序的新构造函数。

**注意**  
本主题专为从 AWS Encryption SDK 早期版本迁移到版本 2.0.*x* 或更高版本的用户而设计。如果您不熟悉 AWS Encryption SDK，则可以在默认设置下立即开始使用最新的可用版本。

为避免出现无法解密需要读取的加密文字的严重情况，我们建议您分多个不同阶段进行迁移和部署。在开始下一阶段之前，请确认各阶段均已结束并全面部署。这对于具有多台主机的分布式应用程序尤其重要。

## 阶段 1：将您的应用程序更新到最新版本 1.*x*
<a name="migrate-stage1"></a>

更新到适用于您的编程语言的最新版本 1.*x*。在开始阶段 2 之前，请仔细测试、部署更改并确认更新已传播到所有目标主机。

**重要**  
验证最新版本 1.*x* 为 AWS Encryption SDK版本 1.7.*x* 或更高版本。

最新的 1. *x* 版本向后兼容的旧版本， AWS Encryption SDK 向前兼容版本 2.0。 AWS Encryption SDK *x* 及更高版本。最新版本包括版本 2.0.*x* 的新功能，但也包括为此迁移设计的安全默认值。它们允许您在必要时升级 AWS KMS 主密钥提供程序，并使用可通过密钥承诺解密密文的算法套件进行全面部署。
+ 替换弃用元素，包括旧版 AWS KMS 主密钥提供程序的构造函数。在 [Python](https://docs.python.org/3/library/warnings.html) 中，请确保打开弃用警告。最新版本 1.*x* 弃用的代码元素已从版本 2.0.*x* 及更高版本中移除。
+ 将您的承诺策略明确设置为 `ForbidEncryptAllowDecrypt`。尽管这是最新版本中唯一的有效值 1. *x* 版本，当您使用本版本中 APIs 引入的版本时，需要此设置。当您迁移到版本 2.0.*x* 及更高版本时，其可防止您的应用程序拒绝未使用密钥承诺加密的加密文字。有关更多信息，请参阅 [设置您的承诺策略](migrate-commitment-policy.md)。
+ 如果您使用 AWS KMS 主密钥提供程序，则必须将旧版主密钥提供程序更新为支持*严格模式和*发现模式**的主密钥提供程序。 AWS Encryption SDK for Java、 AWS Encryption SDK for Python和 AWS 加密 CLI 需要进行此更新。如果您在发现模式下使用主密钥提供程序，我们建议您实施发现筛选条件，将使用的包装密钥限制为特定 AWS 账户的密钥。此项更新为可选项，但却是我们建议的[最佳实践](best-practices.md)。有关更多信息，请参阅 [更新 AWS KMS 主密钥提供程序](migrate-mkps-v2.md)。
+ 如果您使用 [AWS KMS Discovery 密钥环](use-kms-keyring.md#kms-keyring-discovery)，我们建议您纳入将可用于解密的包装密钥限制为特定 AWS 账户密钥的发现筛选条件。此项更新为可选项，但却是我们建议的[最佳实践](best-practices.md)。有关更多信息，请参阅 [更新 AWS KMS 钥匙圈](migrate-keyrings-v2.md)。

## 阶段 2：将您的应用程序更新到最新版本
<a name="migrate-stage2"></a>

所有主机成功部署最新版本 1.*x* 版本后，您可以升级到版本 2.0.*x* 及更高版本。版本 2.0。 *x* 包括对所有早期版本的重大更改 AWS Encryption SDK。但是，如果您按照阶段 1 的建议更改代码，可以避免在迁移到最新版本时出错。

在更新到最新版本之前，请确认您的承诺策略始终设置为 `ForbidEncryptAllowDecrypt`。然后，根据您的数据配置，您可以按照自己的节奏迁移到 `RequireEncryptAllowDecrypt`，然后迁移到默认设置 `RequireEncryptRequireDecrypt`。我们建议采取一系列过渡步骤，例如以下模式。

1. 首先，将您的[承诺策略](migrate-commitment-policy.md)设置为 `ForbidEncryptAllowDecrypt`。 AWS Encryption SDK 可以使用密钥承诺解密消息，但尚未使用密钥承诺进行加密。

1. 准备就绪后，将承诺策略更新为 `RequireEncryptAllowDecrypt`。 AWS Encryption SDK 开始使用密[钥承诺](concepts.md#key-commitment)对您的数据进行加密。其可使用也可不使用密钥承诺解密加密文字。

   在将您的承诺策略更新为 `RequireEncryptAllowDecrypt` 之前，请确认您的最新版本 1.*x* 部署到所有主机，包括解密您生成的加密文字的任何应用程序的主机。1.7 AWS Encryption SDK 之前版本的版本。 *x* 无法解密使用密钥承诺加密的消息。

   这也是向应用程序添加指标的好时机，以衡量您是否仍在未使用密钥承诺处理加密文字。这将帮助您确定何时可以安全地将承诺策略设置更新为 `RequireEncryptRequireDecrypt`。对于某些应用程序，例如对 Amazon SQS 队列中的消息进行加密的应用程序，这可能意味着要等待足够长的时间才能重新加密或删除使用旧版本加密的所有加密文字。对于其他应用程序，例如加密的 S3 对象，您可能需要下载、重新加密和重新上传所有对象。

1. 如果您确定没有任何未使用密钥承诺加密的消息，则可以将承诺策略更新为 `RequireEncryptRequireDecrypt`。此值可确保您的数据始终使用密钥承诺进行加密和解密。此设置为默认设置，因此您无需明确设置，但我们建议您这样做。如果您的应用程序遇到未使用密钥承诺加密的加密文字，明确设置将[协助调试](troubleshooting-migration.md)和可能需要的任何潜在回滚。

# 更新 AWS KMS 主密钥提供程序
<a name="migrate-mkps-v2"></a>

要迁移到最新版本 1. *x* 版本的 AWS Encryption SDK，然后是 2.0 版。 *x* 或更高版本，您必须将传统 AWS KMS 的主密钥提供程序替换为在[*严格模式或*发现模式*下*](about-versions.md#changes-to-mkps)显式创建的主密钥提供程序。旧版主密钥提供程序在版本 1.7.*x* 中弃用并在版本 2.0.*x* 中移除。使用 [AWS Encryption SDK for Java](java.md)、[AWS Encryption SDK for Python](python.md) 和 [AWS Encryption CLI](crypto-cli.md) 的应用程序和脚本需要进行此项更改。本节中的示例将演示如何更新代码。

**注意**  
在 Python 中，[打开弃用警告](https://docs.python.org/3/library/warnings.html)。这将帮助您识别代码中需要更新的部分。

如果您使用的是 AWS KMS 主密钥（不是主密钥提供程序），则可以跳过此步骤。 AWS KMS 主密钥不会被弃用或删除。这些密钥仅使用您指定的包装密钥进行加密和解密。

本节中的示例重点介绍需要更改的代码元素。有关更新后的代码的完整示例，请参阅您的[编程语言 GitHub](programming-languages.md)存储库的 “示例” 部分。此外，这些示例通常使用 key ARNs 来表示 AWS KMS keys。在创建用于加密的主密钥提供程序时，可以使用任何有效的 AWS KMS [密钥标识符](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id)来表示。 AWS KMS key 如果创建用于解密的主密钥提供程序，必须使用密钥 ARN。

**了解有关迁移的更多信息**

对于所有 AWS Encryption SDK 用户，请在中了解如何设置您的承诺政策[设置您的承诺策略](migrate-commitment-policy.md)。

对于 AWS Encryption SDK for C 和 AWS Encryption SDK for JavaScript 用户，请在中[更新 AWS KMS 钥匙圈](migrate-keyrings-v2.md)了解钥匙圈的可选更新。

**Topics**
+ [迁移到严格模式](#migrate-mkp-strict-mode)
+ [迁移到发现模式](#migrate-mkp-discovery-mode)

## 迁移到严格模式
<a name="migrate-mkp-strict-mode"></a>

更新到最新版本后 1. *x* 版本的 AWS Encryption SDK，在严格模式下，用主密钥提供程序替换旧版主密钥提供程序。在严格模式下，必须指定加密和解密时要使用的包装密钥。仅 AWS Encryption SDK 使用您指定的包装密钥。已弃用的主密钥提供程序可以使用任何加密数据密钥的提供程序 AWS KMS key 来解密数据，包括在不同的 AWS KMS keys AWS 账户 地区和区域。

1.7 AWS Encryption SDK 版本中引入了严格模式的主密钥提供程序。 *x*。这些主密钥提供程序取代旧版主密钥提供程序，其在 1.7.*x* 中弃用并在 2.0.*x* 中移除。在严格模式下使用主密钥提供程序是一种 AWS Encryption SDK [最佳实践](best-practices.md)。

以下代码创建可用于加密和解密的严格模式下的主密钥提供程序。

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

此示例表示使用版本 AWS Encryption SDK for Java 1.6.2 或更早版本的应用程序中的代码。

此代码使用该`KmsMasterKeyProvider.builder()`方法来实例化使用 AWS KMS 主密钥提供程序 AWS KMS 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();
```

此示例表示使用 AWS Encryption SDK for Java 版本 1.7.*x* 或更高版本的应用程序中的代码。有关完整的示例，请参阅 [BasicEncryptionExample.java。](https://github.com/aws/aws-encryption-sdk-java/blob/master/src/examples/java/com/amazonaws/crypto/examples/v2/BasicEncryptionExample.java)

前面的示例使用的 `Builder.build()` 和 `Builder.withKeysForEncryption()` 方法在版本 1.7.*x* 中弃用并在版本 2.0.*x* 中移除。

为了更新为严格模式下的主密钥提供程序，此代码将对弃用方法的调用替换为对新 `Builder.buildStrict()` 方法的调用。此示例指定一个 AWS KMS key 作为包装密钥，但该`Builder.buildStrict()`方法可以采用多个列表 AWS KMS keys。

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

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

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

此示例表示使用 AWS Encryption SDK for Python版本 1.4.1 的应用程序中的代码。此代码使用 `KMSMasterKeyProvider`，其在版本 1.7.*x* 中弃用并在版本 2.0.*x* 中移除。解密时，它会使用任何加密数据密钥的密钥 AWS KMS key ，而不考虑 AWS KMS keys 您指定的密钥。

请注意，`KMSMasterKey` 并未弃用或移除。加密和解密时，它仅使用您指定的。 AWS KMS key 

```
# 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]
)
```

此示例表示使用 AWS Encryption SDK for Python版本 1.7.*x* 的应用程序中的代码。有关完整示例，请参阅 [basic\$1encryption.py](https://github.com/aws/aws-encryption-sdk-python/blob/master/examples/src/legacy/basic_encryption.py)。

为了更新为严格模式下的主密钥提供程序，此代码将对 `KMSMasterKeyProvider()` 的调用替换为对 `StrictAwsKmsMasterKeyProvider()` 的调用。

```
# Create a master key provider in strict mode
# Replace the example key ARNs with valid values from your AWS 账户
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 ]

此示例说明如何使用加密 AWS CLI 版本 1.1.7 或更早版本进行加密和解密。

在版本 1.1.7 及更早版本中，加密时，您可以在指定一个或多个主密钥（或*包装密钥*），例如 AWS KMS key。解密时，除非您使用的是自定义主密钥提供程序，否则无法指定任何包装密钥。 AWS 加密 CLI 可以使用任何对数据密钥进行加密的包装密钥。

```
\\ 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 .
```

此示例说明如何使用加密 AWS CLI 版本 1.7 进行加密和解密。 *x* 或更高版本。有关完整示例，请参阅 [AWS 加密 CLI 的示例](crypto-cli-examples.md)。

`--master-keys` 参数在版本 1.7.*x* 中弃用并在版本 2.0.*x* 中移除。该参数由加密和解密命令所需的 `--wrapping-keys` 参数取代。该参数支持严格模式和发现模式。严格模式是一种 AWS Encryption SDK 最佳实践，可确保您使用所需的包装密钥。

要升级到*严格模式*，请在加密和解密时使用 `--wrapping-keys` 参数的**密钥**属性指定包装密钥。

```
\\ 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 .
```

------

## 迁移到发现模式
<a name="migrate-mkp-discovery-mode"></a>

从 1.7 版本开始。 *x*， AWS Encryption SDK [最佳做法](best-practices.md)是对 AWS KMS 主密钥提供者使用*严格模式*，也就是说，在加密和解密时指定包装密钥。加密时必须始终指定包装密钥。但是在某些情况下，指定用于解密 ARNs 的 AWS KMS keys 密钥是不切实际的。例如，如果您在加密 AWS KMS keys 时使用别名进行识别，那么如果在解密时必须列出密钥 ARNs ，则会失去别名的好处。此外，由于发现模式下的主密钥提供程序的行为类似于原始主密钥提供程序，因此您可以暂时将其用作迁移策略的一部分，然后升级到严格模式下的主密钥提供程序。

在这种情况下，您可以在*发现模式*下使用主密钥提供程序。这些主密钥提供程序不允许您指定包装密钥，因此您不能用其进行加密。在解密时，这些提供程序可以任何使用加密数据密钥的包装密钥。但是，与行为方式相同的旧版主密钥提供程序不同，您可以在发现模式下明确创建。在发现模式下使用主密钥提供程序时，您可以将可以使用的包装密钥限制为特定 AWS 账户。此发现筛选条件为可选项，但却是我们建议的最佳实践。有关 AWS 分区和账户的信息，请参阅《AWS 一般参考》** 中的 [Amazon 资源名称](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#arns-syntax)。

以下示例在严格模式下创建用于加密 AWS KMS 的主密钥提供程序和在发现模式下创建用于解密 AWS KMS 的主密钥提供程序。发现模式下的主密钥提供程序使用发现筛选条件将用于解密的包装密钥限制在 `aws` 分区和特定示例 AWS 账户的密钥。尽管这一简易示例没有必要使用账户筛选条件，但是当一个应用程序加密数据而另一个应用程序解密数据时，这是一种非常有益的最佳实践。

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

此示例表示使用 AWS Encryption SDK for Java版本 1.7.*x* 或更高版本的应用程序中的代码。有关完整的示例，请参阅 [DiscoveryDecryptionExample.java。](https://github.com/aws/aws-encryption-sdk-java/blob/master/src/examples/java/com/amazonaws/crypto/examples/)

为了实例化用于加密的严格模式下的主密钥提供程序，此示例使用 `Builder.buildStrict()` 方法。为了实例化用于解密的发现模式下的主密钥提供程序，此示例使用 `Builder.buildDiscovery()` 方法。该`Builder.buildDiscovery()`方法采用`DiscoveryFilter`，将限制 AWS Encryption SDK AWS KMS keys 为指定 AWS 分区和帐户。

```
// Create a master key provider in strict mode for encrypting
// Replace the example alias ARN with a valid one from your AWS 账户.
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 ]

 此示例表示使用 AWS Encryption SDK for Python 版本 1.7.*x* 或更高版本的应用程序中的代码。有关完整示例，请参阅 [discovery\$1kms\$1provider.py](https://github.com/aws/aws-encryption-sdk-python/blob/master/examples/src/legacy/discovery_kms_provider.py)。

为了在创建用于加密的严格模式下的主密钥提供程序，此示例使用 `StrictAwsKmsMasterKeyProvider`。要在发现模式下创建用于解密的主密钥提供程序，`DiscoveryFilter`该提供程序 AWS Encryption SDK 将`DiscoveryAwsKmsMasterKeyProvider`与限制 AWS KMS keys 在指定的 AWS 分区和帐户中。

```
# Create a master key provider in strict mode
# Replace the example key ARN and alias ARNs with valid values from your AWS 账户.
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 ]

此示例说明如何使用加密 AWS CLI 版本 1.7 进行加密和解密。 *x* 或更高版本。从版本 1.7.*x* 开始，加密和解密时需要使用 `--wrapping-keys` 参数。`--wrapping-keys` 参数支持严格模式和发现模式。有关完整示例，请参阅 [AWS 加密 CLI 的示例](crypto-cli-examples.md)。

加密时，此示例指定包装密钥，这是必需的。解密时，此示例使用值为 `true` 的 `--wrapping-keys` 参数的 `discovery` 属性明确选择*发现模式*。

为了将 AWS Encryption SDK 可以在发现模式下使用的包装密钥限制为特定的封装密钥 AWS 账户，此示例使用了`--wrapping-keys`参数的`discovery-partition`和`discovery-account`属性。这些可选属性仅在 `discovery` 属性设置为 `true` 时有效。必须同时使用 `discovery-partition` 和 `discovery-account` 属性；单独使用则无效。

```
\\ 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 .
```

------

# 更新 AWS KMS 钥匙圈
<a name="migrate-keyrings-v2"></a>

中的 AWS KMS 密钥环[AWS Encryption SDK for C](c-language.md)、[AWS Encryption SDK 适用于.NET 的](dot-net.md)密钥圈以及允许您在加密和解密时指定包装密钥来[AWS Encryption SDK for JavaScript](javascript.md)支持[最佳实践](best-practices.md)。如果您创建了 [AWS KMS Discovery 密钥环](use-kms-keyring.md#kms-keyring-discovery)，需要明确执行此操作。

**注意**  
.NET AWS Encryption SDK 的最早版本是 3.0 版。 *x*。.NET 的所有版本都支持 2.0 中引入的安全最佳实践。 AWS Encryption SDK *的 x 个* AWS Encryption SDK。无需更改任何代码或数据即可安全升级到最新版本。

当你更新到最新版本时 1. *x* 版本的 AWS Encryption SDK，您可以使用[发现过滤器将发现](use-kms-keyring.md#kms-keyring-discovery)密钥[环或AWS KMS 区域发现密钥环](use-kms-keyring.md#kms-keyring-discovery)[在解密时使用的包装密钥](use-kms-keyring.md#kms-keyring-regional)限制为特定的封装密钥。AWS KMS AWS 账户筛选发现密钥环是 AWS Encryption SDK [最佳做法](best-practices.md)。

本节中的示例将演示如何向 AWS KMS Regional Discovery 密钥环添加发现筛选条件。

**了解有关迁移的更多信息**

对于所有 AWS Encryption SDK 用户，请在中了解如何设置您的承诺政策[设置您的承诺策略](migrate-commitment-policy.md)。

对于 AWS Encryption SDK for Java AWS Encryption SDK for Python、和 AWS 加密 CLI 用户，请在中了解主密钥提供程序所需的更新[更新 AWS KMS 主密钥提供程序](migrate-mkps-v2.md)。

 

您的应用程序中可能有如下类似代码。此示例创建 AWS KMS Regional Discovery 密钥环，该密钥环仅能在美国西部（俄勒冈州）（us-west-2）区域使用包装密钥。此示例表示 1.7 之前 AWS Encryption SDK 版本中的代码。 *x*。但其在版本 1.7.*x* 及更高版本中仍然有效。

------
#### [ 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 })
```

------

从 1.7 版本开始。 *x*，您可以向任何发现密钥环添加 AWS KMS 发现过滤器。此发现过滤器将 AWS KMS keys AWS Encryption SDK 可用于解密的限制为指定分区和帐户中的分区和帐户。在使用此代码之前，如有必要，请更改分区，并将示例帐户 IDs 替换为有效的帐户。

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

有关完整示例，请参阅：[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 ]

有关完整示例，请参阅：[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' }
})
```

------

# 设置您的承诺策略
<a name="migrate-commitment-policy"></a>

[密钥承诺](concepts.md#key-commitment)确保您的加密数据始终解密为相同的明文。要提供此安全属性，请从 1.7 版本开始。 *x*， AWS Encryption SDK 使用带有密钥承诺的新[算法套件](supported-algorithms.md)。要确定您的数据是否使用密钥承诺进行加密和解密，请使用[承诺策略](concepts.md#commitment-policy)配置设置。使用密钥承诺加密和解密数据是 [AWS Encryption SDK 最佳实践](best-practices.md)。

设置承诺政策是迁移过程第二步的重要组成部分，即从最新版本迁移 1. *x* 版本是 AWS Encryption SDK to 版本 2.0。 *x* 及更高版本。设置并更改承诺策略后，请确保在将应用程序部署到生产环境之前对其进行全面测试。有关迁移指南，请参阅 [如何迁移和部署 AWS Encryption SDK](migration-guide.md)。

在版本 2.0.*x* 及更高版本中，承诺策略设置有三个有效值。在最新版本 1.*x*（从版本 1.7.*x* 开始），仅 `ForbidEncryptAllowDecrypt` 有效。
+ `ForbidEncryptAllowDecrypt`— AWS Encryption SDK 无法使用密钥承诺进行加密。可以解密使用或不使用密钥承诺加密的加密文字。

  在最新版本 1.*x* 中，这是唯一的有效值。其可确保您在完全准备好使用密钥承诺进行解密之前不会使用密钥承诺进行加密。明确设置该值可防止您的承诺策略在升级到版本 2.0.*x* 或更高版本时自动更改为 `require-encrypt-require-decrypt`。相反，您可以分阶段[迁移承诺策略](#migrate-commitment-policy)。
+ `RequireEncryptAllowDecrypt`— AWS Encryption SDK 始终使用密钥承诺进行加密。可以解密使用或不使用密钥承诺加密的加密文字。版本 2.0.*x* 中加入了此值。
+ `RequireEncryptRequireDecrypt`— AWS Encryption SDK 始终使用密钥承诺进行加密和解密。版本 2.0.*x* 中加入了此值。在版本 2.0.*x* 和更高版本中，这是默认值。

在最新版本 1.*x* 中，唯一有效的承诺策略值为 `ForbidEncryptAllowDecrypt`。迁移到版本 2.0.*x* 或更高版本之后，您可以在准备就绪后[分阶段更改承诺策略](migration-guide.md)。除非您确定所有消息均使用密钥承诺加密，否则请勿将您的承诺策略更新为 `RequireEncryptRequireDecrypt`。

这些示例演示了如何在最新版本 1.*x*、版本 2.0.*x* 及更高版本中设置承诺策略。该方法取决于您的编程语言。

**了解有关迁移的更多信息**

对于 AWS Encryption SDK for Java AWS Encryption SDK for Python、和 AWS Encryption CLI，请在中了解主密钥提供程序所需的更改[更新 AWS KMS 主密钥提供程序](migrate-mkps-v2.md)。

对于 AWS Encryption SDK for C 和 AWS Encryption SDK for JavaScript，请在中了解钥匙圈的可选更新。[更新 AWS KMS 钥匙圈](migrate-keyrings-v2.md)

## 如何设置您的承诺策略
<a name="migrate-commitment-step1"></a>

您使用的承诺策略设置方法因语言实施而略有不同。这些示例演示了如何进行操作。在更改承诺策略之前，请查看 [如何迁移和部署](migration-guide.md) 中的多阶段方法。

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

从 1.7 版本开始。 *其中 x* AWS Encryption SDK for C，您可以使用`aws_cryptosdk_session_set_commitment_policy`函数为加密和解密会话设置承诺策略。您设置的承诺策略适用于在该会话中调用的所有加密和解密操作。

`aws_cryptosdk_session_new_from_keyring` 和 `aws_cryptosdk_session_new_from_cmm` 函数在版本 1.7.*x* 中弃用并在版本 2.0.*x* 中移除。这些函数由返回会话的 `aws_cryptosdk_session_new_from_keyring_2` 和 `aws_cryptosdk_session_new_from_cmm_2` 函数取代。

在最新版本 1.*x* 中使用 `aws_cryptosdk_session_new_from_keyring_2` 和 `aws_cryptosdk_session_new_from_cmm_2` 时，需要使用 `COMMITMENT_POLICY_FORBID_ENCRYPT_ALLOW_DECRYPT` 承诺策略值调用 `aws_cryptosdk_session_set_commitment_policy` 函数。在版本 2.0.*x* 及更高版本中，调用此函数为可选项，需要所有有效值。版本 2.0.*x* 及更高版本的默认承诺策略为 `COMMITMENT_POLICY_REQUIRE_ENCRYPT_REQUIRE_DECRYPT`。

有关完整的示例，请参阅 [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 ]

该`require-encrypt-require-decrypt`值是 AWS Encryption SDK 适用于.NET 的所有版本中的默认承诺策略。您可以将其明确设置为最佳实践，但这并非必需。但是，如果您使用 for .NET 来解密由 AWS Encryption SDK 无密钥承诺的另一种语言实现加密的密文，则需要将承诺策略值更改为或。 AWS Encryption SDK `REQUIRE_ENCRYPT_ALLOW_DECRYPT` `FORBID_ENCRYPT_ALLOW_DECRYPT`否则，加密文字解密尝试会失败。

在 f AWS Encryption SDK or .NET 中，您可以为的实例设置承诺策略 AWS Encryption SDK。使用`CommitmentPolicy`参数实例化`AwsEncryptionSdkConfig`对象，然后使用配置对象创建实例。 AWS Encryption SDK 然后，调用已配置 AWS Encryption SDK 实例的`Encrypt()`和`Decrypt()`方法。

此示例将承诺策略设置为 `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 ]

要在 AWS 加密 CLI 中设置承诺策略，请使用`--commitment-policy`参数。此参数在版本 1.8.*x* 中引入。

在最新版本 1.*x* 中，当您在 `--encrypt` 或 `--decrypt` 命令中使用 `--wrapping-keys` 参数时，需要有 `forbid-encrypt-allow-decrypt` 值的 `--commitment-policy` 参数。否则 `--commitment-policy` 参数无效。

在版本 2.1.*x* 及更高版本中，`--commitment-policy` 参数为可选项，默认为 `require-encrypt-require-decrypt` 值，其不会加密或解密任何不使用密钥承诺加密的加密文字。但是，我们建议您在所有加密和解密调用中明确设置承诺策略，以便进行维护和故障排除。

此示例设置了承诺策略。从版本 1.8.*x* 开始，此示例还使用取代 `--master-keys` 参数的 `--wrapping-keys` 参数。有关更多信息，请参阅 [更新 AWS KMS 主密钥提供程序](migrate-mkps-v2.md)。有关完整示例，请参阅 [AWS 加密 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 ]

从 1.7 版本开始。 *其中 x* AWS Encryption SDK for Java，您对代表 AWS Encryption SDK 客户端的对象的`AwsCrypto`实例设置了承诺策略。该承诺策略设置适用于在该客户端中调用的所有加密和解密操作。

在最新的 1 版本中，该`AwsCrypto()`构造函数已被弃用。 在 2.0 版本中移除了 AWS Encryption SDK for Java 和的 *x* 版本。 *x*。该构造函数由新的 `Builder` 类、`Builder.withCommitmentPolicy()` 方法和 `CommitmentPolicy` 枚举类型取代。

在最新版本 1.*x* 中，`Builder` 类需要 `Builder.withCommitmentPolicy()` 方法和 `CommitmentPolicy.ForbidEncryptAllowDecrypt` 参数。从版本 2.0.*x* 开始，`Builder.withCommitmentPolicy()` 方法为可选项；默认值为 `CommitmentPolicy.RequireEncryptRequireDecrypt`。

有关完整的示例，请参阅 [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 ]

从 1.7 版本开始。 *x* 中 AWS Encryption SDK for JavaScript，您可以在调用实例化客户端的新`buildClient`函数时设置承诺策略。 AWS Encryption SDK `buildClient` 函数需要表示承诺策略的枚举值。进行加密和解密时，该函数会返回强制执行您的承诺策略的已更新 `encrypt` 和 `decrypt` 函数。

在最新版本 1.*x* 中，`buildClient` 函数需要 `CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT` 参数。从版本 2.0.*x* 开始，承诺策略参数为可选项，默认值为 `CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT`。

Node.js 和浏览器的代码相同，唯一区别在于浏览器需要使用语句设置凭证。

以下示例使用密 AWS KMS 钥环对数据进行加密。新的 `buildClient` 函数将承诺策略设置为 `FORBID_ENCRYPT_ALLOW_DECRYPT`，其为最新版本 1.*x* 的默认值。`buildClient` 返回的已升级 `encrypt` 和 `decrypt` 函数强制执行您设置的承诺策略。

```
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 ]

从 1.7 版本开始。 *其中 x* AWS Encryption SDK for Python，您对代表 AWS Encryption SDK 客户端的新对象的`EncryptionSDKClient`实例设置了承诺策略。您设置的承诺策略适用于所有使用该客户端实例的 `encrypt` 和 `decrypt` 调用。

在最新版本 1.*x* 中，`EncryptionSDKClient` 构造函数需要 `CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT` 枚举值。从版本 2.0.*x* 开始，承诺策略参数为可选项，默认值为 `CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT`。

此示例使用新的 `EncryptionSDKClient` 构造函数并将承诺策略设置为 1.7.*x* 默认值。构造函数实例化表示 AWS Encryption SDK的客户端。当您在此客户端上调用 `encrypt`、`decrypt` 或 `stream` 方法时，这些方法会强制执行您设置的承诺策略。此示例还使用了`StrictAwsKmsMasterKeyProvider`类的新构造函数，该构造函数指定了 AWS KMS keys 何时加密和解密。

有关完整示例，请参阅 [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 ]

该`require-encrypt-require-decrypt`值是 for Rust 所有版本中的 AWS Encryption SDK 默认承诺策略。您可以将其明确设置为最佳实践，但这并非必需。但是，如果您使用 for Rust 来解密由 AWS Encryption SDK 无密钥承诺的另一种语言实现加密的密文，则需要将承诺策略值更改为或。 AWS Encryption SDK `REQUIRE_ENCRYPT_ALLOW_DECRYPT` `FORBID_ENCRYPT_ALLOW_DECRYPT`否则，加密文字解密尝试会失败。

在 f AWS Encryption SDK or Rust 中，您可以为的实例设置承诺策略 AWS Encryption SDK。使用`comitment_policy`参数实例化`AwsEncryptionSdkConfig`对象，然后使用配置对象创建实例。 AWS Encryption SDK 然后，调用已配置 AWS Encryption SDK 实例的`Encrypt()`和`Decrypt()`方法。

此示例将承诺策略设置为 `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)
}
```

------

# 对迁移到至最新版本进行故障排除
<a name="troubleshooting-migration"></a>

在将应用程序更新到 2.0 版之前。 *x* 或更高版本 AWS Encryption SDK，更新到最新的 1。 *x* 版本的， AWS Encryption SDK 然后将其完全部署。这将有助于避免在更新到版本 2.0.*x* 及更高版本时可能遇到的多数错误。有关详细指南（包括示例），请参阅 [迁移你的 AWS Encryption SDK](migration.md)。

**重要**  
验证最新版本 1.*x* 为 AWS Encryption SDK版本 1.7.*x* 或更高版本。

**注意**  
**AWS 加密 CLI**：本指南中对版本 1.7 的参考。 其中的 *x* AWS Encryption SDK 适用于版本 1.8。 AWS 加密 CLI 中的 *x*。本指南中对版本 2.0 的引用。 其中的 *x* AWS Encryption SDK 适用于 2.1。 AWS 加密 CLI 中的 *x*。  
新的安全功能最初是在 AWS 加密 CLI 版本 1.7 中发布的。 *x* 和 2.0。 *x*。但是， AWS 加密 CLI 版本为 1.8。 *x* 取代了 1.7 版。 *x* 和 AWS 加密 CLI 2.1。 *x* 取代 2.0。 *x*。有关详细信息，请参阅[aws-encryption-sdk-cli](https://github.com/aws/aws-encryption-sdk-cli/)存储库中的相关[安全公告](https://github.com/aws/aws-encryption-sdk-cli/security/advisories/GHSA-2xwp-m7mq-7q3r) GitHub。

本主题旨在帮助您识别和解决可能遇到的最常见错误。

**Topics**
+ [弃用或移除的对象](#deprecated-removed)
+ [配置冲突：承诺策略和算法套件](#configuration-conflict_1)
+ [配置冲突：承诺策略和加密文字](#configuration-conflict_2)
+ [密钥承诺验证失败](#commitment-failed)
+ [其他加密故障](#encrypt-failed)
+ [其他加密故障](#decrypt-failed)
+ [回滚注意事项](#migration-rollback)

## 弃用或移除的对象
<a name="deprecated-removed"></a>

版本 2.0.*x* 包含几项重大更改，包括移除版本 1.7.*x* 中弃用的旧版构造函数、方法、函数和类。为避免编译器错误、导入错误、语法错误和未找到符号错误（取决于您的编程语言），请先升级到最新的 1。 AWS Encryption SDK 适用于您的编程语言的 *x* 版本。（此版本必须为版本 1.7.*x* 或更高版本。） 在使用最新版本 1.*x* 时，您可以在移除原始符号之前开始使用替换元素。

如果需要立即升级到版本 2.0.*x* 或更高版本，[请查阅您的编程语言的更改日志](about-versions.md)，然后用更改日志建议的符号替换旧版符号。

## 配置冲突：承诺策略和算法套件
<a name="configuration-conflict_1"></a>

如果您指定的算法套件与您的[承诺策略](concepts.md#commitment-policy)冲突，加密调用会失败并出现*配置冲突*错误。

为避免此类错误，请勿指定算法套件。默认情况下， AWS Encryption SDK 会选择与您的承诺策略兼容的最安全的算法。但是，如果您必须指定算法套件（例如不具有签名的算法套件），请确保选择与您的承诺策略兼容的算法套件。


| 承诺策略 | 兼容算法套件 | 
| --- | --- | 
| ForbidEncryptAllowDecrypt | 任何*不具有*密钥承诺的算法套件，例如：AES\$1256\$1GCM\$1IV12\$1TAG16\$1HKDF\$1SHA384\$1ECDSA\$1P384（[03 78](algorithms-reference.md)）（具有签名） `AES_256_GCM_IV12_TAG16_HKDF_SHA256`（[01 78](algorithms-reference.md)）（不具有签名） | 
| RequireEncryptAllowDecryptRequireEncryptRequireDecrypt | 任何*具有*密钥承诺的算法套件，例如：AES\$1256\$1GCM\$1HKDF\$1SHA512\$1COMMIT\$1KEY\$1ECDSA\$1P384（[05 78](algorithms-reference.md)）（具有签名） `AES_256_GCM_HKDF_SHA512_COMMIT_KEY`（[04 78](algorithms-reference.md)）（不具有签名） | 

如果您在未指定算法套件时遇到此错误，则可能是您的[加密材料管理器](concepts.md#crypt-materials-manager) （CMM）选择了冲突算法套件。默认 CMM 不会选择冲突算法套件，但自定义 CMM 可能会。如需帮助，请参阅自定义 CMM 相关文档。

## 配置冲突：承诺策略和加密文字
<a name="configuration-conflict_2"></a>

`RequireEncryptRequireDecrypt`[承诺策略](concepts.md#commitment-policy)不允许 AWS Encryption SDK 解密未使用[密钥承诺](concepts.md#key-commitment)加密的消息。如果您要求解 AWS Encryption SDK 密未承诺密钥的消息，则会返回*配置冲突错误*。

为避免此错误，在设置 `RequireEncryptRequireDecrypt` 承诺策略之前，请确保所有未使用密钥承诺加密的加密文字均使用密钥承诺进行解密和重新加密，或者由其他应用程序处理。如果您遇到此错误，可以针对冲突加密文字返回错误，或者将您的承诺策略暂时更改为 `RequireEncryptAllowDecrypt`。

如果您因为在未首先升级到最新版本 1.*x*（1.7.*x* 或更高版本）的情况下，从 1.7.*x* 之前的版本升级到版本 2.0.*x* 或更高版本遇到此错误，可以考虑[回滚](#migration-rollback)到最新版本 1.*x*，并在升级到版本 2.0.*x* 或更高版本之前将该版本部署到所有主机。有关帮助信息，请参阅 [如何迁移和部署 AWS Encryption SDK](migration-guide.md)。

## 密钥承诺验证失败
<a name="commitment-failed"></a>

解密使用密钥承诺加密的消息时，可能会收到*密钥承诺验证失败*的错误消息。这表示解密调用失败，因为[加密消息](concepts.md#DEK)中的数据密钥与消息的唯一数据密钥不同。通过在解密过程中验证数据密钥，[密钥承诺](concepts.md#key-commitment)可以避免解密可能生成多个明文的消息。

此错误表示 AWS Encryption SDK未返回您尝试解密的加密消息。此错误可能是手动制作的消息或数据损坏的结果。如果您遇到此错误，您的应用程序可能会拒绝该消息并继续，或者停止处理新消息。

## 其他加密故障
<a name="encrypt-failed"></a>

加密故障原因多种多样。您不可使用 [AWS KMS Discovery 密钥环](use-kms-keyring.md#kms-keyring-discovery)或[发现模式下的主密钥提供程序](migrate-mkps-v2.md)加密消息。

请确保指定包含您[有权用其](use-kms-keyring.md#kms-keyring-permissions)加密的包装密钥的密钥环或主密钥提供程序。有关权限的帮助 AWS KMS keys，请参阅《*AWS Key Management Service 开发者指南》 AWS KMS key*中的[查看密钥策略](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-viewing.html)和[确定对的访问](https://docs.aws.amazon.com/kms/latest/developerguide/determining-access.html)权限。

## 其他加密故障
<a name="decrypt-failed"></a>

如果加密消息解密尝试失败，则意味着 AWS Encryption SDK 无法（或不会）解密消息中的任何加密数据密钥。

如果您使用的是指定包装密钥的密钥环或主密钥提供程序，则仅 AWS Encryption SDK 使用您指定的包装密钥。请确认您使用的是打算使用且拥有至少一个包装密钥 `kms:Decrypt` 权限的包装密钥。如果您使用的是备用方法 AWS KMS keys，则可以尝试在发现模式下使用[AWS KMS 发现密钥环或主密钥](use-kms-keyring.md#kms-keyring-discovery)[提供程序](migrate-mkps-v2.md)来解密消息。如果操作成功，在返回明文之前，请验证用于解密消息的密钥是否是您信任的密钥。

## 回滚注意事项
<a name="migration-rollback"></a>

如果您的应用程序无法加密或解密数据，则通常可以通过更新代码符号、密钥环、主密钥提供程序或[承诺策略](concepts.md#commitment-policy)来解决问题。但是，在某些情况下，您可能会决定最好将应用程序回滚到 AWS Encryption SDK先前版本。

如果必须回滚，请谨慎操作。1.7 AWS Encryption SDK 之前的版本。 *x* [无法解密使用密钥承诺加密的密文。](concepts.md#key-commitment)
+ 从最新版本 1.*x* 回滚到 AWS Encryption SDK 先前版本通常是安全的。您可能需要撤消对代码所做更改才能使用先前版本不支持的符号和对象。
+ 在版本 2.0.*x* 或更高版本中开始使用密钥承诺进行加密后（将您的承诺策略设置为 `RequireEncryptAllowDecrypt`），您可以回滚到版本 1.7.*x* 而非任何早期版本。1.7 AWS Encryption SDK 之前的版本。 *x* [无法解密使用密钥承诺加密的密文。](concepts.md#key-commitment)

如果您在所有主机均可使用密钥承诺解密之前意外启用了使用密钥承诺进行加密，则最好继续推出而非回滚。如果消息是暂时的，或者可以安全删除，则可以考虑在消息丢失的情况下进行回滚。如果需要回滚，您可以考虑编写解密和重新加密所有消息的工具。