

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

# 设置您的承诺策略
<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)
}
```

------