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