• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Encryption and Decryption with an AES Symmetric Key (GCM Mode) (ArkTS)
2
3<!--Kit: Crypto Architecture Kit-->
4<!--Subsystem: Security-->
5<!--Owner: @zxz--3-->
6<!--Designer: @lanming-->
7<!--Tester: @PAFT-->
8<!--Adviser: @zengyawen-->
9
10For details about the algorithm specifications, see [AES](crypto-sym-encrypt-decrypt-spec.md#aes).
11
12**Encryption**
13
141. Call [cryptoFramework.createSymKeyGenerator](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatesymkeygenerator) to generate a symmetric key (**SymKey**) with the key algorithm being AES and the key length being 128 bits. Then, call [SymKeyGenerator.generateSymKey](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#generatesymkey-1) to generate a symmetric key.
15
16   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.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.
17
182. Call [cryptoFramework.createCipher](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatecipher) 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**.
19
203. Call [Cipher.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-1) to initialize the **Cipher** instance. In the **Cipher.init** API, set **opMode** to **CryptoMode.ENCRYPT_MODE** (encryption), **key** to **SymKey** (the key for encryption), and **params** to **GcmParamsSpec** corresponding to the GCM mode.
21
224. Call [Cipher.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-1) to pass in the data to be encrypted (plaintext).
23
24   Currently, there is no length limit for a single update. You can call **Cipher.update** based on the data volume.
25
26   - If a small amount of data is to be encrypted, you can use **Cipher.doFinal** immediately after **Cipher.init**.
27   - If a large amount of data is to be encrypted, you can call **Cipher.update** multiple times to [pass in the data by segment](crypto-aes-sym-encrypt-decrypt-gcm-by-segment.md).
28
295. Call [Cipher.doFinal](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#dofinal-1) to obtain the encrypted data. Note that if data has been passed in by **Cipher.update**, pass in **null** in the **data** parameter of **Cipher.doFinal**. The output of **Cipher.doFinal** may be **null**. To avoid exceptions, always check whether the result is **null** before accessing specific data.
30   - If data has been passed in by **Cipher.update**, pass in **null** in the **data** parameter of **Cipher.doFinal**.
31   - The output of **doFinal** may be **null**. Check the result before accessing the data.
32
336. Obtain [GcmParamsSpec](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#gcmparamsspec).authTag as the authentication information for decryption.
34   In GCM mode, the algorithm library supports only 16-byte **authTag**, which is used for initialization authentication during decryption. In the following example, **authTag** is of 16 bytes.
35
36**Decryption**
37
381. Call [cryptoFramework.createCipher](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatecipher) 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**.
39
402. Call [Cipher.init](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#init-1) to initialize the **Cipher** instance. In the **Cipher.init** API, set **opMode** to **CryptoMode.DECRYPT_MODE** (decryption), **key** to **SymKey** (the key for decryption), and **params** to **GcmParamsSpec** corresponding to the GCM mode.
41
423. Call [Cipher.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-1) to pass in the data to be decrypted (ciphertext).
43
444. Call [Cipher.doFinal](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#dofinal-1) to obtain the decrypted data.
45
46- Example (using asynchronous APIs):
47
48  ```ts
49  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
50  import { buffer } from '@kit.ArkTS';
51
52  function generateRandom(len: number) {
53    let rand = cryptoFramework.createRandom();
54    let generateRandSync = rand.generateRandomSync(len);
55    return generateRandSync;
56  }
57
58  function genGcmParamsSpec() {
59    let ivBlob = generateRandom(12);
60    let arr = [1, 2, 3, 4, 5, 6, 7, 8]; // 8 bytes
61    let dataAad = new Uint8Array(arr); // Convert the arr array to a Uint8Array.
62    let aadBlob: cryptoFramework.DataBlob = { data: dataAad }; // Create a DataBlob object.
63    arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 16 bytes
64    let dataTag = new Uint8Array(arr); // Convert the arr array to a Uint8Array.
65    let tagBlob: cryptoFramework.DataBlob = {
66      data: dataTag
67    };
68    // Obtain the GCM authTag from the Cipher.doFinal result in encryption and fill it in the params parameter of Cipher.init in decryption.
69    let gcmParamsSpec: cryptoFramework.GcmParamsSpec = {
70      iv: ivBlob,
71      aad: aadBlob,
72      authTag: tagBlob,
73      algName: "GcmParamsSpec"
74    };
75    return gcmParamsSpec;
76  }
77
78  let gcmParams = genGcmParamsSpec();
79
80  // Encrypt the message.
81  async function encryptMessagePromise(symKey: cryptoFramework.SymKey, plainText: cryptoFramework.DataBlob) {
82    let cipher = cryptoFramework.createCipher('AES128|GCM|PKCS7');
83    await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, gcmParams);
84    let encryptUpdate = await cipher.update(plainText);
85    // In GCM mode, pass in null in Cipher.doFinal in encryption. Obtain the tag data and fill it in the gcmParams object.
86    gcmParams.authTag = await cipher.doFinal(null);
87    return encryptUpdate;
88  }
89  // Decrypt the message.
90  async function decryptMessagePromise(symKey: cryptoFramework.SymKey, cipherText: cryptoFramework.DataBlob) {
91    let decoder = cryptoFramework.createCipher('AES128|GCM|PKCS7');
92    await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, gcmParams);
93    let decryptUpdate = await decoder.update(cipherText);
94    // In GCM mode, pass in null in Cipher.doFinal in decryption. Verify the tag data passed in Cipher.init. If the verification fails, an exception will be thrown.
95    let decryptData = await decoder.doFinal(null);
96    if (decryptData === null) {
97      console.info('GCM decrypt success, decryptData is null');
98    }
99    return decryptUpdate;
100  }
101  async function genSymKeyByData(symKeyData: Uint8Array) {
102    let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData };
103    let aesGenerator = cryptoFramework.createSymKeyGenerator('AES128');
104    let symKey = await aesGenerator.convertKey(symKeyBlob);
105    console.info('convertKey success');
106    return symKey;
107  }
108  async function main() {
109    let keyData = new Uint8Array([83, 217, 231, 76, 28, 113, 23, 219, 250, 71, 209, 210, 205, 97, 32, 159]); // Create a Uint8Array object.
110    let symKey = await genSymKeyByData(keyData);
111    let message = "This is a test";
112    let plainText: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(message, 'utf-8').buffer) }; // Create a DataBlob object.
113    let encryptText = await encryptMessagePromise(symKey, plainText);
114    let decryptText = await decryptMessagePromise(symKey, encryptText);
115    if (plainText.data.toString() === decryptText.data.toString()) {
116      console.info('decrypt ok');
117      console.info('decrypt plainText: ' + buffer.from(decryptText.data).toString('utf-8'));
118    } else {
119      console.error('decrypt failed');
120    }
121  }
122  ```
123
124- Example (using synchronous APIs):
125
126  ```ts
127  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
128  import { buffer } from '@kit.ArkTS';
129
130  function generateRandom(len: number) {
131    let rand = cryptoFramework.createRandom();
132    let generateRandSync = rand.generateRandomSync(len);
133    return generateRandSync;
134  }
135
136  function genGcmParamsSpec() {
137    let ivBlob = generateRandom(12);
138    let arr = [1, 2, 3, 4, 5, 6, 7, 8]; // 8 bytes
139    let dataAad = new Uint8Array(arr); // Convert the arr array to a Uint8Array.
140    let aadBlob: cryptoFramework.DataBlob = { data: dataAad }; // Create a DataBlob object.
141    arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 16 bytes
142    let dataTag = new Uint8Array(arr); // Convert the arr array to a Uint8Array.
143    let tagBlob: cryptoFramework.DataBlob = {
144      data: dataTag
145    };
146    // Obtain the GCM authTag from the Cipher.doFinal result in encryption and fill it in the params parameter of Cipher.init in decryption.
147    let gcmParamsSpec: cryptoFramework.GcmParamsSpec = {
148      iv: ivBlob,
149      aad: aadBlob,
150      authTag: tagBlob,
151      algName: "GcmParamsSpec"
152    };
153    return gcmParamsSpec;
154  }
155
156  let gcmParams = genGcmParamsSpec();
157
158  // Encrypt the message.
159  function encryptMessage(symKey: cryptoFramework.SymKey, plainText: cryptoFramework.DataBlob) {
160    let cipher = cryptoFramework.createCipher('AES128|GCM|PKCS7');
161    cipher.initSync(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, gcmParams);
162    let encryptUpdate = cipher.updateSync(plainText);
163    // In GCM mode, pass in null in Cipher.doFinal in encryption. Obtain the tag data and fill it in the gcmParams object.
164    gcmParams.authTag = cipher.doFinalSync(null);
165    return encryptUpdate;
166  }
167  // Decrypt the message.
168  function decryptMessage(symKey: cryptoFramework.SymKey, cipherText: cryptoFramework.DataBlob) {
169    let decoder = cryptoFramework.createCipher('AES128|GCM|PKCS7');
170    decoder.initSync(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, gcmParams);
171    let decryptUpdate = decoder.updateSync(cipherText);
172    // In GCM mode, pass in null in Cipher.doFinal in decryption. Verify the tag data passed in Cipher.init. If the verification fails, an exception will be thrown.
173    let decryptData = decoder.doFinalSync(null);
174    if (decryptData === null) {
175      console.info('GCM decrypt success, decryptData is null');
176    }
177    return decryptUpdate;
178  }
179  function genSymKeyByData(symKeyData: Uint8Array) {
180    let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData };
181    let aesGenerator = cryptoFramework.createSymKeyGenerator('AES128');
182    let symKey = aesGenerator.convertKeySync(symKeyBlob);
183    console.info('convertKeySync success');
184    return symKey;
185  }
186  function main() {
187    let keyData = new Uint8Array([83, 217, 231, 76, 28, 113, 23, 219, 250, 71, 209, 210, 205, 97, 32, 159]); // Create a Uint8Array object.
188    let symKey = genSymKeyByData(keyData);
189    let message = "This is a test";
190    let plainText: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(message, 'utf-8').buffer) }; // Create a DataBlob object.
191    let encryptText = encryptMessage(symKey, plainText);
192    let decryptText = decryptMessage(symKey, encryptText);
193    if (plainText.data.toString() === decryptText.data.toString()) {
194      console.info('decrypt ok');
195      console.info('decrypt plainText: ' + buffer.from(decryptText.data).toString('utf-8'));
196    } else {
197      console.error('decrypt failed');
198    }
199  }
200  ```
201