

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

# 使用 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);
```