1# Encryption and Decryption with an AES Symmetric Key (CCM Mode) (ArkTS) 2 3 4For details about the algorithm specifications, see [AES](crypto-sym-encrypt-decrypt-spec.md#aes). 5 6 7**Encryption** 8 9 101. Use [cryptoFramework.createSymKeyGenerator](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatesymkeygenerator) and [SymKeyGenerator.generateSymKey](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#generatesymkey-1) to generate a 128-bit AES symmetric key (**SymKey**). 11 12 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. 13 142. Use [cryptoFramework.createCipher](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatecipher) with the string parameter **'AES128|CCM'** to create a **Cipher** instance. The key type is AES128, and the block cipher mode is CCM. 15 163. Use [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 **CcmParamsSpec** corresponding to the CCM mode. 17 184. Use [Cipher.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-1) to pass in the data to be encrypted (plaintext). 19 20 Currently, the amount of data to be passed in by a single **Cipher.update** is not limited. You can determine how to pass in data based on the data volume. 21 22 The CCM mode does not support segment-based encryption and decryption. 23 245. Use [Cipher.doFinal](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#dofinal-1) to obtain the encrypted data. 25 - If data has been passed in by **Cipher.update**, pass in **null** in the **data** parameter of **Cipher.doFinal**. 26 - The output of **Cipher.doFinal** may be **null**. To avoid exceptions, always check whether the result is **null** before accessing specific data. 27 286. Obtain [CcmParamsSpec.authTag](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#ccmparamsspec) as the authentication information for decryption. 29 30 In CCM mode, extract the last 12 bytes from the encrypted data as the authentication information for initializing the **Cipher** instance in decryption. In the example, **authTag** is of 12 bytes. 31 32**Decryption** 33 34 351. Use [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 **CcmParamsSpec** corresponding to the CCM mode. 36 372. Use [Cipher.doFinal](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#dofinal-1) to obtain the decrypted data. 38 39 40- Example (using asynchronous APIs): 41 42 ```ts 43 import { cryptoFramework } from '@kit.CryptoArchitectureKit'; 44 import { buffer } from '@kit.ArkTS'; 45 46 function genCcmParamsSpec() { 47 let rand: cryptoFramework.Random = cryptoFramework.createRandom(); 48 let ivBlob: cryptoFramework.DataBlob = rand.generateRandomSync(7); 49 let aadBlob: cryptoFramework.DataBlob = rand.generateRandomSync(8); 50 let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 12 bytes 51 let dataTag = new Uint8Array(arr); 52 let tagBlob: cryptoFramework.DataBlob = { 53 data: dataTag 54 }; 55 // Obtain the CCM authTag from the Cipher.doFinal result in encryption and fill it in the params parameter of Cipher.init in decryption. 56 let ccmParamsSpec: cryptoFramework.CcmParamsSpec = { 57 iv: ivBlob, 58 aad: aadBlob, 59 authTag: tagBlob, 60 algName: "CcmParamsSpec" 61 }; 62 return ccmParamsSpec; 63 } 64 let ccmParams = genCcmParamsSpec(); 65 66 // Encrypt the message. 67 async function encryptMessagePromise(symKey: cryptoFramework.SymKey, plainText: cryptoFramework.DataBlob) { 68 let cipher = cryptoFramework.createCipher('AES128|CCM'); 69 await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, ccmParams); 70 let encryptUpdate = await cipher.update(plainText); 71 // In CCM mode, pass in null in Cipher.doFinal in encryption. Obtain the tag data and fill it in the ccmParams object. 72 ccmParams.authTag = await cipher.doFinal(null); 73 return encryptUpdate; 74 } 75 // Decrypt the message. 76 async function decryptMessagePromise(symKey: cryptoFramework.SymKey, cipherText: cryptoFramework.DataBlob) { 77 let decoder = cryptoFramework.createCipher('AES128|CCM'); 78 await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, ccmParams); 79 let decryptUpdate = await decoder.doFinal(cipherText); 80 return decryptUpdate; 81 } 82 async function genSymKeyByData(symKeyData: Uint8Array) { 83 let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData }; 84 let aesGenerator = cryptoFramework.createSymKeyGenerator('AES128'); 85 let symKey = await aesGenerator.convertKey(symKeyBlob); 86 console.info('convertKey success'); 87 return symKey; 88 } 89 async function main() { 90 let keyData = new Uint8Array([83, 217, 231, 76, 28, 113, 23, 219, 250, 71, 209, 210, 205, 97, 32, 159]); 91 let symKey = await genSymKeyByData(keyData); 92 let message = "This is a test"; 93 let plainText: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(message, 'utf-8').buffer) }; 94 let encryptText = await encryptMessagePromise(symKey, plainText); 95 let decryptText = await decryptMessagePromise(symKey, encryptText); 96 if (plainText.data.toString() === decryptText.data.toString()) { 97 console.info('decrypt ok'); 98 console.info('decrypt plainText: ' + buffer.from(decryptText.data).toString('utf-8')); 99 } else { 100 console.error('decrypt failed'); 101 } 102 } 103 ``` 104 105- Example (using synchronous APIs): 106 107 ```ts 108 import { cryptoFramework } from '@kit.CryptoArchitectureKit'; 109 import { buffer } from '@kit.ArkTS'; 110 111 112 function genCcmParamsSpec() { 113 let rand: cryptoFramework.Random = cryptoFramework.createRandom(); 114 let ivBlob: cryptoFramework.DataBlob = rand.generateRandomSync(7); 115 let aadBlob: cryptoFramework.DataBlob = rand.generateRandomSync(8); 116 let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 12 bytes 117 let dataTag = new Uint8Array(arr); 118 let tagBlob: cryptoFramework.DataBlob = { 119 data: dataTag 120 }; 121 // Obtain the CCM authTag from the Cipher.doFinal result in encryption and fill it in the params parameter of Cipher.init in decryption. 122 let ccmParamsSpec: cryptoFramework.CcmParamsSpec = { 123 iv: ivBlob, 124 aad: aadBlob, 125 authTag: tagBlob, 126 algName: "CcmParamsSpec" 127 }; 128 return ccmParamsSpec; 129 } 130 131 let ccmParams = genCcmParamsSpec(); 132 133 // Encrypt the message. 134 function encryptMessage(symKey: cryptoFramework.SymKey, plainText: cryptoFramework.DataBlob) { 135 let cipher = cryptoFramework.createCipher('AES128|CCM'); 136 cipher.initSync(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, ccmParams); 137 let encryptUpdate = cipher.updateSync(plainText); 138 // In CCM mode, pass in null in Cipher.doFinal in encryption. Obtain the tag data and fill it in the ccmParams object. 139 ccmParams.authTag = cipher.doFinalSync(null); 140 return encryptUpdate; 141 } 142 // Decrypt the message. 143 function decryptMessage(symKey: cryptoFramework.SymKey, cipherText: cryptoFramework.DataBlob) { 144 let decoder = cryptoFramework.createCipher('AES128|CCM'); 145 decoder.initSync(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, ccmParams); 146 let decryptUpdate = decoder.doFinalSync(cipherText); 147 return decryptUpdate; 148 } 149 async function genSymKeyByData(symKeyData: Uint8Array) { 150 let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData }; 151 let aesGenerator = cryptoFramework.createSymKeyGenerator('AES128'); 152 let symKey = await aesGenerator.convertKey(symKeyBlob); 153 console.info('convertKey success'); 154 return symKey; 155 } 156 async function main() { 157 let keyData = new Uint8Array([83, 217, 231, 76, 28, 113, 23, 219, 250, 71, 209, 210, 205, 97, 32, 159]); 158 let symKey = await genSymKeyByData(keyData); 159 let message = "This is a test"; 160 let plainText: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(message, 'utf-8').buffer) }; 161 let encryptText = encryptMessage(symKey, plainText); 162 let decryptText = decryptMessage(symKey, encryptText); 163 if (plainText.data.toString() === decryptText.data.toString()) { 164 console.info('decrypt ok'); 165 console.info('decrypt plainText: ' + buffer.from(decryptText.data).toString('utf-8')); 166 } else { 167 console.error('decrypt failed'); 168 } 169 } 170 ``` 171 172 173 174 175