

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

# 設定您的承諾政策
<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)
}
```

------