• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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