• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 加解密算法库框架开发指导
2
3> **说明:**
4>
5> 本开发指导需使用API version 9及以上版本SDK,仅适用于JS语言开发。
6
7## 密钥对象生成与转换操作
8
9### 场景说明
10
11使用密钥生成操作中,典型的场景有:
12
131. 随机生成算法库密钥对象。该对象可用于后续的加解密等操作。
142. 根据密钥参数生成指定的算法库密钥对象。该对象可用于后续的加解密等操作。
153. 根据指定数据生成算法库密钥对象(也就是将外部或存储的二进制数据转换为算法库的密钥对象)。该对象可用于后续的加解密等操作。
164. 获取算法库密钥对象的二进制数据,用于存储或传输。
175. 对于非对称密钥,获取密钥对象的参数属性,用于存储或运输。
18
19> **说明:**
20>
21> 密钥对象Key包括对称密钥SymKey和非对称密钥(公钥PubKey和私钥PriKey),其中公钥和私钥组成密钥对KeyPair。密钥之间的具体关系可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。
22
23### 接口及参数说明
24
25详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。
26
27以上场景涉及的常用接口如下表所示:
28
29|实例名|接口名|描述|
30|---|---|---|
31|cryptoFramework|createAsyKeyGenerator(algName : string) : AsyKeyGenerator|根据algName设置的非对称密钥规格,创建非对称密钥生成器对象|
32|cryptoFramework|createAsyKeyGeneratorBySpec(asyKeySpec: AsyKeySpec): AsyKeyGeneratorBySpec;|根据密钥参数设置的非对称密钥规格,创建非对称密钥生成器对象|
33|cryptoFramework|createSymKeyGenerator(algName : string) : SymKeyGenerator|根据algName设置的对称密钥规格,创建对称密钥生成器对象|
34|AsyKeyGenerator|generateKeyPair(callback : AsyncCallback\<KeyPair>) : void|使用callback方式,随机生成非对称密钥对象KeyPair|
35|AsyKeyGenerator|generateKeyPair() : Promise\<KeyPair>|使用Promise方式,随机生成非对称密钥对象KeyPair|
36|SymKeyGenerator|generateSymKey(callback : AsyncCallback\<SymKey>) : void|使用callback方式,随机生成对称密钥对象SymKey|
37|SymKeyGenerator|generateSymKey() : Promise\<SymKey>|使用Promise方式,随机生成对称密钥对象SymKey|
38| AsyKeyGenerator          | convertKey(pubKey : DataBlob, priKey : DataBlob, callback : AsyncCallback\<KeyPair>) : void | 使用callback方式,根据指定的公钥和私钥二进制数据生成KeyPair对象<br/>(允许公钥/私钥为null,即只传入单一公钥或私钥,生成只携带公钥或私钥的KeyPair对象) |
39| AsyKeyGenerator          | convertKey(pubKey : DataBlob, priKey : DataBlob) : Promise\<KeyPair> | 使用Promise方式,根据指定的公钥和私钥二进制数据生成KeyPair对象<br/>(允许公钥/私钥为null,即只传入单一公钥或私钥,生成只携带公钥或私钥的KeyPair对象) |
40| SymKeyGenerator         | convertKey(key : DataBlob, callback : AsyncCallback\<SymKey>) : void| 使用callback方式,根据指定的二进制数据,生成对称密钥对象SymKey |
41| SymKeyGenerator         |convertKey(pubKey : DataBlob, priKey : DataBlob) : Promise\<KeyPair>| 使用Promise方式,根据指定的二进制数据,生成对称密钥对象SymKey |
42| Key | getEncoded() : DataBlob;  | 获取Key密钥对象的二进制数据(Key的子类实例包括对称密钥SymKey、公钥PubKey、私钥PriKey) |
43
44### 随机生成RSA密钥对,并获得二进制数据
45
46示例1:随机生成非对称密钥KeyPair,并获得二进制数据(场景1、3)
47
481. 创建非对称密钥生成器。
492. 通过非对称密钥生成器随机生成非对称密钥。
503. 获取密钥对象的二进制数据。
51
52以使用Promise方式随机生成RSA密钥(1024位,素数个数为2)为例:
53
54```ts
55import cryptoFramework from '@ohos.security.cryptoFramework';
56import { BusinessError } from '@ohos.base';
57
58function generateAsyKey() {
59  // Create an AsyKeyGenerator instance.
60  let rsaGenerator = cryptoFramework.createAsyKeyGenerator('RSA1024|PRIMES_2');
61  // Use the key generator to randomly generate an asymmetric key pair.
62  let keyGenPromise = rsaGenerator.generateKeyPair();
63  keyGenPromise.then(keyPair => {
64    let pubKey = keyPair.pubKey;
65    let priKey = keyPair.priKey;
66    // Obtain the binary data of the asymmetric key pair.
67    let pkBlob = pubKey.getEncoded();
68    let skBlob = priKey.getEncoded();
69    AlertDialog.show({ message: 'pk bin data' + pkBlob.data });
70    AlertDialog.show({ message: 'sk bin data' + skBlob.data });
71  })
72}
73```
74
75### 随机生成AES密钥,并获得二进制数据
76
77示例2:随机生成对称密钥SymKey,并获得二进制数据(场景1、3)
78
791. 创建对称密钥生成器。
802. 通过对称密钥生成器随机生成对称密钥。
813. 获取算法库密钥对象的二进制数据。
82
83以使用Promise方式随机生成AES密钥(256位)为例:
84
85```ts
86import cryptoFramework from '@ohos.security.cryptoFramework';
87import { BusinessError } from '@ohos.base';
88
89function testGenerateAesKey() {
90  // Create a SymKeyGenerator instance.
91  let symKeyGenerator = cryptoFramework.createSymKeyGenerator('AES256');
92  // Use the key generator to randomly generate a symmetric key.
93  let promiseSymKey = symKeyGenerator.generateSymKey();
94  promiseSymKey.then(key => {
95    // Obtain the binary data of the symmetric key and output the 256-bit key. The length is 32 bytes.
96    let encodedKey = key.getEncoded();
97    console.info('key hex:' + encodedKey.data);
98  })
99}
100```
101
102### 根据RSA密钥二进制数据,生成密钥对
103
104示例3:根据指定的RSA非对称密钥二进制数据,生成KeyPair对象(场景2)
105
1061. 获取RSA公钥或私钥二进制数据,公钥需满足ASN.1语法、X.509规范、DER编码格式,私钥需满足ASN.1语法、PKCS#8规范、DER编码格式。
1072. 创建AsyKeyGenerator对象,调用convertKey方法,传入公钥二进制和私钥二进制(二者非必选项,可只传入其中一个),转换为KeyPair对象。
108
109```ts
110import cryptoFramework from '@ohos.security.cryptoFramework';
111import { BusinessError } from '@ohos.base';
112
113function convertAsyKey() {
114  let rsaGenerator = cryptoFramework.createAsyKeyGenerator('RSA1024');
115  let pkVal = new Uint8Array([48, 129, 159, 48, 13, 6, 9, 42, 134, 72, 134, 247, 13, 1, 1, 1, 5, 0, 3, 129, 141, 0, 48, 129, 137, 2, 129, 129, 0, 174, 203, 113, 83, 113, 3, 143, 213, 194, 79, 91, 9, 51, 142, 87, 45, 97, 65, 136, 24, 166, 35, 5, 179, 42, 47, 212, 79, 111, 74, 134, 120, 73, 67, 21, 19, 235, 80, 46, 152, 209, 133, 232, 87, 192, 140, 18, 206, 27, 106, 106, 169, 106, 46, 135, 111, 118, 32, 129, 27, 89, 255, 183, 116, 247, 38, 12, 7, 238, 77, 151, 167, 6, 102, 153, 126, 66, 28, 253, 253, 216, 64, 20, 138, 117, 72, 15, 216, 178, 37, 208, 179, 63, 204, 39, 94, 244, 170, 48, 190, 21, 11, 73, 169, 156, 104, 193, 3, 17, 100, 28, 60, 50, 92, 235, 218, 57, 73, 119, 19, 101, 164, 192, 161, 197, 106, 105, 73, 2, 3, 1, 0, 1]);
116  let pkBlob: cryptoFramework.DataBlob = { data: pkVal };
117  rsaGenerator.convertKey(pkBlob, null, (err, keyPair) => {
118    if (err) {
119      AlertDialog.show({ message: 'Convert keyPair fail' });
120      return;
121    }
122    AlertDialog.show({ message: 'Convert keyPair success' });
123  })
124}
125```
126
127> **说明:**
128>
129> 当前convertKey操作,公钥只支持转换满足X.509规范的DER格式,私钥只支持PKCS#8规范的DER格式。
130
131### 根据ECC密钥二进制数据,生成密钥对
132
133示例4:根据指定的ECC非对称密钥二进制数据,生成KeyPair对象(场景2、3)
134
1351. 获取ECC二进制密钥数据,封装成DataBlob对象。
1362. 调用convertKey方法,传入公钥二进制和私钥二进制(二者非必选项,可只传入其中一个),转换为KeyPair对象。
137
138```ts
139import cryptoFramework from '@ohos.security.cryptoFramework';
140import { BusinessError } from '@ohos.base';
141
142function convertEccAsyKey() {
143  let pubKeyArray = new Uint8Array([48, 89, 48, 19, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 8, 42, 134, 72, 206, 61, 3, 1, 7, 3, 66, 0, 4, 83, 96, 142, 9, 86, 214, 126, 106, 247, 233, 92, 125, 4, 128, 138, 105, 246, 162, 215, 71, 81, 58, 202, 121, 26, 105, 211, 55, 130, 45, 236, 143, 55, 16, 248, 75, 167, 160, 167, 106, 2, 152, 243, 44, 68, 66, 0, 167, 99, 92, 235, 215, 159, 239, 28, 106, 124, 171, 34, 145, 124, 174, 57, 92]);
144  let priKeyArray = new Uint8Array([48, 49, 2, 1, 1, 4, 32, 115, 56, 137, 35, 207, 0, 60, 191, 90, 61, 136, 105, 210, 16, 27, 4, 171, 57, 10, 61, 123, 40, 189, 28, 34, 207, 236, 22, 45, 223, 10, 189, 160, 10, 6, 8, 42, 134, 72, 206, 61, 3, 1, 7]);
145  let pubKeyBlob: cryptoFramework.DataBlob = { data: pubKeyArray };
146  let priKeyBlob: cryptoFramework.DataBlob = { data: priKeyArray };
147  let generator = cryptoFramework.createAsyKeyGenerator('ECC256');
148  generator.convertKey(pubKeyBlob, priKeyBlob, (error, data) => {
149    if (error) {
150      AlertDialog.show({ message: 'Convert keyPair fail' });
151      return;
152    }
153    AlertDialog.show({ message: 'Convert keyPair success' });
154  })
155}
156```
157
158### 根据3DES密钥二进制数据,生成密钥
159
160示例5:根据指定的对称密钥二进制数据,生成SymKey对象(场景2、3)
161
1621. 创建对称密钥生成器。
1632. 通过对称密钥生成器,根据指定的对称密钥二进制数据,生成SymKey对象。
1643. 获取算法库密钥对象的二进制数据。
165
166以使用callback方式生成3DES密钥(3DES密钥只能为192位)为例:
167
168```ts
169import cryptoFramework from '@ohos.security.cryptoFramework';
170import { BusinessError } from '@ohos.base';
171
172function genKeyMaterialBlob(): cryptoFramework.DataBlob {
173  let arr = [
174    0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56,
175    0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c,
176    0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72]; // keyLen = 192 (24 bytes)
177  let keyMaterial = new Uint8Array(arr);
178  return { data: keyMaterial };
179}
180
181function testConvertSymKey() {
182  // Create a SymKeyGenerator instance.
183  let symKeyGenerator = cryptoFramework.createSymKeyGenerator('3DES192');
184  // Generate a symmetric key based on the specified data.
185  let keyMaterialBlob = genKeyMaterialBlob();
186  try {
187    symKeyGenerator.convertKey(keyMaterialBlob, (error, key) => {
188      if (error) { // If the service logic fails to be executed, the first parameter of callback returns error information, that is, an exception is thrown asynchronously.
189        let e: BusinessError = error as BusinessError;
190        console.error(`convertKey error, ${e.code}, ${e.message}`);
191        return;
192      }
193      console.info(`key algName: ${key.algName}`);
194      console.info(`key format: ${key.format}`);
195      let encodedKey = key.getEncoded(); // Obtain the binary data of the symmetric key and output in bytes array. The length is 24 bytes.
196      console.info('key getEncoded hex: ' + encodedKey.data);
197    })
198  } catch (error) { // Throw an exception immediately when an error is detected in parameter check.
199    let e: BusinessError = error as BusinessError;
200    console.error(`convertKey failed, ${e.code}, ${e.message}`);
201    return;
202  }
203}
204```
205
206### 随机生成SM2密钥对,并获得二进制数据
207
208> **说明:**
209>
210> 从API version 10开始, 支持SM2非对称密钥随机生成。
211
212示例6:随机生成非对称密钥KeyPair,并获得二进制数据(场景1、3)
213
2141. 创建非对称密钥生成器。
2152. 通过非对称密钥生成器随机生成非对称密钥。
2163. 获取密钥对象的二进制数据。
217
218以使用Promise方式随机生成SM2密钥(256位)为例:
219
220```ts
221import cryptoFramework from '@ohos.security.cryptoFramework';
222import { BusinessError } from '@ohos.base';
223
224function generateSM2Key() {
225  // Create an AsyKeyGenerator instance.
226  let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256");
227  // Use the key generator to randomly generate an asymmetric key pair.
228  let keyGenPromise = sm2Generator.generateKeyPair();
229  keyGenPromise.then(keyPair => {
230    let pubKey = keyPair.pubKey;
231    let priKey = keyPair.priKey;
232    // Obtain the binary data of the asymmetric key pair.
233    let pkBlob = pubKey.getEncoded();
234    let skBlob = priKey.getEncoded();
235    AlertDialog.show({ message: "pk bin data" + pkBlob.data });
236    AlertDialog.show({ message: "sk bin data" + skBlob.data });
237  })
238}
239```
240
241### 随机生成SM4密钥,并获得二进制数据
242
243 > **说明:**
244 >
245 > 从API version 10开始, 支持SM4密钥随机生成。
246
247示例7:随机生成对称密钥SymKey,并获得二进制数据(场景1、3)
248
2491. 创建对称密钥生成器。
2502. 通过对称密钥生成器随机生成对称密钥。
2513. 获取算法库密钥对象的二进制数据。
252
253以使用Promise方式随机生成SM4密钥(128位)为例:
254
255```ts
256import cryptoFramework from '@ohos.security.cryptoFramework';
257import { BusinessError } from '@ohos.base';
258
259function testGenerateSM4Key() {
260  // Create a SymKeyGenerator instance.
261  let symKeyGenerator = cryptoFramework.createSymKeyGenerator("SM4_128");
262  // Use the key generator to randomly generate a symmetric key.
263  let promiseSymKey = symKeyGenerator.generateSymKey();
264  promiseSymKey.then(key => {
265    // Obtain the binary data of the symmetric key and output a 128-bit byte stream. The length is 16 bytes.
266    let encodedKey = key.getEncoded();
267    console.info('key hex:' + encodedKey.data);
268  })
269}
270```
271
272### 根据SM2密钥二进制数据,生成密钥对
273
274 > **说明:**
275 >
276 > 从API version 10开始, 支持SM2密钥转换。
277
278示例8:根据指定的SM2非对称密钥二进制数据,生成KeyPair对象(场景2、3)
279
2801. 获取SM2二进制密钥数据,封装成DataBlob对象。
2812. 调用convertKey方法,传入公钥二进制和私钥二进制(二者非必选项,可只传入其中一个),转换为KeyPair对象。
282
283```ts
284import cryptoFramework from '@ohos.security.cryptoFramework';
285import { BusinessError } from '@ohos.base';
286
287function convertSM2AsyKey() {
288  let pubKeyArray = new Uint8Array([48, 89, 48, 19, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 8, 42, 129, 28, 207, 85, 1, 130, 45, 3, 66, 0, 4, 90, 3, 58, 157, 190, 248, 76, 7, 132, 200, 151, 208, 112, 230, 96, 140, 90, 238, 211, 155, 128, 109, 248, 40, 83, 214, 78, 42, 104, 106, 55, 148, 249, 35, 61, 32, 221, 135, 143, 100, 45, 97, 194, 176, 52, 73, 136, 174, 40, 70, 70, 34, 103, 103, 161, 99, 27, 187, 13, 187, 109, 244, 13, 7]);
289  let priKeyArray = new Uint8Array([48, 49, 2, 1, 1, 4, 32, 54, 41, 239, 240, 63, 188, 134, 113, 31, 102, 149, 203, 245, 89, 15, 15, 47, 202, 170, 60, 38, 154, 28, 169, 189, 100, 251, 76, 112, 223, 156, 159, 160, 10, 6, 8, 42, 129, 28, 207, 85, 1, 130, 45]);
290  let pubKeyBlob: cryptoFramework.DataBlob = { data: pubKeyArray };
291  let priKeyBlob: cryptoFramework.DataBlob = { data: priKeyArray };
292  let generator = cryptoFramework.createAsyKeyGenerator("SM2_256");
293  generator.convertKey(pubKeyBlob, priKeyBlob, (error, data) => {
294    if (error) {
295      AlertDialog.show({ message: "Convert keypair fail" });
296      return;
297    }
298    AlertDialog.show({ message: "Convert KeyPair success" });
299  })
300}
301```
302
303## 非对称密钥对象根据参数生成与获取参数
304
305### 场景说明
306
307使用密钥生成操作中,典型的场景有:
3081. 根据非对称密钥参数生成指定的算法库密钥对象。该对象可用于后续的加解密等操作。
3092. 对于非对称密钥,获取密钥对象的参数属性,用于存储或运输。
310
311> **说明:**
312>
313> 1. 从API version 10开始, 支持使用密钥参数来生成非对称密钥。
314> 2. 非对称密钥(公钥PubKey和私钥PriKey),其中公钥和私钥组成密钥对KeyPair。非对称密钥参数具体可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。
315
316### 接口及参数说明
317
318详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md#asykeygeneratorbyspec10)。
319
320以上场景涉及的常用接口如下表所示:
321
322|实例名|接口名|描述|
323|---|---|---|
324|AsyKeyGeneratorBySpec|generateKeyPair(callback: AsyncCallback\<KeyPair>): void;|使用callback方式,根据密钥参数生成非对称密钥对象KeyPair
325|AsyKeyGeneratorBySpec|generateKeyPair(): Promise\<KeyPair>;|使用Promise方式,根据密钥参数生成非对称密钥对象KeyPair
326|AsyKeyGeneratorBySpec|generatePriKey(callback: AsyncCallback\<KeyPair>): void;|使用callback方式,根据密钥参数生成非对称私钥对象PriKey
327|AsyKeyGeneratorBySpec|generatePriKey(): Promise\<KeyPair>;|使用Promise方式,根据密钥参数生成非对称私钥对象PriKey
328|AsyKeyGeneratorBySpec|generatePubKey(callback: AsyncCallback\<KeyPair>): void;|使用callback方式,根据密钥参数生成非对称公钥对象PubKey
329|AsyKeyGeneratorBySpec|generatePubKey(): Promise\<KeyPair>;|使用Promise方式,根据密钥参数生成非对称公钥对象PubKey
330| PriKey | getAsyKeySpec(itemType: AsyKeySpecItem): bigint \| string \| number;  | 获取非对称密钥私钥对象的密钥参数属性 |
331| PubKey | getAsyKeySpec(itemType: AsyKeySpecItem): bigint \| string \| number;  | 获取非对称密钥公钥对象的密钥参数属性 |
332
333### 根据参数生成ECC密钥对,并获得密钥参数开发步骤
334
335示例1:根据参数生成ECC密钥对,并获得密钥参数(场景1、2)
336
3371. 创建根据密钥参数的非对称密钥生成器。
3382. 通过根据密钥参数的非对称密钥生成器由指定密钥参数生成非对称密钥对。
3393. 获取密钥对象的密钥参数属性。
340
341以使用Promise方式根据密钥参数生成ECC密钥为例:
342
343```ts
344import cryptoFramework from '@ohos.security.cryptoFramework';
345import { BusinessError } from '@ohos.base';
346
347// Print bigint information.
348function showBigIntInfo(bnName: string, bnValue: bigint | string | number) {
349  if (typeof bnValue === 'string') {
350    console.error('type is string');
351    return;
352  }
353  if (typeof bnValue === 'number') {
354    console.error('type is number');
355    return;
356  }
357  console.info(bnName + ":");
358  console.info(". Decimal: " + bnValue.toString());
359  console.info(". Hexadecimal: " + bnValue.toString(16));
360  console.info(". Length (bits): " + bnValue.toString(2).length);
361}
362
363// Construct the EccCommonSpec struct based on the key specifications. The EccCommonSpec struct defines the common parameters of the ECC private key and public key.
364function genEccCommonSpec(): cryptoFramework.ECCCommonParamsSpec {
365  let fieldFp: cryptoFramework.ECFieldFp = {
366    fieldType: "Fp",
367    p: BigInt("0xffffffffffffffffffffffffffffffff000000000000000000000001")
368  }
369
370  let G: cryptoFramework.Point = {
371    x: BigInt("0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21"),
372    y: BigInt("0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34")
373  }
374
375  let eccCommonSpec: cryptoFramework.ECCCommonParamsSpec = {
376    algName: "ECC",
377    specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC,
378    field: fieldFp,
379    a: BigInt("0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe"),
380    b: BigInt("0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4"),
381    g: G,
382    n: BigInt("0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d"),
383    h: 1
384  }
385  return eccCommonSpec;
386}
387
388// Print the ECC key specifications.
389function showEccSpecDetailInfo(key: cryptoFramework.PubKey | cryptoFramework.PriKey, keyType: string) {
390  console.info("show detail of " + keyType + ":");
391  try {
392    let p = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FP_P_BN);
393    showBigIntInfo("--- p", p); // length is 224, hex : ffffffffffffffffffffffffffffffff000000000000000000000001
394
395    let a = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_A_BN);
396    showBigIntInfo("--- a", a); // length is 224, hex : fffffffffffffffffffffffffffffffefffffffffffffffffffffffe
397
398    let b = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_B_BN);
399    showBigIntInfo("--- b", b); // length is 224, hex : b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4
400
401    let gX = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_G_X_BN);
402    showBigIntInfo("--- gX", gX); // length is 224, hex : b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21
403
404    let gY = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_G_Y_BN);
405    showBigIntInfo("--- gY", gY); // length is 224, hex : bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34
406
407    let n = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_N_BN);
408    showBigIntInfo("--- n", n); // length is 224, hex : ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d
409
410    let h = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_H_NUM);
411    console.warn("--- h: " + h); // key h: 1
412
413    let fieldType = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FIELD_TYPE_STR);
414    console.warn("--- field type: " + fieldType); // key field type: Fp
415
416    let fieldSize = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FIELD_SIZE_NUM);
417    console.warn("--- field size: " + fieldSize); // key field size: 224
418
419    let curveName = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_CURVE_NAME_STR);
420    console.warn("--- curve name: " + curveName); // key curve name: NID_secp224r1
421
422    if (keyType == "priKey") {
423      let sk = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_SK_BN);
424      showBigIntInfo("--- sk", sk);
425    } else if (keyType == "pubKey") {
426      let pkX = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_PK_X_BN);
427      showBigIntInfo("--- pkX", pkX);
428      let pkY = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_PK_Y_BN);
429      showBigIntInfo("--- pkY", pkY);
430    }
431  } catch (error) {
432    console.error("getAsyKeySpec error");
433    let e: BusinessError = error as BusinessError;
434    console.error(`getAsyKeySpec failed, ${e.code}, ${e.message}`);
435  }
436}
437
438// Generate an ECC key pair based on the EccCommonSpec instance and obtain the key specifications.
439function testEccUseCommKeySpecGet() {
440  try {
441    let commKeySpec = genEccCommonSpec(); // Construct the EccCommonSpec object.
442    let generatorBySpec = cryptoFramework.createAsyKeyGeneratorBySpec(commKeySpec); // Create an AsyKeyGenerator instance based on the EccCommonSpec object.
443    let keyPairPromise = generatorBySpec.generateKeyPair(); // Generate an ECC key pair.
444    keyPairPromise.then(keyPair => {
445      showEccSpecDetailInfo(keyPair.priKey, "priKey"); // Obtain the ECC specifications of the private key.
446      showEccSpecDetailInfo(keyPair.pubKey, "pubKey"); // Obtain the ECC specifications of the public key.
447    }).catch((error: BusinessError) => {
448      // Capture exceptions such as logic errors asynchronously here.
449      console.error("generateComm error");
450      console.error("error code: " + error.code + ", message is: " + error.message);
451    })
452  } catch (error) {
453    // Capture parameter errors synchronously here.
454    console.error("testEccUseCommSpec error");
455    let e: BusinessError = error as BusinessError;
456    console.error(`ecc comm spec failed, ${e.code}, ${e.message}`);
457  }
458}
459```
460
461### 根据参数生成RSA公钥,并获得密钥参数属性
462
463示例2:根据参数生成RSA公钥,并获得密钥参数(场景1、2)
464
4651. 创建根据密钥参数的非对称密钥生成器。
4662. 通过根据密钥参数的非对称密钥生成器由指定密钥参数生成非对称密钥的公钥。
4673. 获取密钥对象的密钥参数属性。
468
469以使用Callback方式根据密钥参数生成RSA公钥为例:
470```ts
471import cryptoFramework from '@ohos.security.cryptoFramework';
472import { BusinessError } from '@ohos.base';
473// RSA公钥密钥参数生成函数
474function genRsaPubKeySpec(nIn: bigint, eIn: bigint): cryptoFramework.RSAPubKeySpec {
475  let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = {
476    n: nIn,
477    algName: "RSA",
478    specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC
479  };
480  let rsaPubKeySpec: cryptoFramework.RSAPubKeySpec = {
481    params: rsaCommSpec,
482    pk: eIn,
483    algName: "RSA",
484    specType: cryptoFramework.AsyKeySpecType.PUBLIC_KEY_SPEC
485  };
486  return rsaPubKeySpec;
487}
488
489// Construct an RSA public key specifications object based on the key parameters.
490function genRsa2048PubKeySpec() {
491  let nIn = BigInt("0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25");
492  let eIn = BigInt("0x010001");
493  return genRsaPubKeySpec(nIn, eIn);
494}
495
496// Compare the RSA public key specifications with the expected values.
497function compareRsaPubKeyBySpec(rsaKeySpec: cryptoFramework.RSAPubKeySpec, n: bigint | string | number, e: bigint | string | number) {
498  if (typeof n === 'string' || typeof e === 'string') {
499    console.error('type is string');
500    return false;
501  }
502  if (typeof n === 'number' || typeof e === 'number') {
503    console.error('type is number');
504    return false;
505  }
506  if (rsaKeySpec.params.n != n) {
507    return false;
508  }
509  if (rsaKeySpec.pk != e) {
510    return false;
511  }
512  return true;
513}
514
515// Generate an RSA public key based on the RSA public key specifications, obtain the key specifications, and compare the key specifications with the expected values.
516function rsaUsePubKeySpecGetCallback() {
517  let rsaPubKeySpec = genRsa2048PubKeySpec();
518  let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaPubKeySpec);
519  rsaGeneratorSpec.generatePubKey((error, key) => {
520    let pubKey = key;
521    let nBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_N_BN);
522    let eBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_PK_BN);
523    if (compareRsaPubKeyBySpec(rsaPubKeySpec, nBN, eBN) != true) {
524      AlertDialog.show({ message: "error pub key big number" });
525    } else {
526      console.info("n, e in the pubKey are same as the spec.");
527    }
528    if (error) {
529      console.error("generate pubKey error" + "error code: " + error.code + "error message" + error.message);
530    }
531  });
532}
533```
534
535## 使用加解密操作
536
537### 场景说明
538
539在数据存储或传输场景中,可以使用加解密操作用于保证数据的机密性,防止敏感数据泄露。使用加解密操作中,典型的场景有:
5401. 使用对称密钥的加解密操作。
5412. 使用非对称密钥的加解密操作。
5423. 使用RSA, PKCS1_OAEP填充模式时,获取、设置CipherSpecItem参数。
543
544> **说明:**
545>
546> 1. 从API version 10开始, 支持RSA使用PKCS1_OAEP填充模式时,获取、设置[CipherSpecItem](../reference/apis/js-apis-cryptoFramework.md#cipherspecitem10)参数。
547> 2. 从API version 10开始,支持加解密时字符串参数不带密钥长度。
548
549### 接口及参数说明
550
551详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。<br/>由于密码算法的复杂性,在选取不同规格和参数时,开发差异较大,无法通过代码示例一一列举,请仔细阅读API参考资料中的相关接口,确保使用正确。
552
553以上场景设计的常用接口如下表所示:
554
555|实例名|接口名|描述|
556|---|---|---|
557|cryptoFramework|createCipher(transformation : string) : Cipher|根据transformation设置的算法参数创建Cipher对象|
558|Cipher|init(opMode : CryptoMode, key : Key, params : ParamsSpec, callback : AsyncCallback\<void>) : void|使用callback方式设置密钥并初始化Cipher对象|
559|Cipher|init(opMode : CryptoMode, key : Key, params : ParamsSpec) : Promise\<void>|使用Promise方式设置密钥并初始化Cipher对象|
560|Cipher|update(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|使用callback方式添加加解密数据|
561|Cipher|update(data : DataBlob) : Promise\<DataBlob>|使用Promise方式添加加解密数据|
562|Cipher|doFinal(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|使用callback方式结束对所有数据的加解密|
563|Cipher|doFinal(data : DataBlob) : Promise\<DataBlob>|使用Promise方式结束对所有数据的加解密|
564|Cipher|getCipherSpec(itemType: CipherSpecItem): string \| Uint8Array|获取加解密的参数,当前仅支持RSA算法|
565|Cipher|setCipherSpec(itemType: CipherSpecItem, itemValue: Uint8Array): void|设置加解密的参数,当前仅支持RSA算法|
566
567### AES GCM以Promise方式加解密开发步骤:
568
569示例1:使用AES对称密钥的加解密操作
570
5711. 创建对称密钥生成器。
5722. 通过密钥生成器随机生成对称密钥。
5733. 创建加解密生成器。
5744. 通过加解密生成器加密或解密数据。
575
576```ts
577import cryptoFramework from '@ohos.security.cryptoFramework';
578import { BusinessError } from '@ohos.base';
579
580function genGcmParamsSpec() {
581  let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 12 bytes
582  let dataIv = new Uint8Array(arr);
583  let ivBlob: cryptoFramework.DataBlob = { data: dataIv };
584
585  arr = [0, 0, 0, 0, 0, 0, 0, 0]; // 8 bytes
586  let dataAad = new Uint8Array(arr);
587  let aadBlob: cryptoFramework.DataBlob = { data: dataAad };
588
589  arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 16 bytes
590  let dataTag = new Uint8Array(arr);
591  let tagBlob: cryptoFramework.DataBlob = {
592    data: dataTag
593  }; // The GCM authTag is obtained by doFinal() in encryption and passed in params of init() in decryption.
594
595  let gcmParamsSpec: cryptoFramework.GcmParamsSpec = {
596    iv: ivBlob,
597    aad: aadBlob,
598    authTag: tagBlob,
599    algName: "GcmParamsSpec"
600  };
601  return gcmParamsSpec;
602}
603
604// Convert strings in plaintext into byte streams.
605function stringToUint8Array(str: string) {
606  let arr = new Uint8Array(str.length);
607  for (let i = 0, j = str.length; i < j; ++i) {
608    arr[i] = str.charCodeAt(i);
609  }
610  return arr;
611}
612
613// Convert byte streams into strings in plaintext.
614function uint8ArrayToString(array: Uint8Array) {
615  let arrayString = '';
616  for (let i = 0; i < array.length; i++) {
617    arrayString += String.fromCharCode(array[i]);
618  }
619  return arrayString;
620}
621
622// AES GCM模式示例,自动生成密钥(promise写法)
623function testAesGcm() {
624  let symAlgName = 'AES128';
625  let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);
626  console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`);
627  // Generate GCM parameter specifications.
628  let globalGcmParams = genGcmParamsSpec();
629  // Create a Cipher instance.
630  let cipherAlgName = 'AES128|GCM|PKCS7';
631  let globalCipher = cryptoFramework.createCipher(cipherAlgName);
632  console.info(`cipher algName: ${globalCipher.algName}`);
633  // Use the key generator to randomly generate a 128-bit symmetric key.
634  let globalCipherText: cryptoFramework.DataBlob;
635  let globalKey: cryptoFramework.SymKey;
636  let promiseSymKey = symKeyGenerator.generateSymKey();
637  promiseSymKey.then(key => {
638    // Initialize the Cipher instance and start encryption.
639    globalKey = key;
640    let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
641    return globalCipher.init(mode, globalKey, globalGcmParams);
642  })
643    .then(() => {
644      let plainText: cryptoFramework.DataBlob = { data: stringToUint8Array('this is test!') };
645      return globalCipher.update(plainText);
646    })
647    .then((updateOutput: cryptoFramework.DataBlob): Promise<cryptoFramework.DataBlob> => {
648      globalCipherText = updateOutput;
649      return globalCipher.doFinal(null);
650    })
651    .then(tag => {
652      // In GCM mode, the encrypted authentication information needs to be obtained from the output of doFinal() and passed in globalGcmParams of init() in decryption.
653      globalGcmParams.authTag = tag;
654      return;
655    })
656    .then(() => {
657      // Initialize the Cipher instance and start decryption.
658      let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
659      return globalCipher.init(mode, globalKey, globalGcmParams);
660    })
661    .then(() => {
662      return globalCipher.update(globalCipherText); // update
663    })
664    .then((updateOutput: cryptoFramework.DataBlob): Promise<cryptoFramework.DataBlob> => {
665      console.info('decrypt plainText: ' + uint8ArrayToString(updateOutput.data));
666      return globalCipher.doFinal(null);
667    })
668    .then(finalOutput => {
669      if (finalOutput == null) { // Check whether the result is null before using finalOutput.data.
670        console.info('GCM finalOutput is null');
671      }
672    })
673    .catch((error: BusinessError) => {
674      console.error(`catch error, ${error.code}, ${error.message}`);
675    })
676}
677```
678
679### 3DES ECB以callback方式加解密开发步骤:
680
681示例2:使用3DES对称密钥的加解密操作
682
6831. 创建对称密钥生成器。
6842. 通过已有二进制数据生成密钥。
6853. 创建加解密生成器。
6864. 通过加解密生成器加密或解密数据。
687
688```ts
689import cryptoFramework from '@ohos.security.cryptoFramework';
690import { BusinessError } from '@ohos.base';
691
692// Convert strings in plaintext into byte streams.
693function stringToUint8Array(str: string) {
694  let arr = new Uint8Array(str.length);
695  for (let i = 0, j = str.length; i < j; ++i) {
696    arr[i] = str.charCodeAt(i);
697  }
698  return arr;
699}
700
701// Convert byte streams into strings in plaintext.
702function uint8ArrayToString(array: Uint8Array) {
703  let arrayString = '';
704  for (let i = 0; i < array.length; i++) {
705    arrayString += String.fromCharCode(array[i]);
706  }
707  return arrayString;
708}
709
710function genKeyMaterialBlob(): cryptoFramework.DataBlob {
711  let arr = [
712    0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56,
713    0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c,
714    0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72]; // keyLen = 192 (24 bytes)
715  let keyMaterial = new Uint8Array(arr);
716  return { data: keyMaterial };
717}
718
719// Generate a 3DES ECB key from the existing data in callback mode.
720function test3DesEcb() {
721  // Create a SymKeyGenerator instance.
722  let symAlgName = '3DES192';
723  let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);
724  if (symKeyGenerator == null) {
725    console.error('createSymKeyGenerator failed');
726    return;
727  }
728  console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`);
729
730  // Create a Cipher instance.
731  let cipherAlgName = '3DES192|ECB|PKCS7';
732  let globalCipher = cryptoFramework.createCipher(cipherAlgName);
733
734  // Generate a symmetric key based on the specified data.
735  let keyMaterialBlob = genKeyMaterialBlob();
736  try {
737    symKeyGenerator.convertKey(keyMaterialBlob, (error, key) => {
738      if (error) {
739        console.error(`convertKey error, ${error.code}, ${error.message}`);
740        return;
741      }
742      console.info(`key algName: ${key.algName}`);
743      console.info(`key format: ${key.format}`);
744      let encodedKey = key.getEncoded();
745      console.info('key getEncoded: ' + encodedKey.data);
746      let globalKey = key;
747
748      // Initialize the Cipher instance and start encryption.
749      let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
750      // init
751      globalCipher.init(mode, key, null, (err,) => {
752        let plainText: cryptoFramework.DataBlob = { data: stringToUint8Array('this is test!') };
753        // update
754        globalCipher.update(plainText, (err, updateOutput) => {
755          let globalCipherText = updateOutput;
756          //doFinal
757          globalCipher.doFinal(null, (err, finalOutput) => {
758            if (err) {
759              console.error(`doFinal error, ${err.code}, ${err.message}`);
760              return;
761            }
762            if (finalOutput != null) {
763              let tmpCipherText = Array.from(globalCipherText.data);
764              let tmpFinalOutput = Array.from(finalOutput.data);
765              tmpCipherText = tmpCipherText.concat(tmpFinalOutput);
766              globalCipherText = { data: new Uint8Array(tmpCipherText) };
767            }
768            // Initialize the Cipher instance and start decryption.
769            let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
770            // init
771            globalCipher.init(mode, globalKey, null, (err,) => {
772              // update
773              globalCipher.update(globalCipherText, (err, updateOutput) => {
774                console.info('decrypt plainText: ' + uint8ArrayToString(updateOutput.data));
775                // doFinal
776                globalCipher.doFinal(null, (error, finalOutput) => {
777                  if (finalOutput != null) { // Check whether the result is null before using finalOutput.data.
778                    console.info('decrypt plainText: ' + uint8ArrayToString(finalOutput.data));
779                  }
780                })
781              })
782            })
783          })
784        })
785      })
786    })
787  } catch (error) {
788    let e: BusinessError = error as BusinessError;
789    console.error(`3des failed, ${e.code}, ${e.message}`);
790    return;
791  }
792}
793```
794
795### AES GCM以promise方式,分段update()加解密开发步骤:
796
797示例3:使用AES对称密钥的分段update()加解密操作
798
7991. 创建对称密钥生成器。
8002. 通过已有二进制数据生成密钥。
8013. 创建加解密生成器。
8024. 通过加解密生成器加密或解密数据。
803
804以AES GCM以promise方式,分段update()实现加解密为例:
805
806```ts
807import cryptoFramework from '@ohos.security.cryptoFramework';
808import { BusinessError } from '@ohos.base';
809
810function genGcmParamsSpec() {
811  let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 12 bytes
812  let dataIv = new Uint8Array(arr);
813  let ivBlob: cryptoFramework.DataBlob = { data: dataIv };
814
815  arr = [0, 0, 0, 0, 0, 0, 0, 0]; // 8 bytes
816  let dataAad = new Uint8Array(arr);
817  let aadBlob: cryptoFramework.DataBlob = { data: dataAad };
818
819  arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 16 bytes
820  let dataTag = new Uint8Array(arr);
821  let tagBlob: cryptoFramework.DataBlob = {
822    data: dataTag
823  }; // The GCM authTag is obtained by doFinal() in encryption and passed in params of init() in decryption.
824
825  let gcmParamsSpec: cryptoFramework.GcmParamsSpec = {
826    iv: ivBlob,
827    aad: aadBlob,
828    authTag: tagBlob,
829    algName: "GcmParamsSpec"
830  };
831  return gcmParamsSpec;
832}
833
834// Convert strings in plaintext into byte streams.
835function stringToUint8Array(str: string) {
836  let arr = new Uint8Array(str.length);
837  for (let i = 0, j = str.length; i < j; ++i) {
838    arr[i] = str.charCodeAt(i);
839  }
840  return arr;
841}
842
843// Convert byte streams into strings in plaintext.
844function uint8ArrayToString(array: Uint8Array) {
845  let arrayString = '';
846  for (let i = 0; i < array.length; i++) {
847    arrayString += String.fromCharCode(array[i]);
848  }
849  return arrayString;
850}
851
852function testAesMultiUpdate() {
853  let symAlgName = 'AES128';
854  let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);
855  console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`);
856  // Generate GCM parameter specifications.
857  let globalGcmParams = genGcmParamsSpec();
858  // Create a Cipher instance.
859  let cipherAlgName = 'AES128|GCM|PKCS7';
860  let globalCipher = cryptoFramework.createCipher(cipherAlgName);
861  console.info(`cipher algName: ${globalCipher.algName}`);
862  // Use the key generator to randomly generate a 128-bit symmetric key.
863  let globalCipherText: cryptoFramework.DataBlob;
864  let globalKey: cryptoFramework.SymKey;
865  let globalPlainText = '';
866  let promiseSymKey = symKeyGenerator.generateSymKey();
867  promiseSymKey.then(key => {
868    // Initialize the Cipher instance and start encryption.
869    globalKey = key;
870    let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
871    return globalCipher.init(mode, globalKey, globalGcmParams);
872  })
873    .then(async () => {
874      let plainText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // Assume that the plaintext is of 43 bytes.
875      let messageArr: number[] = [];
876      let updateLength = 20; // Pass in 20 bytes by update() each time.
877      let tmpCipherText = new Uint8Array();
878
879      for (let i = 0; i <= plainText.length; i++) {
880        if ((i % updateLength == 0 || i == plainText.length) && messageArr.length != 0) {
881          let message = new Uint8Array(messageArr);
882          let messageBlob: cryptoFramework.DataBlob = { data: message };
883          let updateOutput = await globalCipher.update(messageBlob); // Update by segment.
884          // Combine the result of each update() to obtain the ciphertext. In certain cases, the doFinal() results need to be combined, which depends on the cipher block mode
885          // and padding mode you use. In this example, the doFinal() result in GCM mode contains authTag but not ciphertext. Therefore, there is no need to combine the results.
886          let mergeText = new Uint8Array(tmpCipherText.length + updateOutput.data.length);
887          mergeText.set(tmpCipherText);
888          mergeText.set(updateOutput.data, tmpCipherText.length);
889          tmpCipherText = mergeText;
890          // tmpCipherText = tmpCipherText.concat(Array.from(updateOutput.data));
891          messageArr = [];
892        }
893        if (i < plainText.length) {
894          messageArr.push(plainText.charCodeAt(i));
895        }
896      }
897      globalCipherText = { data: tmpCipherText };
898      return;
899    })
900    .then((): Promise<cryptoFramework.DataBlob> => {
901      return globalCipher.doFinal(null);
902    })
903    .then(tag => {
904      // In GCM mode, the encrypted authentication information needs to be obtained from the output of doFinal() and passed in globalGcmParams of init() in decryption.
905      globalGcmParams.authTag = tag;
906      return;
907    })
908    .then(() => {
909      // Initialize the Cipher instance and start decryption.
910      let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
911      return globalCipher.init(mode, globalKey, globalGcmParams);
912    })
913    .then(async () => {
914      let updateLength = 20;
915      let updateTimes = Math.ceil(globalCipherText.data.length / updateLength); // Round up to the nearest integer.
916      for (let i = 0; i < updateTimes; i++) {
917        let messageArr = globalCipherText.data.slice(i * updateLength, (i + 1) * updateLength);
918        let message = new Uint8Array(messageArr);
919        let messageBlob: cryptoFramework.DataBlob = { data: message };
920        let updateOutput = await globalCipher.update(messageBlob); // Update by segment.
921        globalPlainText += uint8ArrayToString(updateOutput.data); // Restore the original plaintext.
922      }
923      return;
924    })
925    .then((): Promise<cryptoFramework.DataBlob> => {
926      return globalCipher.doFinal(null);
927    })
928    .then(finalOutput => {
929      if (finalOutput == null) { // Check whether the result is null before using finalOutput.data.
930        console.info('GCM finalOutput is null');
931      }
932      console.info(`decrypt output: ${globalPlainText}`);
933    })
934    .catch((error: BusinessError) => {
935      console.error(`catch error, ${error.code}, ${error.message}`);
936    })
937}
938```
939
940### RSA加解密开发步骤
941
942示例4:使用RSA非对称密钥的加解密操作
943
9441. 生成RSA密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成RSA非对称密钥。
9452. 生成Cipher对象。通过createCipher接口创建Cipher对象,执行初始化操作,设置密钥及加解密模式。
9463. 执行加解密操作。通过调用Cipher对象提供的doFinal接口,执行加密操作生成密文或执行解密操作生成明文。
947
948```ts
949import cryptoFramework from '@ohos.security.cryptoFramework';
950import { BusinessError } from '@ohos.base';
951
952let plan = "This is cipher test.";
953
954// Convert strings in plaintext into byte streams.
955function stringToUint8Array(str: string) {
956  let arr = new Uint8Array(str.length);
957  for (let i = 0, j = str.length; i < j; ++i) {
958    arr[i] = str.charCodeAt(i);
959  }
960  return arr;
961}
962
963// Encrypt the message in promise mode.
964function encryptMessagePromise() {
965  // Create an AsyKeyGenerator instance.
966  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
967  // Create a Cipher instance.
968  let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
969  // Generate an asymmetric key pair using the AsyKeyGenerator instance.
970  let keyGenPromise = rsaGenerator.generateKeyPair();
971  keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => {
972    let pubKey = rsaKeyPair.pubKey;
973    // Initialize the Cipher instance and use the public key to encrypt the data.
974    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null);
975  }).then(() => {
976    // doFinal
977    let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) };
978    return cipher.doFinal(input);
979  }).then(dataBlob => {
980    // Obtain the encrypted data.
981    console.info("EncryptOutPut is " + dataBlob.data);
982  });
983}
984
985// Encrypt the message in callback mode.
986function encryptMessageCallback() {
987  // Create an AsyKeyGenerator instance.
988  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
989  // Create a Cipher instance.
990  let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
991  // Generate an asymmetric key pair using the AsyKeyGenerator instance.
992  rsaGenerator.generateKeyPair((err, keyPair) => {
993    let pubKey = keyPair.pubKey;
994    // Initialize the Cipher instance and use the public key to encrypt the data.
995    cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null, (err, data) => {
996      let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) };
997      // doFinal
998      cipher.doFinal(input, (err, data) => {
999        // Obtain the encrypted data.
1000        console.info("EncryptOutPut is " + data.data);
1001      })
1002    })
1003  })
1004}
1005
1006// Encrypt and decrypt the message in promise mode.
1007function decryptMessagePromise() {
1008  // Create an AsyKeyGenerator instance.
1009  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
1010  // Create a Cipher instance for encryption.
1011  let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
1012  // Create a Cipher instance for decryption.
1013  let decoder = cryptoFramework.createCipher("RSA1024|PKCS1");
1014  // Generate an asymmetric key pair using the AsyKeyGenerator instance.
1015  let keyGenPromise = rsaGenerator.generateKeyPair();
1016  let keyPair: cryptoFramework.KeyPair;
1017  let cipherDataBlob: cryptoFramework.DataBlob;
1018  let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) };
1019  keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => {
1020    keyPair = rsaKeyPair;
1021    // Initialize the Cipher instance and use the public key to encrypt the message.
1022    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null);
1023  })
1024    .then(() => {
1025      // Call doFinal() to encrypt data.
1026      return cipher.doFinal(input);
1027    })
1028    .then((dataBlob: cryptoFramework.DataBlob): Promise<void> => {
1029      // Obtain the encrypted information and use it as the input parameter for decryption.
1030      console.info("EncryptOutPut is " + dataBlob.data);
1031      AlertDialog.show({ message: "output" + dataBlob.data });
1032      cipherDataBlob = dataBlob;
1033      // Initialize the Cipher instance and use the private key to decrypt the message.
1034      return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null);
1035    })
1036    .then(() => {
1037      // Call doFinal() to decrypt the message.
1038      return decoder.doFinal(cipherDataBlob);
1039    })
1040    .then(decodeData => {
1041      // Check whether the decrypted data is consistent with the original data.
1042      if (decodeData.data.toString() === input.data.toString()) {
1043        AlertDialog.show({ message: "decrypt success" });
1044        return;
1045      }
1046      AlertDialog.show({ message: "decrypt fail" });
1047    });
1048}
1049
1050// Encrypt and decrypt the message in callback mode.
1051function decryptMessageCallback() {
1052  // Create an AsyKeyGenerator instance.
1053  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
1054  // Create a Cipher instance for encryption.
1055  let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
1056  // Create a Cipher instance for decryption.
1057  let decoder = cryptoFramework.createCipher("RSA1024|PKCS1");
1058  let plainText = "this is cipher text";
1059  let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plainText) };
1060  // Generate an asymmetric key pair using the AsyKeyGenerator instance.
1061  rsaGenerator.generateKeyPair((err, newKeyPair) => {
1062    let keyPair = newKeyPair;
1063    // Initialize the Cipher instance and use the public key to encrypt the message.
1064    cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null, (err, data) => {
1065      // Call doFinal() to encrypt the message.
1066      cipher.doFinal(input, (err, data) => {
1067        // Obtain the encrypted information and use it as the input parameter for decryption.
1068        AlertDialog.show({ message: "EncryptOutPut is " + data.data });
1069        let cipherData = data;
1070        // Initialize the Cipher instance and use the private key to decrypt the message.
1071        decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null, (err, data) => {
1072          // Call doFinal() to decrypt the message.
1073          decoder.doFinal(cipherData, (err, data) => {
1074            // Check whether the decrypted data is consistent with the original data.
1075            if (input.data.toString() === data.data.toString()) {
1076              AlertDialog.show({ message: "decrype success" });
1077              return;
1078            }
1079            AlertDialog.show({ message: "decrype fail" });
1080          });
1081        });
1082      });
1083    });
1084  });
1085}
1086```
1087
1088### RSA分段加解密开发步骤
1089
1090示例5:使用RSA非对称密钥的分段加解密操作
1091
10921. 生成RSA密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成RSA非对称密钥。
10932. 生成Cipher对象。通过createCipher接口创建Cipher对象,执行初始化操作,设置密钥及加解密模式。
10943. 执行加解密操作。通过调用Cipher对象提供的doFinal接口,执行加密操作生成密文或执行解密操作生成明文,多次调用doFinal实现分段。
1095
1096```ts
1097import cryptoFramework from '@ohos.security.cryptoFramework';
1098import { BusinessError } from '@ohos.base';
1099
1100// Convert strings in plaintext into byte streams.
1101function stringToUint8Array(str: string) {
1102  let arr = new Uint8Array(str.length);
1103  for (let i = 0, j = str.length; i < j; ++i) {
1104    arr[i] = str.charCodeAt(i);
1105  }
1106  return arr;
1107}
1108
1109// Convert byte streams into strings in plaintext.
1110function uint8ArrayToString(array: Uint8Array) {
1111  let arrayString = '';
1112  for (let i = 0; i < array.length; i++) {
1113    arrayString += String.fromCharCode(array[i]);
1114  }
1115  return arrayString;
1116}
1117
1118function encryptLongMessagePromise() {
1119  let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1120    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1121    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1122    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1123    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1124    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1125    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1126    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!";
1127  let globalKeyPair: cryptoFramework.KeyPair;
1128  let plainTextSplitLen = 64; // The length of the plaintext to be encrypted or decrypted each time by RSA depends on the number of key bits and padding mode. For details, see the Crypto Framework Overview.
1129  let cipherTextSplitLen = 128; // Length of the ciphertext = Number of key bits/8
1130  let keyGenName = "RSA1024";
1131  let cipherAlgName = "RSA1024|PKCS1";
1132  let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // Create an AsyKeyGenerator object.
1133  let cipher = cryptoFramework.createCipher(cipherAlgName); // Create a Cipher object.
1134  let decoder = cryptoFramework.createCipher(cipherAlgName); // Create a Decoder object.
1135  let keyGenPromise = asyKeyGenerator.generateKeyPair(); // Generate an RSA key pair.
1136  let globalCipherText: cryptoFramework.DataBlob;
1137
1138  keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => {
1139    globalKeyPair = rsaKeyPair; // Save the key pair as a global variable.
1140    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, globalKeyPair.pubKey, null);
1141  })
1142    .then(async () => {
1143      let tmpCipherText = new Uint8Array();
1144      // Split the plaintext by 64 characters and cyclically call doFinal() to encrypt the plaintext. If a 1024-bit key is used, 128-byte ciphertext is generated each time.
1145      for (let i = 0; i < (globalPlainText.length / plainTextSplitLen); i++) {
1146        let tempStr = globalPlainText.substr(i * plainTextSplitLen, plainTextSplitLen);
1147        let tempBlob: cryptoFramework.DataBlob = { data: stringToUint8Array(tempStr) };
1148        let tempCipherOutput = await cipher.doFinal(tempBlob);
1149        let mergeText = new Uint8Array(tmpCipherText.length + tempCipherOutput.data.length);
1150        mergeText.set(tmpCipherText);
1151        mergeText.set(tempCipherOutput.data, tmpCipherText.length);
1152        tmpCipherText = mergeText;
1153      }
1154      globalCipherText = { data: tmpCipherText };
1155      console.info(`globalCipherOutput len is ${tmpCipherText.length}, data is: ${tmpCipherText.toString()}`);
1156      return;
1157    })
1158    .then((): Promise<void> => {
1159      return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, globalKeyPair.priKey, null);
1160    })
1161    .then(async () => {
1162      let tmpDecodeText = new Uint8Array();
1163      // Split and decrypt the ciphertext by 128 bytes, and combine the plaintext obtained each time.
1164      for (let i = 0; i < (globalCipherText.data.length / cipherTextSplitLen); i++) {
1165        let tempBlobData = globalCipherText.data.slice(i * cipherTextSplitLen, (i + 1) * cipherTextSplitLen);
1166        let message = new Uint8Array(tempBlobData);
1167        let tempBlob: cryptoFramework.DataBlob = { data: message };
1168        let tempDecodeOutput = await decoder.doFinal(tempBlob);
1169        let mergeText = new Uint8Array(tmpDecodeText.length + tempDecodeOutput.data.length);
1170        mergeText.set(tmpDecodeText);
1171        mergeText.set(tempDecodeOutput.data, tmpDecodeText.length);
1172        tmpDecodeText = mergeText;
1173      }
1174      let globalDecodeOutput = uint8ArrayToString(tmpDecodeText);
1175      if (globalDecodeOutput === globalPlainText) {
1176        console.info(`encode and decode success`);
1177      } else {
1178        console.info(`encode and decode error`);
1179      }
1180      return;
1181    })
1182    .catch((error: BusinessError) => {
1183      console.error(`catch error, ${error.code}, ${error.message}`);
1184    })
1185}
1186```
1187
1188> **说明:**
1189>
1190> 1. 使用RSA加解密时,Cipher对象不可重复调用init方法初始化,在创建了一个加密Cipher对象后,如果要进行解密,则需要重新创建另一个Cipher对象执行解密操作。
1191> 2. RSA加密有长度限制,允许加密明文的最大长度见[加解密算法库框架概述](cryptoFramework-overview.md)中的基本概念加解密章节。
1192> 3. RSA解密每次允许解密的密文长度为,RSA密钥的位数/8。
1193
1194### RSA加解密PKCS1_OAEP模式开发步骤
1195
1196示例6:使用RSA非对称密钥使用PKCS1_OAEP模式的以Promise形式的加解密操作
1197
11981. 根据密钥参数生成RSA密钥。通过createAsyKeyGeneratorBySpec接口创建AsyKeyGeneratorBySpec对象,并生成RSA非对称密钥对(也可以使用createAsyKeyGenerator接口随机生成或转换得到RSA密钥对象)。
11992. 生成Cipher对象。通过createCipher接口创建Cipher对象,执行初始化操作,设置密钥及加解密模式,在Update前通过setCipherSpec设置PKCS1_OAEP填充字节流P。
12003. 执行加解密操作。通过调用Cipher对象提供的doFinal接口,执行加密操作生成密文或执行解密操作生成明文,需要加解密Cipher对象的字节流P一致。
1201
1202```ts
1203import cryptoFramework from '@ohos.security.cryptoFramework';
1204import { BusinessError } from '@ohos.base';
1205
1206// 可理解的字符串转成字节流
1207function stringToUint8Array(str: string) {
1208  let arr = new Uint8Array(str.length);
1209  for (let i = 0, j = str.length; i < j; ++i) {
1210    arr[i] = str.charCodeAt(i);
1211  }
1212  return arr;
1213}
1214
1215// 根据密钥参数属性构造RSA非对称密钥对密钥参数
1216function genRsaKeyPairSpec(nIn: bigint, eIn: bigint, dIn: bigint) {
1217  let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = {
1218    n: nIn,
1219    algName: "RSA",
1220    specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC
1221  };
1222  let rsaKeyPairSpec: cryptoFramework.RSAKeyPairSpec = {
1223    params: rsaCommSpec,
1224    sk: dIn,
1225    pk: eIn,
1226    algName: "RSA",
1227    specType: cryptoFramework.AsyKeySpecType.KEY_PAIR_SPEC
1228  };
1229  return rsaKeyPairSpec;
1230}
1231
1232// 生成RSA2048密钥对参数
1233function genRsa2048KeyPairSpec(): cryptoFramework.RSAKeyPairSpec {
1234  let nIn = BigInt("0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25");
1235  let eIn = BigInt("0x010001");
1236  let dIn = BigInt("0x6a7df2ca63ead4dda191d614b6b385e0d9056a3d6d5cfe07db1daabee022db08212d97613d3328e0267c9dd23d787abde2afcb306aeb7dfce69246cc73f5c87fdf06030179a2114b767db1f083ff841c025d7dc00cd82435b9a90f695369e94df23d2ce458bc3b3283ad8bba2b8fa1ba62e2dce9accff3799aae7c840016f3ba8e0048c0b6cc4339af7161003a5beb864a0164b2c1c9237b64bc87556994351b27506c33d4bcdfce0f9c491a7d6b0628c7c852be4f0a9c3132b2ed3a2c8881e9aab07e20e17deb074691be677776a78b5c502e05d9bdde72126b3738695e2dd1a0a98a14247c65d8a7ee79432a092cb0721a12df798e44f7cfce0c498147a9b1");
1237  return genRsaKeyPairSpec(nIn, eIn, dIn);
1238}
1239
1240function rsaUseSpecDecryptOAEPPromise() {
1241  let plan = "This is cipher test.";
1242  // Obtain the key parameter object of the RSA key pair.
1243  let rsaKeyPairSpec = genRsa2048KeyPairSpec();
1244  // Generate an RSA key pair based on the RSA key parameters.
1245  let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaKeyPairSpec);
1246  let keyGenPromise = rsaGeneratorSpec.generateKeyPair();
1247  let cipher = cryptoFramework.createCipher("RSA|PKCS1_OAEP|SHA256|MGF1_SHA1");
1248  let decoder = cryptoFramework.createCipher("RSA|PKCS1_OAEP|SHA256|MGF1_SHA1");
1249  let keyPair: cryptoFramework.KeyPair;
1250  let cipherDataBlob: cryptoFramework.DataBlob;
1251  // Set the pSource, which defines the encoding input P filled by OAEP.
1252  let pSource = new Uint8Array([1, 2, 3, 4]);
1253  let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) };
1254  // Generate the key pair.
1255  keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => {
1256    keyPair = rsaKeyPair;
1257    // Initialize the Cipher instance for encryption.
1258    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null);
1259  })
1260    .then(() => {
1261      // Set and obtain the cipher specifications after the initialization.
1262      cipher.setCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_PSRC_UINT8ARR, pSource);
1263      let retP = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_PSRC_UINT8ARR);
1264      // Check whether the obtained PSource is the same as the PSource set.
1265      if (retP.toString() != pSource.toString()) {
1266        AlertDialog.show({ message: "error init pSource" + retP });
1267      } else {
1268        console.info("pSource changed ==" + retP);
1269      }
1270      // Obtain other OAEP parameters.
1271      let md = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MD_NAME_STR);
1272      console.info("md == " + md);
1273      let mgf = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF_NAME_STR);
1274      console.info("mgf == " + mgf);
1275      let mgf1Md = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_MD_STR);
1276      console.info("mgf1Md == " + mgf1Md);
1277      return cipher.doFinal(input);
1278    })
1279    .then((dataBlob: cryptoFramework.DataBlob): Promise<void> => {
1280      console.info("EncryptOutPut is " + dataBlob.data);
1281      cipherDataBlob = dataBlob;
1282      // The get() and set() operations can be performed before the init() operation of the Cipher object and are equivalent to those after the init() operation. For example, set and get the decoder.
1283      decoder.setCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_PSRC_UINT8ARR, pSource);
1284      let retP = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_PSRC_UINT8ARR);
1285      // Check whether the obtained PSource is the same as the PSource set.
1286      if (retP.toString() != pSource.toString()) {
1287        AlertDialog.show({ message: "error init pSource" + retP });
1288      } else {
1289        console.info("pSource changed ==" + retP);
1290      }
1291      // Obtain other OAEP parameters.
1292      let md = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MD_NAME_STR);
1293      console.info("md == " + md);
1294      let mgf = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF_NAME_STR);
1295      console.info("mgf == " + mgf);
1296      let mgf1Md = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_MD_STR);
1297      console.info("mgf1Md == " + mgf1Md);
1298      // Initialize the decryption operation.
1299      return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null);
1300    })
1301    .then(() => {
1302      return decoder.doFinal(cipherDataBlob);
1303    })
1304    .then(decodeData => {
1305      // The decryption is successful.
1306      if (decodeData.data.toString() === input.data.toString()) {
1307        console.info("oaep decrypt success");
1308        AlertDialog.show({ message: " oaep decrypt success" });
1309      } else {
1310        AlertDialog.show({ message: "oeap decrypt fail" });
1311      }
1312    });
1313}
1314```
1315
1316### SM2加解密开发步骤
1317
1318> **说明:**
1319>
1320> 从API version 10开始, 支持SM2加解密。
1321
1322示例7:使用SM2非对称密钥的加解密操作
1323
13241. 生成SM2密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成SM2非对称密钥。
13252. 生成Cipher对象。通过createCipher接口创建Cipher对象,执行初始化操作,设置密钥及加解密模式。
13263. 执行加解密操作。通过调用Cipher对象提供的doFinal接口,执行加密操作生成密文或执行解密操作生成明文。
1327
1328```ts
1329import cryptoFramework from '@ohos.security.cryptoFramework';
1330import { BusinessError } from '@ohos.base';
1331
1332let plan = "This is cipher test.";
1333
1334// Convert strings in plaintext into byte streams.
1335function stringToUint8Array(str: string) {
1336  let arr = new Uint8Array(str.length);
1337  for (let i = 0, j = str.length; i < j; ++i) {
1338    arr[i] = str.charCodeAt(i);
1339  }
1340  return arr;
1341}
1342
1343// 以Promise方式加密
1344function encryptMessagePromise() {
1345  // Create an AsyKeyGenerator instance.
1346  let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256");
1347  // Create a Cipher instance.
1348  let cipher = cryptoFramework.createCipher("SM2_256|SM3");
1349  // Generate an asymmetric key pair using the AsyKeyGenerator instance.
1350  let keyGenPromise = sm2Generator.generateKeyPair();
1351  keyGenPromise.then((sm2KeyPair: cryptoFramework.KeyPair): Promise<void> => {
1352    let pubKey = sm2KeyPair.pubKey;
1353    // Initialize the Cipher instance and use the public key to encrypt the message.
1354    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null);
1355  }).then(() => {
1356    // doFinal
1357    let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) };
1358    return cipher.doFinal(input);
1359  }).then(dataBlob => {
1360    // Obtain the encrypted data.
1361    console.info("EncryptOutPut is " + dataBlob.data);
1362  });
1363}
1364
1365// Encrypt the message in callback mode.
1366function encryptMessageCallback() {
1367  // Create an AsyKeyGenerator instance.
1368  let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256");
1369  // Create a Cipher instance.
1370  let cipher = cryptoFramework.createCipher("SM2_256|SM3");
1371  // Generate an asymmetric key pair using the AsyKeyGenerator instance.
1372  sm2Generator.generateKeyPair((err, keyPair) => {
1373    let pubKey = keyPair.pubKey;
1374    // Initialize the Cipher instance and use the public key to encrypt the message.
1375    cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null, (err, data) => {
1376      let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) };
1377      // doFinal
1378      cipher.doFinal(input, (err, data) => {
1379        // Obtain the encrypted data.
1380        console.info("EncryptOutPut is " + data.data);
1381      })
1382    })
1383  })
1384}
1385
1386// Encrypt and decrypt data in promise mode.
1387function decryptMessagePromise() {
1388  // Create an AsyKeyGenerator instance.
1389  let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256");
1390  // Create a Cipher instance for encryption.
1391  let cipher = cryptoFramework.createCipher("SM2_256|SM3");
1392  // Create a Cipher instance for decryption.
1393  let decoder = cryptoFramework.createCipher("SM2_256|SM3");
1394  // Generate an asymmetric key pair using the AsyKeyGenerator instance.
1395  let keyGenPromise = sm2Generator.generateKeyPair();
1396  let keyPair: cryptoFramework.KeyPair;
1397  let cipherDataBlob: cryptoFramework.DataBlob;
1398  let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) };
1399  keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => {
1400    keyPair = rsaKeyPair;
1401    // Initialize the Cipher instance and use the public key to encrypt the data.
1402    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null);
1403  })
1404    .then(() => {
1405      // Call doFinal() to encrypt data.
1406      return cipher.doFinal(input);
1407    })
1408    .then((dataBlob: cryptoFramework.DataBlob): Promise<void> => {
1409      // Obtain the encrypted information and use it as the input parameter for decryption.
1410      console.info("EncryptOutPut is " + dataBlob.data);
1411      AlertDialog.show({ message: "output" + dataBlob.data });
1412      cipherDataBlob = dataBlob;
1413      // Initialize the Cipher instance and use the private key to decrypt the data.
1414      return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null);
1415    })
1416    .then(() => {
1417      // Call doFinal() to decrypt data.
1418      return decoder.doFinal(cipherDataBlob);
1419    })
1420    .then(decodeData => {
1421      // Check whether the decrypted data is consistent with the original data.
1422      if (decodeData.data.toString() === input.data.toString()) {
1423        AlertDialog.show({ message: "decrypt success" });
1424        return;
1425      }
1426      AlertDialog.show({ message: "decrypt fail" });
1427    });
1428}
1429
1430// Encrypt and decrypt data in callback mode.
1431function decryptMessageCallback() {
1432  // Create an AsyKeyGenerator instance.
1433  let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256");
1434  // Create a Cipher instance for encryption.
1435  let cipher = cryptoFramework.createCipher("SM2_256|SM3");
1436  // Create a Cipher instance for decryption.
1437  let decoder = cryptoFramework.createCipher("SM2_256|SM3");
1438  let plainText = "this is cipher text";
1439  let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plainText) };
1440  let cipherData: cryptoFramework.DataBlob;
1441  let keyPair: cryptoFramework.KeyPair;
1442  // Generate an asymmetric key pair using the AsyKeyGenerator instance.
1443  sm2Generator.generateKeyPair((err, newKeyPair) => {
1444    keyPair = newKeyPair;
1445    // Initialize the Cipher instance and use the public key to encrypt the data.
1446    cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null, (err, data) => {
1447      // Call doFinal() to encrypt data.
1448      cipher.doFinal(input, (err, data) => {
1449        // Obtain the encrypted information and use it as the input parameter for decryption.
1450        AlertDialog.show({ message: "EncryptOutPut is " + data.data });
1451        cipherData = data;
1452        // Initialize the Cipher instance and use the private key to decrypt the data.
1453        decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null, (err, data) => {
1454          // Call doFinal() to decrypt data.
1455          decoder.doFinal(cipherData, (err, data) => {
1456            // Check whether the decrypted data is consistent with the original data.
1457            if (input.data.toString() === data.data.toString()) {
1458              AlertDialog.show({ message: "decrypt success" });
1459              return;
1460            }
1461            AlertDialog.show({ message: "decrypt fail" });
1462          });
1463        });
1464      });
1465    });
1466  });
1467}
1468```
1469
1470### SM4 ECB以callback方式加解密开发步骤:
1471
1472> **说明:**
1473>
1474> 从API version 10开始, 支持SM4加解密。
1475
1476示例8:使用SM4对称密钥的加解密操作
1477
14781. 创建对称密钥生成器。
14792. 通过已有二进制数据生成密钥。
14803. 创建加解密生成器。
14814. 通过加解密生成器加密或解密数据。
1482
1483```ts
1484import cryptoFramework from '@ohos.security.cryptoFramework';
1485import { BusinessError } from '@ohos.base';
1486
1487// Convert strings in plaintext into byte streams.
1488function stringToUint8Array(str: string) {
1489  let arr = new Uint8Array(str.length);
1490  for (let i = 0, j = str.length; i < j; ++i) {
1491    arr[i] = str.charCodeAt(i);
1492  }
1493  return arr;
1494}
1495
1496// Convert byte streams into strings in plaintext.
1497function uint8ArrayToString(array: Uint8Array) {
1498  let arrayString = '';
1499  for (let i = 0; i < array.length; i++) {
1500    arrayString += String.fromCharCode(array[i]);
1501  }
1502  return arrayString;
1503}
1504
1505// SM4 ECB模式示例,callback写法
1506function testSM4Ecb() {
1507  // Create an AsyKeyGenerator instance.
1508  let sm4Generator = cryptoFramework.createSymKeyGenerator('SM4_128');
1509  // Create a Cipher instance for encryption.
1510  let cipher = cryptoFramework.createCipher("SM4_128|ECB|PKCS7");
1511  // Create a Cipher instance for decryption.
1512  let decoder = cryptoFramework.createCipher("SM4_128|ECB|PKCS7");
1513  let plainText = "this is cipher text";
1514  let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plainText) };
1515  let cipherData: cryptoFramework.DataBlob;
1516  let key: cryptoFramework.SymKey;
1517  // Generate an asymmetric key pair using the AsyKeyGenerator instance.
1518  sm4Generator.generateSymKey((err, newKey) => {
1519    key = newKey;
1520    // Initialize the Cipher instance and use the public key to encrypt the data.
1521    cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, key, null, (err, data) => {
1522      // Call doFinal() to encrypt data.
1523      cipher.doFinal(input, (err, data) => {
1524        // Obtain the encrypted information and use it as the input parameter for decryption.
1525        AlertDialog.show({ message: "EncryptOutPut is " + data.data });
1526        cipherData = data;
1527        // Initialize the Cipher instance and use the private key to decrypt the data.
1528        decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, key, null, (err, data) => {
1529          // Call doFinal() to decrypt data.
1530          decoder.doFinal(cipherData, (err, data) => {
1531            // Check whether the decrypted data is consistent with the original data.
1532            if (input.data.toString() === data.data.toString()) {
1533              AlertDialog.show({ message: "decrypt success" });
1534              return;
1535            }
1536            AlertDialog.show({ message: "decrypt fail" });
1537          });
1538        });
1539      });
1540    });
1541  });
1542}
1543```
1544
1545## 使用签名验签操作
1546
1547### 场景说明
1548
1549当需要判断接收的数据是否被篡改且是否为指定对象发送的数据时,可以使用签名验签操作。使用签名验签操作中,典型的场景有:
15501. 使用RSA签名验签操作
15512. 使用ECC签名验签操作
15523. 使用RSA签名验签,PSS模式时,获取、设置SignSpecItem参数。
15534. 使用SM2签名验签操作
1554
1555> **说明:**
1556>
1557> 1. 从API version 10开始,支持RSA使用PSS填充模式时,获取、设置[SignSpecItem](../reference/apis/js-apis-cryptoFramework.md#signspecitem10)参数。
1558> 2. 从API version 10开始,支持签名验签时字符串参数不带密钥长度。
1559
1560### 接口及参数说明
1561
1562详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。<br/>由于密码算法的复杂性,在选取不同规格和参数时,开发差异较大,无法通过代码示例一一列举,请仔细阅读API参考资料中的相关接口,确保使用正确。
1563
1564|实例名|接口名|描述|
1565|---|---|---|
1566|cryptoFramework|createSign(algName : string) : Sign|根据String设置的参数创建Sign对象|
1567|Sign|init(priKey : PriKey, callback : AsyncCallback\<void>) : void|使用callback方式设置密钥并初始化Sign对象|
1568|Sign|init(priKey : PriKey) : Promise\<void>|使用Promise方式设置密钥并初始化Sign对象|
1569|Sign|update(data : DataBlob, callback : AsyncCallback\<void>) : void|使用callback方式添加签名数据|
1570|Sign|update(data : DataBlob) : Promise\<void>|用Promise方式添加签名数据|
1571|Sign|sign(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|使用callback方式签名所有数据|
1572|Sign|sign(data : DataBlob) : Promise\<DataBlob>|使用Promise方式签名所有数据|
1573|Sign|getSignSpec(itemType: SignSpecItem): string \| number|获得签名的参数,当前仅支持RSA算法|
1574|Sign|setSignSpec(itemType: SignSpecItem, itemValue: number): void|设置签名的参数,当前仅支持RSA算法|
1575|cryptoFramework|function createVerify(algName : string) : Verify|根据String设置的参数创建Verify对象|
1576|Verify|init(pubKey : PubKey, callback : AsyncCallback\<void>) : void|使用callback方式设置密钥并初始化Verify对象|
1577|Verify|init(pubKey : PubKey) : Promise\<void>|使用Promise方式设置密钥并初始化Verify对象|
1578|Verify|update(data : DataBlob, callback : AsyncCallback\<void>) : void|使用callback方式添加验签数据|
1579|Verify|update(data : DataBlob) : Promise\<void>|用Promise方式添加验签数据|
1580|Verify|verify(data : DataBlob, signatureData : DataBlob, callback : AsyncCallback\<boolean>) : void|使用callback方式验签所有数据|
1581|Verify|verify(data : DataBlob, signatureData : DataBlob) : Promise\<boolean>|使用Promise方式验签所有数据|
1582|Verify|getVerifySpec(itemType: SignSpecItem): string \| number|获得验签的参数,当前仅支持RSA算法|
1583|Verify|setVerifySpec(itemType: SignSpecItem, itemValue: number): void|设置验签的参数,当前仅支持RSA算法|
1584
1585### RSA签名验签开发步骤
1586
1587示例1:使用RSA签名验签操作
1588
15891. 生成RSA密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成RSA非对称密钥。
15902. 生成Sign对象。通过createSign接口创建Sign对象,执行初始化操作并设置签名私钥。
15913. 执行签名操作。通过Sign类提供的update接口,添加签名数据,并调用sign接口生成数据的签名。
15924. 生成Verify对象。通过createVerify接口创建Verify对象,执行初始化操作并设置验签公钥。
15935. 执行验签操作。通过Verify类提供的update接口,添加签名数据,并调用verify接口传入签名进行验签。
1594
1595```ts
1596import cryptoFramework from '@ohos.security.cryptoFramework';
1597import { BusinessError } from '@ohos.base';
1598
1599// 可理解的字符串转成字节流
1600function stringToUint8Array(str: string) {
1601  let arr = new Uint8Array(str.length);
1602  for (let i = 0, j = str.length; i < j; ++i) {
1603    arr[i] = str.charCodeAt(i);
1604  }
1605  return arr;
1606}
1607
1608let globalKeyPair: cryptoFramework.KeyPair;
1609let signMessageBlob: cryptoFramework.DataBlob;
1610let plan1 = "This is Sign test plan1";
1611let plan2 = "This is Sign test plan1";
1612let input1: cryptoFramework.DataBlob = { data: stringToUint8Array(plan1) };
1613let input2: cryptoFramework.DataBlob = { data: stringToUint8Array(plan2) };
1614
1615function signMessagePromise() {
1616  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
1617  let signer = cryptoFramework.createSign("RSA1024|PKCS1|SHA256"); // From API version 10, a Sign instance can be created by specifying a string parameter defining the key specifications.
1618  let keyGenPromise = rsaGenerator.generateKeyPair();
1619  keyGenPromise.then(keyPair => {
1620    globalKeyPair = keyPair;
1621    let priKey = globalKeyPair.priKey;
1622    return signer.init(priKey);
1623  }).then(() => {
1624    return signer.update(input1);
1625  }).then(() => {
1626    return signer.sign(input2);
1627  }).then(dataBlob => {
1628    signMessageBlob = dataBlob;
1629    console.info("sign output is " + signMessageBlob.data);
1630  });
1631}
1632
1633// Call verify() after sign() is called.
1634function verifyMessagePromise() {
1635  let verifyer = cryptoFramework.createVerify("RSA1024|PKCS1|SHA256");
1636  let verifyInitPromise = verifyer.init(globalKeyPair.pubKey);
1637  verifyInitPromise.then(() => {
1638    return verifyer.update(input1);
1639  }).then(() => {
1640    return verifyer.verify(input2, signMessageBlob);
1641  }).then(res => {
1642    console.log("Verify result is " + res);
1643  });
1644}
1645
1646function signMessageCallback() {
1647  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
1648  let signer = cryptoFramework.createSign("RSA1024|PKCS1|SHA256"); // From API version 10, a Sign instance can be created by specifying a string parameter defining the key specifications.
1649  rsaGenerator.generateKeyPair((err, keyPair) => {
1650    globalKeyPair = keyPair;
1651    let priKey = globalKeyPair.priKey;
1652    signer.init(priKey, err => {
1653      signer.update(input1, err => {
1654        signer.sign(input2, (err, data) => {
1655          signMessageBlob = data;
1656          console.info("sign output is " + signMessageBlob.data);
1657        });
1658      });
1659    });
1660  });
1661}
1662
1663// Call verify() after sign() is called.
1664function verifyMessageCallback() {
1665  let verifyer = cryptoFramework.createVerify("RSA1024|PKCS1|SHA256");
1666  verifyer.init(globalKeyPair.pubKey, err => {
1667    verifyer.update(input1, err => {
1668      verifyer.verify(input2, signMessageBlob, (err, data) => {
1669        console.info("verify result is " + data);
1670      });
1671    });
1672  })
1673}
1674```
1675
1676### ECDSA签名验签开发步骤
1677
1678示例2:使用ECDSA操作
1679
16801. 生成ECC密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成ECC非对称密钥。
16812. 生成Sign对象。通过createSign接口创建Sign对象,执行初始化操作并设置签名私钥。
16823. 执行签名操作。通过Sign类提供的update接口,添加签名数据,并调用doFinal接口生成数据的签名。
16834. 生成Verify对象。通过createVerify接口创建Verify对象,执行初始化操作并设置验签公钥。
16845. 执行验签操作。通过Verify类提供的update接口,添加签名数据,并调用doFinal接口传入签名进行验签。
1685
1686```ts
1687import cryptoFramework from '@ohos.security.cryptoFramework';
1688import { BusinessError } from '@ohos.base';
1689
1690// 可理解的字符串转成字节流
1691function stringToUint8Array(str: string) {
1692  let arr = new Uint8Array(str.length);
1693  for (let i = 0, j = str.length; i < j; ++i) {
1694    arr[i] = str.charCodeAt(i);
1695  }
1696  return arr;
1697}
1698
1699let globalKeyPair: cryptoFramework.KeyPair;
1700let signMessageBlob: cryptoFramework.DataBlob;
1701let plan1 = "This is Sign test plan1";
1702let plan2 = "This is Sign test plan1";
1703let input1: cryptoFramework.DataBlob = { data: stringToUint8Array(plan1) };
1704let input2: cryptoFramework.DataBlob = { data: stringToUint8Array(plan2) };
1705
1706function signMessagePromise() {
1707  let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
1708  let signer = cryptoFramework.createSign("ECC256|SHA256");
1709  let keyGenPromise = eccGenerator.generateKeyPair();
1710  keyGenPromise.then(keyPair => {
1711    globalKeyPair = keyPair;
1712    let priKey = globalKeyPair.priKey;
1713    return signer.init(priKey);
1714  }).then(() => {
1715    return signer.update(input1);
1716  }).then(() => {
1717    return signer.sign(input2);
1718  }).then(dataBlob => {
1719    signMessageBlob = dataBlob;
1720    console.info("sign output is " + signMessageBlob.data);
1721  });
1722}
1723
1724function verifyMessagePromise() {
1725  let verifyer = cryptoFramework.createVerify("ECC256|SHA256");
1726  let verifyInitPromise = verifyer.init(globalKeyPair.pubKey);
1727  verifyInitPromise.then(() => {
1728    return verifyer.update(input1);
1729  }).then(() => {
1730    return verifyer.verify(input2, signMessageBlob);
1731  }).then(res => {
1732    console.log("Verify result is " + res);
1733  });
1734}
1735
1736function signMessageCallback() {
1737  let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
1738  let signer = cryptoFramework.createSign("ECC256|SHA256");
1739  eccGenerator.generateKeyPair((err, keyPair) => {
1740    globalKeyPair = keyPair;
1741    let priKey = globalKeyPair.priKey;
1742    signer.init(priKey, err => {
1743      signer.update(input1, err => {
1744        signer.sign(input2, (err, data) => {
1745          signMessageBlob = data;
1746          console.info("sign output is " + signMessageBlob.data);
1747        });
1748      });
1749    });
1750  });
1751}
1752
1753function verifyMessageCallback() {
1754  let verifyer = cryptoFramework.createVerify("ECC256|SHA256");
1755  verifyer.init(globalKeyPair.pubKey, err => {
1756    verifyer.update(input1, err => {
1757      verifyer.verify(input2, signMessageBlob, (err, data) => {
1758        console.info("verify result is " + data);
1759      });
1760    });
1761  })
1762}
1763```
1764
1765### RSA分段签名验签开发步骤
1766
1767示例3:使用RSA签名验签操作
1768
17691. 生成RSA密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成RSA非对称密钥。
17702. 生成Sign对象。通过createSign接口创建Sign对象,执行初始化操作并设置签名私钥。
17713. 执行签名操作。通过Sign类提供的update接口,多次添加签名数据,并调用sign接口生成数据的签名,完成分段签名。
17724. 生成Verify对象。通过createVerify接口创建Verify对象,执行初始化操作并设置验签公钥。
17735. 执行验签操作。多次通过Verify类提供的update接口,添加签名数据,并调用verify接口传入签名进行验签,完成分段验签。
1774
1775```ts
1776import cryptoFramework from '@ohos.security.cryptoFramework';
1777import { BusinessError } from '@ohos.base';
1778
1779// 可理解的字符串转成字节流
1780function stringToUint8Array(str: string) {
1781  let arr = new Uint8Array(str.length);
1782  for (let i = 0, j = str.length; i < j; ++i) {
1783    arr[i] = str.charCodeAt(i);
1784  }
1785  return arr;
1786}
1787
1788function signLongMessagePromise() {
1789  let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1790    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1791    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1792    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1793    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1794    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1795    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1796    "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!";
1797  let globalSignData: Uint8Array;
1798  let textSplitLen = 64; // Customized data splitting length.
1799  let keyGenName = "RSA1024";
1800  let signAlgName = "RSA1024|PKCS1|SHA256";
1801  let globalKeyPair: cryptoFramework.KeyPair;
1802  let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // Create an AsyKeyGenerator object.
1803  let signer = cryptoFramework.createSign(signAlgName); // Create a Signer instance.
1804  let verifier = cryptoFramework.createVerify(signAlgName); // Create a Verifier instance.
1805  let keyGenPromise = asyKeyGenerator.generateKeyPair();
1806  keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => {
1807    globalKeyPair = rsaKeyPair; // Save the key pair as a global variable.
1808    return signer.init(globalKeyPair.priKey);
1809  })
1810    .then(async (): Promise<void> => {
1811      // If the plaintext is too large, split the plaintext based on the specified length and cyclically call update() to pass in the plaintext.
1812      for (let i = 0; i < (globalPlainText.length / textSplitLen); i++) {
1813        let tempStr = globalPlainText.substr(i * textSplitLen, textSplitLen);
1814        let tempBlob: cryptoFramework.DataBlob = { data: stringToUint8Array(tempStr) };
1815        await signer.update(tempBlob);
1816      }
1817    })
1818    .then((): Promise<cryptoFramework.DataBlob> => {
1819      return signer.sign(null);
1820    })
1821    .then((signData: cryptoFramework.DataBlob): Promise<void> => {
1822      globalSignData = signData.data;
1823      console.info(`globalSignOutput len is ${globalSignData.length}, data is: ${globalSignData.toString()}`);
1824      return verifier.init(globalKeyPair.pubKey);
1825    })
1826    .then(async () => {
1827      // If the plaintext is too large, split the plaintext based on the specified length and cyclically call update() to pass in the plaintext.
1828      for (let i = 0; i < (globalPlainText.length / textSplitLen); i++) {
1829        let tempData = globalPlainText.slice(i * textSplitLen, (i + 1) * textSplitLen);
1830        let tempBlob: cryptoFramework.DataBlob = { data: stringToUint8Array(tempData) };
1831        await verifier.update(tempBlob);
1832      }
1833      return;
1834    })
1835    .then((): Promise<boolean> => {
1836      return verifier.verify(null, { data: globalSignData });
1837    })
1838    .then(res => {
1839      console.info(`verify res is ${res}`);
1840    })
1841    .catch((error: BusinessError) => {
1842      console.error(`catch error, ${error.code}, ${error.message}`);
1843    })
1844}
1845```
1846
1847### RSA签名验签PSS模式开发步骤
1848
1849示例4:使用RSA签名验签PSS模式,以Callback形式完成签名验签流程。
1850
18511. 根据密钥参数生成RSA密钥。通过createAsyKeyGeneratorBySpec接口创建AsyKeyGeneratorBySpec对象,并生成RSA非对称密钥对。
18522. 生成Sign对象。通过createSign接口创建Sign对象,执行初始化操作并设置签名私钥,可以获得、设置PSS模式相关参数。
18533. 执行签名操作。通过Sign类提供的update接口,添加签名数据,并调用sign接口生成数据的签名。
18544. 生成Verify对象。通过createVerify接口创建Verify对象,执行初始化操作并设置验签公钥,可以获得、设置PSS模式相关参数,验签成功需要保证盐值长度一致。
18555. 执行验签操作。通过Verify类提供的update接口,添加签名数据,并调用verify接口传入签名进行验签。
1856
1857```ts
1858import cryptoFramework from '@ohos.security.cryptoFramework';
1859import { BusinessError } from '@ohos.base';
1860
1861// Convert strings in plaintext into byte streams.
1862function stringToUint8Array(str: string) {
1863  let arr = new Uint8Array(str.length);
1864  for (let i = 0, j = str.length; i < j; ++i) {
1865    arr[i] = str.charCodeAt(i);
1866  }
1867  return arr;
1868}
1869
1870// Convert byte streams into strings in plaintext.
1871function uint8ArrayToString(array: Uint8Array) {
1872  let arrayString = '';
1873  for (let i = 0; i < array.length; i++) {
1874    arrayString += String.fromCharCode(array[i]);
1875  }
1876  return arrayString;
1877}
1878
1879// 根据密钥参数属性构造RSA非对称密钥对密钥参数
1880function genRsaKeyPairSpec(nIn: bigint, eIn: bigint, dIn: bigint) {
1881  let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = {
1882    n: nIn,
1883    algName: "RSA",
1884    specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC
1885  };
1886  let rsaKeyPairSpec: cryptoFramework.RSAKeyPairSpec = {
1887    params: rsaCommSpec,
1888    sk: dIn,
1889    pk: eIn,
1890    algName: "RSA",
1891    specType: cryptoFramework.AsyKeySpecType.KEY_PAIR_SPEC
1892  };
1893  return rsaKeyPairSpec;
1894}
1895
1896// 生成RSA2048密钥对参数
1897function genRsa2048KeyPairSpec(): cryptoFramework.RSAKeyPairSpec {
1898  let nIn = BigInt("0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25");
1899  let eIn = BigInt("0x010001");
1900  let dIn = BigInt("0x6a7df2ca63ead4dda191d614b6b385e0d9056a3d6d5cfe07db1daabee022db08212d97613d3328e0267c9dd23d787abde2afcb306aeb7dfce69246cc73f5c87fdf06030179a2114b767db1f083ff841c025d7dc00cd82435b9a90f695369e94df23d2ce458bc3b3283ad8bba2b8fa1ba62e2dce9accff3799aae7c840016f3ba8e0048c0b6cc4339af7161003a5beb864a0164b2c1c9237b64bc87556994351b27506c33d4bcdfce0f9c491a7d6b0628c7c852be4f0a9c3132b2ed3a2c8881e9aab07e20e17deb074691be677776a78b5c502e05d9bdde72126b3738695e2dd1a0a98a14247c65d8a7ee79432a092cb0721a12df798e44f7cfce0c498147a9b1");
1901  return genRsaKeyPairSpec(nIn, eIn, dIn);
1902}
1903
1904function verifyMessageCallbackPSS() {
1905  let plan1 = "This is Sign test plan1";
1906  let plan2 = "This is Sign test plan1";
1907  let input1: cryptoFramework.DataBlob = { data: stringToUint8Array(plan1) };
1908  let input2: cryptoFramework.DataBlob = { data: stringToUint8Array(plan2) };
1909  let globalKeyPair: cryptoFramework.KeyPair;
1910  let signMessageBlob: cryptoFramework.DataBlob;
1911  // Obtain the key parameter object of the RSA key pair.
1912  let rsaKeyPairSpec = genRsa2048KeyPairSpec();
1913  // Create an RSA key pair generator.
1914  let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaKeyPairSpec);
1915  // Both sign() and verify() support the RSA key with or without the length.
1916  let signer = cryptoFramework.createSign("RSA|PSS|SHA256|MGF1_SHA256");
1917  let verifyer = cryptoFramework.createVerify("RSA2048|PSS|SHA256|MGF1_SHA256");
1918  rsaGeneratorSpec.generateKeyPair((err, keyPair) => {
1919    globalKeyPair = keyPair;
1920    signer.init(globalKeyPair.priKey, err => {
1921      // After the initialization, set and obtain the PSS parameters.
1922      let setN = 32;
1923      signer.setSignSpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM, setN);
1924      let saltLen = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM);
1925      console.info("SaltLen == " + saltLen);
1926      let tf = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_TRAILER_FIELD_NUM);
1927      console.info("trailer field == " + tf);
1928      let md = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MD_NAME_STR);
1929      console.info("md == " + md);
1930      let mgf = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MGF_NAME_STR);
1931      console.info("mgf == " + mgf);
1932      let mgf1Md = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MGF1_MD_STR);
1933      console.info("mgf1Md == " + mgf1Md);
1934      signer.update(input1, err => {
1935        signer.sign(input2, (err, data) => {
1936          // Before signature verification initialization, set and obtain PSS parameters. The functions are the same as those after initialization.
1937          signMessageBlob = data;
1938          AlertDialog.show({ message: "res" + signMessageBlob.data });
1939          let setN = 32;
1940          verifyer.setVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM, setN);
1941          let saltLen = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM);
1942          console.info("SaltLen == " + saltLen);
1943          let tf = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_TRAILER_FIELD_NUM);
1944          console.info("trailer field == " + tf);
1945          let md = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MD_NAME_STR);
1946          console.info("md == " + md);
1947          let mgf = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF_NAME_STR);
1948          console.info("mgf == " + mgf);
1949          let mgf1Md = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF1_MD_STR);
1950          console.info("mgf1Md == " + mgf1Md);
1951          verifyer.init(globalKeyPair.pubKey, err => {
1952            verifyer.update(input1, err => {
1953              verifyer.verify(input2, signMessageBlob, (err, data) => {
1954                AlertDialog.show({ message: "res " + data });
1955              })
1956            });
1957          });
1958        });
1959      });
1960    });
1961  });
1962}
1963```
1964
1965### SM2签名验签开发步骤
1966
1967> **说明:**
1968>
1969> 从API version 10开始, 支持SM2签名验签。
1970
1971示例5:使用SM2操作
1972
19731. 生成SM2密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成SM2非对称密钥。
19742. 生成Sign对象。通过createSign接口创建Sign对象,执行初始化操作并设置签名私钥。
19753. 执行签名操作。通过Sign类提供的update接口,添加签名数据,并调用doFinal接口生成数据的签名。
19764. 生成Verify对象。通过createVerify接口创建Verify对象,执行初始化操作并设置验签公钥。
19775. 执行验签操作。通过Verify类提供的update接口,添加签名数据,并调用doFinal接口传入签名进行验签。
1978
1979```ts
1980import cryptoFramework from '@ohos.security.cryptoFramework';
1981import { BusinessError } from '@ohos.base';
1982
1983// Convert strings in plaintext into byte streams.
1984function stringToUint8Array(str: string) {
1985  let arr = new Uint8Array(str.length);
1986  for (let i = 0, j = str.length; i < j; ++i) {
1987    arr[i] = str.charCodeAt(i);
1988  }
1989  return arr;
1990}
1991
1992let plan1 = "This is Sign test plan1";
1993let plan2 = "This is Sign test plan2";
1994let input1: cryptoFramework.DataBlob = { data: stringToUint8Array(plan1) };
1995let input2: cryptoFramework.DataBlob = { data: stringToUint8Array(plan2) };
1996
1997function signAndVerify() {
1998  let signMessageBlob: cryptoFramework.DataBlob;
1999  let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256");
2000  let signer = cryptoFramework.createSign("SM2_256|SM3");
2001  sm2Generator.generateKeyPair((err, keyPair) => {
2002    let priKey = keyPair.priKey;
2003    signer.init(priKey, err => {
2004      signer.update(input1, err => {
2005        signer.sign(input2, (err, data) => {
2006          signMessageBlob = data;
2007          console.info("sign output is " + signMessageBlob.data);
2008          let verifyer = cryptoFramework.createVerify("SM2_256|SM3");
2009          verifyer.init(keyPair.pubKey, err => {
2010            verifyer.update(input1, err => {
2011              verifyer.verify(input2, signMessageBlob, (err, data) => {
2012                console.info("verify result is " + data);
2013                AlertDialog.show({ message: "verify success" })
2014              });
2015            });
2016          })
2017        });
2018      });
2019    });
2020  });
2021}
2022```
2023
2024## 使用密钥协商操作
2025
2026### 场景说明
2027
2028使用密钥协商操作中,典型的场景有:
2029
2030通信双方可以在一个公开的信道上通过相互传送一些消息,共同建立一个安全的共享秘密密钥。
2031
2032> **说明:**
2033>
2034> 从API version 10开始,支持密钥协商时字符串参数不带密钥长度。
2035
2036### 接口及参数说明
2037
2038详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。
2039
2040|实例名|接口名|描述|
2041|---|---|---|
2042|cryptoFramework|createKeyAgreement(algName : string) : KeyAgreement|根据String设置的参数创建KeyAgreement对象|
2043|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey, callback : AsyncCallback\<DataBlob>) : void|使用callback方式进行密钥协商|
2044|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey) : Promise\<DataBlob>|使用Promise方式进行密钥协商|
2045
2046### 开发步骤
2047
20481. 生成ECC密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成ECC非对称密钥。
20492. 基于ECC密钥的私钥及公钥执行ECDH操作。
2050
2051```ts
2052import cryptoFramework from '@ohos.security.cryptoFramework';
2053import { BusinessError } from '@ohos.base';
2054
2055let globalKeyPair: cryptoFramework.KeyPair;
2056
2057function ecdhPromise() {
2058  let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
2059  let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256"); // ECC is supported for key agreement from API version 10.
2060  let keyGenPromise = eccGenerator.generateKeyPair();
2061  keyGenPromise.then(keyPair => {
2062    globalKeyPair = keyPair;
2063    return eccKeyAgreement.generateSecret(keyPair.priKey, keyPair.pubKey);
2064  }).then((secret) => {
2065    console.info("ecdh output is " + secret.data);
2066  }).catch((error: BusinessError) => {
2067    console.error("ecdh error.");
2068  });
2069}
2070
2071function ecdhCallback() {
2072  let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
2073  let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256");
2074  eccGenerator.generateKeyPair((err, keyPair) => {
2075    globalKeyPair = keyPair;
2076    eccKeyAgreement.generateSecret(keyPair.priKey, keyPair.pubKey, (err, secret) => {
2077      if (err) {
2078        console.error("ecdh error.");
2079        return;
2080      }
2081      console.info("ecdh output is " + secret.data);
2082    });
2083  });
2084}
2085```
2086
2087## 使用摘要操作
2088
2089### 场景说明
2090
2091用户指定摘要算法(如SHA256)生成Md实例,并输入单段或多段需要摘要的信息,进行摘要计算更新,并返回消息摘要计算结果,在指定算法后可获取当前算法名与摘要计算长度(字节)
2092
2093使用摘要操作的主要场景为:
2094
2095用户指定摘要算法(如SHA256)生成Md实例,并输入单段或多段需要摘要的信息,进行摘要计算更新,并返回消息摘要计算结果,在指定算法后可获取当前算法名与摘要计算长度(字节)
2096
2097### 接口及参数说明
2098
2099详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。
2100
2101| 实例名          | 接口名                                                       | 描述                                               |
2102| --------------- | ------------------------------------------------------------ | -------------------------------------------------- |
2103| cryptoFramework | function createMd(algName : string) : Md;                    | 指定摘要算法,生成摘要操作实例Md                   |
2104| Md              | update(input : DataBlob, callback : AsyncCallback\<void>) : void; | 接受用户输入数据,通过Callback的方式,异步更新摘要 |
2105| Md              | update(input : DataBlob) : Promise\<void>;                  | 接受用户输入数据,通过Promise的方式,异步更新摘要  |
2106| Md              | digest(callback : AsyncCallback\<DataBlob>) : void;         | 通过Callback的方式,返回结果                       |
2107| Md              | digest() : Promise\<DataBlob>;                              | 通过Promise的方式,返回结果                        |
2108| Md              | getMdLength() : number;                                      | 获取摘要的长度(由指定的摘要算法决定)             |
2109| Md              | readonly algName : string;                                   | 获取当前设置的摘要算法名                           |
2110
2111### 摘要算法开发步骤
2112
21131. 设置算法,通过接口`createMd`生成摘要操作实例。
21142. 接受用户数据,通过接口`update`,更新摘要,此步骤可重复,算法库不限制单次update的长度。
21153. 通过接口`digest`,返回摘要计算结果。
21164. 获取当前摘要算法名与摘要计算长度。
2117
2118```ts
2119import cryptoFramework from '@ohos.security.cryptoFramework';
2120import { BusinessError } from '@ohos.base';
2121
2122// Convert strings in plaintext into byte streams.
2123function stringToUint8Array(str: string) {
2124  let arr = new Uint8Array(str.length);
2125  for (let i = 0, j = str.length; i < j; ++i) {
2126    arr[i] = str.charCodeAt(i);
2127  }
2128  return arr;
2129}
2130
2131// 以Promise方式完成摘要
2132function doMdByPromise() {
2133  let mdAlgName = "SHA256"; // Digest algorithm name.
2134  let message = "mdTestMessgae"; // Data to be digested.
2135  let md = cryptoFramework.createMd(mdAlgName);
2136  ;
2137  console.info("[Promise]: Md algName is: " + md.algName);
2138  // If the data volume is small, you can use update() once to pass in all data. There is no limit on the length of the input parameter.
2139  let promiseMdUpdate = md.update({ data: stringToUint8Array(message) });
2140  promiseMdUpdate.then(() => {
2141    // Call digest() to return the result.
2142    let PromiseMdDigest = md.digest();
2143    return PromiseMdDigest;
2144  }).then(digestOutput => {
2145    let mdOutput = digestOutput;
2146    console.info("[Promise]: MD result: " + mdOutput.data);
2147    let mdLen = md.getMdLength();
2148    console.info("[Promise]: MD len: " + mdLen);
2149  }).catch((error: BusinessError) => {
2150    console.error("[Promise]: error: " + error.message);
2151  });
2152}
2153
2154// 以Callback方式完成摘要
2155function doMdByCallback() {
2156  let mdAlgName = "SHA256"; // Digest algorithm name.
2157  let message = "mdTestMessgae"; // Data to be digested.
2158  let md = cryptoFramework.createMd(mdAlgName);
2159  console.info("[Callback]: Md algName is: " + md.algName);
2160  // If the data volume is small, you can use update() once to pass in all data. There is no limit on the length of the input parameter.
2161  md.update({ data: stringToUint8Array(message) }, (err,) => {
2162    if (err) {
2163      console.error("[Callback]: err: " + err.code);
2164    }
2165    md.digest((err1, digestOutput) => {
2166      if (err1) {
2167        console.error("[Callback]: err: " + err1.code);
2168      } else {
2169        let mdOutput = digestOutput;
2170        console.info("[Callback]: MD result: " + mdOutput.data);
2171        let mdLen = md.getMdLength();
2172        console.info("[Callback]: MD len: " + mdLen);
2173      }
2174    });
2175  });
2176}
2177```
2178
2179### 分段摘要算法开发步骤
2180
21811. 设置算法,通过接口`createMd`生成摘要操作实例。
21822. 接受用户数据,多次通过接口`update`,更新摘要,实现分段。
21833. 通过接口`digest`,返回摘要计算结果。
21844. 获取当前摘要算法名与摘要计算长度。
2185
2186```ts
2187import cryptoFramework from '@ohos.security.cryptoFramework';
2188import { BusinessError } from '@ohos.base';
2189
2190// 可理解的字符串转成字节流
2191function stringToUint8Array(str: string) {
2192  let arr = new Uint8Array(str.length);
2193  for (let i = 0, j = str.length; i < j; ++i) {
2194    arr[i] = str.charCodeAt(i);
2195  }
2196  return arr;
2197}
2198
2199// 使用Promise方式,完成分段摘要
2200async function doLoopMdPromise() {
2201  let mdAlgName = "SHA256"; // Digest algorithm name.
2202  let md = cryptoFramework.createMd(mdAlgName);
2203  ;
2204  console.info("[Promise]: Md algName is: " + md.algName);
2205  let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // Assume that the message is of 43 bytes.
2206  let messageArr: number[] = [];
2207  let updateLength = 20; // For example, pass in 20 bytes in each update().
2208
2209  for (let i = 0; i <= messageText.length; i++) {
2210    if ((i % updateLength == 0 || i == messageText.length) && messageArr.length != 0) {
2211      let message = new Uint8Array(messageArr);
2212      let messageBlob: cryptoFramework.DataBlob = { data: message };
2213      // Use await to process the update() in the for() loop.
2214      try {
2215        await md.update(messageBlob); // Use update() to process data by segment.
2216      } catch (error) {
2217        let e: BusinessError = error as BusinessError;
2218        console.error(`await update error, ${e.code}, ${e.message}`);
2219        return;
2220      }
2221      messageArr = [];
2222    }
2223    // Pad messageArr based on the segment length.
2224    if (i < messageText.length) {
2225      messageArr.push(messageText.charCodeAt(i));
2226    }
2227  }
2228  let PromiseMdDigest = md.digest();
2229  PromiseMdDigest.then(digestOutput => {
2230    let mdOutput = digestOutput;
2231    console.info("[Promise]: MD result: " + mdOutput.data);
2232    let mdLen = md.getMdLength();
2233    console.info("[Promise]: MD len: " + mdLen);
2234  }).catch((error: BusinessError) => {
2235    console.error("[Promise]: error: " + error.message);
2236  });
2237}
2238```
2239
2240## 使用消息认证码操作
2241
2242### 场景说明
2243
2244消息认证码操作主要应用于身份认证的场景:
2245
2246Mac(message authentication code)可以对消息进行完整性校验,通过使用双方共享的密钥,识别出信息伪装篡改等行为。
2247
2248用户指定摘要算法(如SHA256)生成消息认证码Mac实例,输入对称密钥初始化Mac,并传入单段或多段需要摘要的信息,进行消息认证码计算,并获取消息认证码计算结果,在指定算法后可获取当前算法名与消息认证码计算长度(字节)。
2249
2250### 接口及参数说明
2251
2252详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。
2253
2254| 实例名          | 接口名                                                       | 描述                                                |
2255| --------------- | ------------------------------------------------------------ | --------------------------------------------------- |
2256| cryptoFramework | function createMac(algName : string) : Mac;                  | 指定摘要算法,生成消息认证码实例Mac                 |
2257| Mac             | init(key : SymKey, callback : AsyncCallback\<void>) : void; | 接收输入对称密钥,通过Callback的方式,异步初始化MAC |
2258| Mac             | init(key : SymKey) : Promise\<void>;                        | 接收输入对称密钥,通过Promise的方式,异步初始化MAC  |
2259| Mac             | update(input : DataBlob, callback : AsyncCallback\<void>) : void; | 接受输入数据,通过Callback的方式,异步更新MAC       |
2260| Mac             | update(input : DataBlob) : Promise\<void>;                  | 接受输入数据,通过Promise的方式,异步更新MAC        |
2261| Mac             | doFinal(callback : AsyncCallback\<DataBlob>) : void;        | 通过Callback的方式,返回MAC计算结果                 |
2262| Mac             | doFinal() : Promise\<DataBlob>;                             | 通过Promise的方式,返回MAC计算结果                  |
2263| Mac             | getMacLength() : number;                                     | 获取MAC的长度(由指定的摘要算法决定)               |
2264| Mac             | readonly algName : string;                                   | 获取当前设置的摘要算法名                            |
2265
2266### HMAC开发步骤
2267
22681. 设置算法,通过接口`createMac`生成消息认证码操作实例。
22692. 接受输入对称密钥,通过接口`init`,初始化Mac。
22703. 接受数据,通过接口`update`,更新Mac,此步骤可重复。
22714. 通过接口`doFinal`,返回Mac计算结果。
22725. 获取当前摘要算法名与Mac计算长度。
2273
2274```ts
2275import cryptoFramework from '@ohos.security.cryptoFramework';
2276import { BusinessError } from '@ohos.base';
2277
2278// 可理解的字符串转成字节流
2279function stringToUint8Array(str: string) {
2280  let arr = new Uint8Array(str.length);
2281  for (let i = 0, j = str.length; i < j; ++i) {
2282    arr[i] = str.charCodeAt(i);
2283  }
2284  return arr;
2285}
2286
2287// Generate an HMAC in promise mode.
2288function doHmacByPromise() {
2289  let macAlgName = "SHA256"; // Digest algorithm name.
2290  let message = "hmacTestMessgae"; // Data used to generate an HMAC.
2291  let mac = cryptoFramework.createMac(macAlgName);
2292  console.info("[Promise]: Mac algName is: " + mac.algName);
2293  let KeyBlob: cryptoFramework.DataBlob = {
2294    // 128-bit key
2295    data: stringToUint8Array("12345678abcdefgh")
2296  }
2297  let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128");
2298  // Convert the binary data into a key.
2299  let promiseConvertKey = symKeyGenerator.convertKey(KeyBlob);
2300  promiseConvertKey.then(symKey => {
2301    let promiseMacInit = mac.init(symKey);
2302    return promiseMacInit;
2303  })
2304    .then(() => {
2305      // If the data volume is small, you can use update() once to pass in all data. There is no limit on the length of the input parameter.
2306      let promiseMacUpdate = mac.update({ data: stringToUint8Array(message) });
2307      return promiseMacUpdate;
2308    })
2309    .then(() => {
2310      let PromiseMacDoFinal = mac.doFinal();
2311      return PromiseMacDoFinal;
2312    })
2313    .then(output => {
2314      let macOutput = output;
2315      console.info("[Promise]: HMAC result: " + macOutput.data);
2316      let macLen = mac.getMacLength();
2317      console.info("[Promise]: MAC len: " + macLen);
2318    })
2319    .catch((error: BusinessError) => {
2320      console.error("[Promise]: error: " + error.message);
2321    });
2322}
2323
2324// Generate an HMAC in callback mode.
2325function doHmacByCallback() {
2326  let macAlgName = "SHA256"; // Digest algorithm name.
2327  let message = "hmacTestMessgae"; // Data used to generate an HMAC.
2328  let mac = cryptoFramework.createMac(macAlgName);
2329  console.info("[Promise]: Mac algName is: " + mac.algName);
2330  let KeyBlob: cryptoFramework.DataBlob = {
2331    // 128-bit key
2332    data: stringToUint8Array("12345678abcdefgh")
2333  }
2334  let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128");
2335  // Convert the binary data into a key.
2336  symKeyGenerator.convertKey(KeyBlob, (err, symKey) => {
2337    if (err) {
2338      console.error("[Callback]: err: " + err.code);
2339    }
2340    mac.init(symKey, (err1,) => {
2341      if (err1) {
2342        console.error("[Callback]: err: " + err1.code);
2343      }
2344      // If the data volume is small, you can use update() once to pass in all data. There is no limit on the length of the input parameter.
2345      mac.update({ data: stringToUint8Array(message) }, (err2,) => {
2346        if (err2) {
2347          console.error("[Callback]: err: " + err2.code);
2348        }
2349        mac.doFinal((err3, output) => {
2350          if (err3) {
2351            console.error("[Callback]: err: " + err3.code);
2352          } else {
2353            let macOutput = output;
2354            console.error("[Callback]: HMAC result: " + macOutput.data);
2355            let macLen = mac.getMacLength();
2356            console.error("[Callback]: MAC len: " + macLen);
2357          }
2358        });
2359      });
2360    });
2361  });
2362}
2363```
2364
2365### 分段HMAC开发步骤
2366
2367以HMAC更新MAC时多次调用update实现分段为例:
2368
23691. 设置算法,通过接口`createMac`生成消息认证码操作实例。
23702. 接受输入对称密钥,通过接口`init`,初始化Mac。
23713. 接受数据,多次通过接口`update`,以实现分段。
23724. 通过接口`doFinal`,返回Mac计算结果。
23735. 获取当前摘要算法名与Mac计算长度。
2374
2375```ts
2376import cryptoFramework from '@ohos.security.cryptoFramework';
2377import { BusinessError } from '@ohos.base';
2378
2379function stringToUint8Array(str: string) {
2380  let arr = new Uint8Array(str.length);
2381  for (let i = 0, j = str.length; i < j; ++i) {
2382    arr[i] = str.charCodeAt(i);
2383  }
2384  return arr;
2385}
2386
2387function doLoopHmacPromise() {
2388  let macAlgName = "SHA256"; // Digest algorithm name.
2389  let mac = cryptoFramework.createMac(macAlgName);
2390  console.info("[Promise]: Mac algName is: " + mac.algName);
2391  let KeyBlob: cryptoFramework.DataBlob = {
2392    // 128-bit key
2393    data: stringToUint8Array("12345678abcdefgh")
2394  }
2395  let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // Assume that the message is of 43 bytes.
2396  let updateLength = 20; // For example, pass in 20 bytes in each update().
2397  let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128");
2398  // Convert the binary data into a key.
2399  let promiseConvertKey = symKeyGenerator.convertKey(KeyBlob);
2400  promiseConvertKey.then((symKey: cryptoFramework.SymKey): Promise<void> => {
2401    let promiseMacInit = mac.init(symKey);
2402    return promiseMacInit;
2403  })
2404    .then(async () => {
2405      let messageArr: number[] = [];
2406      for (let i = 0; i <= messageText.length; i++) {
2407        if ((i % updateLength == 0 || i == messageText.length) && messageArr.length != 0) {
2408          let message = new Uint8Array(messageArr);
2409          let messageBlob: cryptoFramework.DataBlob = { data: message };
2410          // Use await to process the update() in the for() loop.
2411          try {
2412            await mac.update(messageBlob); // Invoke update() multiple times.
2413          } catch (error) {
2414            let e: BusinessError = error as BusinessError;
2415            console.error(`await update error, ${e.code}, ${e.message}`);
2416            return;
2417          }
2418          messageArr = [];
2419        }
2420        // Pad messageArr based on the segment length.
2421        if (i < messageText.length) {
2422          messageArr.push(messageText.charCodeAt(i));
2423        }
2424      }
2425      return;
2426    })
2427    .then(() => {
2428      let PromiseMacDoFinal = mac.doFinal();
2429      return PromiseMacDoFinal;
2430    })
2431    .then(output => {
2432      let macOutput = output;
2433      console.log("[Promise]: HMAC result: " + macOutput.data);
2434      let macLen = mac.getMacLength();
2435      console.log("[Promise]: MAC len: " + macLen);
2436    })
2437    .catch((error: BusinessError) => {
2438      console.error("[Promise]: error: " + error.message);
2439    });
2440}
2441```
2442
2443## 使用随机数操作
2444
2445### 场景说明
2446
2447使用随机数操作的主要场景为:
2448
2449- 用户生成随机数Random实例,输入随机数生成的长度(字节),生成指定长度(范围为1~INT_MAX)的安全随机数。
2450- 用户使用生成的随机数作为参数,进行种子设置。
2451
2452### 接口及参数说明
2453
2454详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。
2455
2456| 实例名          | 接口名                                                       | 描述                                       |
2457| --------------- | ------------------------------------------------------------ | ------------------------------------------ |
2458| cryptoFramework | function createRandom() : Random;                            | 生成随机数Random实例                       |
2459| Random          | generateRandom(len : number, callback: AsyncCallback\<DataBlob>) : void; | 接受输入长度,通过Callback,异步生成随机数 |
2460| Random          | generateRandom(len : number) : Promise\<DataBlob>;           | 接受输入长度,通过Promise,异步生成随机数  |
2461| Random          | generateRandomSync(len: number): DataBlob;                   | 接受输入长度,同步生成随机数               |
2462| Random          | setSeed(seed : DataBlob) : void;                             | 接受输入Blob,设置种子                     |
2463
2464### 开发步骤
2465
24661. 通过接口`createRandom`生成随机数操作实例。
24672. 接受输入长度,通过接口`generateRandom`,生成指定长度的随机数。
24683. 接受DataBlob数据,通过接口`setSeed`,为随机数生成池设置种子。
2469
2470```ts
2471import cryptoFramework from '@ohos.security.cryptoFramework';
2472import { BusinessError } from '@ohos.base';
2473
2474// Generate a random number in promise mode.
2475function doRandByPromise() {
2476  let rand = cryptoFramework.createRandom();
2477  let len = 4; // Generate a 4-byte random number.
2478  let promiseGenerateRand = rand.generateRandom(len);
2479  promiseGenerateRand.then(randData => {
2480    console.info("[Promise]: rand result: " + randData.data);
2481    try {
2482      rand.setSeed(randData);
2483    } catch (error) {
2484      let e: BusinessError = error as BusinessError;
2485      console.error(`setSeed failed, ${e.code}, ${e.message}`);
2486    }
2487  }).catch((error: BusinessError) => {
2488    console.error("[Promise]: error: " + error.message);
2489  });
2490}
2491
2492// Generate a random number in callback mode.
2493function doRandByCallback() {
2494  let rand = cryptoFramework.createRandom();
2495  let len = 4; // Generate a 4-byte random number.
2496  rand.generateRandom(len, (err, randData) => {
2497    if (err) {
2498      console.error("[Callback]: err: " + err.code);
2499    } else {
2500      console.info("[Callback]: generate random result: " + randData.data);
2501      try {
2502        rand.setSeed(randData);
2503      } catch (error) {
2504        let e: BusinessError = error as BusinessError;
2505        console.error(`setSeed failed, ${e.code}, ${e.message}`);
2506      }
2507    }
2508  });
2509}
2510
2511// Generate a random number synchronously.
2512function doRandBySync() {
2513  let rand = cryptoFramework.createRandom();
2514  let len = 24; // Generate a 24-byte random number.
2515  try {
2516    let randData = rand.generateRandomSync(len);
2517    if (randData != null) {
2518      console.info("[Sync]: rand result: " + randData.data);
2519    } else {
2520      console.error("[Sync]: get rand result fail!");
2521    }
2522  } catch (error) {
2523    let e: BusinessError = error as BusinessError;
2524    console.error(`do rand failed, ${e.code}, ${e.message}`);
2525  }
2526}
2527```
2528
2529## 相关实例
2530
2531针对加解密算法开发,有以下相关实例可供参考:
2532
2533- [支付(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-4.0-Release/code/BasicFeature/Security/PaySecurely)
2534
2535- [通用密钥库系统(cryptoFramework)(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-4.0-Release/code/BasicFeature/Security/CryptoFramework)
2536
2537- [加解密(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-4.0-Release/code/BasicFeature/Security/Cipher)
2538
2539- [字符串加解密(ArkTS)(API9)](https://gitee.com/openharmony/codelabs/tree/master/Security/StringCipherArkTS)
2540