適用於 C 的 AWS Encryption SDK 範例 - AWS Encryption SDK

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

適用於 C 的 AWS Encryption SDK 範例

以下範例說明如何使用 適用於 C 的 AWS Encryption SDK 來加密和解密資料。

本節中的範例會示範如何使用 2.0 版。x和後來的適用於 C 的 AWS Encryption SDK。有關使用早期版本的示例,請在版本的清單aws-encryption-sdk-c 儲存庫的儲存庫GitHub。

安裝和建置 適用於 C 的 AWS Encryption SDK,這些原始程式碼和其他範例的原始程式碼會包含在 examples 子目錄中,並且將它們編譯和建置到 build 目錄。您也可以在例子子目錄的aws-encryption-sdk-c的儲存庫GitHub。

加密和解密字串

以下範例說明如何使用 適用於 C 的 AWS Encryption SDK 來加密和解密字串。

此示例的特點是AWS KMSKeyring,一種密鑰環類型,它使用AWS KMS key在AWS Key Management Service(AWS KMS)生成和加密數據密鑰。範例包括使用 C ++ 編寫的代碼。所以此適用於 C 的 AWS Encryption SDK需要AWS SDK for C++呼叫AWS KMS當您使用時,AWS KMSkeyring。如果您使用的密鑰環不與AWS KMS,例如原始 AES 密鑰環、原始 RSA 密鑰環或不包含AWS KMSkeyring,AWS SDK for C++不是必要項目。

有關創建AWS KMS key,請參建立金鑰中的AWS Key Management Service開發人員指南。為了幫助識別AWS KMS keys在AWS KMSkeyring,請參在 AWS KMS 鑰匙圈 AWS KMS keys 中識別

請參閱完整的程式碼範例string.cpp

加密字串

此範例中的第一個部分會使用AWS KMS使用一個的 keyringAWS KMS key來加密明文字符串。

步驟 1. 載入錯誤字串。

呼叫aws_cryptosdk_load_error_strings()方法,請參考 C 或 C ++ 代碼。它加載對調試非常有用的錯誤信息。

您只需調用一次,例如在main方法。

/* Load error strings for debugging */ aws_cryptosdk_load_error_strings();
步驟 2:建構 keyring。

建立AWS KMS用於加密的 keyring。本示例中的密鑰環配置為一個AWS KMS key,但是您可以配置AWS KMS使用多個的 keyringAWS KMS keys,包括AWS KMS keys在不同的AWS 區域和不同的帳户.

要標識AWS KMS key在加密密鑰環中適用於 C 的 AWS Encryption SDK中,指定金鑰 ARN或者別名 ARN。在解密 Keyring 中,您必須使用金鑰 ARN。如需詳細資訊,請參閱 在 AWS KMS 鑰匙圈 AWS KMS keys 中識別

在 AWS KMS 鑰匙圈 AWS KMS keys 中識別

當您創建一個帶有多個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:建立工作階段。

使用分配器、模式列舉器和 keyring 來建立工作階段。

每個工作階段需要模式:AWS_CRYPTOSDK_ENCRYPT 用來加密或 AWS_CRYPTOSDK_DECRYPT 用來解密。若要變更現有工作階段的模式,請使用 aws_cryptosdk_session_reset 方法。

建立具有 keyring 的工作階段之後,您可以使用 SDK 提供的方法,將您的參考釋出給 keyring。工作階段會在其生命週期期間保留 keyring 物件的參考。當您銷毀工作階段時,會釋出 keyring 和工作階段物件的參考。此參考計數技術有助於避免記憶體流失,並避免在使用物件時釋出物件。

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:設定加密內容。

加密內容是一種任意、非私密額外驗證資料。在加密時提供加密內容時,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 方法搭配加密模式的工作階段。這種方法,在AWS Encryption SDK1.9 版本。x和 2.2.x,專為非流式加密和解密而設計。要處理流數據,請調用aws_cryptosdk_session_process在一個循環中。

加密時,純文字欄位為輸入欄位;加密文字欄位為輸出欄位。當處理完成時,ciphertext_output 欄位會包含加密的訊息,包括實際加密文字、加密的資料金鑰和加密內容。您可以在任何支援的程式設計語言中使用 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 和 keyring 的參考。

如果您偏好不要銷毀工作階段,則可以對工作階段重複使用相同的 keyring 和 CMM 來解密字串,或是加密或解密其他訊息。若要將工作階段用於解密,請使用 aws_cryptosdk_session_reset 方法來將模式變更為 AWS_CRYPTOSDK_DECRYPT

解密字串

此範例的第二個部分會將包含原始字串之加密文字的加密訊息解密。

步驟 1:載入錯誤字串。

呼叫aws_cryptosdk_load_error_strings()方法,請參考 C 或 C ++ 代碼。它加載對調試非常有用的錯誤信息。

您只需調用一次,例如在main方法。

/* Load error strings for debugging */ aws_cryptosdk_load_error_strings();
步驟 2:建構 keyring。

在 AWS KMS 中解密資料時,您會傳入加密 API 傳回的加密的訊息。所以此解密 API不採用AWS KMS key作為輸入。相反地,AWS KMS 會使用相同的 AWS KMS key 來解密加密所用的加密文字。但是,AWS Encryption SDK可讓您指定AWS KMSkeyringAWS KMS keys的加密和解密。

在解密時,您可以設定讓 keyring 只具有您要用來解密已加密訊息的 AWS KMS keys。例如,您可能想要建立只具有組織中特定角色所使用 AWS KMS key 的 keyring。所以此AWS Encryption SDK將永遠不會使用AWS KMS key除非它出現在解密 Keyring 中。如果 SDK 無法使用您提供的 keyring 中的 AWS KMS keys 來解密加密的資料金鑰,可能是因為 keyring 中的任一個 AWS KMS keys 均未用來加密任何資料金鑰,或因為任何發起人沒有許可可使用 keyring 中的 AWS KMS keys 來解密,而造成解密呼叫失敗。

當您指定AWS KMS key的解密 Keyring,則必須使用其金鑰 ARN别名 ARN僅允許在加密 keyring 中。為了幫助識別AWS KMS keys在AWS KMSkeyring,請參在 AWS KMS 鑰匙圈 AWS KMS keys 中識別

在此範例中,我們會指定一個 keyring,其中設定了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:建立工作階段。

使用分配器和 keyring 來建立工作階段。若要設定用於解密的工作階段,請使用 AWS_CRYPTOSDK_DECRYPT 模式設定工作階段。

建立具有 keyring 的工作階段之後,您可以使用 SDK 提供的方法,將您的參考釋出給 keyring。工作階段會在其生命週期期間保留對 keyring 物件的參考,當您銷毀工作階段時,工作階段和 keyring 都會釋出。此參考計數技術有助於避免記憶體流失,並避免在使用物件時釋出物件。

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 SDK1.9 版本。x和 2.2.x,專為非流式加密和解密而設計。要處理流數據,請調用aws_cryptosdk_session_process在一個循環中。

解密時,加密文字欄位為輸入欄位,而純文字欄位為輸出欄位。ciphertext_input 欄位會保存加密方法傳回的加密的訊息。當處理完成時,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:驗證加密內容。

請確定實際加密內容(用來解密訊息的內容)包含加密訊息時您提供的加密內容。實際加密內容可能包含額外配對,因為密碼編譯資料管理員 (CMM) 可以在加密訊息之前,將配對新增到提供的加密內容。

在 適用於 C 的 AWS Encryption SDK 中,解密時您不需要提供加密內容,因為加密內容包含在 SDK 傳回的加密訊息中。但是,在它傳回純文字訊息之前,您的解密函數應該驗證提供的解密內容中的所有配對會出現在解密訊息所用的加密內容中。

首先,取得工作階段中雜湊表格的唯讀指標。此雜湊表格中包含解密訊息所用的加密內容。

const struct aws_hash_table *session_enc_ctx = aws_cryptosdk_session_get_enc_ctx_ptr(session);

然後循環回應您在加密時複製的 my_enc_ctx 雜湊表格中的加密內容。驗證用來解密的 my_enc_ctx 雜湊表格中的每個配對顯示在解密所用的 session_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);