

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

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

本主題說明其他程式設計語言實作 適用於 C 的 AWS Encryption SDK 中不支援的部分 功能。

本節中的範例示範如何使用 [2.0.*x* 版](about-versions.md)和更新版本 適用於 C 的 AWS Encryption SDK。如需使用舊版的範例，請在 GitHub 上 [aws-encryption-sdk-c 儲存庫](https://github.com/aws/aws-encryption-sdk-c/)的[版本](https://github.com/aws/aws-encryption-sdk-c/releases)清單中找到您的版本。

如需使用 進行程式設計的詳細資訊 適用於 C 的 AWS Encryption SDK，請參閱 [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)，以及 [適用於 C 的 AWS Encryption SDK API 文件](https://aws.github.io/aws-encryption-sdk-c/html/)。

另請參閱：[Keyring](choose-keyring.md)

**Topics**
+ [加密和解密資料的模式](#c-language-using-pattern)
+ [參考計數](#c-language-using-release)

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

當您使用 時 適用於 C 的 AWS Encryption SDK，請遵循類似如下的模式：建立 [keyring](concepts.md#keyring)、建立使用 keyring 的 [CMM](concepts.md#crypt-materials-manager)、建立使用 CMM （和 keyring) 的工作階段，然後處理工作階段。

1. 載入錯誤字串。  
在 C 或 C\$1\$1 程式碼中呼叫 `aws_cryptosdk_load_error_strings()`方法。它會載入對偵錯非常有用的錯誤資訊。  
您只需呼叫一次，例如在您的`main`方法中。  

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

2. 建立 keyring。  
使用您想用來加密資料金鑰的包裝金鑰來設定 [keyring](concepts.md#keyring)。此範例使用 [AWS KMS keyring](use-kms-keyring.md) 搭配 keyring AWS KMS key，但您可以在其位置使用任何類型的 keyring。  
若要在 AWS KMS key 的加密 keyring 中識別 適用於 C 的 AWS Encryption SDK，請指定[金鑰 ARN](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN) 或[別名 ARN](https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-alias-arn)。在解密 Keyring 中，您必須使用金鑰 ARN。如需詳細資訊，請參閱[在 AWS KMS keyring 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. 建立工作階段。  
在 中 適用於 C 的 AWS Encryption SDK，您可以使用*工作階段*來加密單一純文字訊息或解密單一加密文字訊息，無論其大小為何。此工作階段在整個處理過程中會維護訊息的狀態。  
使用分配器、keyring 和模式來設定您的工作階段：`AWS_CRYPTOSDK_ENCRYPT` 或 `AWS_CRYPTOSDK_DECRYPT`。如果您需要變更工作階段的模式，請使用 `aws_cryptosdk_session_reset` 方法。  
當您使用 keyring 建立工作階段時， 適用於 C 的 AWS Encryption SDK 會自動為您建立預設密碼編譯資料管理員 (CMM)。您不需要建立、維護或銷毀此物件。  
例如，以下工作階段使用在步驟 1 中定義的分配器和 keyring。當您加密資料時，模式為 `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.*x* 和 2.2.*x* AWS Encryption SDK 版中推出。  
當工作階段設定為加密資料時，純文字欄位描述輸入，加密文字欄位描述輸出。`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>

為了防止記憶體流失，當您使用完您建立的所有物件參考時，請務必將其釋出。否則會造成記憶體失流。此開發套件提供方法讓您輕鬆這樣做。

每當您使用下列其中一個子物件建立父物件時，父物件會取得並維護對子物件的參考，如下所示：
+ [keyring](concepts.md#keyring)，例如，使用 keyring 建立工作階段
+ 預設[密碼編譯資料管理員](concepts.md#crypt-materials-manager) (CMM)，例如使用預設 CMM 建立工作階段或自訂 CMM
+ [資料金鑰快取](data-key-caching.md)，例如，使用 keyring 和快取建立快取 CMM

除非您需要對子物件的獨立參考，否則您可以在建立父物件後立即釋出對子物件的參考。在銷毀父物件時，對子物件的其餘參考即會釋出。此模式可確保只在您需要的一段時間內維護每個物件的參考，您不會因為參考未釋放而流失記憶體。

您只需負責釋出您明確建立的子物件參考。您不需負責管理 SDK 為您建立的任何物件的參考。如果 SDK 建立物件，例如 `aws_cryptosdk_caching_cmm_new_from_keyring`方法新增至工作階段的預設 CMM，則 SDK 會管理物件及其參考的建立和銷毀。

在下列範例中，當您使用 [keyring](concepts.md#keyring) 建立工作階段，該工作階段會取得 keyring 的參考，並保留該參考，直到工作階段銷毀為止。如果您不需要保有 keyring 的其他參考，您可以使用 `aws_cryptosdk_keyring_release` 方法在建立工作階段後立即釋出 keyring 物件。此方法可遞減 keyring 的參考計數。當您呼叫 `aws_cryptosdk_session_destroy` 來銷毀工作階段時，將會釋出工作階段對 keyring 的參考。

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

對於更複雜的任務，例如針對多個工作階段重複使用 keyring，或在 CMM 中指定演算法套件，您可能需要維護物件的獨立參考。如果是這樣，請勿立即呼叫釋出方法。而是除了銷毀工作階段之外，當您不再使用這些物件時，請釋出您的參考。

當您使用替代 CMMs 時，此參考計數技術也適用，例如[資料金鑰](data-key-caching.md)快取的快取 CMM。當您從快取和 keyring 建立快取 CMM 時，快取 CMM 會取得兩個物件的參考。除非您需要用於其他任務，否則您可以在快取 CMM 建立後立即釋出快取和 keyring 的獨立參考。然後，當您使用快取 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);
```