• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Encryption and Decryption by Segment with an AES Symmetric Key (GCM Mode) (C/C++)
2
3
4For details about the algorithm specifications, see [AES](crypto-sym-encrypt-decrypt-spec.md#aes).
5
6
7## Adding the Dynamic Library in the CMake Script
8```txt
9target_link_libraries(entry PUBLIC libohcrypto.so)
10```
11
12## How to Develop
13
14**Creating an Object**
15
16Call [OH_CryptoSymKeyGenerator_Create](../../reference/apis-crypto-architecture-kit/_crypto_sym_key_api.md#oh_cryptosymkeygenerator_create) and [OH_CryptoSymKeyGenerator_Generate](../../reference/apis-crypto-architecture-kit/_crypto_sym_key_api.md#oh_cryptosymkeygenerator_generate) to generate a 128-bit AES symmetric key (**OH_CryptoSymKey**).
17
18   In addition to the example in this topic, [AES](crypto-sym-key-generation-conversion-spec.md#aes) and [Randomly Generating a Symmetric Key](crypto-generate-sym-key-randomly-ndk.md) may help you better understand how to generate an AES symmetric key. Note that the input parameters in the reference documents may be different from those in the example below.
19
20**Encrypting a Message**
21
221. Call [OH_CryptoSymCipher_Create](../../reference/apis-crypto-architecture-kit/_crypto_sym_cipher_api.md#oh_cryptosymcipher_create) with the string parameter **'AES128|GCM|PKCS7'** to create a **Cipher** instance for encryption. The key type is **AES128**, block cipher mode is **GCM**, and the padding mode is **PKCS7**.
23
242. Call [OH_CryptoSymCipherParams_Create](../../reference/apis-crypto-architecture-kit/_crypto_sym_cipher_api.md#oh_cryptosymcipherparams_create) to create a symmetric cipher parameter instance, and call [OH_CryptoSymCipherParams_SetParam](../../reference/apis-crypto-architecture-kit/_crypto_sym_cipher_api.md#oh_cryptosymcipherparams_setparam) to set cipher parameters.
25
263. Call [OH_CryptoSymCipher_Init](../../reference/apis-crypto-architecture-kit/_crypto_sym_cipher_api.md#oh_cryptosymcipher_init) to initialize the **Cipher** instance. Specifically, set **mode** to **CRYPTO_ENCRYPT_MODE**, and specify the key for encryption (**OH_CryptoSymKey**) and the encryption parameter instance (**OH_CryptoSymCipherParams**) corresponding to the GCM mode.
27
284. Set the size of the data to be passed in each time to 20 bytes, and call [OH_CryptoSymCipher_Update](../../reference/apis-crypto-architecture-kit/_crypto_sym_cipher_api.md#oh_cryptosymcipher_update) multiple times to pass in the data (plaintext) to be encrypted.
29
30   - Currently, the amount of data to be passed in by a single **OH_CryptoSymCipher_Update()** is not limited. You can determine how to pass in data based on the data volume.
31   - You are advised to check the result of each **OH_CryptoSymCipher_Update()**. If the result is not **null**, obtain the data and combine the data segments into complete ciphertext. The **OH_CryptoSymCipher_Update()** result may vary with the key specifications.
32
33      If a block cipher mode (ECB or CBC) is used, data is encrypted and output based on the block size. That is, if the data of an **OH_CryptoSymCipher_Update()** operation matches the block size, the ciphertext is output. Otherwise, **null** is output, and the plaintext will be combined with the input data of the next **OH_CryptoSymCipher_Update()** to form a block. When **OH_CryptoSymCipher_Final()** is called, the unencrypted data is padded to the block size based on the specified padding mode, and then encrypted. The **OH_CryptoSymCipher_Update()** API works in the same way in decryption.
34
35      If a stream cipher mode (CTR or OFB) is used, the ciphertext length is usually the same as the plaintext length.
36
376. Call [OH_CryptoSymCipher_Final](../../reference/apis-crypto-architecture-kit/_crypto_sym_cipher_api.md#oh_cryptosymcipher_final) to generate the ciphertext.
38
39   - If data has been passed in by **OH_CryptoSymCipher_Update()**, pass in **null** in the **data** parameter of **OH_CryptoSymCipher_Final**.
40   - The output of **OH_CryptoSymCipher_Final** may be **null**. To avoid exceptions, always check whether the result is **null** before accessing specific data.
41   > **NOTE**<br>
42   > If GCM mode is used, **authTag** returned by **OH_CryptoSymCipher_Final()** will be used to initialize the authentication information during decryption and needs to be saved.
43   > In GCM mode, **authTag** must be of 16 bytes. It is used as the authentication information during decryption. In the example, **authTag** is of 16 bytes.
44
45
46**Decrypting a Message**
47
481. Call [OH_CryptoSymCipher_Create](../../reference/apis-crypto-architecture-kit/_crypto_sym_cipher_api.md#oh_cryptosymcipher_create) with the string parameter **'AES128|GCM|PKCS7'** to create a **Cipher** instance for decryption. The key type is **AES128**, block cipher mode is **GCM**, and the padding mode is **PKCS7**.
49
502. Call [OH_CryptoSymCipherParams_SetParam](../../reference/apis-crypto-architecture-kit/_crypto_sym_cipher_api.md#oh_cryptosymcipherparams_setparam) to set **authTag** as the authentication information for decryption.
51
52   In GCM mode, extract the last 16 bytes from the encrypted data as the authentication information for initializing the **Cipher** instance in decryption. In the example, **authTag** is of 16 bytes.
53
543. Call [OH_CryptoSymCipher_Init](../../reference/apis-crypto-architecture-kit/_crypto_sym_cipher_api.md#oh_cryptosymcipher_init) to initialize the **Cipher** instance. Specifically, set **mode** to **CRYPTO_DECRYPT_MODE**, and specify the key for decryption (**OH_CryptoSymKey**) and the decryption parameter instance (**OH_CryptoSymCipherParams**) corresponding to the GCM mode.
55
564. Set the size of the data to be passed in each time to 20 bytes, and call [OH_CryptoSymCipher_Update](../../reference/apis-crypto-architecture-kit/_crypto_sym_cipher_api.md#oh_cryptosymcipher_update) multiple times to pass in the data (ciphertext) to be decrypted.
57
585. Call [OH_CryptoSymCipher_Final](../../reference/apis-crypto-architecture-kit/_crypto_sym_cipher_api.md#oh_cryptosymcipher_final) to generate the plaintext.
59
60**Destroying Objects**
61
62Call [OH_CryptoSymKeyGenerator_Destroy](../../reference/apis-crypto-architecture-kit/_crypto_sym_key_api.md#oh_cryptosymkeygenerator_destroy), [OH_CryptoSymCipher_Destroy](../../reference/apis-crypto-architecture-kit/_crypto_sym_cipher_api.md#oh_cryptosymcipher_destroy), and [OH_CryptoSymCipherParams_Destroy](../../reference/apis-crypto-architecture-kit/_crypto_sym_cipher_api.md#oh_cryptosymcipherparams_destroy) to destroy the instances created.
63
64
65**Example**
66
67```c++
68#include <string.h>
69#include "CryptoArchitectureKit/crypto_common.h"
70#include "CryptoArchitectureKit/crypto_sym_cipher.h"
71
72#define OH_CRYPTO_GCM_TAG_LEN 16
73#define OH_CRYPTO_MAX_TEST_DATA_LEN 128
74static OH_Crypto_ErrCode doTestAesGcmSeg()
75{
76    OH_CryptoSymKeyGenerator *genCtx = nullptr;
77    OH_CryptoSymCipher *encCtx = nullptr;
78    OH_CryptoSymCipher *decCtx = nullptr;
79    OH_CryptoSymKey *keyCtx = nullptr;
80    OH_CryptoSymCipherParams *params = nullptr;
81
82    char *plainText = const_cast<char *>("aaaaa.....bbbbb.....ccccc.....ddddd.....eee");
83    Crypto_DataBlob msgBlob = {.data = (uint8_t *)(plainText), .len = strlen(plainText)};
84
85    uint8_t aad[8] = {1, 2, 3, 4, 5, 6, 7, 8};
86    uint8_t tagArr[16] = {0};
87    uint8_t iv[12] = {1, 2, 4, 12, 3, 4, 2, 3, 3, 2, 0, 4}; // iv is generated from an array of secure random numbers.
88    Crypto_DataBlob tag = {.data = nullptr, .len = 0};
89    Crypto_DataBlob ivBlob = {.data = iv, .len = sizeof(iv)};
90    Crypto_DataBlob aadBlob = {.data = aad, .len = sizeof(aad)};
91    Crypto_DataBlob encData = {.data = nullptr, .len = 0};
92    Crypto_DataBlob decData = {.data = nullptr, .len = 0};
93    Crypto_DataBlob tagInit = {.data = tagArr, .len = sizeof(tagArr)};
94    int32_t cipherLen = 0;
95    int blockSize = 20;
96    int32_t randomLen = strlen(plainText);
97    Crypto_DataBlob cipherBlob;
98    // Define the encryption variables.
99    int cnt = randomLen / blockSize;
100    int rem = randomLen % blockSize;
101    uint8_t cipherText[OH_CRYPTO_MAX_TEST_DATA_LEN] = {0};
102
103    // Define the decryption variables.
104    int decCnt = cipherLen / blockSize;
105    int decRem = cipherLen % blockSize;
106    int32_t plantLen = 0;
107    uint8_t plantText[OH_CRYPTO_MAX_TEST_DATA_LEN] = {0};
108
109    // Generate a key.
110    OH_Crypto_ErrCode ret;
111    ret = OH_CryptoSymKeyGenerator_Create("AES128", &genCtx);
112    if (ret != CRYPTO_SUCCESS) {
113        goto end;
114    }
115    ret = OH_CryptoSymKeyGenerator_Generate(genCtx, &keyCtx);
116    if (ret != CRYPTO_SUCCESS) {
117        goto end;
118    }
119
120    // Set parameters.
121    ret = OH_CryptoSymCipherParams_Create(&params);
122    if (ret != CRYPTO_SUCCESS) {
123        goto end;
124    }
125    ret = OH_CryptoSymCipherParams_SetParam(params, CRYPTO_IV_DATABLOB, &ivBlob);
126    if (ret != CRYPTO_SUCCESS) {
127        goto end;
128    }
129    ret = OH_CryptoSymCipherParams_SetParam(params, CRYPTO_AAD_DATABLOB, &aadBlob);
130    if (ret != CRYPTO_SUCCESS) {
131        goto end;
132    }
133    ret = OH_CryptoSymCipherParams_SetParam(params, CRYPTO_TAG_DATABLOB, &tagInit);
134    if (ret != CRYPTO_SUCCESS) {
135        goto end;
136    }
137
138    // Encrypt data.
139    ret = OH_CryptoSymCipher_Create("AES128|GCM|PKCS7", &encCtx);
140    if (ret != CRYPTO_SUCCESS) {
141        goto end;
142    }
143    ret = OH_CryptoSymCipher_Init(encCtx, CRYPTO_ENCRYPT_MODE, keyCtx, params);
144    if (ret != CRYPTO_SUCCESS) {
145        goto end;
146    }
147
148    for (int i = 0; i < cnt; i++) {
149        msgBlob.len = blockSize;
150        ret = OH_CryptoSymCipher_Update(encCtx, &msgBlob, &encData);
151        if (ret != CRYPTO_SUCCESS) {
152            goto end;
153        }
154        msgBlob.data += blockSize;
155        memcpy(&cipherText[cipherLen], encData.data, encData.len);
156        cipherLen += encData.len;
157    }
158    if (rem > 0) {
159        msgBlob.len = rem;
160        ret = OH_CryptoSymCipher_Update(encCtx, (Crypto_DataBlob *)&msgBlob, &encData);
161        if (ret != CRYPTO_SUCCESS) {
162            goto end;
163        }
164        memcpy(&cipherText[cipherLen], encData.data, encData.len);
165        cipherLen += encData.len;
166    }
167    ret = OH_CryptoSymCipher_Final(encCtx, nullptr, &tag);
168    if (ret != CRYPTO_SUCCESS) {
169        goto end;
170    }
171
172    // Decrypt data.
173    cipherBlob = {.data = reinterpret_cast<uint8_t *>(cipherText), .len = (size_t)cipherLen};
174    ret = OH_CryptoSymCipher_Create("AES128|GCM|PKCS7", &decCtx);
175    if (ret != CRYPTO_SUCCESS) {
176        goto end;
177    }
178    ret = OH_CryptoSymCipherParams_SetParam(params, CRYPTO_TAG_DATABLOB, &tag);
179    if (ret != CRYPTO_SUCCESS) {
180        goto end;
181    }
182    ret = OH_CryptoSymCipher_Init(decCtx, CRYPTO_DECRYPT_MODE, keyCtx, params);
183    if (ret != CRYPTO_SUCCESS) {
184        goto end;
185    }
186    for (int i = 0; i < decCnt; i++) {
187        cipherBlob.len = blockSize;
188        ret = OH_CryptoSymCipher_Update(decCtx, &cipherBlob, &decData);
189        if (ret != CRYPTO_SUCCESS) {
190            goto end;
191        }
192        cipherBlob.data += blockSize;
193        memcpy(&plantText[plantLen], decData.data, decData.len);
194        plantLen += decData.len;
195    }
196    if (decRem > 0) {
197        cipherBlob.len = decRem;
198        ret = OH_CryptoSymCipher_Update(decCtx, &cipherBlob, &decData);
199        if (ret != CRYPTO_SUCCESS) {
200            goto end;
201        }
202        memcpy(&plantText[plantLen], decData.data, decData.len);
203        plantLen += decData.len;
204    }
205    ret = OH_CryptoSymCipher_Final(decCtx, nullptr, &decData);
206    if (ret != CRYPTO_SUCCESS) {
207        goto end;
208    }
209
210end:
211    OH_CryptoSymCipherParams_Destroy(params);
212    OH_CryptoSymCipher_Destroy(encCtx);
213    OH_CryptoSymCipher_Destroy(decCtx);
214    OH_CryptoSymKeyGenerator_Destroy(genCtx);
215    OH_CryptoSymKey_Destroy(keyCtx);
216    OH_Crypto_FreeDataBlob(&encData);
217    OH_Crypto_FreeDataBlob(&tag);
218    OH_Crypto_FreeDataBlob(&decData);
219    return ret;
220}
221```
222