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