

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 遷移您的 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。

**注意**  
for .NET AWS Encryption SDK 的最早版本是 3.0.*x* 版。 AWS Encryption SDK 適用於 .NET 的所有版本都支援 2.0.*x* 中引入的安全最佳實務。 AWS Encryption SDK您可以安全地升級至最新版本，無需變更任何程式碼或資料。  
AWS Encryption CLI：閱讀此遷移指南時，請使用 AWS Encryption CLI 1.8.*x* 的 1.7.*x* 遷移說明，並使用 AWS Encryption CLI 2.1.x 的 2.0.*x* **遷移說明。如需詳細資訊，請參閱[AWS 加密 CLI 的版本](crypto-cli-versions.md)。  
新的安全功能最初在 AWS 加密 CLI 版本 1.7.*x* 和 2.0.*x* 中發行。不過， AWS Encryption CLI 1.8.*x* 版取代了 1.7.*x* 版，而 AWS Encryption CLI 2.1.*x* 版取代了 2.0.*x*。如需詳細資訊，請參閱 GitHub 上 [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)。

**新使用者**  
如果您是初次使用 AWS Encryption SDK， AWS Encryption SDK 請為您的程式設計語言安裝最新版本的 。預設值會啟用 的所有安全功能 AWS Encryption SDK，包括使用簽署、金鑰衍生和[金鑰承諾](concepts.md#key-commitment)進行加密。 AWS Encryption SDK

**目前使用者**  
建議您盡快從目前版本升級至最新的可用版本。所有 1.*x* 版本的 AWS Encryption SDK 都處於[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* 版和更新版本提供新的安全功能，以協助保護您的資料。不過，2.0.*x* AWS Encryption SDK 版包含無法回溯相容的重大變更。為了確保安全的轉換，請先將程式設計語言中的目前版本遷移至最新的 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/)。

尋找 適用於 JAVA 的 AWS Encryption SDK 搭配 使用 的協助 AWS SDK for Java 2.x？ 請參閱 [先決條件](java.md#java-prerequisites)。

**Topics**
+ [如何遷移和部署 AWS Encryption SDK](migration-guide.md)
+ [更新 AWS KMS 主金鑰提供者](migrate-mkps-v2.md)
+ [更新 AWS KMS keyring](migrate-keyrings-v2.md)
+ [設定您的承諾政策](migrate-commitment-policy.md)
+ [對遷移至最新版本進行故障診斷](troubleshooting-migration.md)

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

從 1.7.*x* 以前的 AWS Encryption SDK 版本遷移至 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* 版本是 1.7.*x* 或更新版本 AWS Encryption SDK。

最新的 1.*x* 版本 AWS Encryption SDK 與舊版 回溯相容， AWS Encryption SDK 且與 2.0.*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 主金鑰提供者，則必須將舊版主金鑰提供者更新為支援*嚴格模式*和*探索模式*的主金鑰提供者。 適用於 JAVA 的 AWS Encryption SDK 適用於 Python 的 AWS Encryption SDK、 和 AWS Encryption CLI 需要此更新。如果您在探索模式中使用主金鑰提供者，我們建議您實作探索篩選條件，將所使用的包裝金鑰限制在那些金鑰 AWS 帳戶。此更新是選用的，但我們建議採用[最佳實務](best-practices.md)。如需詳細資訊，請參閱[更新 AWS KMS 主金鑰提供者](migrate-mkps-v2.md)。
+ 如果您使用[AWS KMS 探索 keyring](use-kms-keyring.md#kms-keyring-discovery)，我們建議您包含探索篩選條件，將解密中使用的包裝金鑰限制為特定 的金鑰 AWS 帳戶。此更新是選用的，但我們建議採用[最佳實務](best-practices.md)。如需詳細資訊，請參閱[更新 AWS KMS keyring](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`。會透過[金鑰承諾](concepts.md#key-commitment) AWS Encryption SDK 開始加密您的資料。它可以使用和不使用金鑰承諾來解密加密文字。

   將承諾政策更新至 之前`RequireEncryptAllowDecrypt`，請確認您的最新 1.*x* 版本已部署至所有主機，包括解密您產生之加密文字的任何應用程式的主機。1.7.*x* 版 AWS Encryption SDK 之前的 版本無法解密以金鑰承諾加密的訊息。

   這也是將指標新增至應用程式的好時機，以測量您是否仍在處理加密文字，而無需金鑰承諾。這將協助您判斷何時可安全地將承諾政策設定更新為 `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* 版中移除。使用 [適用於 JAVA 的 AWS Encryption SDK](java.md)、 和 [AWS Encryption CLI](crypto-cli.md) 的應用程式[適用於 Python 的 AWS Encryption SDK](python.md)和指令碼需要此變更。本節中的範例將示範如何更新程式碼。

**注意**  
在 Python 中，[開啟棄用警告](https://docs.python.org/3/library/warnings.html)。這將協助您識別您需要更新的程式碼部分。

如果您使用的是 AWS KMS 主金鑰 （不是主金鑰提供者），您可以略過此步驟。 AWS KMS 主金鑰不會棄用或移除。它們只會使用您指定的包裝金鑰來加密和解密。

本節中的範例著重於您需要變更的程式碼元素。如需更新程式碼的完整範例，請參閱[程式設計語言](programming-languages.md)的 GitHub 儲存庫範例一節。此外，這些範例通常會使用金鑰 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)。

對於 適用於 C 的 AWS Encryption SDK 和 適用於 JavaScript 的 AWS Encryption SDK 使用者，了解 中 keyring 的選用更新[更新 AWS KMS keyring](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.*x* AWS Encryption SDK 版中推出。它們取代了舊版主金鑰提供者，這些提供者已在 1.7.*x* 中棄用，並在 2.0.*x* 中移除。在嚴格模式下使用主金鑰提供者是 AWS Encryption SDK [最佳實務](best-practices.md)。

下列程式碼會以嚴格模式建立主金鑰提供者，您可以用來加密和解密。

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

此範例代表使用 1.6.2 版或更早版本的應用程式中的程式碼。 適用於 JAVA 的 AWS Encryption SDK

此程式碼使用 `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();
```

此範例代表應用程式中使用 1.7.*x* 版或更新版本的程式碼。 適用於 JAVA 的 AWS Encryption SDK 如需完整範例，請參閱 [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 ]

此範例代表應用程式中使用 1.4.1 版的程式碼。 適用於 Python 的 AWS Encryption SDK此程式碼使用 `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]
)
```

此範例代表應用程式中使用 1.7.*x* 版的程式碼。 適用於 Python 的 AWS Encryption SDK如需完整範例，請參閱 [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 Encryption 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 Encryption 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 主金鑰提供者使用*嚴格模式*，也就是在加密和解密時指定包裝金鑰。加密時，您必須一律指定包裝金鑰。但在某些情況下，指定用於 AWS KMS keys 解密的 金鑰 ARNs 並不切實際。例如，如果您使用別名來識別加密 AWS KMS keys 時，如果您在解密時必須列出金鑰 ARNs，則會失去別名的好處。此外，由於探索模式中的主金鑰提供者的行為與原始主金鑰提供者類似，因此您可以在遷移策略中暫時使用這些提供者，稍後再以嚴格模式升級至主金鑰提供者。

在這種情況下，您可以在*探索模式中*使用主金鑰提供者。這些主金鑰提供者不會讓您指定包裝金鑰，因此您無法使用它們進行加密。解密時，他們可以使用任何加密資料金鑰的包裝金鑰。但與行為相同的舊版主金鑰提供者不同，您可以在探索模式中明確建立它們。在探索模式下使用主金鑰提供者時，您可以限制可用於這些提供者的包裝金鑰 AWS 帳戶。此探索篩選條件是選用的，但我們建議採用最佳實務。如需有關 AWS 分割區和帳戶的資訊，請參閱 中的 [Amazon Resource Names](https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#arns-syntax)*AWS 一般參考*。

下列範例會在嚴格模式下建立用於加密 AWS KMS 的主金鑰提供者，並在探索模式下建立用於解密 AWS KMS 的主金鑰提供者。探索模式中的主金鑰提供者會使用探索篩選條件，將用於解密的包裝金鑰限制為`aws`分割區和特定範例 AWS 帳戶。雖然在此非常簡單的範例中不需要帳戶篩選條件，但當一個應用程式加密資料，而另一個應用程式解密資料時，這是非常有益的最佳實務。

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

此範例代表應用程式中使用 1.7.*x* 版或更新版本的程式碼。 適用於 JAVA 的 AWS Encryption SDK如需完整範例，請參閱 [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 分割區和帳戶中的 限制 AWS Encryption SDK AWS KMS keys 為 。

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

 此範例代表應用程式中使用 1.7.*x* 版或更新版本的程式碼。 適用於 Python 的 AWS Encryption SDK 如需完整範例，請參閱 [探索\$1kms\$1provider.py](https://github.com/aws/aws-encryption-sdk-python/blob/master/examples/src/legacy/discovery_kms_provider.py)。

若要在嚴格模式下建立用於加密的主金鑰提供者，此範例使用 `StrictAwsKmsMasterKeyProvider`。若要在探索模式中建立主要金鑰提供者以進行解密，它會使用 `DiscoveryAwsKmsMasterKeyProvider`搭配 `DiscoveryFilter`，在指定的 AWS 分割區和帳戶中將 限制 AWS Encryption SDK AWS KMS keys 為 。

```
# 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 Encryption CLI 1.7.*x* 版或更新版本來加密和解密。從 1.7.*x* 版開始，在加密和解密時需要 `--wrapping-keys` 參數。`--wrapping-keys` 參數支援嚴格模式和探索模式。如需完整範例，請參閱 [AWS 加密 CLI 的範例](crypto-cli-examples.md)。

加密時，此範例會指定需要的包裝金鑰。解密時，它會使用值為 的 `--wrapping-keys` 參數`discovery`屬性來明確選擇*探索模式*`true`。

若要將 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 keyring
<a name="migrate-keyrings-v2"></a>

中的 AWS KMS keyring[適用於 C 的 AWS Encryption SDK](c-language.md)、 [AWS Encryption SDK for .NET](dot-net.md) 和 [適用於 JavaScript 的 AWS Encryption SDK](javascript.md) 支援[最佳實務](best-practices.md)，可讓您在加密和解密時指定包裝金鑰。如果您建立[AWS KMS 探索 keyring](use-kms-keyring.md#kms-keyring-discovery)，請明確執行此操作。

**注意**  
for .NET AWS Encryption SDK 的最早版本是 3.0.*x* 版。 AWS Encryption SDK 適用於 .NET 的所有版本都支援 2.0.*x* 中引入的安全最佳實務。 AWS Encryption SDK您可以安全地升級至最新版本，無需變更任何程式碼或資料。

當您更新至最新的 1.*x* 版本時 AWS Encryption SDK，您可以使用[探索篩選條件](use-kms-keyring.md#kms-keyring-discovery)來限制[AWS KMS 探索 keyring](use-kms-keyring.md#kms-keyring-discovery) 或[AWS KMS 區域探索 keyring](use-kms-keyring.md#kms-keyring-regional) 在解密時所使用的包裝金鑰 AWS 帳戶。篩選探索 keyring 是 AWS Encryption SDK [最佳實務](best-practices.md)。

本節中的範例將示範如何將探索篩選條件 AWS KMS 新增至區域探索 keyring。

**進一步了解遷移**

對於 AWS Encryption SDK 所有使用者，了解如何在 中設定您的承諾政策[設定您的承諾政策](migrate-commitment-policy.md)。

對於 適用於 JAVA 的 AWS Encryption SDK 適用於 Python 的 AWS Encryption SDK和 AWS Encryption CLI 使用者，了解 中主金鑰提供者的必要更新[更新 AWS KMS 主金鑰提供者](migrate-mkps-v2.md)。

 

您的應用程式中可能會有如下的程式碼。此範例會建立只能在美國西部 （奧勒岡） (us-west-2) 區域中使用包裝金鑰的區域 AWS KMS 探索 keyring。此範例代表 1.7.*x* 之前 AWS Encryption SDK 版本的程式碼。不過，它在 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 探索 keyring。此探索篩選條件會將 AWS Encryption SDK 可用於解密 AWS KMS keys 的 限制為指定分割區和帳戶中的 。使用此程式碼之前，請視需要變更分割區，並以有效的帳戶 ID 取代範例帳戶 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 至 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* 及更新版本中設定您的承諾政策。技術取決於您的程式設計語言。

**進一步了解遷移**

對於 適用於 JAVA 的 AWS Encryption SDK 適用於 Python 的 AWS Encryption SDK和 AWS 加密 CLI，了解 中主金鑰提供者的必要變更[更新 AWS KMS 主金鑰提供者](migrate-mkps-v2.md)。

對於 適用於 C 的 AWS Encryption SDK 和 適用於 JavaScript 的 AWS Encryption SDK，了解 中 keyring 的選用更新[更新 AWS KMS keyring](migrate-keyrings-v2.md)。

## 如何設定您的承諾政策
<a name="migrate-commitment-step1"></a>

您用來設定承諾政策的技術會因每種語言實作而略有不同。這些範例會示範如何執行。在變更您的承諾政策之前，請檢閱 中的多階段方法[如何遷移和部署](migration-guide.md)。

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

從 1.7.*x* 版開始 適用於 C 的 AWS Encryption SDK，您可以使用 `aws_cryptosdk_session_set_commitment_policy`函數在加密和解密工作階段上設定承諾政策。您設定的承諾政策適用於在該工作階段上呼叫的所有加密和解密操作。

在 1.7.*x* 版中取代 `aws_cryptosdk_session_new_from_keyring`和 `aws_cryptosdk_session_new_from_cmm`函數，並在 2.0.*x* 版中移除。這些函數會替換為傳回工作階段的 `aws_cryptosdk_session_new_from_keyring_2`和 `aws_cryptosdk_session_new_from_cmm_2`函數。

當您在最新的 1.*x* 版本`aws_cryptosdk_session_new_from_cmm_2`中使用 `aws_cryptosdk_session_new_from_keyring_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 的所有 版本中的預設承諾政策。您可以明確地將其設定為最佳實務，但這不是必要的。不過，如果您使用 AWS Encryption SDK for .NET 來解密由 其他語言實作加密的加密文字， AWS Encryption SDK 而不需要金鑰承諾，則需要將承諾政策值變更為 `REQUIRE_ENCRYPT_ALLOW_DECRYPT`或 `FORBID_ENCRYPT_ALLOW_DECRYPT`。否則，嘗試解密加密文字將會失敗。

在 AWS Encryption SDK 適用於 .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`值，不會加密或解密任何在沒有金鑰承諾的情況下加密的加密文字。不過，我們建議您在所有加密和解密呼叫中明確設定承諾政策，以協助維護和故障診斷。

此範例會設定承諾政策。它也會使用 `--wrapping-keys` 參數來取代從 1.8.*x* 版開始的 `--master-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* 版開始 適用於 JAVA 的 AWS Encryption SDK，您可以在 執行個體上設定承諾政策`AwsCrypto`，即代表 AWS Encryption SDK 用戶端的 物件。此承諾政策設定適用於該用戶端上呼叫的所有加密和解密操作。

`AwsCrypto()` 建構函數在最新的 1.*x* 版本中已棄用， 適用於 JAVA 的 AWS Encryption SDK 並在 2.0.*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* 版開始 適用於 JavaScript 的 AWS Encryption SDK，您可以在呼叫執行個體化 AWS Encryption SDK 用戶端的新 `buildClient`函數時設定承諾政策。`buildClient` 函數會採用列舉值來代表您的承諾政策。它會傳回更新 `encrypt`和 `decrypt`函數，在您加密和解密時強制執行您的承諾政策。

在最新的 1.*x* 版本中，`buildClient`函數需要 `CommitmentPolicy.FORBID_ENCRYPT_ALLOW_DECRYPT`引數。從 2.0.*x* 版開始，承諾政策引數為選用，預設值為 `CommitmentPolicy.REQUIRE_ENCRYPT_REQUIRE_DECRYPT`。

為此目的，Node.js 和瀏覽器的程式碼完全相同，但瀏覽器需要陳述式來設定登入資料。

下列範例使用 AWS KMS keyring 加密資料。新`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* 版開始 適用於 Python 的 AWS Encryption SDK，您可以在 執行個體上設定承諾政策`EncryptionSDKClient`，這是代表 AWS Encryption SDK 用戶端的新物件。您設定的承諾政策適用於使用該用戶端執行個體的所有 `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。當您在此用戶端上呼叫 `decrypt`、 `encrypt`或 `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`值是 AWS Encryption SDK Rust 所有版本的預設承諾政策。您可以明確地將其設定為最佳實務，但這不是必要的。不過，如果您使用 AWS Encryption SDK for Rust 來解密由 其他語言實作加密的加密文字， AWS Encryption SDK 而不需要金鑰承諾，則需要將承諾政策值變更為 `REQUIRE_ENCRYPT_ALLOW_DECRYPT`或 `FORBID_ENCRYPT_ALLOW_DECRYPT`。否則，嘗試解密加密文字將會失敗。

在 AWS Encryption SDK for 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* 版本是 1.7.*x* 或更新版本 AWS Encryption SDK。

**注意**  
**AWS 加密 CLI**：本指南中 1.7.*x* 版的參考 AWS Encryption SDK 適用於 AWS 加密 CLI 1.8.*x* 版。本指南中 2.0.*x* 版的參考 AWS Encryption SDK 適用於 AWS 加密 CLI 的 2.1.*x*。  
新的安全功能最初在 AWS 加密 CLI 版本 1.7.*x* 和 2.0.*x* 中發行。不過， AWS Encryption CLI 1.8.*x* 版取代了 1.7.*x* 版，而 AWS Encryption CLI 2.1.*x* 版取代了 2.0.*x*。如需詳細資訊，請參閱 GitHub 上 [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)。

本主題旨在協助您識別和解決可能遇到的最常見錯誤。

**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* 版中棄用的傳統建構函數、方法、函數和類別。為了避免編譯器錯誤、匯入錯誤、語法錯誤和符號找不到錯誤 （取決於您的程式設計語言），請先升級到 AWS Encryption SDK 程式設計語言的最新 1.*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.7.*x* 的版本升級至 2.0.*x* 版或更新版本而遇到此錯誤，但未先升級至最新的 1.*x* 版本 (1.7.*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 探索模式中使用探索 keyring](use-kms-keyring.md#kms-keyring-discovery) 或主金鑰提供者來加密訊息。 [更新 AWS KMS 主金鑰提供者](migrate-mkps-v2.md)

請務必使用您有權[用於](use-kms-keyring.md#kms-keyring-permissions)加密的包裝金鑰來指定 keyring 或主金鑰提供者。如需 許可的說明 AWS KMS keys，請參閱《 *AWS Key Management Service 開發人員指南*》中的[檢視金鑰政策和](https://docs.aws.amazon.com/kms/latest/developerguide/key-policy-viewing.html)[判斷對 的存取權 AWS KMS key](https://docs.aws.amazon.com/kms/latest/developerguide/determining-access.html)。

## 其他解密失敗
<a name="decrypt-failed"></a>

如果您嘗試解密加密的訊息失敗，表示 AWS Encryption SDK 無法 （或不會） 解密訊息中的任何加密資料金鑰。

如果您使用指定包裝金鑰的 keyring 或主金鑰提供者，則 只會 AWS Encryption SDK 使用您指定的包裝金鑰。確認您使用的是您想要的包裝金鑰，而且您至少擁有其中一個包裝金鑰的`kms:Decrypt`許可。如果您使用 做為備用 AWS KMS keys，則可以嘗試使用[AWS KMS 探索 keyring](use-kms-keyring.md#kms-keyring-discovery) 或[探索模式中的主金鑰提供者](migrate-mkps-v2.md)來解密訊息。如果操作成功，在傳回純文字之前，請確認用來解密訊息的金鑰是您信任的金鑰。

## 回復考量
<a name="migration-rollback"></a>

如果您的應用程式無法加密或解密資料，您通常可以透過更新程式碼符號、 keyring、主金鑰提供者或[承諾政策](concepts.md#commitment-policy)來解決問題。不過，在某些情況下，您可能會決定最好將應用程式復原至舊版的 AWS Encryption SDK。

如果您必須復原，請謹慎執行。1.7.*x* AWS Encryption SDK 之前的 版本無法解密以[金鑰承諾](concepts.md#key-commitment)加密的加密文字。
+ 從最新的 1.*x* 版本轉返到舊版 通常 AWS Encryption SDK 很安全。您可能需要復原對程式碼所做的變更，才能使用先前版本中不支援的符號和物件。
+ 一旦您開始加密 2.0.*x* 版或更新版本中的金鑰承諾 （將承諾政策設定為 `RequireEncryptAllowDecrypt`)，即可轉返至 1.7.*x* 版，但無法轉返至任何較早版本。1.7.*x* AWS Encryption SDK 之前的 版本無法解密以[金鑰承諾](concepts.md#key-commitment)加密的加密文字。

如果您在所有主機都可以使用金鑰承諾解密之前不小心啟用使用金鑰承諾加密，最好繼續進行推出，而不是轉返。如果訊息是暫時性的，或可以安全地捨棄，則您可能會考慮訊息遺失的轉返。如果需要轉返，您可以考慮撰寫工具來解密並重新加密所有訊息。