1# Encryption and Decryption with an SM4 Symmetric Key (CBC Mode) (ArkTS)
2
3
4For details about the algorithm specifications, see [SM4](crypto-sym-encrypt-decrypt-spec.md#sm4).
5
6**Encryption**
7
8
91. 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 SM4 symmetric key (**SymKey**).
10   
11   In addition to the example in this topic, [SM4](crypto-sym-key-generation-conversion-spec.md#sm4) and [Randomly Generating a Symmetric Key](crypto-generate-sym-key-randomly.md) may help you better understand how to generate an SM4 symmetric key. Note that the input parameters in the reference documents may be different from those in the example below.
12
132. Use [cryptoFramework.createCipher](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#cryptoframeworkcreatecipher) with the string parameter **'SM4_128|CBC|PKCS7'** to create a **Cipher** instance. The key type is **SM4_128**, block cipher mode is **CBC**, and the padding mode is **PKCS7**.
14
153. 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 **IvParamsSpec** corresponding to the CBC mode.
16
174. Use [Cipher.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-1) to pass in the data to be encrypted (plaintext).
18   
19   - If a small amount of data is to be encrypted, you can use **Cipher.doFinal** immediately after **Cipher.init**.
20   - If a large amount of data is to be encrypted, you can call **Cipher.update** multiple times to pass in the data by segment.
21
225. Use [Cipher.doFinal](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#dofinal-1) to obtain the encrypted data.
23   
24   - If data has been passed in by **Cipher.update**, pass in **null** in the **data** parameter of **Cipher.doFinal**.
25   - The output of **Cipher.doFinal** may be **null**. To avoid exceptions, always check whether the result is **null** before accessing specific data.
26
27
28**Decryption**
29
30
311. 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 **IvParamsSpec** corresponding to the CBC mode.
32
332. Use [Cipher.update](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#update-1) to pass in the data to be decrypted (ciphertext).
34
353. Use [Cipher.doFinal](../../reference/apis-crypto-architecture-kit/js-apis-cryptoFramework.md#dofinal-1) to obtain the decrypted data.
36
37
38- Example (using asynchronous APIs):
39
40  ```ts
41  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
42  import { buffer } from '@kit.ArkTS';
43
44  function genIvParamsSpec() {
45    let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 16 bytes
46    let dataIv = new Uint8Array(arr);
47    let ivBlob: cryptoFramework.DataBlob = { data: dataIv };
48    let ivParamsSpec: cryptoFramework.IvParamsSpec = {
49      algName: "IvParamsSpec",
50      iv: ivBlob
51    };
52    return ivParamsSpec;
53  }
54  // Encrypt the message.
55  async function encryptMessagePromise(symKey: cryptoFramework.SymKey, plainText: cryptoFramework.DataBlob) {
56    let cipher = cryptoFramework.createCipher('SM4_128|CBC|PKCS7');
57    let iv = genIvParamsSpec();
58    await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, iv);
59    let encryptData = await cipher.doFinal(plainText);
60    return encryptData;
61  }
62  // Decrypt the message.
63  async function decryptMessagePromise(symKey: cryptoFramework.SymKey, cipherText: cryptoFramework.DataBlob) {
64    let decoder = cryptoFramework.createCipher('SM4_128|CBC|PKCS7');
65    let iv = genIvParamsSpec();
66    await decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, iv);
67    let decryptData = await decoder.doFinal(cipherText);
68    return decryptData;
69  }
70  async function genSymKeyByData(symKeyData: Uint8Array) {
71    let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData };
72    let symGenerator = cryptoFramework.createSymKeyGenerator('SM4_128');
73    let symKey = await symGenerator.convertKey(symKeyBlob);
74    console.info('convertKey success');
75    return symKey;
76  }
77  async function main() {
78    try {
79      let keyData = new Uint8Array([7, 154, 52, 176, 4, 236, 150, 43, 237, 9, 145, 166, 141, 174, 224, 131]);
80      let symKey = await genSymKeyByData(keyData);
81      let message = "This is a test";
82      let plainText: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(message, 'utf-8').buffer) };
83      let encryptText = await encryptMessagePromise(symKey, plainText);
84      let decryptText = await decryptMessagePromise(symKey, encryptText);
85      if (plainText.data.toString() === decryptText.data.toString()) {
86        console.info('decrypt ok');
87        console.info('decrypt plainText: ' + buffer.from(decryptText.data).toString('utf-8'));
88      } else {
89        console.error('decrypt failed');
90      }
91    } catch (error) {
92      console.error(`SM4 "${error}", error code: ${error.code}`);
93    }
94  }
95  ```
96
97- Example (using synchronous APIs):
98
99  ```ts
100  import { cryptoFramework } from '@kit.CryptoArchitectureKit';
101  import { buffer } from '@kit.ArkTS';
102
103  function genIvParamsSpec() {
104    let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 16 bytes
105    let dataIv = new Uint8Array(arr);
106    let ivBlob: cryptoFramework.DataBlob = { data: dataIv };
107    let ivParamsSpec: cryptoFramework.IvParamsSpec = {
108      algName: "IvParamsSpec",
109      iv: ivBlob
110    };
111    return ivParamsSpec;
112  }
113  // Encrypt the message.
114  function encryptMessage(symKey: cryptoFramework.SymKey, plainText: cryptoFramework.DataBlob) {
115    let cipher = cryptoFramework.createCipher('SM4_128|CBC|PKCS7');
116    let iv = genIvParamsSpec();
117    cipher.initSync(cryptoFramework.CryptoMode.ENCRYPT_MODE, symKey, iv);
118    let encryptData = cipher.doFinalSync(plainText);
119    return encryptData;
120  }
121  // Decrypt the message.
122  function decryptMessage(symKey: cryptoFramework.SymKey, cipherText: cryptoFramework.DataBlob) {
123    let decoder = cryptoFramework.createCipher('SM4_128|CBC|PKCS7');
124    let iv = genIvParamsSpec();
125    decoder.initSync(cryptoFramework.CryptoMode.DECRYPT_MODE, symKey, iv);
126    let decryptData = decoder.doFinalSync(cipherText);
127    return decryptData;
128  }
129  async function genSymKeyByData(symKeyData: Uint8Array) {
130    let symKeyBlob: cryptoFramework.DataBlob = { data: symKeyData };
131    let symGenerator = cryptoFramework.createSymKeyGenerator('SM4_128');
132    let symKey = symGenerator.convertKey(symKeyBlob);
133    console.info('convertKey success');
134    return symKey;
135  }
136  async function main() {
137    try {
138      let keyData = new Uint8Array([7, 154, 52, 176, 4, 236, 150, 43, 237, 9, 145, 166, 141, 174, 224, 131]);
139      let symKey = await genSymKeyByData(keyData);
140      let message = "This is a test";
141      let plainText: cryptoFramework.DataBlob = { data: new Uint8Array(buffer.from(message, 'utf-8').buffer) };
142      let encryptText = encryptMessage(symKey, plainText);
143      let decryptText = decryptMessage(symKey, encryptText);
144      if (plainText.data.toString() === decryptText.data.toString()) {
145        console.info('decrypt ok');
146        console.info('decrypt plainText: ' + buffer.from(decryptText.data).toString('utf-8'));
147      } else {
148        console.error('decrypt failed');
149      }
150    } catch (error) {
151      console.error(`SM4 "${error}", error code: ${error.code}`);
152    }
153  }
154  ```
155