• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 加解密算法库框架开发指导
2
3> **说明**
4>
5> 本开发指导基于API version 9,OH SDK版本3.2.7以上,适用于JS语言开发
6
7## 使用密钥对象生成与转换操作
8
9**场景说明**
10
11使用密钥生成操作中,典型的场景有:
12
131. 随机生成算法库密钥对象。该对象可用于后续的加解密等操作。
142. 根据指定数据生成算法库密钥对象(也就是将外部或存储的二进制数据转换为算法库的密钥对象)。该对象可用于后续的加解密等操作。
153. 获取算法库密钥对象的二进制数据,用于存储或传输。
16> **说明**:密钥对象Key包括对称密钥SymKey和非对称密钥(公钥PubKey和私钥PriKey),其中公钥和私钥组成密钥对KeyPair。密钥之间的具体关系可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。
17
18
19**接口及参数说明**
20
21详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。
22
23以上场景涉及的常用接口如下表所示:
24
25|实例名|接口名|描述|
26|---|---|---|
27|cryptoFramework|createAsyKeyGenerator(algName : string) : AsyKeyGenerator|根据algName设置的非对称密钥规格,创建非对称密钥生成器对象|
28|cryptoFramework|createSymKeyGenerator(algName : string) : SymKeyGenerator|根据algName设置的对称密钥规格,创建对称密钥生成器对象|
29|AsyKeyGenerator|generateKeyPair(callback : AsyncCallback\<KeyPair>) : void|使用callback方式,随机生成非对称密钥对象KeyPair|
30|AsyKeyGenerator|generateKeyPair() : Promise\<KeyPair>|使用Promise方式,随机生成非对称密钥对象KeyPair|
31|SymKeyGenerator|generateSymKey(callback : AsyncCallback\<SymKey>) : void|使用callback方式,随机生成对称密钥对象SymKey|
32|SymKeyGenerator|generateSymKey() : Promise\<SymKey>|使用Promise方式,随机生成对称密钥对象SymKey|
33| AsyKeyGenerator          | convertKey(pubKey : DataBlob, priKey : DataBlob, callback : AsyncCallback\<KeyPair>) : void | 使用callback方式,根据指定的公钥和私钥二进制数据生成KeyPair对象<br/>(允许公钥/私钥为null,即只传入单一公钥或私钥,生成只携带公钥或私钥的KeyPair对象) |
34| AsyKeyGenerator          | convertKey(pubKey : DataBlob, priKey : DataBlob) : Promise\<KeyPair> | 使用Promise方式,根据指定的公钥和私钥二进制数据生成KeyPair对象<br/>(允许公钥/私钥为null,即只传入单一公钥或私钥,生成只携带公钥或私钥的KeyPair对象) |
35| SymKeyGenerator         | convertKey(key : DataBlob, callback : AsyncCallback\<SymKey>) : void| 使用callback方式,根据指定的二进制数据,生成对称密钥对象SymKey |
36| SymKeyGenerator         |convertKey(pubKey : DataBlob, priKey : DataBlob) : Promise\<KeyPair>| 使用Promise方式,根据指定的二进制数据,生成对称密钥对象SymKey |
37| Key | getEncoded() : DataBlob;  | 获取Key密钥对象的二进制数据(Key的子类实例包括对称密钥SymKey、公钥PubKey、私钥PriKey) |
38
39**开发步骤**
40
41示例1:随机生成非对称密钥KeyPair,并获得二进制数据(场景1、3)
42
431. 创建非对称密钥生成器;
442. 通过非对称密钥生成器随机生成非对称密钥;
453. 获取密钥对象的二进制数据;
46
47以使用Promise方式随机生成RSA密钥(1024位,素数个数为2)为例:
48
49```javascript
50import cryptoFramework from '@ohos.security.cryptoFramework';
51
52function generateAsyKey() {
53  // 创建非对称密钥生成器
54  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
55  // 通过非对称密钥生成器,随机生成非对称密钥
56  let keyGenPromise = rsaGenerator.generateKeyPair();
57  keyGenPromise.then( keyPair => {
58    globalKeyPair = keyPair;
59    let pubKey = globalKeyPair.pubKey;
60    let priKey = globalKeyPair.priKey;
61    // 获取非对称密钥的二进制数据
62    pkBlob = pubKey.getEncoded();
63    skBlob = priKey.getEncoded();
64    AlertDialog.show({ message : "pk bin data" + pkBlob.data} );
65    AlertDialog.show({ message : "sk bin data" + skBlob.data} );
66  })
67}
68```
69
70示例2:随机生成对称密钥SymKey,并获得二进制数据(场景1、3)
71
721. 创建对称密钥生成器;
732. 通过对称密钥生成器随机生成对称密钥;
743. 获取算法库密钥对象的二进制数据;
75
76以使用Promise方式随机生成AES密钥(256位)为例:
77
78```javascript
79import cryptoFramework from '@ohos.security.cryptoFramework';
80
81// 字节流以16进制输出
82function uint8ArrayToShowStr(uint8Array) {
83  return Array.prototype.map
84    .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2))
85    .join('');
86}
87
88function testGenerateAesKey() {
89  // 创建对称密钥生成器
90  let symKeyGenerator = cryptoFramework.createSymKeyGenerator('AES256');
91  // 通过密钥生成器随机生成对称密钥
92  let promiseSymKey = symKeyGenerator.generateSymKey();
93  promiseSymKey.then( key => {
94    // 获取对称密钥的二进制数据,输出长度为256bit的字节流
95    let encodedKey = key.getEncoded();
96    console.info('key hex:' + uint8ArrayToShowStr(encodedKey.data));
97  })
98}
99```
100
101示例3:根据指定的RSA非对称密钥二进制数据,生成KeyPair对象(场景2)
102
1031. 获取RSA公钥或私钥二进制数据,公钥需满足ASN.1语法、X.509规范、DER编码格式,私钥需满足ASN.1语法、PKCS#8规范、DER编码格式。
1042. 创建AsyKeyGenerator对象,调用convertKey方法,传入公钥二进制和私钥二进制(二者非必选项,可只传入其中一个),转换为KeyPair对象。
105
106```javascript
107import cryptoFramework from '@ohos.security.cryptoFramework';
108
109function convertAsyKey() {
110  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024");
111  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]);
112  let pkBlob = {data : pkval};
113  rsaGenerator.convertKey(pkBlob, null, function(err, keyPair) {
114    if (keyPair == null) {
115      AlertDialog.show({message : "Convert keypair fail"});
116    }
117    AlertDialog.show({message : "Convert KeyPair success"});
118  })
119}
120```
121
122**说明**
123
124 当前convertKey操作,公钥只支持转换满足X.509规范的DER格式,私钥只支持PKCS#8规范的DER格式;
125
126示例4:根据指定的ECC非对称密钥二进制数据,生成KeyPair对象(场景2、3)
127
1281. 获取ECC二进制密钥数据,封装成DataBlob对象。
1292. 调用convertKey方法,传入公钥二进制和私钥二进制(二者非必选项,可只传入其中一个),转换为KeyPair对象。
130
131```javascript
132import cryptoFramework from "@ohos.security.cryptoFramework"
133
134function convertEccAsyKey() {
135    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]);
136    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]);
137    let pubKeyBlob = { data: pubKeyArray };
138    let priKeyBlob = { data: priKeyArray };
139    let generator = cryptoFramework.createAsyKeyGenerator("ECC256");
140    generator.convertKey(pubKeyBlob, priKeyBlob, (error, data) => {
141        if (error) {
142            AlertDialog.show({message : "Convert keypair fail"});
143        }
144        AlertDialog.show({message : "Convert KeyPair success"});
145    })
146}
147```
148
149示例5:根据指定的对称密钥二进制数据,生成SymKey对象(场景2、3)
150
1511. 创建对称密钥生成器;
1522. 通过对称密钥生成器,根据指定的对称密钥二进制数据,生成SymKey对象;
1533. 获取算法库密钥对象的二进制数据;
154
155以使用callback方式生成3DES密钥(3DES密钥只能为192位)为例:
156
157```javascript
158import cryptoFramework from '@ohos.security.cryptoFramework';
159
160// 字节流以16进制输出
161function uint8ArrayToShowStr(uint8Array) {
162  return Array.prototype.map
163    .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2))
164    .join('');
165}
166
167function genKeyMaterialBlob() {
168  let arr = [
169    0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56,
170    0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c,
171    0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72];    // keyLen = 192 (24 bytes)
172  let keyMaterial = new Uint8Array(arr);
173  return {data : keyMaterial};
174}
175
176function testConvertAesKey() {
177  // 生成对称密钥生成器
178  let symKeyGenerator = cryptoFramework.createSymKeyGenerator('3DES192');
179  // 根据用户指定的数据,生成对称密钥
180  let keyMaterialBlob = genKeyMaterialBlob();
181  try {
182    symKeyGenerator.convertKey(keyMaterialBlob, (error, key) => {
183      if (error) {    // 业务逻辑执行错误通过callback的第一个参数返回错误信息
184        console.error(`convertKey error, ${error.code}, ${error.message}`);
185        return;
186      }
187      console.info(`key algName: ${key.algName}`);
188      console.info(`key format: ${key.format}`);
189      let encodedKey = key.getEncoded();    // 获取对称密钥的二进制数据,输出长度为192bit的字节流
190      console.info('key getEncoded hex: ' + uint8ArrayToShowStr(encodedKey.data));
191    })
192  } catch (error) {    // 参数检查的错误以同步的方式立即抛出异常
193    console.error(`convertKey failed, ${error.code}, ${error.message}`);
194    return;
195  }
196}
197```
198
199## 使用加解密操作
200
201**场景说明**
202
203在数据存储或传输场景中,可以使用加解密操作用于保证数据的机密性,防止敏感数据泄露。使用加解密操作中,典型的场景有:
2041. 使用对称密钥的加解密操作
2052. 使用非对称密钥的加解密操作
206
207**接口及参数说明**
208
209详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。<br/>由于密码算法的复杂性,在选取不同规格和参数时,开发差异较大,无法通过代码示例一一列举,请仔细阅读API参考资料中的相关接口,确保使用正确。
210
211以上场景设计的常用接口如下表所示:
212
213|实例名|接口名|描述|
214|---|---|---|
215|cryptoFramework|createCipher(transformation : string) : Cipher|根据transformation设置的算法参数创建Cipher对象|
216|Cipher|init(opMode : CryptoMode, key : Key, params : ParamsSpec, callback : AsyncCallback\<void>) : void|使用callback方式设置密钥并初始化Cipher对象|
217|Cipher|init(opMode : CryptoMode, key : Key, params : ParamsSpec) : Promise\<void>|使用Promise方式设置密钥并初始化Cipher对象|
218|Cipher|update(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|使用callback方式添加加解密数据|
219|Cipher|update(data : DataBlob) : Promise\<DataBlob>|使用Promise方式添加加解密数据|
220|Cipher|doFinal(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|使用callback方式结束对所有数据的加解密|
221|Cipher|doFinal(data : DataBlob) : Promise\<DataBlob>|使用Promise方式结束对所有数据的加解密|
222
223**开发步骤**
224
225示例1:使用对称密钥的加解密操作
226
2271. 创建对称密钥生成器。
2282. 通过密钥生成器生成对称密钥。
2293. 创建加解密生成器。
2304. 通过加解密生成器加密或解密数据。
231
232以AES GCM以Promise方式加解密为例:
233
234```js
235import cryptoFramework from '@ohos.security.cryptoFramework';
236
237var globalCipher;
238var globalGcmParams;
239var globalKey;
240var globalCipherText;
241
242function genGcmParamsSpec() {
243  let arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0 , 0, 0]; // 12 bytes
244  let dataIv = new Uint8Array(arr);
245  let ivBlob = {data : dataIv};
246
247  arr = [0, 0, 0, 0 , 0, 0, 0, 0]; // 8 bytes
248  let dataAad = new Uint8Array(arr);
249  let aadBlob = {data : dataAad};
250
251  arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0]; // 16 bytes
252  let dataTag = new Uint8Array(arr);
253  let tagBlob = {data : dataTag};  // GCM的authTag在加密时从doFinal结果中获取,在解密时填入init函数的params参数中
254
255  let gcmParamsSpec = {iv : ivBlob, aad : aadBlob, authTag : tagBlob, algName : "GcmParamsSpec"};
256  return gcmParamsSpec;
257}
258
259// 可理解的字符串转成字节流
260function stringToUint8Array(str) {
261  let arr = [];
262  for (let i = 0, j = str.length; i < j; ++i) {
263    arr.push(str.charCodeAt(i));
264  }
265  return new Uint8Array(arr);
266}
267
268// 字节流以16进制输出
269function uint8ArrayToShowStr(uint8Array) {
270  return Array.prototype.map
271    .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2))
272    .join('');
273}
274
275// 字节流转成可理解的字符串
276function uint8ArrayToString(array) {
277  let arrayString = '';
278  for (let i = 0; i < array.length; i++) {
279    arrayString += String.fromCharCode(array[i]);
280  }
281  return arrayString;
282}
283
284function genKeyMaterialBlob() {
285  let arr = [
286    0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56,
287    0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c,
288    0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72];    // keyLen = 192 (24 bytes)
289  let keyMaterial = new Uint8Array(arr);
290  return {data : keyMaterial};
291}
292
293
294// AES GCM模式示例,自动生成密钥(promise写法)
295function testAesGcm() {
296  return new Promise((resolve, reject) => {
297    setTimeout(() => {
298      resolve('testAesGcm');
299    }, 10)
300  }).then(() => {
301    // 生成对称密钥生成器
302    let symAlgName = 'AES128';
303    let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);
304    if (symKeyGenerator == null) {
305      console.error('createSymKeyGenerator failed');
306      return;
307    }
308    console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`);
309    // 通过密钥生成器随机生成128位长度的对称密钥
310    let promiseSymKey = symKeyGenerator.generateSymKey();
311    // 构造参数
312    globalGcmParams = genGcmParamsSpec();
313
314    // 生成加解密生成器
315    let cipherAlgName = 'AES128|GCM|PKCS7';
316    try {
317      globalCipher = cryptoFramework.createCipher(cipherAlgName);
318      console.info(`cipher algName: ${globalCipher.algName}`);
319    } catch (error) {
320      console.error(`createCipher failed, ${error.code}, ${error.message}`);
321      return;
322    }
323    return promiseSymKey;
324  }).then(key => {
325      let encodedKey = key.getEncoded();
326      console.info('key hex:' + uint8ArrayToShowStr(encodedKey.data));
327      globalKey = key;
328      return key;
329  }).then(key => {
330      // 初始化加解密操作环境:开始加密
331      let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
332      let promiseInit = globalCipher.init(mode, key, globalGcmParams);    // init
333      return promiseInit;
334  }).then(() => {
335      let plainText = {data : stringToUint8Array('this is test!')};
336      let promiseUpdate = globalCipher.update(plainText);   // update
337      return promiseUpdate;
338  }).then(updateOutput => {
339      globalCipherText = updateOutput;
340      let promiseFinal = globalCipher.doFinal(null);    // doFinal
341      return promiseFinal;
342  }).then(authTag => {
343      // GCM模式需要从doFinal的输出中取出加密后的认证信息并填入globalGcmParams,在解密时传入init()
344      globalGcmParams.authTag = authTag;
345      return;
346  }).then(() => {
347      // 初始化加解密操作环境:开始解密
348      let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
349      let promiseInit = globalCipher.init(mode, globalKey, globalGcmParams);    // init
350      return promiseInit;
351  }).then(() => {
352      let promiseUpdate = globalCipher.update(globalCipherText);    // update
353      return promiseUpdate;
354  }).then(updateOutput => {
355      console.info('decrypt plainText: ' + uint8ArrayToString(updateOutput.data));
356      let promiseFinal = globalCipher.doFinal(null);    // doFinal
357      return promiseFinal;
358  }).then(finalOutput => {
359      if (finalOutput == null) {  // 使用finalOutput.data前,先判断结果是否为null
360          console.info('GCM finalOutput is null');
361      }
362  }).catch(error => {
363      console.error(`catch error, ${error.code}, ${error.message}`);
364  })
365}
366```
367
368以3DES ECB以callback方式加解密(采用已有数据生成密钥)为例:
369
370```js
371import cryptoFramework from '@ohos.security.cryptoFramework';
372
373var globalCipher;
374var globalGcmParams;
375var globalKey;
376var globalCipherText;
377
378// 可理解的字符串转成字节流
379function stringToUint8Array(str) {
380  let arr = [];
381  for (let i = 0, j = str.length; i < j; ++i) {
382    arr.push(str.charCodeAt(i));
383  }
384  return new Uint8Array(arr);
385}
386
387// 字节流以16进制输出
388function uint8ArrayToShowStr(uint8Array) {
389  return Array.prototype.map
390    .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2))
391    .join('');
392}
393
394// 字节流转成可理解的字符串
395function uint8ArrayToString(array) {
396  let arrayString = '';
397  for (let i = 0; i < array.length; i++) {
398    arrayString += String.fromCharCode(array[i]);
399  }
400  return arrayString;
401}
402
403function genKeyMaterialBlob() {
404  let arr = [
405    0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56,
406    0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c,
407    0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72];    // keyLen = 192 (24 bytes)
408  let keyMaterial = new Uint8Array(arr);
409  return {data : keyMaterial};
410}
411
412// 3DES ECB模式示例,采用已有数据生成密钥(callback写法)
413function test3DesEcb() {
414  // 生成对称密钥生成器
415  let symAlgName = '3DES192';
416  let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);
417  if (symKeyGenerator == null) {
418    console.error('createSymKeyGenerator failed');
419    return;
420  }
421  console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`);
422
423  // 生成加解密生成器
424  let cipherAlgName = '3DES192|ECB|PKCS7';
425  try {
426    globalCipher = cryptoFramework.createCipher(cipherAlgName);
427    console.info(`cipher algName: ${globalCipher.algName}`);
428  } catch (error) {
429    console.error(`createCipher failed, ${error.code}, ${error.message}`);
430    return;
431  }
432
433  // 根据指定的数据,生成对称密钥
434  let keyMaterialBlob = genKeyMaterialBlob();
435  try {
436    symKeyGenerator.convertKey(keyMaterialBlob, (error, key) => {
437      if (error) {
438        console.error(`convertKey error, ${error.code}, ${error.message}`);
439        return;
440      }
441      console.info(`key algName: ${key.algName}`);
442      console.info(`key format: ${key.format}`);
443      let encodedKey = key.getEncoded();
444      console.info('key getEncoded hex: ' + uint8ArrayToShowStr(encodedKey.data));
445      globalKey = key;
446
447      // 初始化加解密操作环境:开始加密
448      let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
449      // init
450      globalCipher.init(mode, key, null, (err, ) => {
451        let plainText = {data : stringToUint8Array('this is test!')};
452        // update
453        globalCipher.update(plainText, (err, updateOutput) => {
454          globalCipherText = updateOutput;
455          //doFinal
456          globalCipher.doFinal(null, (err, finalOutput) => {
457            if (error) {
458              console.error(`doFinal error, ${error.code}, ${error.message}`);
459              return;
460            }
461            if (finalOutput != null) {
462              globalCipherText = Array.from(globalCipherText.data);
463              finalOutput = Array.from(finalOutput.data);
464              globalCipherText = globalCipherText.concat(finalOutput);
465              globalCipherText = new Uint8Array(globalCipherText);
466              globalCipherText = {data : globalCipherText};
467            }
468            // 初始化加解密操作环境:开始解密
469            let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
470            // init
471            globalCipher.init(mode, globalKey, null, (err, ) => {
472              // update
473              globalCipher.update(globalCipherText, (err, updateOutput) => {
474                console.info('decrypt plainText: ' + uint8ArrayToString(updateOutput.data));
475                // doFinal
476                globalCipher.doFinal(null, (error, finalOutput) => {
477                  if (finalOutput != null) {  // 使用finalOutput.data前,先判断结果是否为null
478                    console.info("decrypt plainText:" + uint8ArrayToString(finalOutput.data));
479                  }
480                })
481              })
482            })
483          })
484        })
485      })
486    })
487  } catch (error) {
488    console.error(`convertKey failed, ${error.code}, ${error.message}`);
489    return;
490  }
491}
492```
493以AES GCM以promise方式,分段update()实现加解密为例:
494
495```javascript
496import cryptoFramework from '@ohos.security.cryptoFramework';
497
498var globalCipher;
499var globalGcmParams;
500var globalKey;
501var globalCipherText;
502var globalPlainText;
503
504function genGcmParamsSpec() {
505  let arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0 , 0, 0]; // 12 bytes
506  let dataIv = new Uint8Array(arr);
507  let ivBlob = {data : dataIv};
508
509  arr = [0, 0, 0, 0 , 0, 0, 0, 0]; // 8 bytes
510  let dataAad = new Uint8Array(arr);
511  let aadBlob = {data : dataAad};
512
513  arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0]; // 16 bytes
514  let dataTag = new Uint8Array(arr);
515  let tagBlob = {data : dataTag};
516  let gcmParamsSpec = {iv : ivBlob, aad : aadBlob, authTag : tagBlob, algName : "GcmParamsSpec"};
517  return gcmParamsSpec;
518}
519
520// 字节流以16进制输出
521function uint8ArrayToShowStr(uint8Array) {
522  return Array.prototype.map
523    .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2))
524    .join('');
525}
526
527// 字节流转成可理解的字符串
528function uint8ArrayToString(array) {
529  let arrayString = '';
530  for (let i = 0; i < array.length; i++) {
531    arrayString += String.fromCharCode(array[i]);
532  }
533  return arrayString;
534}
535
536// 算法库不限定update的次数和每次加解密的数据量,业务可根据自身内存情况对明文/密文进行多次分段。
537function testAesMultiUpdate() {
538  return new Promise((resolve, reject) => {
539    setTimeout(() => {
540      resolve('testAesMultiUpdate');
541    }, 10)
542  }).then(() => {
543    // 生成对称密钥生成器
544    let symAlgName = 'AES128';
545    let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);
546    if (symKeyGenerator == null) {
547      console.error('createSymKeyGenerator failed');
548      return;
549    }
550    console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`);
551    // 通过密钥生成器随机生成128位长度的对称密钥
552    let promiseSymKey = symKeyGenerator.generateSymKey();
553    // 构造参数
554    globalGcmParams = genGcmParamsSpec();
555
556    // 生成加解密生成器
557    let cipherAlgName = 'AES128|GCM|PKCS7';
558    try {
559      globalCipher = cryptoFramework.createCipher(cipherAlgName);
560      console.info(`cipher algName: ${globalCipher.algName}`);
561    } catch (error) {
562      console.error(`createCipher failed, ${error.code}, ${error.message}`);
563      return;
564    }
565    return promiseSymKey;
566  }).then(key => {
567    let encodedKey = key.getEncoded();
568    console.info('key hex:' + uint8ArrayToShowStr(encodedKey.data));
569    globalKey = key;
570    return key;
571  }).then(key => {
572    // 初始化加解密操作环境:开始加密
573    let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
574    let promiseInit = globalCipher.init(mode, key, globalGcmParams);    // init
575    return promiseInit;
576  }).then(async () => {
577    let plainText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee";   // 假设明文总共43字节
578    let messageArr = [];
579    let updateLength = 20;  // 假设每20字节分段update一次
580    globalCipherText = [];
581
582    for (let i = 0; i <= plainText.length; i++) {
583      if ((i % updateLength == 0 || i == plainText.length) && messageArr.length != 0) {
584        let message = new Uint8Array(messageArr);
585        let messageBlob = { data : message };
586        let updateOutput = await globalCipher.update(messageBlob);    // 分段update
587        // 把update的结果拼接起来,得到密文(有些情况下还需拼接doFinal的结果,这取决于分组模式
588        // 和填充模式,本例中GCM模式的doFinal结果只包含authTag而不含密文,所以不需要拼接)
589        globalCipherText = globalCipherText.concat(Array.from(updateOutput.data));
590        messageArr = [];
591      }
592      if (i < plainText.length) {
593        messageArr.push(plainText.charCodeAt(i));
594      }
595    }
596    return;
597  }).then(() => {
598    let promiseFinal = globalCipher.doFinal(null);    // doFinal
599    return promiseFinal;
600  }).then(authTag => {
601    // 获取加密后的认证信息
602    globalGcmParams.authTag = authTag;
603    return;
604  }).then(() => {
605    // 初始化加解密操作环境:开始解密
606    let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
607    let promiseInit = globalCipher.init(mode, globalKey, globalGcmParams);    // init
608    return promiseInit;
609  }).then(async () => {
610    let updateLength = 20;
611    let updateTimes = Math.ceil(globalCipherText.length / updateLength);  // 上取整
612    globalPlainText = "";
613    for (let i = 0; i < updateTimes; i++) {
614      let messageArr = globalCipherText.slice(i * updateLength, (i + 1) * updateLength);
615      let message = new Uint8Array(messageArr);
616      let messageBlob = { data : message };
617      let updateOutput = await globalCipher.update(messageBlob);    // 分段update
618      globalPlainText += uint8ArrayToString(updateOutput.data);     // 恢复出原始明文
619    }
620    return;
621  }).then(() => {
622    let promiseFinal = globalCipher.doFinal(null);      // doFinal
623    return promiseFinal;
624  }).then(finalOutput => {
625    if (finalOutput == null) {
626      console.info('GCM finalOutput is null');
627    }
628    console.info(`decrypt output: ${globalPlainText}`);
629  }).catch(error => {
630      console.error(`catch error, ${error.code}, ${error.message}`);
631  })
632}
633```
634
635示例2:使用非对称密钥的加解密操作
636
6371. 生成RSA密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成RSA非对称密钥。
6382. 生成Cipher对象。通过createCipher接口创建Cipher对象,执行初始化操作,设置密钥及加解密模式。
6393. 执行加解密操作。通过调用Cipher对象提供的doFinal接口,执行加密操作生成密文或执行解密操作生成明文。
640
641```javascript
642import cryptoFramework from "@ohos.security.cryptoFramework"
643
644let plan = "This is cipher test.";
645
646function stringToUint8Array(str) {
647  var arr = [];
648  for (var i = 0, j = str.length; i < j; ++i) {
649    arr.push(str.charCodeAt(i));
650  }
651  var tmpArray = new Uint8Array(arr);
652  return tmpArray;
653}
654
655function encryptMessageProMise() {
656  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
657  let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
658  let keyGenPromise = rsaGenerator.generateKeyPair();
659  keyGenPromise.then(rsaKeyPair => {
660    let pubKey = rsaKeyPair.pubKey;
661    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null);
662  }).then(() => {
663    let input = { data : stringToUint8Array(plan) };
664    return cipher.doFinal(input);
665  }).then(dataBlob => {
666    console.info("EncryptOutPut is " + dataBlob.data);
667  });
668}
669
670function encryptMessageCallback() {
671  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
672  let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
673  rsaGenerator.generateKeyPair(function (err, keyPair) {
674    let pubKey = keyPair.pubKey;
675    cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null, function (err, data) {
676      let input = {data : stringToUint8Array(plan) };
677      cipher.doFinal(input, function (err, data) {
678        console.info("EncryptOutPut is " + data.data);
679      })
680    })
681  })
682}
683
684function decryptMessageProMise() {
685  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
686  let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
687  let decoder = cryptoFramework.createCipher("RSA1024|PKCS1");
688  let keyGenPromise = rsaGenerator.generateKeyPair();
689  let keyPair;
690  let cipherDataBlob;
691  let input = { data : stringToUint8Array(plan) };
692  keyGenPromise.then(rsaKeyPair => {
693    keyPair = rsaKeyPair;
694    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null);
695  }).then(() => {
696    return cipher.doFinal(input);
697  }).then(dataBlob => {
698    console.info("EncryptOutPut is " + dataBlob.data);
699    AlertDialog.show({message : "output" + dataBlob.data});
700    cipherDataBlob = dataBlob;
701    return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null);
702  }).then(() => {
703    return decoder.doFinal(cipherDataBlob);
704  }).then(decodeData => {
705    if (decodeData.data.toString() === input.data.toString()) {
706      AlertDialog.show({message : "decrypt success"});
707      return;
708    }
709    AlertDialog.show({message : "decrypt fail"});
710  });
711}
712
713function decryptMessageCallback() {
714  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
715  let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
716  let decoder = cryptoFramework.createCipher("RSA1024|PKCS1");
717  let plainText = "this is cipher text";
718  let input = {data : stringToUint8Array(plainText) };
719  let cipherData;
720  let keyPair;
721  rsaGenerator.generateKeyPair(function (err, newKeyPair) {
722    keyPair = newKeyPair;
723    cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null, function (err, data) {
724      cipher.doFinal(input, function (err, data) {
725        AlertDialog.show({ message : "EncryptOutPut is " + data.data} );
726        cipherData = data;
727        decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null, function (err, data) {
728          decoder.doFinal(cipherData, function (err, data) {
729            if (input.data.toString() === data.data.toString()) {
730              AlertDialog.show({ message : "decrype success"} );
731              return;
732            }
733            AlertDialog.show({ message : "decrype fail"} );
734          });
735        });
736      });
737    });
738  });
739}
740```
741以RSA非对称加解密(多次调用doFinal实现分段)为例:
742```javascript
743import cryptoFramework from "@ohos.security.cryptoFramework"
744
745function stringToUint8Array(str) {
746  var arr = [];
747  for (var i = 0, j = str.length; i < j; ++i) {
748    arr.push(str.charCodeAt(i));
749  }
750  var tmpArray = new Uint8Array(arr);
751  return tmpArray;
752}
753
754// 字节流转成可理解的字符串
755function uint8ArrayToString(array) {
756  let arrayString = '';
757  for (let i = 0; i < array.length; i++) {
758    arrayString += String.fromCharCode(array[i]);
759  }
760  return arrayString;
761}
762
763function encryptLongMessagePromise() {
764  let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
765  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
766  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
767  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
768  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
769  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
770  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
771  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!";
772  let globalCipherOutput;
773  let globalDecodeOutput;
774  var globalKeyPair;
775  let plainTextSplitLen = 64; // RSA每次加解密允许的原文长度大小与密钥位数和填充模式等有关,详细规格内容见overview文档
776  let cipherTextSplitLen = 128; // RSA密钥每次加密生成的密文数据长度计算方式:密钥位数/8
777  let keyGenName = "RSA1024";
778  let cipherAlgName = "RSA1024|PKCS1";
779  let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // 创建非对称密钥生成器对象
780  let cipher = cryptoFramework.createCipher(cipherAlgName); // 创建加密Cipher对象
781  let decoder = cryptoFramework.createCipher(cipherAlgName); // 创建解密Decoder对象
782  return new Promise((resolve, reject) => {
783    setTimeout(() => {
784      resolve("testRsaMultiDoFinal");
785    }, 10);
786  }).then(() => {
787    return asyKeyGenerator.generateKeyPair(); // 生成rsa密钥
788  }).then(keyPair => {
789    globalKeyPair = keyPair; // 保存到密钥对全局变量
790    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, globalKeyPair.pubKey, null);
791  }).then(async () => {
792    globalCipherOutput = [];
793    // 将原文按64字符进行拆分,循环调用doFinal进行加密,使用1024bit密钥时,每次加密生成128B长度的密文
794    for (let i = 0; i < (globalPlainText.length / plainTextSplitLen); i++) {
795      let tempStr = globalPlainText.substr(i * plainTextSplitLen, plainTextSplitLen);
796      let tempBlob = { data : stringToUint8Array(tempStr) };
797      let tempCipherOutput = await cipher.doFinal(tempBlob);
798      globalCipherOutput = globalCipherOutput.concat(Array.from(tempCipherOutput.data));
799    }
800    console.info(`globalCipherOutput len is ${globalCipherOutput.length}, data is: ${globalCipherOutput.toString()}`);
801    return;
802  }).then(() =>{
803    return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, globalKeyPair.priKey, null);
804  }).then(async() => {
805    globalDecodeOutput = [];
806    // 将密文按128B进行拆分解密,得到原文后进行拼接
807    for (let i = 0; i < (globalCipherOutput.length / cipherTextSplitLen); i++) {
808      let tempBlobData = globalCipherOutput.slice(i * cipherTextSplitLen, (i + 1) * cipherTextSplitLen);
809      let message = new Uint8Array(tempBlobData);
810      let tempBlob = { data : message };
811      let tempDecodeOutput = await decoder.doFinal(tempBlob);
812      globalDecodeOutput += uint8ArrayToString(tempDecodeOutput.data);
813    }
814    if (globalDecodeOutput === globalPlainText) {
815      console.info(`encode and decode success`);
816    } else {
817      console.info(`encode and decode error`);
818    }
819    return;
820  }).catch(error => {
821    console.error(`catch error, ${error.code}, ${error.message}`);
822  })
823}
824```
825
826**说明**
827
8281. 使用RSA加解密时,Cipher对象不可重复调用init方法初始化,在创建了一个加密Cipher对象后,如果要进行解密,则需要重新创建另一个Cipher对象执行解密操作。
8292. RSA加密有长度限制,允许加密明文的最大长度见[加解密算法库框架概述](cryptoFramework-overview.md)中的基本概念章节。
8303. RSA解密每次允许解密的密文长度为,RSA密钥的位数/8。
831
832## 使用签名验签操作
833
834**场景说明**
835
836当需要判断接收的数据是否被篡改且是否为指定对象发送的数据时,可以使用签名验签操作。使用签名验签操作中,典型的场景有:
8371. 使用RSA签名验签操作
8382. 使用ECC签名验签操作
839
840**接口及参数说明**
841
842详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。<br/>由于密码算法的复杂性,在选取不同规格和参数时,开发差异较大,无法通过代码示例一一列举,请仔细阅读API参考资料中的相关接口,确保使用正确。
843
844|实例名|接口名|描述|
845|---|---|---|
846|cryptoFramework|createSign(algName : string) : Sign|根据String设置的参数创建Sign对象|
847|Sign|init(priKey : PriKey, callback : AsyncCallback\<void>) : void|使用callback方式设置密钥并初始化Sign对象|
848|Sign|init(priKey : PriKey) : Promise\<void>|使用Promise方式设置密钥并初始化Sign对象|
849|Sign|update(data : DataBlob, callback : AsyncCallback\<void>) : void|使用callback方式添加签名数据|
850|Sign|update(data : DataBlob) : Promise\<void>|用Promise方式添加签名数据|
851|Sign|sign(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|使用callback方式签名所有数据|
852|Sign|sign(data : DataBlob) : Promise\<DataBlob>|使用Promise方式签名所有数据|
853|cryptoFramework|function createVerify(algName : string) : Verify|根据String设置的参数创建Verify对象|
854|Verify|init(priKey : PriKey, callback : AsyncCallback\<void>) : void|使用callback方式设置密钥并初始化Verify对象|
855|Verify|init(priKey : PriKey) : Promise\<void>|使用Promise方式设置密钥并初始化Verify对象|
856|Verify|update(data : DataBlob, callback : AsyncCallback\<void>) : void|使用callback方式添加验签数据|
857|Verify|update(data : DataBlob) : Promise\<void>|用Promise方式添加验签数据|
858|Verify|verify(data : DataBlob, signatureData : DataBlob, callback : AsyncCallback\<boolean>) : void|使用callback方式验签所有数据|
859|Verify|verify(data : DataBlob, signatureData : DataBlob) : Promise\<boolean>|使用Promise方式验签所有数据|
860
861**开发步骤**
862
863示例1:使用RSA签名验签操作
8641. 生成RSA密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成RSA非对称密钥。
8652. 生成Sign对象。通过createSign接口创建Sign对象,执行初始化操作并设置签名私钥。
8663. 执行签名操作。通过Sign类提供的update接口,添加签名数据,并调用sign接口生成数据的签名。
8674. 生成Verify对象。通过createVerify接口创建Verify对象,执行初始化操作并设置验签公钥。
8685. 执行验签操作。通过Verify类提供的update接口,添加签名数据,并调用verify接口传入签名进行验签。
869```javascript
870import cryptoFramework from "@ohos.security.cryptoFramework"
871
872function stringToUint8Array(str) {
873	var arr = [];
874	for (var i = 0, j = str.length; i < j; ++i) {
875		arr.push(str.charCodeAt(i));
876	}
877	var tmpArray = new Uint8Array(arr);
878	return tmpArray;
879}
880
881let globalKeyPair;
882let SignMessageBlob;
883let plan1 = "This is Sign test plan1";
884let plan2 = "This is Sign test plan1";
885let input1 = { data : stringToUint8Array(plan1) };
886let input2 = { data : stringToUint8Array(plan2) };
887
888function signMessagePromise() {
889  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
890  let signer = cryptoFramework.createSign("RSA1024|PKCS1|SHA256");
891  let keyGenPromise = rsaGenerator.generateKeyPair();
892  keyGenPromise.then( keyPair => {
893    globalKeyPair = keyPair;
894    let priKey = globalKeyPair.priKey;
895    return signer.init(priKey);
896  }).then(() => {
897    return signer.update(input1);
898  }).then(() => {
899    return signer.sign(input2);
900  }).then(dataBlob => {
901    SignMessageBlob = dataBlob;
902    console.info("sign output is " + SignMessageBlob.data);
903  });
904}
905
906function verifyMessagePromise() {
907  let verifyer = cryptoFramework.createVerify("RSA1024|PKCS1|SHA256");
908  let verifyInitPromise = verifyer.init(globalKeyPair.pubKey);
909  verifyInitPromise.then(() => {
910    return verifyer.update(input1);
911  }).then(() => {
912    return verifyer.verify(input2, SignMessageBlob);
913  }).then(res => {
914    console.log("Verify result is " + res);
915  });
916}
917
918function signMessageCallback() {
919  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
920  let signer = cryptoFramework.createSign("RSA1024|PKCS1|SHA256");
921  rsaGenerator.generateKeyPair(function (err, keyPair) {
922    globalKeyPair = keyPair;
923    let priKey = globalKeyPair.priKey;
924    signer.init(priKey, function (err, data) {
925      signer.update(input1, function (err, data) {
926        signer.sign(input2, function (err, data) {
927          SignMessageBlob = data;
928          console.info("sign output is " + SignMessageBlob.data);
929        });
930      });
931    });
932  });
933}
934
935function verifyMessageCallback() {
936  let verifyer = cryptoFramework.createVerify("RSA1024|PKCS1|SHA256");
937  verifyer.init(globalKeyPair.pubKey, function (err, data) {
938    verifyer.update(input1, function(err, data) {
939      verifyer.verify(input2, SignMessageBlob, function(err, data) {
940        console.info("verify result is " + data);
941      });
942    });
943  })
944}
945```
946
947示例2:使用ECDSA操作
9481. 生成ECC密钥。通过createAsyKeyGenerator接口创建AsyKeyGenerator对象,并生成ECC非对称密钥。
9492. 生成Sign对象。通过createSign接口创建Sign对象,执行初始化操作并设置签名私钥。
9503. 执行签名操作。通过Sign类提供的update接口,添加签名数据,并调用doFinal接口生成数据的签名。
9514. 生成Verify对象。通过createVerify接口创建Verify对象,执行初始化操作并设置验签公钥。
9525. 执行验签操作。通过Verify类提供的update接口,添加签名数据,并调用doFinal接口传入签名进行验签。
953
954```javascript
955import cryptoFramework from "@ohos.security.cryptoFramework"
956
957function stringToUint8Array(str) {
958	var arr = [];
959	for (var i = 0, j = str.length; i < j; ++i) {
960		arr.push(str.charCodeAt(i));
961	}
962	var tmpArray = new Uint8Array(arr);
963	return tmpArray;
964}
965
966let globalKeyPair;
967let SignMessageBlob;
968let plan1 = "This is Sign test plan1";
969let plan2 = "This is Sign test plan1";
970let input1 = { data : stringToUint8Array(plan1) };
971let input2 = { data : stringToUint8Array(plan2) };
972
973function signMessagePromise() {
974  let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
975  let signer = cryptoFramework.createSign("ECC256|SHA256");
976  let keyGenPromise = eccGenerator.generateKeyPair();
977  keyGenPromise.then( keyPair => {
978    globalKeyPair = keyPair;
979    let priKey = globalKeyPair.priKey;
980    return signer.init(priKey);
981  }).then(() => {
982    return signer.update(input1);
983  }).then(() => {
984    return signer.sign(input2);
985  }).then(dataBlob => {
986    SignMessageBlob = dataBlob;
987    console.info("sign output is " + SignMessageBlob.data);
988  });
989}
990
991function verifyMessagePromise() {
992  let verifyer = cryptoFramework.createVerify("ECC256|SHA256");
993  let verifyInitPromise = verifyer.init(globalKeyPair.pubKey);
994  verifyInitPromise.then(() => {
995    return verifyer.update(input1);
996  }).then(() => {
997    return verifyer.verify(input2, SignMessageBlob);
998  }).then(res => {
999    console.log("Verify result is " + res);
1000  });
1001}
1002
1003function signMessageCallback() {
1004  let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
1005  let signer = cryptoFramework.createSign("ECC256|SHA256");
1006  eccGenerator.generateKeyPair(function (err, keyPair) {
1007    globalKeyPair = keyPair;
1008    let priKey = globalKeyPair.priKey;
1009    signer.init(priKey, function (err, data) {
1010      signer.update(input1, function (err, data) {
1011        signer.sign(input2, function (err, data) {
1012          SignMessageBlob = data;
1013          console.info("sign output is " + SignMessageBlob.data);
1014        });
1015      });
1016    });
1017  });
1018}
1019
1020function verifyMessageCallback() {
1021  let verifyer = cryptoFramework.createVerify("ECC256|SHA256");
1022  verifyer.init(globalKeyPair.pubKey, function (err, data) {
1023    verifyer.update(input1, function(err, data) {
1024      verifyer.verify(input2, SignMessageBlob, function(err, data) {
1025        console.info("verify result is " + data);
1026      });
1027    });
1028  })
1029}
1030```
1031以执行签名、验签操作时多次调用update实现分段为例:
1032
1033```javascript
1034import cryptoFramework from "@ohos.security.cryptoFramework"
1035
1036function stringToUint8Array(str) {
1037  var arr = [];
1038  for (var i = 0, j = str.length; i < j; ++i) {
1039    arr.push(str.charCodeAt(i));
1040  }
1041  var tmpArray = new Uint8Array(arr);
1042  return tmpArray;
1043}
1044
1045function signLongMessagePromise() {
1046  let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1047  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1048  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1049  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1050  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1051  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1052  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1053  "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!";
1054  let globalSignData;
1055  let textSplitLen = 64; // 自定义的数据拆分长度
1056  let keyGenName = "RSA1024";
1057  let cipherAlgName = "RSA1024|PKCS1|SHA256";
1058  let globalKeyPair;
1059  let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // 创建非对称密钥生成器对象
1060  let signer = cryptoFramework.createSign(cipherAlgName); // 创建加密Cipher对象
1061  let verifier = cryptoFramework.createVerify(cipherAlgName); // 创建解密Decoder对象
1062  return new Promise((resolve, reject) => {
1063    setTimeout(() => {
1064      resolve("testRsaMultiUpdate");
1065    }, 10);
1066  }).then(() => {
1067    return asyKeyGenerator.generateKeyPair(); // 生成rsa密钥
1068  }).then(keyPair => {
1069    globalKeyPair = keyPair; // 保存到密钥对全局变量
1070    return signer.init(globalKeyPair.priKey);
1071  }).then(async () => {
1072    // 当原文过大时,可将原文按理想长度进行拆分,循环调用update添加原文
1073    for (let i = 0; i < (globalPlainText.length / textSplitLen); i++) {
1074      let tempStr = globalPlainText.substr(i * textSplitLen, textSplitLen);
1075      let tempBlob = { data : stringToUint8Array(tempStr) };
1076      await signer.update(tempBlob);
1077    }
1078    return signer.sign(null);
1079  }).then(data =>{
1080    globalSignData = data.data;
1081    console.info(`globalSignOutput len is ${globalSignData.length}, data is: ${globalSignData.toString()}`);
1082    return verifier.init(globalKeyPair.pubKey);
1083  }).then(async() => {
1084    // 将密文按128B进行拆分解密,得到原文后进行拼接
1085    for (let i = 0; i < (globalPlainText.length / textSplitLen); i++) {
1086      let tempData = globalPlainText.slice(i * textSplitLen, (i + 1) * textSplitLen);
1087      let tempBlob = { data : stringToUint8Array(tempData) };
1088      await verifier.update(tempBlob);
1089    }
1090    return verifier.verify(null, { data : globalSignData});
1091  }).then(res => {
1092    console.info(`verify res is ${res}`);
1093  }).catch(error => {
1094    console.error(`catch error, ${error.code}, ${error.message}`);
1095  })
1096}
1097```
1098
1099## 使用摘要操作
1100
1101**场景说明**
1102
1103用户指定摘要算法(如SHA256)生成Md实例,并输入单段或多段需要摘要的信息,进行摘要计算更新,并返回消息摘要计算结果,在指定算法后可获取当前算法名与摘要计算长度(字节)
1104
1105使用摘要操作的主要场景为:
1106
1107用户指定摘要算法(如SHA256)生成Md实例,并输入单段或多段需要摘要的信息,进行摘要计算更新,并返回消息摘要计算结果,在指定算法后可获取当前算法名与摘要计算长度(字节)
1108
1109**接口及参数说明**
1110
1111详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。
1112
1113| 实例名          | 接口名                                                       | 描述                                               |
1114| --------------- | ------------------------------------------------------------ | -------------------------------------------------- |
1115| cryptoFramework | function createMd(algName : string) : Md;                    | 指定摘要算法,生成摘要操作实例Md                   |
1116| Md              | update(input : DataBlob, callback : AsyncCallback\<void>) : void; | 接受用户输入数据,通过Callback的方式,异步更新摘要 |
1117| Md              | update(input : DataBlob) : Promise\<void>;                  | 接受用户输入数据,通过Promise的方式,异步更新摘要  |
1118| Md              | digest(callback : AsyncCallback\<DataBlob>) : void;         | 通过Callback的方式,返回结果                       |
1119| Md              | digest() : Promise\<DataBlob>;                              | 通过Promise的方式,返回结果                        |
1120| Md              | getMdLength() : number;                                      | 获取摘要的长度(由指定的摘要算法决定)             |
1121| Md              | readonly algName : string;                                   | 获取当前设置的摘要算法名                           |
1122
1123**开发步骤**
1124
11251. 设置算法,通过接口`createMd`生成摘要操作实例
11262. 接受用户数据,通过接口`update`,更新摘要,此步骤可重复
11273. 通过接口`digest`,返回摘要计算结果
11284. 获取当前摘要算法名与摘要计算长度
1129
1130```javascript
1131import cryptoFramework from "@ohos.security.cryptoFramework"
1132
1133// 可理解的字符串转成字节流
1134function stringToUint8Array(str) {
1135  let arr = [];
1136  for (let i = 0, j = str.length; i < j; ++i) {
1137    arr.push(str.charCodeAt(i));
1138  }
1139  return new Uint8Array(arr);
1140}
1141
1142// 以Promise方式完成摘要
1143function doMdByPromise() {
1144  let mdAlgName = "SHA256"; // 摘要算法名
1145  let message = "mdTestMessgae"; // 待摘要数据
1146  let md;
1147  let mdOutput;
1148  try {
1149    md = cryptoFramework.createMd(mdAlgName);
1150  } catch (error) {
1151    console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
1152    return;
1153  }
1154  console.info("[Promise]: Md algName is: " + md.algName);
1155  // 数据量较少时,可以只做一次update,将数据全部传入,接口未对入参长度做限制
1156  let promiseMdUpdate = md.update({ data: stringToUint8Array(message) });
1157  promiseMdUpdate.then(() => {
1158    // 通过digest,返回摘要结果
1159    let PromiseMdDigest = md.digest();
1160    return PromiseMdDigest;
1161  }).then(digestOutput => {
1162    mdOutput = digestOutput;
1163    console.info("[Promise]: MD result: " + mdOutput.data);
1164    let mdLen = md.getMdLength();
1165    console.info("[Promise]: MD len: " + mdLen);
1166  }).catch(error => {
1167    console.error("[Promise]: error: " + error.message);
1168  });
1169}
1170
1171// 以Callback方式完成摘要
1172function doMdByCallback() {
1173  let mdAlgName = "SHA256"; // 摘要算法名
1174  let message = "mdTestMessgae"; // 待摘要数据
1175  let md;
1176  let mdOutput;
1177  try {
1178    md = cryptoFramework.createMd(mdAlgName);
1179  } catch (error) {
1180    console.error("[Callback]: error code: " + error.code + ", message is: " + error.message);
1181  }
1182  console.info("[Callback]: Md algName is: " + md.algName);
1183  // 数据量较少时,可以只做一次update,将数据全部传入,接口未对入参长度做限制
1184  md.update({ data: stringToUint8Array(message) }, (err,) => {
1185    if (err) {
1186      console.error("[Callback]: err: " + err.code);
1187    }
1188    md.digest((err1, digestOutput) => {
1189      if (err1) {
1190        console.error("[Callback]: err: " + err1.code);
1191      } else {
1192        mdOutput = digestOutput;
1193        console.info("[Callback]: MD result: " + mdOutput.data);
1194        let mdLen = md.getMdLength();
1195        console.info("[Callback]: MD len: " + mdLen);
1196      }
1197    });
1198  });
1199}
1200```
1201以MD更新时多次调用update实现分段为例:
1202```javascript
1203import cryptoFramework from "@ohos.security.cryptoFramework"
1204
1205// 可理解的字符串转成字节流
1206function stringToUint8Array(str) {
1207  let arr = [];
1208  for (let i = 0, j = str.length; i < j; ++i) {
1209    arr.push(str.charCodeAt(i));
1210  }
1211  return new Uint8Array(arr);
1212}
1213
1214
1215// 使用Promise方式,完成分段摘要
1216async function doLoopMdPromise() {
1217  let mdAlgName = "SHA256"; // 摘要算法名
1218  let md;
1219  let mdOutput;
1220  try {
1221    md = cryptoFramework.createMd(mdAlgName);
1222  } catch (error) {
1223    console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
1224    return;
1225  }
1226  console.info("[Promise]: Md algName is: " + md.algName);
1227  let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // 假设信息总共43字节
1228  let messageArr = [];
1229  let updateLength = 20; // 假设每20字节分段update一次,实际并无要求
1230
1231  for (let i = 0; i <= messageText.length; i++) {
1232    if ((i % updateLength == 0 || i == messageText.length) && messageArr.length != 0) {
1233      let message = new Uint8Array(messageArr);
1234      let messageBlob = { data : message };
1235      // 使用await处理for循环里的update
1236      try {
1237        await md.update(messageBlob); // 分段update
1238      } catch (error) {
1239        console.error("await update error code: " + error.code + ", message is: " + error.message);
1240        return;
1241      }
1242      messageArr = [];
1243    }
1244    // 按分割长度,填充messageArr
1245    if (i < messageText.length) {
1246      messageArr.push(messageText.charCodeAt(i));
1247    }
1248  }
1249  let PromiseMdDigest = md.digest();
1250  PromiseMdDigest.then(digestOutput => {
1251    mdOutput = digestOutput;
1252    console.info("[Promise]: MD result: " + mdOutput.data);
1253    let mdLen = md.getMdLength();
1254    console.info("[Promise]: MD len: " + mdLen);
1255  }).catch(error => {
1256    console.error("[Promise]: error: " + error.message);
1257  });
1258}
1259```
1260
1261## 使用密钥协商操作
1262
1263**场景说明**
1264
1265使用密钥协商操作中,典型的场景有:
1266
1267通信双方可以在一个公开的信道上通过相互传送一些消息,共同建立一个安全的共享秘密密钥。
1268
1269**接口及参数说明**
1270
1271详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。
1272
1273|实例名|接口名|描述|
1274|---|---|---|
1275|cryptoFramework|createKeyAgreement(algName : string) : KeyAgreement|根据String设置的参数创建KeyAgreement对象|
1276|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey, callback : AsyncCallback\<DataBlob>) : void|使用callback方式进行密钥协商|
1277|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey) : Promise\<DataBlob>|使用Promise方式进行密钥协商|
1278
1279**开发步骤**
1280
12811. 通过createKeyAgreement接口创建KeyAgreement对象,用于后续的密钥协商操作。
12822. 调用KeyAgreement对象提供的generateSecret方法,传入对端的ECC公钥对象,以及本地生成的ECC私钥对象。
1283
1284```javascript
1285import cryptoFramework from "@ohos.security.cryptoFramework"
1286
1287let globalSelfPriKey;
1288let globalPeerPubKey;
1289
1290function ecdhPromise() {
1291  let peerPubKeyArray = 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]);
1292  let peerPubKeyBlob = { data: peerPubKeyArray };
1293  let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
1294  let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256");
1295  eccGenerator.convertKey(peerPubKeyBlob, null).then((peerKeyPair) => {
1296    globalPeerPubKey = peerKeyPair.pubKey;
1297    return eccGenerator.generateKeyPair();
1298  }).then((keyPair) => {
1299    globalSelfPriKey = keyPair.priKey;
1300    return eccKeyAgreement.generateSecret(globalSelfPriKey, globalPeerPubKey);
1301  }).then((secret) => {
1302    console.info("ecdh promise output is " + secret.data);
1303  }).catch((error) => {
1304    console.error("ecdh error.");
1305  });
1306}
1307
1308function ecdhCallback() {
1309  let peerPubKeyArray = 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]);
1310  let peerPubKeyBlob = { data: peerPubKeyArray };
1311  let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
1312  let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256");
1313  eccGenerator.convertKey(peerPubKeyBlob, null, function (err, peerKeyPair) {
1314    globalPeerPubKey = peerKeyPair.pubKey;
1315    eccGenerator.generateKeyPair(function (err, keyPair) {
1316      globalSelfPriKey = keyPair.priKey;
1317      eccKeyAgreement.generateSecret(globalSelfPriKey, globalPeerPubKey, function (err, secret) {
1318        if (err) {
1319          console.error("ecdh error.");
1320          return;
1321        }
1322        console.info("ecdh callback output is " + secret.data);
1323      });
1324    });
1325  })
1326}
1327```
1328
1329## 使用消息认证码操作
1330
1331**场景说明**
1332
1333消息认证码操作主要应用于身份认证的场景:
1334
1335Mac(message authentication code)可以对消息进行完整性校验,通过使用双方共享的密钥,识别出信息伪装篡改等行为
1336
1337用户指定摘要算法(如SHA256)生成消息认证码Mac实例,输入对称密钥初始化Mac,并传入单段或多段需要摘要的信息,进行消息认证码计算,并获取消息认证码计算结果,在指定算法后可获取当前算法名与消息认证码计算长度(字节)。
1338
1339**接口及参数说明**
1340
1341详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。
1342
1343| 实例名          | 接口名                                                       | 描述                                                |
1344| --------------- | ------------------------------------------------------------ | --------------------------------------------------- |
1345| cryptoFramework | function createMac(algName : string) : Mac;                  | 指定摘要算法,生成消息认证码实例Mac                 |
1346| Mac             | init(key : SymKey, callback : AsyncCallback\<void>) : void; | 接收输入对称密钥,通过Callback的方式,异步初始化MAC |
1347| Mac             | init(key : SymKey) : Promise\<void>;                        | 接收输入对称密钥,通过Promise的方式,异步初始化MAC  |
1348| Mac             | update(input : DataBlob, callback : AsyncCallback\<void>) : void; | 接受输入数据,通过Callback的方式,异步更新MAC       |
1349| Mac             | update(input : DataBlob) : Promise\<void>;                  | 接受输入数据,通过Promise的方式,异步更新MAC        |
1350| Mac             | doFinal(callback : AsyncCallback\<DataBlob>) : void;        | 通过Callback的方式,返回MAC计算结果                 |
1351| Mac             | doFinal() : Promise\<DataBlob>;                             | 通过Promise的方式,返回MAC计算结果                  |
1352| Mac             | getMacLength() : number;                                     | 获取MAC的长度(由指定的摘要算法决定)               |
1353| Mac             | readonly algName : string;                                   | 获取当前设置的摘要算法名                            |
1354
1355**开发步骤**
1356
13571. 设置算法,通过接口`createMac`生成消息认证码操作实例
13582. 接受输入对称密钥,通过接口`init`,初始化Mac
13593. 接受数据,通过接口`update`,更新Mac,此步骤可重复
13604. 通过接口`doFinal`,返回Mac计算结果
13615. 获取当前摘要算法名与Mac计算长度
1362
1363```javascript
1364import cryptoFramework from "@ohos.security.cryptoFramework"
1365
1366// 可理解的字符串转成字节流
1367function stringToUint8Array(str) {
1368  let arr = [];
1369  for (let i = 0, j = str.length; i < j; ++i) {
1370    arr.push(str.charCodeAt(i));
1371  }
1372  return new Uint8Array(arr);
1373}
1374
1375// 以Promise方式完成HMAC
1376function doHmacByPromise() {
1377  let macAlgName = "SHA256"; // 摘要算法名
1378  let message = "hmacTestMessgae"; // 待hmac数据
1379  let macOutput;
1380  let mac;
1381  try {
1382    mac = cryptoFramework.createMac(macAlgName);
1383  } catch (error) {
1384    console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
1385  }
1386  console.info("[Promise]: Mac algName is: " + mac.algName);
1387  let KeyBlob = {
1388    // 128位密钥
1389    data : stringToUint8Array("12345678abcdefgh")
1390  }
1391  let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128");
1392  // 将二进制密钥转换为算法库密钥
1393  let promiseConvertKey = symKeyGenerator.convertKey(KeyBlob);
1394  promiseConvertKey.then(symKey => {
1395    let promiseMacInit = mac.init(symKey);
1396    return promiseMacInit;
1397  }).then(() => {
1398    // 数据量较少时,可以只做一次update,将数据全部传入,接口未对入参长度做限制
1399    let promiseMacUpdate = mac.update({ data: stringToUint8Array(message) });
1400    return promiseMacUpdate;
1401  }).then(() => {
1402    let PromiseMacDoFinal = mac.doFinal();
1403    return PromiseMacDoFinal;
1404  }).then(output => {
1405    macOutput = output;
1406    console.info("[Promise]: HMAC result: " + macOutput.data);
1407    let macLen = mac.getMacLength();
1408    console.info("[Promise]: MAC len: " + macLen);
1409  }).catch(error => {
1410    console.error("[Promise]: error: " + error.message);
1411  });
1412}
1413
1414// 以Callback方式完成HMAC
1415function doHmacByCallback() {
1416  let macAlgName = "SHA256"; // 摘要算法名
1417  let message = "hmacTestMessgae"; // 待hmac数据
1418  let macOutput;
1419  let mac;
1420  try {
1421    mac = cryptoFramework.createMac(macAlgName);
1422  } catch (error) {
1423    console.error("[Callback]: error code: " + error.code + ", message is: " + error.message);
1424  }
1425  console.info("[Promise]: Mac algName is: " + mac.algName);
1426  let KeyBlob = {
1427    // 128位密钥
1428    data : stringToUint8Array("12345678abcdefgh")
1429  }
1430  let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128");
1431  // 将二进制密钥转换为算法库密钥
1432  symKeyGenerator.convertKey(KeyBlob, (err, symKey) => {
1433    if (err) {
1434      console.error("[Callback]: err: " + err.code);
1435    }
1436    mac.init(symKey, (err1, ) => {
1437      if (err1) {
1438        console.error("[Callback]: err: " + err1.code);
1439      }
1440      // 数据量较少时,可以只做一次update,将数据全部传入,接口未对入参长度做限制
1441      mac.update({ data: stringToUint8Array(message) }, (err2, ) => {
1442        if (err2) {
1443          console.error("[Callback]: err: " + err2.code);
1444        }
1445        mac.doFinal((err3, output) => {
1446          if (err3) {
1447            console.error("[Callback]: err: " + err3.code);
1448          } else {
1449            macOutput = output;
1450            console.info("[Callback]: HMAC result: " + macOutput.data);
1451            let macLen = mac.getMacLength();
1452            console.info("[Callback]: MAC len: " + macLen);
1453          }
1454        });
1455      });
1456    });
1457  });
1458}
1459```
1460以HMAC更新MAC时多次调用update实现分段为例:
1461```javascript
1462import cryptoFramework from "@ohos.security.cryptoFramework"
1463
1464function stringToUint8Array(str) {
1465  let arr = [];
1466  for (let i = 0, j = str.length; i < j; ++i) {
1467    arr.push(str.charCodeAt(i));
1468  }
1469  return new Uint8Array(arr);
1470}
1471
1472function doLoopHmacPromise() {
1473  let macAlgName = "SHA256"; // 摘要算法名
1474  let macOutput;
1475  let mac;
1476  try {
1477    mac = cryptoFramework.createMac(macAlgName);
1478  } catch (error) {
1479    console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
1480    return;
1481  }
1482  console.info("[Promise]: Mac algName is: " + mac.algName);
1483  let KeyBlob = {
1484    // 128位密钥
1485    data : stringToUint8Array("12345678abcdefgh")
1486  }
1487  let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // 假设信息总共43字节
1488  let updateLength = 20; // 假设每20字节分段update一次,实际并无要求
1489  let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128");
1490  // 将二进制密钥转换为算法库密钥
1491  let promiseConvertKey = symKeyGenerator.convertKey(KeyBlob);
1492  promiseConvertKey.then(symKey => {
1493    let promiseMacInit = mac.init(symKey);
1494    return promiseMacInit;
1495  }).then(async () => {
1496    let promiseMacUpdate;
1497    let messageArr = [];
1498    for (let i = 0; i <= messageText.length; i++) {
1499      if ((i % updateLength == 0 || i == messageText.length) && messageArr.length != 0) {
1500        let message = new Uint8Array(messageArr);
1501        let messageBlob = { data : message };
1502        // 使用await处理for循环里的update
1503        try {
1504          promiseMacUpdate = await mac.update(messageBlob); // 分段update
1505        } catch (error) {
1506          console.error("await update error code: " + error.code + ", message is: " + error.message);
1507          return;
1508        }
1509        messageArr = [];
1510      }
1511      // 按分割长度,填充messageArr
1512      if (i < messageText.length) {
1513        messageArr.push(messageText.charCodeAt(i));
1514      }
1515    }
1516    return promiseMacUpdate;
1517  }).then(() => {
1518    let PromiseMacDoFinal = mac.doFinal();
1519    return PromiseMacDoFinal;
1520  }).then(output => {
1521    macOutput = output;
1522    console.log("[Promise]: HMAC result: " + macOutput.data);
1523    let macLen = mac.getMacLength();
1524    console.log("[Promise]: MAC len: " + macLen);
1525  }).catch(error => {
1526    console.error("[Promise]: error: " + error.message);
1527  });
1528}
1529```
1530
1531
1532## 使用随机数操作
1533
1534**场景说明**
1535
1536使用随机数操作的主要场景为:
1537
1538- 用户生成随机数Random实例,输入随机数生成的长度(字节),生成指定长度的随机数。
1539- 用户使用生成的随机数作为参数,进行种子设置。
1540
1541**接口及参数说明**
1542
1543详细接口说明可参考[API参考](../reference/apis/js-apis-cryptoFramework.md)。
1544
1545| 实例名          | 接口名                                                       | 描述                                           |
1546| --------------- | ------------------------------------------------------------ | ---------------------------------------------- |
1547| cryptoFramework | function createRandom() : Random;                            | 生成随机数Random实例                           |
1548| Random          | generateRandom(len : number, callback: AsyncCallback\<DataBlob>) : void; | 接受输入长度,通过Callback,异步生成随机数   |
1549| Random          | generateRandom(len : number) : Promise\<DataBlob>;          | 接受输入长度,通过Promise,异步生成随机数      |
1550| Random          | setSeed(seed : DataBlob) : void;                            | 接受输入Blob,设置种子  |
1551
1552**开发步骤**
1553
15541. 通过接口`createRandom`生成随机数操作实例
15552. 接受输入长度,通过接口`generateRandom`,生成指定长度的随机数
15563. 接受DataBlob数据,通过接口`setSeed`,为随机数生成池设置种子
1557
1558```javascript
1559import cryptoFramework from "@ohos.security.cryptoFramework"
1560
1561// process by promise
1562function doRandByPromise(len) {
1563  var rand;
1564  try {
1565    rand = cryptoFramework.createRandom();
1566  } catch (error) {
1567    console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
1568  }
1569  var promiseGenerateRand = rand.generateRandom(len);
1570  promiseGenerateRand.then(randData => {
1571    console.error("[Promise]: rand result: " + randData.data);
1572      try {
1573          rand.setSeed(randData);
1574      } catch (error) {
1575          console.log("setSeed failed, errCode: " + error.code + ", errMsg: " + error.message);
1576      }
1577  }).catch(error => {
1578    console.error("[Promise]: error: " + error.message);
1579  });
1580}
1581
1582// process by callback
1583function doRandByCallback(len) {
1584  var rand;
1585  try {
1586    rand = cryptoFramework.createRandom();
1587  } catch (error) {
1588    console.error("[Callback]: error code: " + error.code + ", message is: " + error.message);
1589  }
1590  rand.generateRandom(len, (err, randData) => {
1591    if (err) {
1592      console.error("[Callback]: err: " + err.code);
1593    } else {
1594      console.error("[Callback]: generate random result: " + randData.data);
1595      try {
1596          rand.setSeed(randData);
1597      } catch (error) {
1598          console.log("setSeed failed, errCode: " + error.code + ", errMsg: " + error.message);
1599      }
1600    }
1601  });
1602}
1603```
1604