

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

# AWS Encryption SDK for C
<a name="c-language"></a>

为使用 C 语言编写应用程序的开发人员 AWS Encryption SDK for C 提供了一个客户端加密库。它也是用更高级编程语言实现 AWS Encryption SDK 的基础。

与的所有实现一样 AWS Encryption SDK， AWS Encryption SDK for C 提供了高级数据保护功能。这些功能包括[信封加密](concepts.md#envelope-encryption)、其他经过身份验证的数据 (AAD) 以及安全、经过身份验证且对称的密钥[算法套件](concepts.md#crypto-algorithm)，如具有密钥派生和签名的 256 位 AES-GCM。

的所有特定于语言的实现 AWS Encryption SDK 都是完全可互操作的。例如，您可以使用加密数据， AWS Encryption SDK for C 并使用[任何支持的语言实现](programming-languages.md)对其进行解密，包括加密 [AWS CLI](crypto-cli.md)。

 AWS Encryption SDK for C 要求与 AWS Key Management Service (AWS KMS) 适用于 C\$1\$1 的 AWS SDK 进行交互。仅当您使用可选的 [AWS KMS 密钥环](use-kms-keyring.md)时，才需要使用该工具。但是， AWS Encryption SDK 不需要 AWS KMS 或任何其他 AWS 服务。

**了解更多**
+ 有关使用编程的详细信息 AWS Encryption SDK for C，请参阅 [C 示](c-examples.md)[例 GitHub、上[aws-encryption-sdk-c 存储库](https://github.com/aws/aws-encryption-sdk-c/)中的示例](https://github.com/aws/aws-encryption-sdk-c/tree/master/examples)以及 [AWS Encryption SDK for C API 文档](https://aws.github.io/aws-encryption-sdk-c/html/)。
+ 有关如何使用加密数据以便可以将其解密为多个区域的讨论 AWS 区域，请参阅安全[博客中的如何使用 C 语言解密多个区域中的密文](https://aws.amazon.com/blogs/security/how-to-decrypt-ciphertexts-multiple-regions-aws-encryption-sdk-in-c/)。 AWS Encryption SDK for C AWS Encryption SDK AWS 

**Topics**
+ [安装](c-language-installation.md)
+ [使用 C 开发工具包](c-language-using.md)
+ [示例](c-examples.md)

# 正在安装 AWS Encryption SDK for C
<a name="c-language-installation"></a>

安装最新版本的 AWS Encryption SDK for C。

**注意**  
[2.0.0 AWS Encryption SDK for C 之前的所有版本都处于该阶段。end-of-support](https://docs.aws.amazon.com/sdkref/latest/guide/maint-policy.html#version-life-cycle)  
您可以安全地从 AWS Encryption SDK for C 版本 2.0.*x* 及更高版本更新为最新版本，无需更改任何代码或数据。但是，版本 2.0.*x* 中引入了[新的安全功能](about-versions.md#version-2)，不向后兼容。要从 1.7.*x* 之前的版本更新到 2.0.*x* 及更高版本，必须先更新到 AWS Encryption SDK for C最新版本 1.*x*。有关更多信息，请参阅 [迁移你的 AWS Encryption SDK](migration.md)。

您可以在[aws-encryption-sdk-c](https://github.com/aws/aws-encryption-sdk-c/)存储库的 [README 文件 AWS Encryption SDK for C](https://github.com/aws/aws-encryption-sdk-c/#readme)中找到有关安装和构建的详细说明。其中包括在 Amazon Linux、Ubuntu、macOS 和 Windows 平台上进行构建的说明。

开始之前，请决定是否要在 AWS Encryption SDK中使用 [AWS KMS 密钥环](use-kms-keyring.md)。如果您使用 AWS KMS 钥匙圈，则需要安装。 适用于 C\$1\$1 的 AWS SDK需要使用 AWS SDK 才能与 [AWS Key Management Service](https://docs.aws.amazon.com/kms/latest/developerguide/)(AWS KMS) 进行交互。使用 AWS KMS 密钥环时， AWS Encryption SDK AWS KMS 用于生成和保护保护数据的加密密钥。

 适用于 C\$1\$1 的 AWS SDK 如果您使用的是其他密钥环类型，例如原始的 AES 密钥环、原始 RSA 密钥环或不包含密钥环的多密钥环，则无需安装。 AWS KMS 但是，使用原始密钥环类型时，您需要生成并保护自己的原始包装密钥。

如果您在安装时遇到问题，请在 `aws-encryption-sdk-c` 存储库中[提交问题](https://github.com/aws/aws-encryption-sdk-c/issues)或使用此页面上的任何反馈链接。

# 使用 AWS Encryption SDK for C
<a name="c-language-using"></a>

本主题解释了其他编程语言实现中不支持的某些功能。 AWS Encryption SDK for C 

本节中的示例说明了如何使用 AWS Encryption SDK for C[版本 2.0.*x*](about-versions.md) 及更高版本。有关使用早期版本的示例，请在[aws-encryption-sdk-c 存储库存储库](https://github.com/aws/aws-encryption-sdk-c/)的[版本](https://github.com/aws/aws-encryption-sdk-c/releases)列表中找到您的版本 GitHub。

有关使用编程的详细信息 AWS Encryption SDK for C，请参阅 [C 示](c-examples.md)[例 GitHub、上[aws-encryption-sdk-c 存储库](https://github.com/aws/aws-encryption-sdk-c/)中的示例](https://github.com/aws/aws-encryption-sdk-c/tree/master/examples)以及 [AWS Encryption SDK for C API 文档](https://aws.github.io/aws-encryption-sdk-c/html/)。

另请参阅：[密钥环](choose-keyring.md)

**Topics**
+ [加密和解密数据的模式](#c-language-using-pattern)
+ [引用计数](#c-language-using-release)

## 加密和解密数据的模式
<a name="c-language-using-pattern"></a>

使用时 AWS Encryption SDK for C，将遵循类似于以下的模式：创建[密钥环，创建使用密钥环](concepts.md#keyring)的 [CMM](concepts.md#crypt-materials-manager)，创建使用 CMM（和密钥环）的会话，然后处理会话。

1. 加载错误字符串。  
在 C 或 C\$1\$1 代码中调用 `aws_cryptosdk_load_error_strings()` 方法。该方法加载对调试非常有用的错误信息。  
您只需要调用一次，例如在 `main` 方法中调用。  

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

2. 创建一个密钥环。  
使用要用于加密数据密钥的包装密钥配置[密钥环](concepts.md#keyring)。此示例使用带[AWS KMS 钥匙圈](use-kms-keyring.md)的密钥环 AWS KMS key，但您可以使用任何类型的密钥环代替它。  
要 AWS KMS key 在中的加密密钥环中识别 AWS Encryption SDK for C，请指定[密钥 ARN](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN) 或[别名](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-alias-arn) ARN。在解密密钥环中，您必须使用密钥 ARN。有关更多信息，请参阅 [在 AWS KMS 钥匙圈 AWS KMS keys 中识别](use-kms-keyring.md#kms-keyring-id)。  

```
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);
```

3. 创建会话。  
在中 AWS Encryption SDK for C，您可以使用*会话*来加密一条纯文本消息或解密一条密文消息，无论其大小如何。会话在整个处理过程中维护消息的状态。  
使用分配器、密钥环和模式（`AWS_CRYPTOSDK_ENCRYPT` 或 `AWS_CRYPTOSDK_DECRYPT`）配置会话。如果需要更改会话模式，请使用 `aws_cryptosdk_session_reset` 方法。  
当您使用密钥环创建会话时， AWS Encryption SDK for C 会自动为您创建默认的加密材料管理器 (CMM)。您无需创建、维护或销毁该对象。  
例如，以下会话使用分配器以及在步骤 1 中定义的密钥环。在加密数据时，模式为 `AWS_CRYPTOSDK_ENCRYPT`。  

```
struct aws_cryptosdk_session * session = aws_cryptosdk_session_new_from_keyring_2(allocator, AWS_CRYPTOSDK_ENCRYPT, kms_keyring);
```

4. 加密或解密数据。  
要处理会话中的数据，请使用 `aws_cryptosdk_session_process` 方法。如果输入缓冲区足够大，可以存放整个明文，并且输出缓冲区足够大，可以存放整个加密文字，则可以调用 `aws_cryptosdk_session_process_full`。不过，如果需要处理串流数据，您可以循环调用 `aws_cryptosdk_session_process`。有关示例，请参阅 [file\$1streaming.cpp](https://github.com/aws/aws-encryption-sdk-c/blob/master/examples/file_streaming.cpp) 示例。`aws_cryptosdk_session_process_full`在 1.9 AWS Encryption SDK 版本中引入。 *x* 和 2.2。 *x*。  
将会话配置为加密数据时，明文字段描述输入，密文字段描述输出。`plaintext` 字段包含要加密的消息，`ciphertext` 字段接收加密方法返回的[加密的消息](message-format.md)。  

```
/* Encrypting data */
aws_cryptosdk_session_process_full(session,
                                   ciphertext,
                                   ciphertext_buffer_size,
                                   &ciphertext_length,
                                   plaintext,
                                   plaintext_length)
```
将会话配置为解密数据时，密文字段描述输入，明文字段描述输出。`ciphertext` 字段包含加密方法返回的[加密的消息](message-format.md)，`plaintext` 字段接收解密方法返回的明文消息。  
要解密数据，请调用 `aws_cryptosdk_session_process_full` 方法。  

```
/* Decrypting data */
aws_cryptosdk_session_process_full(session,
                                   plaintext,
                                   plaintext_buffer_size,
                                   &plaintext_length,
                                   ciphertext,
                                   ciphertext_length)
```

## 引用计数
<a name="c-language-using-release"></a>

为了防止内存泄漏，在使用完创建的所有对象时，请务必释放对它们的引用。否则，可能会造成内存泄漏。本开发工具包提供了简化该任务的方法。

每次使用一个以下子对象创建父对象时，父对象都会获取并保持对该子对象的引用，如下所示：
+ [密钥环](concepts.md#keyring)，例如，使用密钥环创建会话
+ 默认[加密材料管理器](concepts.md#crypt-materials-manager)（CMM），例如，使用默认 CMM 创建会话或自定义 CMM
+ [数据密钥缓存](data-key-caching.md)，例如，使用密钥环和缓存创建缓存 CMM

除非需要对子对象进行单独的引用，否则，您可以在创建父对象后立即释放对子对象的引用。在销毁父对象时，将释放对子对象的其余引用。该模式确保您只在需要时维护对每个对象的引用，不会因为未释放的引用而造成内存泄漏。

您仅负责释放对您明确创建的子对象的引用。您不负责管理对该开发工具包创建的任何对象的引用。如果该软件开发工具包创建一个对象（例如，`aws_cryptosdk_caching_cmm_new_from_keyring` 方法添加到会话中的默认 CMM），该软件开发工具包将管理该对象及其引用的创建和销毁过程。

在以下示例中，在使用[密钥环](concepts.md#keyring)创建会话时，会话将获取对密钥环的引用并保持该引用，直到销毁会话为止。如果不需要保持对密钥环的其他引用，您可以在创建会话后立即使用 `aws_cryptosdk_keyring_release` 方法释放密钥环对象。该方法将减少密钥环的引用计数。在调用 `aws_cryptosdk_session_destroy` 以销毁会话时，将释放会话对密钥环的引用。

```
// The session gets a reference to the keyring.
struct aws_cryptosdk_session *session =	
	aws_cryptosdk_session_new_from_keyring_2(alloc, AWS_CRYPTOSDK_ENCRYPT, keyring);

// After you create a session with a keyring, release the reference to the keyring object.
aws_cryptosdk_keyring_release(keyring);
```

对于更复杂的任务（例如，将密钥环重复用于多个会话或在 CMM 中指定算法套件），您可能需要保持对该对象的单独引用。如果是这样，请不要立即调用 release 方法，而是在不再使用这些对象时，除了销毁会话以外，还要释放引用。

当您使用其他方法（例如缓存 CMM）进行[数据密钥缓](data-key-caching.md)存时 CMMs，这种引用计数技术也适用。从缓存和密钥环中创建缓存 CMM 时，缓存 CMM 将获取对两个对象的引用。除非您需要使用这些 CMM 执行其他任务，否则，您可以在创建缓存 CMM 后立即释放对缓存和密钥环的单独引用。然后，在使用缓存 CMM 创建会话时，您可以释放对缓存 CMM 的引用。

请注意，您仅负责释放对您明确创建的对象的引用。方法创建的对象（例如，作为缓存 CMM 基础的默认 CMM）是由该方法管理的。

```
/ Create the caching CMM from a cache and a keyring.
struct aws_cryptosdk_cmm *caching_cmm = aws_cryptosdk_caching_cmm_new_from_keyring(allocator, cache, kms_keyring, NULL, 60, AWS_TIMESTAMP_SECS);

// Release your references to the cache and the keyring.
aws_cryptosdk_materials_cache_release(cache);
aws_cryptosdk_keyring_release(kms_keyring);

// Create a session with the caching CMM.
struct aws_cryptosdk_session *session = aws_cryptosdk_session_new_from_cmm_2(allocator, AWS_CRYPTOSDK_ENCRYPT, caching_cmm);

// Release your references to the caching CMM.
aws_cryptosdk_cmm_release(caching_cmm);

// ...

aws_cryptosdk_session_destroy(session);
```

# AWS Encryption SDK for C 例子
<a name="c-examples"></a>

以下示例向您展示了如何使用 AWS Encryption SDK for C 来加密和解密数据。

本节中的示例说明了如何使用版本 2.0.*x* 及更高版本的 AWS Encryption SDK for C。有关使用早期版本的示例，请在[aws-encryption-sdk-c 存储库存储库](https://github.com/aws/aws-encryption-sdk-c/)的[版本](https://github.com/aws/aws-encryption-sdk-c/releases)列表中找到您的版本 GitHub。

安装和构建时 AWS Encryption SDK for C，这些示例和其他示例的源代码包含在`examples`子目录中，它们会被编译并内置到该`build`目录中。您也可以在上[aws-encryption-sdk-c](https://github.com/aws/aws-encryption-sdk-c/) GitHub存储库的[示例](https://github.com/aws/aws-encryption-sdk-c/tree/master/examples)子目录中找到它们。

**Topics**
+ [加密和解密字符串](#c-example-strings)

## 加密和解密字符串
<a name="c-example-strings"></a>

以下示例向您展示了如何使用 AWS Encryption SDK for C 来加密和解密字符串。

此示例以[AWS KMS 密钥环](use-kms-keyring.md)为特色，这是一种使用 AWS KMS key in [AWS Key Management Service (AWS KMS)](https://docs.aws.amazon.com/kms/latest/developerguide/) 生成和加密数据密钥的密钥环。该示例包括用 C\$1\$1 编写的代码。使用 AWS KMS 钥匙圈 AWS KMS 时 AWS Encryption SDK for C 适用于 C\$1\$1 的 AWS SDK 需要调用。如果您使用的是不与之交互的密钥环 AWS KMS，例如原始的 AES 密钥环、未处理的 RSA 密钥环或不包含密钥环的多密钥环，则 AWS KMS 不需要使用。 适用于 C\$1\$1 的 AWS SDK 

有关创建的帮助 AWS KMS key，请参阅《*AWS Key Management Service 开发者指南》*中的[创建密钥](https://docs.aws.amazon.com/kms/latest/developerguide/create-keys.html)。有关识别 AWS KMS 钥匙圈 AWS KMS keys 中的的帮助，请参阅[在 AWS KMS 钥匙圈 AWS KMS keys 中识别](use-kms-keyring.md#kms-keyring-id)。

**请参阅完整的代码示例**：[string.cpp](https://github.com/aws/aws-encryption-sdk-c/blob/master/examples/string.cpp)

**Topics**
+ [加密字符串](#c-example-string-encrypt)
+ [解密字符串](#c-example-string-decrypt)

### 加密字符串
<a name="c-example-string-encrypt"></a>

本示例的第一部分使用带有密钥环的 AWS KMS 密钥环 AWS KMS key 来加密纯文本字符串。

步骤 1：加载错误字符串。  
在 C 或 C\$1\$1 代码中调用 `aws_cryptosdk_load_error_strings()` 方法。该方法加载对调试非常有用的错误信息。  
您只需要调用一次，例如在 `main` 方法中调用。  

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

步骤 2：构造密钥环。  
创建用于加密的 AWS KMS 密钥环。本示例中的密钥环配置为一个 AWS KMS key，但您可以将多个密钥环配置为多个 AWS KMS 密钥环 AWS KMS keys，包括在不同 AWS 区域 和不同的账户 AWS KMS keys 中。  
要 AWS KMS key 在中的加密密钥环中识别 AWS Encryption SDK for C，请指定[密钥 ARN](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN) 或[别名](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-alias-arn) ARN。在解密密钥环中，您必须使用密钥 ARN。有关更多信息，请参阅 [在 AWS KMS 钥匙圈 AWS KMS keys 中识别](use-kms-keyring.md#kms-keyring-id)。  
[在 AWS KMS 钥匙圈 AWS KMS keys 中识别](use-kms-keyring.md#kms-keyring-id)  
创建包含多个密钥的密钥环时 AWS KMS keys，可以指定 AWS KMS key 用于生成和加密纯文本数据密钥的，以及用于加密相同纯文本数据密钥的可选附加 AWS KMS keys 数组。在这种情况下，您只需要指定生成器 AWS KMS key。  
在运行该代码之前，请将示例密钥 ARN 替换为有效 ARN。  

```
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);
```

步骤 3：创建会话。  
使用分配器、模式枚举器和密钥环创建一个会话。  
每个会话都需要一种模式：用于加密的 `AWS_CRYPTOSDK_ENCRYPT` 或用于解密的 `AWS_CRYPTOSDK_DECRYPT`。要更改现有会话的模式，请使用 `aws_cryptosdk_session_reset` 方法。  
在使用密钥环创建一个会话后，您可以使用该开发工具包提供的方法释放对密钥环的引用。该会话在生命周期内保留对密钥环对象的引用。在销毁该会话时，将释放对密钥环和会话对象的引用。这种[引用计数](c-language-using.md#c-language-using-release)方法有助于防止内存泄漏，并防止在使用对象时将其释放。  

```
struct aws_cryptosdk_session *session = 
       aws_cryptosdk_session_new_from_keyring_2(alloc, AWS_CRYPTOSDK_ENCRYPT, kms_keyring);

/* When you add the keyring to the session, release the keyring object */
aws_cryptosdk_keyring_release(kms_keyring);
```

步骤 4：设置加密上下文。  
[加密上下文](concepts.md#encryption-context)是任意的非机密其他经过身份验证的数据。当您提供有关加密的加密上下文时，会 AWS Encryption SDK 以加密方式将加密上下文绑定到密文，因此解密数据需要相同的加密上下文。使用加密上下文是可选的，但作为一项最佳实践，建议您提供加密上下文。  
首先，创建一个包含加密上下文字符串的哈希表。  

```
/* Allocate a hash table for the encryption context */
int set_up_enc_ctx(struct aws_allocator *alloc, struct aws_hash_table *my_enc_ctx) 

// Create encryption context strings
AWS_STATIC_STRING_FROM_LITERAL(enc_ctx_key1, "Example");
AWS_STATIC_STRING_FROM_LITERAL(enc_ctx_value1, "String");
AWS_STATIC_STRING_FROM_LITERAL(enc_ctx_key2, "Company");
AWS_STATIC_STRING_FROM_LITERAL(enc_ctx_value2, "MyCryptoCorp");

// Put the key-value pairs in the hash table
aws_hash_table_put(my_enc_ctx, enc_ctx_key1, (void *)enc_ctx_value1, &was_created)
aws_hash_table_put(my_enc_ctx, enc_ctx_key2, (void *)enc_ctx_value2, &was_created)
```
获取会话中加密上下文的可变指针。然后，使用 `aws_cryptosdk_enc_ctx_clone` 函数将加密上下文复制到会话中。请将副本保留在 `my_enc_ctx` 中，以便在解密数据后验证该值。  
加密上下文是会话的一部分，而不是传递给会话进程函数的参数。这可保证对消息的每个分段使用相同的加密上下文，即使多次调用会话进程函数来加密整个消息也是如此。  

```
struct aws_hash_table *session_enc_ctx = aws_cryptosdk_session_get_enc_ctx_ptr_mut(session);

aws_cryptosdk_enc_ctx_clone(alloc, session_enc_ctx, my_enc_ctx)
```

步骤 5：加密字符串。  
要加密明文字符串，请使用 `aws_cryptosdk_session_process_full` 方法和使用加密模式的会话。此方法在 1.9 AWS Encryption SDK 版本中引入。 *x* 和 2.2。 *x*，专为非流式加密和解密而设计。要处理串流数据，请在循环中调用 `aws_cryptosdk_session_process`。  
加密时，明文字段为输入字段；密文字段为输出字段。处理完成后，`ciphertext_output` 字段包含[加密的消息](concepts.md#message)，其中包括实际密文、加密的数据密钥和加密上下文。您可以对任何支持的编程语言使用来解密此加密消息。 AWS Encryption SDK   

```
/* Gets the length of the plaintext that the session processed */
size_t ciphertext_len_output;
if (AWS_OP_SUCCESS != aws_cryptosdk_session_process_full(session,
                                  ciphertext_output,
                                  ciphertext_buf_sz_output,
                                  &ciphertext_len_output,
                                  plaintext_input,
                                  plaintext_len_input)) {
    aws_cryptosdk_session_destroy(session);
    return 8;
}
```

步骤6：清理会话。  
最后一步将销毁会话，包括对 CMM 和密钥环的引用。  
您也可以根据需要重复使用具有相同密钥环和 CMM 的会话来解密字符串，或加密/解密其他消息，而不是销毁会话。要使用会话进行解密，请使用 `aws_cryptosdk_session_reset` 方法将模式更改为 `AWS_CRYPTOSDK_DECRYPT`。

### 解密字符串
<a name="c-example-string-decrypt"></a>

本示例的第二部分将对包含原始字符串密文的加密消息进行解密。

步骤 1：加载错误字符串。  
在 C 或 C\$1\$1 代码中调用 `aws_cryptosdk_load_error_strings()` 方法。该方法加载对调试非常有用的错误信息。  
您只需要调用一次，例如在 `main` 方法中调用。  

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

步骤 2：构造密钥环。  
当你解密数据时 AWS KMS，你会传入加密 API [返回的加密消息](concepts.md#message)。[解密 API](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html) 不以输入 AWS KMS key 为输入。相反， AWS KMS 使用与加密密文相同的方法 AWS KMS key 来解密密文。但是， AWS Encryption SDK 允许您使用加密和解密来 AWS KMS keys 指定密 AWS KMS 钥环。  
在解密时，您可以仅使用要用于解密加密消息 AWS KMS keys 的密钥环来配置密钥环。例如，您可能想创建一个仅包含组织中特定角色使用的密钥环。 AWS KMS key AWS KMS key 除非它出现在解密密钥环中，否则永远不会使用它。 AWS Encryption SDK 如果 SDK 无法使用您提供的密钥环 AWS KMS keys 中的来解密加密的数据密钥，要么是因为密钥环 AWS KMS keys 中没有使用任何数据密钥来加密任何数据密钥，要么是因为调用者无权使用密钥环 AWS KMS keys 中的进行解密，则解密调用将失败。  
 AWS KMS key [为解密密钥环指定时，必须使用其密钥 ARN。](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN)仅允许 ARNs在加密密钥环中使用@@ [别名](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-alias-arn)。有关识别 AWS KMS 钥匙圈 AWS KMS keys 中的的帮助，请参阅[在 AWS KMS 钥匙圈 AWS KMS keys 中识别](use-kms-keyring.md#kms-keyring-id)。  
在此示例中，我们指定了一个密钥环，该密钥环配置为 AWS KMS key 用于加密字符串的密钥环。在运行该代码之前，请将示例密钥 ARN 替换为有效 ARN。  

```
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);
```

步骤 3：创建会话。  
使用分配器和密钥环创建一个会话。要配置解密会话，请使用 `AWS_CRYPTOSDK_DECRYPT` 模式配置会话。  
在使用密钥环创建一个会话后，您可以使用该开发工具包提供的方法释放对密钥环的引用。该会话在生命周期内保留对密钥环对象的引用，在销毁该会话时，将会释放会话和密钥环。这种引用计数方法有助于防止内存泄漏，并防止在使用对象时将其释放。  

```
struct aws_cryptosdk_session *session =	
	aws_cryptosdk_session_new_from_keyring_2(alloc, AWS_CRYPTOSDK_DECRYPT, kms_keyring);

/* When you add the keyring to the session, release the keyring object */
aws_cryptosdk_keyring_release(kms_keyring);
```

步骤 4：解密字符串。  
要解密字符串，请使用 `aws_cryptosdk_session_process_full` 方法和配置用于解密的会话。此方法在 AWS Encryption SDK 版本 1.9.*x* 和 2.2.*x* 中引入，专为非串流加密和解密而设计。要处理串流数据，请在循环中调用 `aws_cryptosdk_session_process`。  
解密时，密文字段为输入字段，明文字段是输出字段。`ciphertext_input` 字段包含加密方法返回的[加密消息](message-format.md)。处理完成后，`plaintext_output` 字段包含明文（解密后的）字符串。  

```
size_t plaintext_len_output;

if (AWS_OP_SUCCESS != aws_cryptosdk_session_process_full(session,
                                  plaintext_output,
                                  plaintext_buf_sz_output,
                                  &plaintext_len_output,
                                  ciphertext_input,
                                  ciphertext_len_input)) {
    aws_cryptosdk_session_destroy(session);
    return 13;
}
```

步骤 5：验证加密上下文。  
请确保实际的加密上下文（用于解密消息的上下文）包含您在加密消息时提供的加密上下文。实际加密上下文可能包含额外的键值对，因为[加密材料管理器](concepts.md#crypt-materials-manager) (CMM) 可以在加密消息前向提供的加密上下文添加键值对。  
在中 AWS Encryption SDK for C，解密时无需提供加密上下文，因为加密上下文包含在 SDK 返回的加密消息中。但是，在其返回明文消息前，您的解密函数应验证用于解密消息的加密上下文中包含所提供的加密上下文中的所有键值对。  
首先，获取会话中哈希表的只读指针。该哈希表包含用于解密消息的加密上下文。  

```
const struct aws_hash_table *session_enc_ctx = aws_cryptosdk_session_get_enc_ctx_ptr(session);
```
然后，遍历加密时复制的 `my_enc_ctx` 哈希表中的加密上下文。验证用于解密的 `session_enc_ctx` 哈希表包含用于加密的 `my_enc_ctx` 哈希表中的所有键值对。如果缺少任何密钥，或密钥具有不同的值，则停止处理并输出错误消息。  

```
for (struct aws_hash_iter iter = aws_hash_iter_begin(my_enc_ctx); !aws_hash_iter_done(&iter);
      aws_hash_iter_next(&iter)) {
     struct aws_hash_element *session_enc_ctx_kv_pair;
     aws_hash_table_find(session_enc_ctx, iter.element.key, &session_enc_ctx_kv_pair)

    if (!session_enc_ctx_kv_pair ||
        !aws_string_eq(
            (struct aws_string *)iter.element.value, (struct aws_string *)session_enc_ctx_kv_pair->value)) {
        fprintf(stderr, "Wrong encryption context!\n");
        abort();
    }
}
```

步骤6：清理会话。  
验证加密上下文后，可以销毁会话，或重用会话。如果需要重新配置会话，请使用 `aws_cryptosdk_session_reset` 方法。  

```
aws_cryptosdk_session_destroy(session);
```