• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Crypto Framework Development
2
3> **NOTE**
4>
5> This guide applies to JS development using OpenHarmony API version 9 and SDK version 3.2.7 or later.
6
7## Generating and Converting a Key
8
9**When to Use**
10
11Typical key generation operations involve the following:
12
13- Randomly create a key instance for subsequent encryption and decryption.
14- Convert external or stored binary data into a key instance for subsequent encryption and decryption.
15- Obtain the binary data of a key for storage or transmission.
16> **NOTE**<br>The key instance can be a symmetric key instance (**SymKey**) or an asymmetric key pair instance (**KeyPair**). The **KeyPair** instance consists a public key (**PubKey**) and a private key (**PriKey**). For details about the relationship between keys, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
17
18**Available APIs**
19
20For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
21
22The table below describes the APIs used in this guide.
23
24|Instance|API|Description|
25|---|---|---|
26|cryptoFramework|createAsyKeyGenerator(algName : string) : AsyKeyGenerator|Creates an **AsyKeyGenerator** instance.|
27|cryptoFramework|createSymKeyGenerator(algName : string) : SymKeyGenerator|Creates a **SymKeyGenerator** instance.|
28|AsyKeyGenerator|generateKeyPair(callback : AsyncCallback\<KeyPair>) : void|Generates an asymmetric key pair randomly. This API uses an asynchronous callback to return the result.|
29|AsyKeyGenerator|generateKeyPair() : Promise\<KeyPair>|Generates an asymmetric key pair randomly. This API uses a promise to return the result.|
30|SymKeyGenerator|generateSymKey(callback : AsyncCallback\<SymKey>) : void|Generates a symmetric key randomly. This API uses an asynchronous callback to return the result.|
31|SymKeyGenerator|generateSymKey() : Promise\<SymKey>|Generates a symmetric key randomly. This API uses a promise to return the result.|
32| AsyKeyGenerator          | convertKey(pubKey : DataBlob, priKey : DataBlob, callback : AsyncCallback\<KeyPair>) : void | Converts binary data into a key pair. This API uses an asynchronous callback to return the result.<br>(**pubKey** or **priKey** can be **null**. That is, you can pass in only **pubKey** or **priKey**. As a result, the returned **KeyPair** instance contains only the public or private key.)|
33| AsyKeyGenerator          | convertKey(pubKey : DataBlob, priKey : DataBlob) : Promise\<KeyPair> | Converts binary data into a key pair. This API uses a promise to return the result.<br>(**pubKey** or **priKey** can be **null**. That is, you can pass in only **pubKey** or **priKey**. As a result, the returned **KeyPair** instance contains only the public or private key.)|
34| SymKeyGenerator         | convertKey(key : DataBlob, callback : AsyncCallback\<SymKey>) : void| Converts binary data into a symmetric key. This API uses an asynchronous callback to return the result.|
35| SymKeyGenerator         |convertKey(pubKey : DataBlob, priKey : DataBlob) : Promise\<KeyPair>| Converts binary data into a symmetric key. This API uses a promise to return the result.|
36| Key | getEncoded() : DataBlob;  | Obtains the binary data of a key. (The child class instances of **Key** include **SymKey**, **PubKey**, and **PriKey**.)|
37
38**How to Develop**
39
40Example 1: Randomly generate an asymmetric key pair and obtain its binary data.
41
421. Create an **AsyKeyGenerator** instance.
432. Randomly generate an asymmetric key pair using **AsyKeyGenerator**.
443. Obtain binary data of the key pair generated.
45
46The following sample code presents how to randomly generate an RSA key (1024 bits and two primes) using promise-based APIs:
47
48```javascript
49import cryptoFramework from '@ohos.security.cryptoFramework';
50
51function generateAsyKey() {
52  // Create an AsyKeyGenerator instance.
53  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
54  // Use the key generator to randomly generate an asymmetric key pair.
55  let keyGenPromise = rsaGenerator.generateKeyPair();
56  keyGenPromise.then( keyPair => {
57    globalKeyPair = keyPair;
58    let pubKey = globalKeyPair.pubKey;
59    let priKey = globalKeyPair.priKey;
60    // Obtain the binary data of the asymmetric key pair.
61    pkBlob = pubKey.getEncoded();
62    skBlob = priKey.getEncoded();
63    AlertDialog.show({ message : "pk bin data" + pkBlob.data} );
64    AlertDialog.show({ message : "sk bin data" + skBlob.data} );
65  })
66}
67```
68
69Example 2: Randomly generate a symmetric key and obtain its binary data.
70
711. Create a **SymKeyGenerator** instance.
722. Randomly generate a symmetric key using **SymKeyGenerator**.
733. Obtain binary data of the key generated.
74
75The following sample code presents how to randomly generate a 256-bit AES key using promise-based APIs:
76
77```javascript
78import cryptoFramework from '@ohos.security.cryptoFramework';
79
80// Output the byte streams in hexadecimal format.
81function uint8ArrayToShowStr(uint8Array) {
82  return Array.prototype.map
83    .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2))
84    .join('');
85}
86
87function testGenerateAesKey() {
88  // Create a SymKeyGenerator instance.
89  let symKeyGenerator = cryptoFramework.createSymKeyGenerator('AES256');
90  // Use the key generator to randomly generate a symmetric key.
91  let promiseSymKey = symKeyGenerator.generateSymKey();
92  promiseSymKey.then( key => {
93    // Obtain the binary data of the symmetric key and output a 256-bit byte stream.
94    let encodedKey = key.getEncoded();
95    console.info('key hex:' + uint8ArrayToShowStr(encodedKey.data));
96  })
97}
98```
99
100Example 3: Generate an asymmetric key pair from the binary RSA key data.
101
1021. Obtain the binary data of the RSA public or private key. The public key must comply with the ASN.1 syntax, X.509 specifications, and DER encoding format. The private key must comply with the ASN.1 syntax, PKCS #8 specifications, and DER encoding format.
1032. Create an **AsyKeyGenerator** instance and call **convertKey()** to convert the key binary data (data of the private or public key, or both) into a **KeyPair** instance.
104
105```javascript
106import cryptoFramework from '@ohos.security.cryptoFramework';
107
108function convertAsyKey() {
109  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024");
110  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]);
111  let pkBlob = {data : pkval};
112  rsaGenerator.convertKey(pkBlob, null, function(err, keyPair) {
113    if (keyPair == null) {
114      AlertDialog.show({message : "Convert keypair fail"});
115    }
116    AlertDialog.show({message : "Convert KeyPair success"});
117  })
118}
119```
120
121> **NOTE**
122>
123> The public key material to be converted in **convertKey()** must be in the DER format complying with X.509 specifications, and the private key material must be in the DER format complying with PKCS #8 specifications.
124
125
126
127Example 4: Generate an asymmetric key pair from the binary ECC key data.
128
1291. Obtain the ECC binary key data and encapsulate it into a **DataBlob** instance.
1302. Call **convertKey()** to convert the key binary data (data of the private or public key, or both) into to a **KeyPair** instance.
131
132```javascript
133function convertEccAsyKey() {
134    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]);
135    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]);
136    let pubKeyBlob = { data: pubKeyArray };
137    let priKeyBlob = { data: priKeyArray };
138    let generator = cryptoFrameWork.createAsyKeyGenerator("ECC256");
139    generator.convertKey(pubKeyBlob, priKeyBlob, (error, data) => {
140        if (error) {
141            AlertDialog.show({message : "Convert keypair fail"});
142        }
143        AlertDialog.show({message : "Convert KeyPair success"});
144    })
145}
146```
147
148Example 5: Generate a symmetric key from binary data.
149
1501. Create a **SymKeyGenerator** instance.
1512. Generate a symmetric key from the binary data passed in.
1523. Obtain binary data of the key generated.
153
154The following sample code presents how to generate a 3DES key (192 bits only) using callback-based APIs:
155
156```javascript
157import cryptoFramework from '@ohos.security.cryptoFramework';
158
159// Output the byte streams in hexadecimal format.
160function uint8ArrayToShowStr(uint8Array) {
161  return Array.prototype.map
162    .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2))
163    .join('');
164}
165
166function genKeyMaterialBlob() {
167  let arr = [
168    0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56,
169    0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c,
170    0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72];    // keyLen = 192 (24 bytes)
171  let keyMaterial = new Uint8Array(arr);
172  return {data : keyMaterial};
173}
174
175function testConvertAesKey() {
176  // Create a SymKeyGenerator instance.
177  let symKeyGenerator = cryptoFramework.createSymKeyGenerator('3DES192');
178  // Generate a symmetric key based on the specified data.
179  let keyMaterialBlob = genKeyMaterialBlob();
180  try {
181    symKeyGenerator.convertKey(keyMaterialBlob, (error, key) => {
182      if (error) {    // If the service logic fails to be executed, return the error information in the first parameter of the callback.
183        console.error(`convertKey error, ${error.code}, ${error.message}`);
184        return;
185      }
186      console.info(`key algName: ${key.algName}`);
187      console.info(`key format: ${key.format}`);
188      let encodedKey = key.getEncoded();    // Obtain the binary data of the symmetric key and output a 192-bit byte stream.
189      console.info('key getEncoded hex: ' + uint8ArrayToShowStr(encodedKey.data));
190    })
191  } catch (error) {    // Throw an exception immediately in synchronous mode when an error is detected during the parameter check.
192    console.error(`convertKey failed, ${error.code}, ${error.message}`);
193    return;
194  }
195}
196```
197
198## Encrypting and Decrypting Data
199
200**When to Use**
201
202Important data needs to be encrypted in data storage or transmission for security purposes. Typical encryption and decryption operations involve the following:
203- Encrypt and decrypt data using a symmetric key.
204- Encrypt and decrypt data using an asymmetric key pair.
205
206**Available APIs**
207
208For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md). <br>Due to the complexity of cryptographic algorithms, the implementation varies depending on the specifications and parameters you use, and cannot be enumerated by sample code. Before you start, understand the APIs in the API reference to ensure correct use of these APIs.
209
210The table below describes the APIs used in this guide.
211
212|Instance|API|Description|
213|---|---|---|
214|cryptoFramework|createCipher(transformation : string) : Cipher|Creates a **Cipher** instance.|
215|Cipher|init(opMode : CryptoMode, key : Key, params : ParamsSpec, callback : AsyncCallback\<void>) : void|Sets a key and initializes the **Cipher** instance. This API uses an asynchronous callback to return the result.|
216|Cipher|init(opMode : CryptoMode, key : Key, params : ParamsSpec) : Promise\<void>|Sets a key and initializes the **Cipher** instance. This API uses a promise to return the result.|
217|Cipher|update(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|Updates the data for encryption and decryption. This API uses an asynchronous callback to return the result.|
218|Cipher|update(data : DataBlob) : Promise\<DataBlob>|Updates the data for encryption and decryption. This API uses a promise to return the result.|
219|Cipher|doFinal(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|Finalizes the encryption or decryption. This API uses an asynchronous callback to return the result.|
220|Cipher|doFinal(data : DataBlob) : Promise\<DataBlob>|Finalizes the encryption or decryption. This API uses a promise to return the result.|
221
222**How to Develop**
223
224Example 1: Encrypt and decrypt data using a symmetric key.
225
2261. Create a **SymKeyGenerator** instance.
2272. Use the key generator to generate a symmetric key.
2283. Create a **Cipher** instance.
2294. Encrypt or decrypt data.
230
231The following sample code presents how to use the AES-GCM to encrypt and decrypt data with promise-based APIs:
232
233```js
234import cryptoFramework from '@ohos.security.cryptoFramework';
235
236var globalCipher;
237var globalGcmParams;
238var globalKey;
239var globalCipherText;
240
241function genGcmParamsSpec() {
242  let arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0 , 0, 0]; // 12 bytes
243  let dataIv = new Uint8Array(arr);
244  let ivBlob = {data : dataIv};
245
246  arr = [0, 0, 0, 0 , 0, 0, 0, 0]; // 8 bytes
247  let dataAad = new Uint8Array(arr);
248  let aadBlob = {data : dataAad};
249
250  arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0]; // 16 bytes
251  let dataTag = new Uint8Array(arr);
252  let tagBlob = {data : dataTag};  // The authTag of GCM is obtained by doFinal() in encryption and passed in params of init() in decryption.
253
254  let gcmParamsSpec = {iv : ivBlob, aad : aadBlob, authTag : tagBlob, algName : "GcmParamsSpec"};
255  return gcmParamsSpec;
256}
257
258// Convert strings in plaintext into byte streams.
259function stringToUint8Array(str) {
260  let arr = [];
261  for (let i = 0, j = str.length; i < j; ++i) {
262    arr.push(str.charCodeAt(i));
263  }
264  return new Uint8Array(arr);
265}
266
267// Output the byte streams in hexadecimal format.
268function uint8ArrayToShowStr(uint8Array) {
269  return Array.prototype.map
270    .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2))
271    .join('');
272}
273
274// Convert byte streams into strings in plaintext.
275function uint8ArrayToString(array) {
276  let arrayString = '';
277  for (let i = 0; i < array.length; i++) {
278    arrayString += String.fromCharCode(array[i]);
279  }
280  return arrayString;
281}
282
283function genKeyMaterialBlob() {
284  let arr = [
285    0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56,
286    0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c,
287    0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72];    // keyLen = 192 (24 bytes)
288  let keyMaterial = new Uint8Array(arr);
289  return {data : keyMaterial};
290}
291
292
293// Automatically generate a key in AES GCM mode and return the result in a promise.
294function testAesGcm() {
295  return new Promise((resolve, reject) => {
296    setTimeout(() => {
297      resolve('testAesGcm');
298    }, 10)
299  }).then(() => {
300    // Create a SymKeyGenerator instance.
301    let symAlgName = 'AES128';
302    let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);
303    if (symKeyGenerator == null) {
304      console.error('createSymKeyGenerator failed');
305      return;
306    }
307    console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`);
308    // Use the key generator to randomly generate a 128-bit symmetric key.
309    let promiseSymKey = symKeyGenerator.generateSymKey();
310    // Constructor
311    globalGcmParams = genGcmParamsSpec();
312
313    // Create a Cipher instance.
314    let cipherAlgName = 'AES128|GCM|PKCS7';
315    try {
316      globalCipher = cryptoFramework.createCipher(cipherAlgName);
317      console.info(`cipher algName: ${globalCipher.algName}`);
318    } catch (error) {
319      console.error(`createCipher failed, ${error.code}, ${error.message}`);
320      return;
321    }
322    return promiseSymKey;
323  }).then(key => {
324      let encodedKey = key.getEncoded();
325      console.info('key hex:' + uint8ArrayToShowStr(encodedKey.data));
326      globalKey = key;
327      return key;
328  }).then(key => {
329      // Initialize the cipher environment and start encryption.
330      let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
331      let promiseInit = globalCipher.init(mode, key, globalGcmParams);    // init
332      return promiseInit;
333  }).then(() => {
334      let plainText = {data : stringToUint8Array('this is test!')};
335      let promiseUpdate = globalCipher.update(plainText);   // update
336      return promiseUpdate;
337  }).then(updateOutput => {
338      globalCipherText = updateOutput;
339      let promiseFinal = globalCipher.doFinal(null);    // doFinal
340      return promiseFinal;
341  }).then(authTag => {
342      // In GCM mode, the encrypted authentication information needs to be obtained from the output of doFinal() and passed in globalGcmParams of init() in decryption.
343      globalGcmParams.authTag = authTag;
344      return;
345  }).then(() => {
346      // Initialize the cipher environment and start decryption.
347      let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
348      let promiseInit = globalCipher.init(mode, globalKey, globalGcmParams);    // init
349      return promiseInit;
350  }).then(() => {
351      let promiseUpdate = globalCipher.update(globalCipherText);    // update
352      return promiseUpdate;
353  }).then(updateOutput => {
354      console.info('decrypt plainText: ' + uint8ArrayToString(updateOutput.data));
355      let promiseFinal = globalCipher.doFinal(null);    // doFinal
356      return promiseFinal;
357  }).then(finalOutput => {
358      if (finalOutput == null) {  // Check whether the result is null before using finalOutput.data.
359          console.info('GCM finalOutput is null');
360      }
361  }).catch(error => {
362      console.error(`catch error, ${error.code}, ${error.message}`);
363  })
364}
365```
366
367The following sample code presents how to use the the 3DES ECB to convert existing data into a key and encrypt and decrypt data using callback-based APIs:
368
369```js
370import cryptoFramework from '@ohos.security.cryptoFramework';
371
372var globalCipher;
373var globalGcmParams;
374var globalKey;
375var globalCipherText;
376
377// Convert strings in plaintext into byte streams.
378function stringToUint8Array(str) {
379  let arr = [];
380  for (let i = 0, j = str.length; i < j; ++i) {
381    arr.push(str.charCodeAt(i));
382  }
383  return new Uint8Array(arr);
384}
385
386// Output the byte streams in hexadecimal format.
387function uint8ArrayToShowStr(uint8Array) {
388  return Array.prototype.map
389    .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2))
390    .join('');
391}
392
393// Convert byte streams into strings in plaintext.
394function uint8ArrayToString(array) {
395  let arrayString = '';
396  for (let i = 0; i < array.length; i++) {
397    arrayString += String.fromCharCode(array[i]);
398  }
399  return arrayString;
400}
401
402function genKeyMaterialBlob() {
403  let arr = [
404    0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56,
405    0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c,
406    0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72];    // keyLen = 192 (24 bytes)
407  let keyMaterial = new Uint8Array(arr);
408  return {data : keyMaterial};
409}
410
411// Use the 3DES ECB to Generate a key from the existing data and encrypt and decrypt data using callback-based APIs.
412function test3DesEcb() {
413  // Create a SymKeyGenerator instance.
414  let symAlgName = '3DES192';
415  let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);
416  if (symKeyGenerator == null) {
417    console.error('createSymKeyGenerator failed');
418    return;
419  }
420  console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`);
421
422  // Create a Cipher instance.
423  let cipherAlgName = '3DES192|ECB|PKCS7';
424  try {
425    globalCipher = cryptoFramework.createCipher(cipherAlgName);
426    console.info(`cipher algName: ${globalCipher.algName}`);
427  } catch (error) {
428    console.error(`createCipher failed, ${error.code}, ${error.message}`);
429    return;
430  }
431
432  // Generate a symmetric key based on the specified data.
433  let keyMaterialBlob = genKeyMaterialBlob();
434  try {
435    symKeyGenerator.convertKey(keyMaterialBlob, (error, key) => {
436      if (error) {
437        console.error(`convertKey error, ${error.code}, ${error.message}`);
438        return;
439      }
440      console.info(`key algName: ${key.algName}`);
441      console.info(`key format: ${key.format}`);
442      let encodedKey = key.getEncoded();
443      console.info('key getEncoded hex: ' + uint8ArrayToShowStr(encodedKey.data));
444      globalKey = key;
445
446      // Initialize the cipher environment and start encryption.
447      let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
448      // init
449      globalCipher.init(mode, key, null, (err, ) => {
450        let plainText = {data : stringToUint8Array('this is test!')};
451        // update
452        globalCipher.update(plainText, (err, updateOutput) => {
453          globalCipherText = updateOutput;
454          //doFinal
455          globalCipher.doFinal(null, (err, finalOutput) => {
456            if (error) {
457              console.error(`doFinal error, ${error.code}, ${error.message}`);
458              return;
459            }
460            if (finalOutput != null) {
461              globalCipherText = Array.from(globalCipherText.data);
462              finalOutput = Array.from(finalOutput.data);
463              globalCipherText = globalCipherText.concat(finalOutput);
464              globalCipherText = new Uint8Array(globalCipherText);
465              globalCipherText = {data : globalCipherText};
466            }
467            // Initialize the cipher environment and start decryption.
468            let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
469            // init
470            globalCipher.init(mode, globalKey, null, (err, ) => {
471              // update
472              globalCipher.update(globalCipherText, (err, updateOutput) => {
473                console.info('decrypt plainText: ' + uint8ArrayToString(updateOutput.data));
474                // doFinal
475                globalCipher.doFinal(null, (error, finalOutput) => {
476                  if (finalOutput == null) {  // Check whether the result is null before using finalOutput.data.
477                    console.info("decrypt plainText:" + uint8ArrayToString(finalOutput.data));
478                  }
479                })
480              })
481            })
482          })
483        })
484      })
485    })
486  } catch (error) {
487    console.error(`convertKey failed, ${error.code}, ${error.message}`);
488    return;
489  }
490}
491```
492The following sample code presents how to call **update()** multiple times to implement AES GCM encryption and decryption by using promise-based APIs:
493
494```javascript
495import cryptoFramework from '@ohos.security.cryptoFramework';
496
497var globalCipher;
498var globalGcmParams;
499var globalKey;
500var globalCipherText;
501var globalPlainText;
502
503function genGcmParamsSpec() {
504  let arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0 , 0, 0]; // 12 bytes
505  let dataIv = new Uint8Array(arr);
506  let ivBlob = {data : dataIv};
507
508  arr = [0, 0, 0, 0 , 0, 0, 0, 0]; // 8 bytes
509  let dataAad = new Uint8Array(arr);
510  let aadBlob = {data : dataAad};
511
512  arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0]; // 16 bytes
513  let dataTag = new Uint8Array(arr);
514  let tagBlob = {data : dataTag};
515  let gcmParamsSpec = {iv : ivBlob, aad : aadBlob, authTag : tagBlob, algName : "GcmParamsSpec"};
516  return gcmParamsSpec;
517}
518
519// Output the byte streams in hexadecimal format.
520function uint8ArrayToShowStr(uint8Array) {
521  return Array.prototype.map
522    .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2))
523    .join('');
524}
525
526// Convert byte streams into strings in plaintext.
527function uint8ArrayToString(array) {
528  let arrayString = '';
529  for (let i = 0; i < array.length; i++) {
530    arrayString += String.fromCharCode(array[i]);
531  }
532  return arrayString;
533}
534
535// The algorithm library does not limit the number of update() times and the amount of data to be encrypted and decrypted each time. You can use update() multiple times based on the memory usage.
536function testAesMultiUpdate() {
537  return new Promise((resolve, reject) => {
538    setTimeout(() => {
539      resolve('testAesMultiUpdate');
540    }, 10)
541  }).then(() => {
542    // Create a SymKeyGenerator instance.
543    let symAlgName = 'AES128';
544    let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);
545    if (symKeyGenerator == null) {
546      console.error('createSymKeyGenerator failed');
547      return;
548    }
549    console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`);
550    // Use the key generator to randomly generate a 128-bit symmetric key.
551    let promiseSymKey = symKeyGenerator.generateSymKey();
552    // Constructor
553    globalGcmParams = genGcmParamsSpec();
554
555    // Create a Cipher instance.
556    let cipherAlgName = 'AES128|GCM|PKCS7';
557    try {
558      globalCipher = cryptoFramework.createCipher(cipherAlgName);
559      console.info(`cipher algName: ${globalCipher.algName}`);
560    } catch (error) {
561      console.error(`createCipher failed, ${error.code}, ${error.message}`);
562      return;
563    }
564    return promiseSymKey;
565  }).then(key => {
566    let encodedKey = key.getEncoded();
567    console.info('key hex:' + uint8ArrayToShowStr(encodedKey.data));
568    globalKey = key;
569    return key;
570  }).then(key => {
571    // Initialize the cipher environment and start encryption.
572    let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
573    let promiseInit = globalCipher.init(mode, key, globalGcmParams);    // init
574    return promiseInit;
575  }).then(async () => {
576    let plainText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // Assume that the plaintext contains 43 bytes.
577    let messageArr = [];
578    let updateLength = 20; // Pass in 20 bytes by update() each time.
579    globalCipherText = [];
580
581    for (let i = 0; i <= plainText.length; i++) {
582      if ((i % updateLength == 0 || i == plainText.length) && messageArr.length != 0) {
583        let message = new Uint8Array(messageArr);
584        let messageBlob = { data : message };
585        let updateOutput = await globalCipher.update(messageBlob); // Update by segment.
586        // 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
587        // 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.
588        globalCipherText = globalCipherText.concat(Array.from(updateOutput.data));
589        messageArr = [];
590      }
591      if (i < plainText.length) {
592        messageArr.push(plainText.charCodeAt(i));
593      }
594    }
595    return;
596  }).then(() => {
597    let promiseFinal = globalCipher.doFinal(null);    // doFinal
598    return promiseFinal;
599  }).then(authTag => {
600    // Obtain the authentication information after encryption.
601    globalGcmParams.authTag = authTag;
602    return;
603  }).then(() => {
604    // Initialize the cipher environment and start decryption.
605    let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
606    let promiseInit = globalCipher.init(mode, globalKey, globalGcmParams);    // init
607    return promiseInit;
608  }).then(async () => {
609    let updateLength = 20;
610    let updateTimes = Math.ceil(globalCipherText.length / updateLength);  // Round up to the nearest integer.
611    globalPlainText = "";
612    for (let i = 0; i < updateTimes; i++) {
613      let messageArr = globalCipherText.slice(i * updateLength, (i + 1) * updateLength);
614      let message = new Uint8Array(messageArr);
615      let messageBlob = { data : message };
616      let updateOutput = await globalCipher.update(messageBlob); // Pass in data by segment.
617      globalPlainText += uint8ArrayToString(updateOutput.data);     // Restore the original plaintext.
618    }
619    return;
620  }).then(() => {
621    let promiseFinal = globalCipher.doFinal(null);      // doFinal
622    return promiseFinal;
623  }).then(finalOutput => {
624    if (finalOutput == null) {
625      console.info('GCM finalOutput is null');
626    }
627    console.info(`decrypt output: ${globalPlainText}`);
628  }).catch(error => {
629      console.error(`catch error, ${error.code}, ${error.message}`);
630  })
631}
632```
633
634Example 2: Encrypt and decrypt data using an asymmetric key pair.
635
6361. Generate an RSA key pair.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an RSA asymmetric key pair.
6372. Create a **Cipher** instance.<br>Call **createCipher()** to create a **Cipher** instance, and set the key and encryption/decryption mode.
6383. Perform encryption and decryption operations.<br>Call **doFinal()** provided by the **Cipher** instance to encrypt data or decrypt data.
639
640```javascript
641import cryptoFramework from "@ohos.security.cryptoFramework"
642
643let plan = "This is cipher test.";
644
645function stringToUint8Array(str) {
646  var arr = [];
647  for (var i = 0, j = str.length; i < j; ++i) {
648    arr.push(str.charCodeAt(i));
649  }
650  var tmpArray = new Uint8Array(arr);
651  return tmpArray;
652}
653
654function encryptMessageProMise() {
655  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
656  let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
657  let keyGenPromise = rsaGenerator.generateKeyPair();
658  keyGenPromise.then(rsaKeyPair => {
659    let pubKey = rsaKeyPair.pubKey;
660    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null);
661  }).then(() => {
662    let input = { data : stringToUint8Array(plan) };
663    return cipher.doFinal(input);
664  }).then(dataBlob => {
665    console.info("EncryptOutPut is " + dataBlob.data);
666  });
667}
668
669function encryptMessageCallback() {
670  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
671  let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
672  rsaGenerator.generateKeyPair(function (err, keyPair) {
673    let pubKey = keyPair.pubKey;
674    cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null, function (err, data) {
675      let input = {data : stringToUint8Array(plan) };
676      cipher.doFinal(input, function (err, data) {
677        console.info("EncryptOutPut is " + data.data);
678      })
679    })
680  })
681}
682
683function decryptMessageProMise() {
684  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
685  let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
686  let decoder = cryptoFramework.createCipher("RSA1024|PKCS1");
687  let keyGenPromise = rsaGenerator.generateKeyPair();
688  let keyPair;
689  let cipherDataBlob;
690  let input = { data : stringToUint8Array(plan) };
691  keyGenPromise.then(rsaKeyPair => {
692    keyPair = rsaKeyPair;
693    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null);
694  }).then(() => {
695    return cipher.doFinal(input);
696  }).then(dataBlob => {
697    console.info("EncryptOutPut is " + dataBlob.data);
698    AlertDialog.show({message : "output" + dataBlob.data});
699    cipherDataBlob = dataBlob;
700    return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null);
701  }).then(() => {
702    return decoder.doFinal(cipherDataBlob);
703  }).then(decodeData => {
704    if (decodeData.data.toString() === input.data.toString()) {
705      AlertDialog.show({message : "decrypt success"});
706      return;
707    }
708    AlertDialog.show({message : "decrypt fail"});
709  });
710}
711
712function decryptMessageCallback() {
713  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
714  let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
715  let decoder = cryptoFramework.createCipher("RSA1024|PKCS1");
716  let plainText = "this is cipher text";
717  let input = {data : stringToUint8Array(plainText) };
718  let cipherData;
719  let keyPair;
720  rsaGenerator.generateKeyPair(function (err, newKeyPair) {
721    keyPair = newKeyPair;
722    cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null, function (err, data) {
723      cipher.doFinal(input, function (err, data) {
724        AlertDialog.show({ message : "EncryptOutPut is " + data.data} );
725        cipherData = data;
726        decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null, function (err, data) {
727          decoder.doFinal(cipherData, function (err, data) {
728            if (input.data.toString() === data.data.toString()) {
729              AlertDialog.show({ message : "decrype success"} );
730              return;
731            }
732            AlertDialog.show({ message : "decrype fail"} );
733          });
734        });
735      });
736    });
737  });
738}
739```
740The following sample code presents how to implement RSA asymmetric encryption and decryption (**doFinal()** is called multiple times):
741```javascript
742import cryptoFramework from "@ohos.security.cryptoFramework"
743
744function stringToUint8Array(str) {
745  var arr = [];
746  for (var i = 0, j = str.length; i < j; ++i) {
747    arr.push(str.charCodeAt(i));
748  }
749  var tmpArray = new Uint8Array(arr);
750  return tmpArray;
751}
752
753// Convert byte streams into strings in plaintext.
754function uint8ArrayToString(array) {
755  let arrayString = '';
756  for (let i = 0; i < array.length; i++) {
757    arrayString += String.fromCharCode(array[i]);
758  }
759  return arrayString;
760}
761
762function encryptLongMessagePromise() {
763  let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
764  "This is a long plainTest! 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  let globalCipherOutput;
772  let globalDecodeOutput;
773  var globalKeyPair;
774  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.
775  let cipherTextSplitLen = 128; // Length of the ciphertext = Number of key bits/8
776  let keyGenName = "RSA1024";
777  let cipherAlgName = "RSA1024|PKCS1";
778  let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // Create an AsyKeyGenerator object.
779  let cipher = cryptoFramework.createCipher(cipherAlgName); // Create a Cipher object.
780  let decoder = cryptoFramework.createCipher(cipherAlgName); // Create a Decoder object.
781  return new Promise((resolve, reject) => {
782    setTimeout(() => {
783      resolve("testRsaMultiDoFinal");
784    }, 10);
785  }).then(() => {
786    return asyKeyGenerator.generateKeyPair(); // Generate an RSA key.
787  }).then(keyPair => {
788    globalKeyPair = keyPair; // Save the key to global variables.
789    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, globalKeyPair.pubKey, null);
790  }).then(async () => {
791    globalCipherOutput = [];
792    // 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.
793    for (let i = 0; i < (globalPlainText.length / plainTextSplitLen); i++) {
794      let tempStr = globalPlainText.substr(i * plainTextSplitLen, plainTextSplitLen);
795      let tempBlob = { data : stringToUint8Array(tempStr) };
796      let tempCipherOutput = await cipher.doFinal(tempBlob);
797      globalCipherOutput = globalCipherOutput.concat(Array.from(tempCipherOutput.data));
798    }
799    console.info(`globalCipherOutput len is ${globalCipherOutput.length}, data is: ${globalCipherOutput.toString()}`);
800    return;
801  }).then(() =>{
802    return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, globalKeyPair.priKey, null);
803  }).then(async() => {
804    globalDecodeOutput = [];
805    // Split and decrypt the ciphertext by 128 bytes, and combine the plaintext obtained each time.
806    for (let i = 0; i < (globalCipherOutput.length / cipherTextSplitLen); i++) {
807      let tempBlobData = globalCipherOutput.slice(i * cipherTextSplitLen, (i + 1) * cipherTextSplitLen);
808      let message = new Uint8Array(tempBlobData);
809      let tempBlob = { data : message };
810      let tempDecodeOutput = await decoder.doFinal(tempBlob);
811      globalDecodeOutput += uint8ArrayToString(tempDecodeOutput.data);
812    }
813    if (globalDecodeOutput === globalPlainText) {
814      console.info(`encode and decode success`);
815    } else {
816      console.info(`encode and decode error`);
817    }
818    return;
819  }).catch(error => {
820    console.error(`catch error, ${error.code}, ${error.message}`);
821  })
822}
823```
824
825> **NOTE**
826>
827> - In RSA encryption and decryption, **init()** cannot be repeatedly called to initialize the **Cipher** instance. You must create a **Cipher** instance for each encryption and decryption.
828> - The RSA encryption has a limit on the length of the plaintext to be encrypted. For details, see "Basic Concepts" in [Cryptographic Framework Overview](cryptoFramework-overview.md).
829> - In RSA decryption, the length of the ciphertext to be decrypted each time is the number of bits of the RSA key divided by 8.
830
831## Generating and Verifying a Signature
832
833**When to Use**
834
835A digital signature can be used to verify the authenticity of a message. Typical signing and signature verification operations involve the following:
836- Use the RSA to generate and verify a signature.
837- Use the ECC to generate and verify a signature.
838
839**Available APIs**
840
841For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md). <br>Due to the complexity of cryptographic algorithms, the implementation varies depending on the specifications and parameters you use, and cannot be enumerated by sample code. Before you start, understand the APIs in the API reference to ensure correct use of these APIs.
842
843|Instance|API|Description|
844|---|---|---|
845|cryptoFramework|createSign(algName : string) : Sign|Creates a **Sign** instance.|
846|Sign|init(priKey : PriKey, callback : AsyncCallback\<void>) : void|Sets a key and initializes the **Sign** instance. This API uses an asynchronous callback to return the result.|
847|Sign|init(priKey : PriKey) : Promise\<void>|Sets a key and initializes the **Sign** instance. This API uses a promise to return the result.|
848|Sign|update(data : DataBlob, callback : AsyncCallback\<void>) : void|Updates the data for signing. This API uses an asynchronous callback to return the result.|
849|Sign|update(data : DataBlob) : Promise\<void>|Updates the data for signing. This API uses a promise to return the result.|
850|Sign|sign(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|Signs the data. This API uses an asynchronous callback to return the result.|
851|Sign|sign(data : DataBlob) : Promise\<DataBlob>|Signs the data. This API uses a promise to return the result.|
852|cryptoFramework|function createVerify(algName : string) : Verify|Creates a **Verify** instance.|
853|Verify|init(priKey : PriKey, callback : AsyncCallback\<void>) : void|Sets a key and initializes the **Verify** instance. This API uses an asynchronous callback to return the result.|
854|Verify|init(priKey : PriKey) : Promise\<void>|Sets a key and initializes the **Verify** instance. This API uses a promise to return the result.|
855|Verify|update(data : DataBlob, callback : AsyncCallback\<void>) : void|Updates the data for signature verification. This API uses an asynchronous callback to return the result.|
856|Verify|update(data : DataBlob) : Promise\<void>|Updates the data for signature verification. This API uses a promise to return the result.|
857|Verify|verify(data : DataBlob, signatureData : DataBlob, callback : AsyncCallback\<boolean>) : void|Verifies the signature. This API uses an asynchronous callback to return the result.|
858|Verify|verify(data : DataBlob, signatureData : DataBlob) : Promise\<boolean>|Verifies the signature. This API uses a promise to return the result.|
859
860**How to Develop**
861
862Example 1: Use the RSA to generate and verify a signature.
8631. Generate an RSA key pair.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an RSA asymmetric key pair.
8642. Create a **Sign** instance.<br>Call **createSign()** to create a **Sign** instance, initialize the **Sign** instance, and set a private key for signing.
8653. Generate a signature.<br>Call **update()** provided by the **Sign** class to add the data for signing and call **sign()** to generate a signature.
8664. Create a **Verify** instance.<br>Call **createVerify()** to create a **Verify** instance, initialize the instance, and set a public key for signature verification.
8675. Verify the signature.<br>Call **update()** provided by the **Verify** class to add signature data and call **verify()** to verify the signature.
868```javascript
869import cryptoFramework from "@ohos.security.cryptoFramework"
870
871function stringToUint8Array(str) {
872	var arr = [];
873	for (var i = 0, j = str.length; i < j; ++i) {
874		arr.push(str.charCodeAt(i));
875	}
876	var tmpArray = new Uint8Array(arr);
877	return tmpArray;
878}
879
880let globalKeyPair;
881let SignMessageBlob;
882let plan1 = "This is Sign test plan1";
883let plan2 = "This is Sign test plan1";
884let input1 = { data : stringToUint8Array(plan1) };
885let input2 = { data : stringToUint8Array(plan2) };
886
887function signMessagePromise() {
888  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
889  let signer = cryptoFramework.createSign("RSA1024|PKCS1|SHA256");
890  let keyGenPromise = rsaGenerator.generateKeyPair();
891  keyGenPromise.then( keyPair => {
892    globalKeyPair = keyPair;
893    let priKey = globalKeyPair.priKey;
894    return signer.init(priKey);
895  }).then(() => {
896    return signer.update(input1);
897  }).then(() => {
898    return signer.sign(input2);
899  }).then(dataBlob => {
900    SignMessageBlob = dataBlob;
901    console.info("sign output is " + SignMessageBlob.data);
902  });
903}
904
905function verifyMessagePromise() {
906  let verifyer = cryptoFramework.createVerify("RSA1024|PKCS1|SHA256");
907  let verifyInitPromise = verifyer.init(globalKeyPair.pubKey);
908  verifyInitPromise.then(() => {
909    return verifyer.update(input1);
910  }).then(() => {
911    return verifyer.verify(input2, SignMessageBlob);
912  }).then(res => {
913    console.log("Verify result is " + res);
914  });
915}
916
917function signMessageCallback() {
918  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
919  let signer = cryptoFramework.createSign("RSA1024|PKCS1|SHA256");
920  rsaGenerator.generateKeyPair(function (err, keyPair) {
921    globalKeyPair = keyPair;
922    let priKey = globalKeyPair.priKey;
923    signer.init(priKey, function (err, data) {
924      signer.update(input1, function (err, data) {
925        signer.sign(input2, function (err, data) {
926          SignMessageBlob = data;
927          console.info("sign output is " + SignMessageBlob.data);
928        });
929      });
930    });
931  });
932}
933
934function verifyMessageCallback() {
935  let verifyer = cryptoFramework.createVerify("RSA1024|PKCS1|SHA256");
936  verifyer.init(globalKeyPair.pubKey, function (err, data) {
937    verifyer.update(input1, function(err, data) {
938      verifyer.verify(input2, SignMessageBlob, function(err, data) {
939        console.info("verify result is " + data);
940      });
941    });
942  })
943}
944```
945
946Example 2: Use the ECDSA to generate and verify a signature.
9471. Generate an ECC key.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an ECC asymmetric key pair.
9482. Create a **Sign** instance.<br>Call **createSign()** to create a **Sign** instance, initialize the **Sign** instance, and set a private key for signing.
9493. Generate a signature.<br>Call **update()** provided by the **Sign** class to add the data for signing and call **doFinal()** to generate a signature.
9504. Create a **Verify** instance.<br>Call **createVerify()** to create a **Verify** instance, initialize the instance, and set a public key for signature verification.
9515. Verify the signature.<br>Call **update()** provided by the **Verify** class to add signature data and call **doFinal()** to verify the signature.
952
953```javascript
954import cryptoFramework from "@ohos.security.cryptoFramework"
955
956function stringToUint8Array(str) {
957	var arr = [];
958	for (var i = 0, j = str.length; i < j; ++i) {
959		arr.push(str.charCodeAt(i));
960	}
961	var tmpArray = new Uint8Array(arr);
962	return tmpArray;
963}
964
965let globalKeyPair;
966let SignMessageBlob;
967let plan1 = "This is Sign test plan1";
968let plan2 = "This is Sign test plan1";
969let input1 = { data : stringToUint8Array(plan1) };
970let input2 = { data : stringToUint8Array(plan2) };
971
972function signMessagePromise() {
973  let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
974  let signer = cryptoFramework.createSign("ECC256|SHA256");
975  let keyGenPromise = eccGenerator.generateKeyPair();
976  keyGenPromise.then( keyPair => {
977    globalKeyPair = keyPair;
978    let priKey = globalKeyPair.priKey;
979    return signer.init(priKey);
980  }).then(() => {
981    return signer.update(input1);
982  }).then(() => {
983    return signer.sign(input2);
984  }).then(dataBlob => {
985    SignMessageBlob = dataBlob;
986    console.info("sign output is " + SignMessageBlob.data);
987  });
988}
989
990function verifyMessagePromise() {
991  let verifyer = cryptoFramework.createVerify("ECC256|SHA256");
992  let verifyInitPromise = verifyer.init(globalKeyPair.pubKey);
993  verifyInitPromise.then(() => {
994    return verifyer.update(input1);
995  }).then(() => {
996    return verifyer.verify(input2, SignMessageBlob);
997  }).then(res => {
998    console.log("Verify result is " + res);
999  });
1000}
1001
1002function signMessageCallback() {
1003  let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
1004  let signer = cryptoFramework.createSign("ECC256|SHA256");
1005  eccGenerator.generateKeyPair(function (err, keyPair) {
1006    globalKeyPair = keyPair;
1007    let priKey = globalKeyPair.priKey;
1008    signer.init(priKey, function (err, data) {
1009      signer.update(input1, function (err, data) {
1010        signer.sign(input2, function (err, data) {
1011          SignMessageBlob = data;
1012          console.info("sign output is " + SignMessageBlob.data);
1013        });
1014      });
1015    });
1016  });
1017}
1018
1019function verifyMessageCallback() {
1020  let verifyer = cryptoFramework.createVerify("ECC256|SHA256");
1021  verifyer.init(globalKeyPair.pubKey, function (err, data) {
1022    verifyer.update(input1, function(err, data) {
1023      verifyer.verify(input2, SignMessageBlob, function(err, data) {
1024        console.info("verify result is " + data);
1025      });
1026    });
1027  })
1028}
1029```
1030The following sample code presents how to call **update()** multiple times to implement signing and signature verification:
1031
1032```javascript
1033import cryptoFramework from "@ohos.security.cryptoFramework"
1034
1035function stringToUint8Array(str) {
1036  var arr = [];
1037  for (var i = 0, j = str.length; i < j; ++i) {
1038    arr.push(str.charCodeAt(i));
1039  }
1040  var tmpArray = new Uint8Array(arr);
1041  return tmpArray;
1042}
1043
1044function signLongMessagePromise() {
1045  let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1046  "This is a long plainTest! 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  let globalSignData;
1054  let textSplitLen = 64; // Customized data splitting length.
1055  let keyGenName = "RSA1024";
1056  let cipherAlgName = "RSA1024|PKCS1|SHA256";
1057  let globalKeyPair;
1058  let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // Create an AsyKeyGenerator object.
1059  let signer = cryptoFramework.createSign(cipherAlgName); //Create a cipher object for encryption.
1060  let verifier = cryptoFramework.createVerify(cipherAlgName); // Create a Decoder object for decryption.
1061  return new Promise((resolve, reject) => {
1062    setTimeout(() => {
1063      resolve("testRsaMultiUpdate");
1064    }, 10);
1065  }).then(() => {
1066    return asyKeyGenerator.generateKeyPair(); // Generate an RSA key.
1067  }).then(keyPair => {
1068    globalKeyPair = keyPair; // Save the key to global variables.
1069    return signer.init(globalKeyPair.priKey);
1070  }).then(async () => {
1071    // If the plaintext is too large, split the plaintext based on the specified length and cyclically call update() to pass in the plaintext.
1072    for (let i = 0; i < (globalPlainText.length / textSplitLen); i++) {
1073      let tempStr = globalPlainText.substr(i * textSplitLen, textSplitLen);
1074      let tempBlob = { data : stringToUint8Array(tempStr) };
1075      await signer.update(tempBlob);
1076    }
1077    return signer.sign(null);
1078  }).then(data =>{
1079    globalSignData = data.data;
1080    console.info(`globalSignOutput len is ${globalSignData.length}, data is: ${globalSignData.toString()}`);
1081    return verifier.init(globalKeyPair.pubKey);
1082  }).then(async() => {
1083    // Split and decrypt the ciphertext by 128 bytes, and combine the plaintext obtained each time.
1084    for (let i = 0; i < (globalPlainText.length / textSplitLen); i++) {
1085      let tempData = globalPlainText.slice(i * textSplitLen, (i + 1) * textSplitLen);
1086      let tempBlob = { data : stringToUint8Array(tempData) };
1087      await verifier.update(tempBlob);
1088    }
1089    return verifier.verify(null, { data : globalSignData});
1090  }).then(res => {
1091    console.info(`verify res is ${res}`);
1092  }).catch(error => {
1093    console.error(`catch error, ${error.code}, ${error.message}`);
1094  })
1095}
1096```
1097
1098## Generating a Digest
1099
1100**When to Use**
1101
1102A message digest (MD) is a fixed size numeric representation of the content of a message, computed by a has function. It is sent with the message. The receiver can generate a digest for the message and compare it with the digest received. If the two digests are the same, the message integrity is verified.
1103
1104Typical MD operations involve the following:
1105
11061. Create an **Md** instance.
11072. Add one or more segments of data for generating a digest.
11083. Compute a digest.
11094. Obtain the algorithm and length of a digest.
1110
1111**Available APIs**
1112
1113For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
1114
1115| Instance         | API                                                      | Description                                              |
1116| --------------- | ------------------------------------------------------------ | -------------------------------------------------- |
1117| cryptoFramework | function createMd(algName : string) : Md;                    | Creates an **Md** instance.                  |
1118| Md              | update(input : DataBlob, callback : AsyncCallback\<void>) : void; | Updates the data for a digest. This API uses an asynchronous callback to return the result.|
1119| Md              | update(input : DataBlob) : Promise\<void>;                  | Updates the data for a digest. This API uses a promise to return the result. |
1120| Md              | digest(callback : AsyncCallback\<DataBlob>) : void;         | Generates the digest. This API uses an asynchronous callback to return the result.                      |
1121| Md              | digest() : Promise\<DataBlob>;                              | Generates the digest. This API uses a promise to return the result.                       |
1122| Md              | getMdLength() : number;                                      | Obtains the digest length based on the specified digest algorithm.            |
1123| Md              | readonly algName : string;                                   | Obtains the digest algorithm.                          |
1124
1125**How to Develop**
1126
11271. Call **createMd()** to create an **Md** instance.
11282. Call **update()** to pass in the data for computing a digest. **update()** can be called multiple times to pass in the data by segment.
11293. Call **digest()** to compute a digest.
11304. Obtain the digest algorithm and length of the digest generated.
1131
1132```javascript
1133import cryptoFramework from "@ohos.security.cryptoFramework"
1134
1135// Convert string into uint8Arr.
1136function stringToUint8Array(str) {
1137  var arr = [];
1138  for (var i = 0, j = str.length; i < j; ++i) {
1139      arr.push(str.charCodeAt(i));
1140  }
1141  var tmpUint8Array = new Uint8Array(arr);
1142  return tmpUint8Array;
1143}
1144
1145// Generate a dataBlob of the given length.
1146function GenDataBlob(dataBlobLen) {
1147  var dataBlob;
1148  if (dataBlobLen == 12) {
1149      dataBlob = {data: stringToUint8Array("my test data")};
1150  } else {
1151      console.error("GenDataBlob: dataBlobLen is invalid");
1152      dataBlob = {data: stringToUint8Array("my test data")};
1153  }
1154  return dataBlob;
1155}
1156
1157// Compute an MD using promise-based APIs.
1158function doMdByPromise(algName) {
1159  var md;
1160  try {
1161    md = cryptoFramework.createMd(algName);
1162  } catch (error) {
1163    console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
1164  }
1165  console.error("[Promise]: Md algName is: " + md.algName);
1166  // Initial update().
1167  var promiseMdUpdate = md.update(GenDataBlob(12));
1168  promiseMdUpdate.then(() => {
1169    // Call update() multiple times based on service requirements.
1170    promiseMdUpdate = md.update(GenDataBlob(12));
1171    return promiseMdUpdate;
1172  }).then(mdOutput => {
1173    var PromiseMdDigest = md.digest();
1174    return PromiseMdDigest;
1175  }).then(mdOutput => {
1176    console.error("[Promise]: MD result: " + mdOutput.data);
1177    var mdLen = md.getMdLength();
1178    console.error("[Promise]: MD len: " + mdLen);
1179  }).catch(error => {
1180    console.error("[Promise]: error: " + error.message);
1181  });
1182}
1183
1184// Compute an MD using callback-based APIs.
1185function doMdByCallback(algName) {
1186  var md;
1187  try {
1188    md = cryptoFramework.createMd(algName);
1189  } catch (error) {
1190    console.error("[Callback]: error code: " + error.code + ", message is: " + error.message);
1191  }
1192  console.error("[Callback]: Md algName is: " + md.algName);
1193  // Initial update().
1194  md.update(GenDataBlob(12), (err,) => {
1195    if (err) {
1196      console.error("[Callback]: err: " + err.code);
1197    }
1198    // Call update() multiple times based on service requirements.
1199    md.update(GenDataBlob(12), (err1,) => {
1200      if (err1) {
1201        console.error("[Callback]: err: " + err1.code);
1202      }
1203      md.digest((err2, mdOutput) => {
1204        if (err2) {
1205          console.error("[Callback]: err: " + err2.code);
1206        } else {
1207          console.error("[Callback]: MD result: " + mdOutput.data);
1208          var mdLen = md.getMdLength();
1209          console.error("[Callback]: MD len: " + mdLen);
1210        }
1211      });
1212    });
1213  });
1214}
1215```
1216The following sample code presents how to call **update()** multiple times to update the MD:
1217```javascript
1218import cryptoFramework from "@ohos.security.cryptoFramework"
1219
1220async function updateData(index, obj, data) {
1221  console.error("update " + (index + 1) + " MB data...");
1222  return obj.update(data);
1223}
1224
1225function stringToUint8Array(str) {
1226  var arr = [];
1227  for (var i = 0, j = str.length; i < j; ++i) {
1228    arr.push(str.charCodeAt(i));
1229  }
1230  var tmpUint8Array = new Uint8Array(arr);
1231  return tmpUint8Array;
1232}
1233
1234function GenDataBlob(dataBlobLen) {
1235  var dataBlob;
1236  if (dataBlobLen == 12) {
1237    dataBlob = {data: stringToUint8Array("my test data")};
1238  } else {
1239    console.error("GenDataBlob: dataBlobLen is invalid");
1240    dataBlob = {data: stringToUint8Array("my test data")};
1241  }
1242  return dataBlob;
1243}
1244
1245function LoopMdPromise(algName, loopSize) {
1246  var md;
1247  try {
1248    md = cryptoFramework.createMd(algName);
1249  } catch (error) {
1250    console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
1251    return;
1252  }
1253  console.error("[Promise]: Md algName is: " + md.algName);
1254  var promiseMdUpdate = md.update(GenDataBlob(12));
1255  promiseMdUpdate.then(() => {
1256    var PromiseMdDigest = md.digest();
1257    return PromiseMdDigest;
1258  }).then(async () => {
1259    for (var i = 0; i < loopSize; i++) {
1260      await updateData(i, md, GenDataBlob(12));
1261    }
1262    var PromiseMdDigest = md.digest();
1263    return PromiseMdDigest;
1264  }).then(mdOutput => {
1265    console.error("[Promise]: MD result: " + mdOutput.data);
1266    var mdLen = md.getMdLength();
1267    console.error("[Promise]: MD len: " + mdLen);
1268  }).catch(error => {
1269    console.error("[Promise]: error: " + error.message);
1270  });
1271}
1272```
1273
1274## Performing Key Agreement
1275
1276**When to Use**
1277
1278Key agreement allows two parties to establish a shared secret over an insecure channel.
1279
1280**Available APIs**
1281
1282For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
1283
1284|Instance|API|Description|
1285|---|---|---|
1286|cryptoFramework|createKeyAgreement(algName : string) : KeyAgreement|Creates a **KeyAgreement** instance.|
1287|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey, callback : AsyncCallback\<DataBlob>) : void|Generates a shared secret. This API uses an asynchronous callback to return the result.|
1288|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey) : Promise\<DataBlob>|Generates a shared secret. This API uses a promise to return the result.|
1289
1290**How to Develop**
1291
12921. Generate an ECC key.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an ECC asymmetric key pair.
12932. Generate a shared secret by using the private and public ECC keys.
1294
1295```javascript
1296import cryptoFramework from "@ohos.security.cryptoFramework"
1297
1298let globalKeyPair;
1299
1300function ecdhPromise() {
1301  let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
1302  let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256");
1303  let keyGenPromise = eccGenerator.generateKeyPair();
1304  keyGenPromise.then( keyPair => {
1305    globalKeyPair = keyPair;
1306    return eccKeyAgreement.generateSecret(keyPair.priKey, keyPair.pubKey);
1307  }).then((secret) => {
1308    console.info("ecdh output is " + secret.data);
1309  }).catch((error) => {
1310    console.error("ecdh error.");
1311  });
1312}
1313
1314function ecdhCallback() {
1315  let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
1316  let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256");
1317  eccGenerator.generateKeyPair(function (err, keyPair) {
1318    globalKeyPair = keyPair;
1319    eccKeyAgreement.generateSecret(keyPair.priKey, keyPair.pubKey, function (err, secret) {
1320      if (err) {
1321        console.error("ecdh error.");
1322        return;
1323      }
1324      console.info("ecdh output is " + secret.data);
1325    });
1326  });
1327}
1328```
1329
1330## Generating a MAC
1331
1332**When to Use**
1333
1334A message authentication code (MAC) can be used to verify both the integrity and authenticity of a message using a shared secret.
1335
1336Typical MAC operations involve the following:
1337
13381. Create a **Mac** instance.
13392. Initialize the **Mac** instance, add one or more segments of data for generating a MAC, and generate a MAC.
13403. Obtain the algorithm and length of a MAC.
1341
1342**Available APIs**
1343
1344For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
1345
1346| Instance         | API                                                      | Description                                               |
1347| --------------- | ------------------------------------------------------------ | --------------------------------------------------- |
1348| cryptoFramework | function createMac(algName : string) : Mac;                  | Creates a **Mac** instance.                |
1349| Mac             | init(key : SymKey, callback : AsyncCallback\<void>) : void; | Initializes the MAC operation. This API uses an asynchronous callback to return the result.|
1350| Mac             | init(key : SymKey) : Promise\<void>;                        | Initializes the MAC operation. This API uses a promise to return the result. |
1351| Mac             | update(input : DataBlob, callback : AsyncCallback\<void>) : void; | Updates the data for the MAC operation. This API uses an asynchronous callback to return the result.      |
1352| Mac             | update(input : DataBlob) : Promise\<void>;                  | Updates the data for the MAC operation. This API uses a promise to return the result.       |
1353| Mac             | doFinal(callback : AsyncCallback\<DataBlob>) : void;        | Finalizes the MAC operation to generate a MAC. This API uses an asynchronous callback to return the result.                |
1354| Mac             | doFinal() : Promise\<DataBlob>;                             | Finalizes the MAC operation to generate a MAC. This API uses a promise to return the result.                 |
1355| Mac             | getMacLength() : number;                                     | Obtains the length of the MAC based on the specified algorithm.              |
1356| Mac             | readonly algName : string;                                   | Obtains the digest algorithm.                           |
1357
1358**How to Develop**
1359
13601. Call **createMac()** to create a **Mac** instance.
13612. Call **init()** to initialize the **Mac** instance with the symmetric key passed in.
13623. Call **update()** one or more times to add the data for computing a MAC.
13634. Call **doFinal()** to generate a MAC.
13645. Obtain the algorithm and length of the MAC.
1365
1366```javascript
1367import cryptoFramework from "@ohos.security.cryptoFramework"
1368
1369// Convert string into uint8Arr.
1370function stringToUint8Array(str) {
1371  var arr = [];
1372  for (var i = 0, j = str.length; i < j; ++i) {
1373      arr.push(str.charCodeAt(i));
1374  }
1375  var tmpUint8Array = new Uint8Array(arr);
1376  return tmpUint8Array;
1377}
1378
1379// Generate a blob.
1380function GenDataBlob(dataBlobLen) {
1381  var dataBlob;
1382  if (dataBlobLen == 12) {
1383      dataBlob = {data: stringToUint8Array("my test data")};
1384  } else {
1385      console.error("GenDataBlob: dataBlobLen is invalid");
1386      dataBlob = {data: stringToUint8Array("my test data")};
1387  }
1388  return dataBlob;
1389}
1390
1391function doHmacByPromise(algName) {
1392  var mac;
1393  try {
1394    mac = cryptoFramework.createMac(algName);
1395  } catch (error) {
1396    console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
1397  }
1398  console.error("[Promise]: Mac algName is: " + mac.algName);
1399  var KeyBlob = {
1400    data : stringToUint8Array("12345678abcdefgh")
1401  }
1402  var symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128");
1403  var promiseConvertKey = symKeyGenerator.convertKey(KeyBlob);
1404  promiseConvertKey.then(symKey => {
1405    var promiseMacInit = mac.init(symKey);
1406    return promiseMacInit;
1407  }).then(() => {
1408    // Initial update().
1409    var promiseMacUpdate = mac.update(GenDataBlob(12));
1410    return promiseMacUpdate;
1411  }).then(() => {
1412    // Call update() multiple times based on service requirements.
1413    var promiseMacUpdate = mac.update(GenDataBlob(12));
1414    return promiseMacUpdate;
1415  }).then(() => {
1416    var PromiseMacDoFinal = mac.doFinal();
1417    return PromiseMacDoFinal;
1418  }).then(macOutput => {
1419    console.error("[Promise]: HMAC result: " + macOutput.data);
1420    var macLen = mac.getMacLength();
1421    console.error("[Promise]: MAC len: " + macLen);
1422  }).catch(error => {
1423    console.error("[Promise]: error: " + error.message);
1424  });
1425}
1426
1427// Generate a MAC using callback-based APIs.
1428function doHmacByCallback(algName) {
1429  var mac;
1430  try {
1431    mac = cryptoFramework.createMac(algName);
1432  } catch (error) {
1433    AlertDialog.show({message: "[Callback]: error code: " + error.code + ", message is: " + error.message});
1434    console.error("[Callback]: error code: " + error.code + ", message is: " + error.message);
1435  }
1436  var KeyBlob = {
1437    data : stringToUint8Array("12345678abcdefgh")
1438  }
1439  var symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128");
1440  symKeyGenerator.convertKey(KeyBlob, (err, symKey) => {
1441    if (err) {
1442      console.error("[Callback]: err: " + err.code);
1443    }
1444    mac.init(symKey, (err1, ) => {
1445      if (err1) {
1446        console.error("[Callback]: err: " + err1.code);
1447      }
1448      // Initial update().
1449      mac.update(GenDataBlob(12), (err2, ) => {
1450        if (err2) {
1451          console.error("[Callback]: err: " + err2.code);
1452        }
1453        // Call update() multiple times based on service requirements.
1454        mac.update(GenDataBlob(12), (err3, ) => {
1455          if (err3) {
1456            console.error("[Callback]: err: " + err3.code);
1457          }
1458          mac.doFinal((err4, macOutput) => {
1459            if (err4) {
1460              console.error("[Callback]: err: " + err4.code);
1461            } else {
1462              console.error("[Callback]: HMAC result: " + macOutput.data);
1463              var macLen = mac.getMacLength();
1464              console.error("[Callback]: MAC len: " + macLen);
1465            }
1466          });
1467        });
1468      });
1469    });
1470  });
1471}
1472```
1473The following sample code presents how to call **update()** multiple times to update the MAC:
1474```javascript
1475import cryptoFramework from "@ohos.security.cryptoFramework"
1476
1477async function updateData(index, obj, data) {
1478  console.error("update " + (index + 1) + " MB data...");
1479  return obj.update(data);
1480}
1481
1482function stringToUint8Array(str) {
1483  var arr = [];
1484  for (var i = 0, j = str.length; i < j; ++i) {
1485    arr.push(str.charCodeAt(i));
1486  }
1487  var tmpUint8Array = new Uint8Array(arr);
1488  return tmpUint8Array;
1489}
1490
1491function GenDataBlob(dataBlobLen) {
1492  var dataBlob;
1493  if (dataBlobLen == 12) {
1494    dataBlob = {data: stringToUint8Array("my test data")};
1495  } else {
1496    console.error("GenDataBlob: dataBlobLen is invalid");
1497    dataBlob = {data: stringToUint8Array("my test data")};
1498  }
1499  return dataBlob;
1500}
1501
1502function LoopHmacPromise(algName, loopSize) {
1503  var mac;
1504  try {
1505    mac = cryptoFramework.createMac(algName);
1506  } catch (error) {
1507    console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
1508    return;
1509  }
1510  console.error("[Promise]: Mac algName is: " + mac.algName);
1511  var KeyBlob = {
1512    data : stringToUint8Array("12345678abcdefgh")
1513  }
1514  var symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128");
1515  var promiseConvertKey = symKeyGenerator.convertKey(KeyBlob);
1516  promiseConvertKey.then(symKey => {
1517    var promiseMacInit = mac.init(symKey);
1518    return promiseMacInit;
1519  }).then(async () => {
1520    for (var i = 0; i < loopSize; i++) {
1521      await updateData(i, mac, GenDataBlob(12));
1522    }
1523    var promiseMacUpdate = mac.update(GenDataBlob(12));
1524    return promiseMacUpdate;
1525  }).then(() => {
1526    var PromiseMacDoFinal = mac.doFinal();
1527    return PromiseMacDoFinal;
1528  }).then(macOutput => {
1529    console.error("[Promise]: HMAC result: " + macOutput.data);
1530    var macLen = mac.getMacLength();
1531    console.error("[Promise]: MAC len: " + macLen);
1532  }).catch(error => {
1533    console.error("[Promise]: error: " + error.message);
1534  });
1535}
1536```
1537
1538
1539## Generating a Random Number
1540
1541**When to Use**
1542
1543Typical random number operations involve the following:
1544
1545- Generate a random number.
1546- Set a seed based on the random number generated.
1547
1548**Available APIs**
1549
1550For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
1551
1552| Instance         | API                                                      | Description                                          |
1553| --------------- | ------------------------------------------------------------ | ---------------------------------------------- |
1554| cryptoFramework | function createRandom() : Random;                            | Creates a **Random** instance.                          |
1555| Random          | generateRandom(len : number, callback: AsyncCallback\<DataBlob>) : void; | Generates a random number. This API uses an asynchronous callback to return the result.  |
1556| Random          | generateRandom(len : number) : Promise\<DataBlob>;          | Generates a random number. This API uses a promise to return the result.     |
1557| Random          | setSeed(seed : DataBlob) : void;                            | Sets a seed. |
1558
1559**How to Develop**
1560
15611. Call **createRandom()** to create a **Random** instance.
15622. Call **generateRandom()** to generate a random number of the given length.
15633. Call **setSeed()** to set a seed.
1564
1565```javascript
1566import cryptoFramework from "@ohos.security.cryptoFramework"
1567
1568// Generate a random number and set a seed using promise-based APIs.
1569function doRandByPromise(len) {
1570  var rand;
1571  try {
1572    rand = cryptoFramework.createRandom();
1573  } catch (error) {
1574    console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
1575  }
1576  var promiseGenerateRand = rand.generateRandom(len);
1577  promiseGenerateRand.then(randData => {
1578    console.error("[Promise]: rand result: " + randData.data);
1579      try {
1580          rand.setSeed(randData);
1581      } catch (error) {
1582          console.log("setSeed failed, errCode: " + error.code + ", errMsg: " + error.message);
1583      }
1584  }).catch(error => {
1585    console.error("[Promise]: error: " + error.message);
1586  });
1587}
1588
1589// Generate a random number and set a seed using callback-based APIs.
1590function doRandByCallback(len) {
1591  var rand;
1592  try {
1593    rand = cryptoFramework.createRandom();
1594  } catch (error) {
1595    console.error("[Callback]: error code: " + error.code + ", message is: " + error.message);
1596  }
1597  rand.generateRandom(len, (err, randData) => {
1598    if (err) {
1599      console.error("[Callback]: err: " + err.code);
1600    } else {
1601      console.error("[Callback]: generate random result: " + randData.data);
1602      try {
1603          rand.setSeed(randData);
1604      } catch (error) {
1605          console.log("setSeed failed, errCode: " + error.code + ", errMsg: " + error.message);
1606      }
1607    }
1608  });
1609}
1610```
1611