• 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## Key Generation and Conversion
8
9### When to Use
10
11Typical key generation operations involve the following:
12
131. Randomly create a key object for subsequent encryption and decryption.
142. Convert external or internal binary data into a key object for subsequent encryption and decryption.
153. Obtain the binary data of a key object 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
19### Available APIs
20
21The following table describes the APIs used in this guide. For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
22
23
24|Instance|API|Description|
25|---|---|---|
26|cryptoFramework|createAsyKeyGenerator(algName : string) : AsyKeyGenerator|Creates an **AsyKeyGenerator** instance based on the asymmetric key pair specifications specified by **algName**.|
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
40Randomly 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 the binary data of the key pair generated.
45
46Example: Randomly generate an RSA key (1024 bits and two primes) in promise mode.
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
69Randomly 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 the binary data of the key generated.
74
75Example: Randomly generate an AES key (256 bits) in promise mode.
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
100Generate an RSA asymmetric key pair from the binary 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 use **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 binary data to be converted by **convertKey()** must be in the DER format complying with X.509 specifications, and the private key binary data must be in the DER format complying with PKCS #8 specifications.
124
125Generate an ECC asymmetric key pair from the binary key data.
126
1271. Obtain the ECC binary key data and encapsulate it into a **DataBlob** instance.
1282. Call **convertKey()** to convert the binary data (data of the private or public key, or both) into a **KeyPair** instance.
129
130```javascript
131import cryptoFramework from "@ohos.security.cryptoFramework"
132
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
148Generate a symmetric key from the binary key data.
149
1501. Create a **SymKeyGenerator** instance.
1512. Generate a symmetric key from the binary data.
1523. Obtain the binary data of the key generated.
153
154Example: Generate a 3DES key (192 bits only) in callback mode.
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 after an error is detected during the parameter check.
192    console.error(`convertKey failed, ${error.code}, ${error.message}`);
193    return;
194  }
195}
196```
197
198## Encryption and Decryption
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:
2031. Encrypt and decrypt data using a symmetric key.
2042. Encrypt and decrypt data using an asymmetric key pair.
205
206### Available APIs
207
208The following table describes the APIs used in this guide. For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md). <br>Due to 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 to ensure correct use of these APIs.
209
210
211|Instance|API|Description|
212|---|---|---|
213|cryptoFramework|createCipher(transformation : string) : Cipher|Creates a **Cipher** instance.|
214|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.|
215|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.|
216|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.|
217|Cipher|update(data : DataBlob) : Promise\<DataBlob>|Updates the data for encryption and decryption. This API uses a promise to return the result.|
218|Cipher|doFinal(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|Finalizes the encryption or decryption. This API uses an asynchronous callback to return the result.|
219|Cipher|doFinal(data : DataBlob) : Promise\<DataBlob>|Finalizes the encryption or decryption. This API uses a promise to return the result.|
220
221### How to Develop
222
223Encrypt and decrypt data using a symmetric key.
224
2251. Create a **SymKeyGenerator** instance.
2262. Use the key generator to generate a symmetric key.
2273. Create a **Cipher** instance.
2284. Encrypt or decrypt data.
229
230Example: Use AES GCM to encrypt and decrypt data in promise mode.
231
232```js
233import cryptoFramework from '@ohos.security.cryptoFramework';
234
235var globalCipher;
236var globalGcmParams;
237var globalKey;
238var globalCipherText;
239
240function genGcmParamsSpec() {
241  let arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0 , 0, 0]; // 12 bytes
242  let dataIv = new Uint8Array(arr);
243  let ivBlob = {data : dataIv};
244
245  arr = [0, 0, 0, 0 , 0, 0, 0, 0]; // 8 bytes
246  let dataAad = new Uint8Array(arr);
247  let aadBlob = {data : dataAad};
248
249  arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0]; // 16 bytes
250  let dataTag = new Uint8Array(arr);
251  let tagBlob = {data : dataTag};  // The authTag of GCM is obtained by doFinal() in encryption and passed in params of init() in decryption.
252
253  let gcmParamsSpec = {iv : ivBlob, aad : aadBlob, authTag : tagBlob, algName : "GcmParamsSpec"};
254  return gcmParamsSpec;
255}
256
257// Convert strings in plaintext into byte streams.
258function stringToUint8Array(str) {
259  let arr = [];
260  for (let i = 0, j = str.length; i < j; ++i) {
261    arr.push(str.charCodeAt(i));
262  }
263  return new Uint8Array(arr);
264}
265
266// Output the byte streams in hexadecimal format.
267function uint8ArrayToShowStr(uint8Array) {
268  return Array.prototype.map
269    .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2))
270    .join('');
271}
272
273// Convert byte streams into strings in plaintext.
274function uint8ArrayToString(array) {
275  let arrayString = '';
276  for (let i = 0; i < array.length; i++) {
277    arrayString += String.fromCharCode(array[i]);
278  }
279  return arrayString;
280}
281
282function genKeyMaterialBlob() {
283  let arr = [
284    0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56,
285    0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c,
286    0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72];    // keyLen = 192 (24 bytes)
287  let keyMaterial = new Uint8Array(arr);
288  return {data : keyMaterial};
289}
290
291
292// Automatically generate an AES GCM key in promise mode.
293function testAesGcm() {
294  return new Promise((resolve, reject) => {
295    setTimeout(() => {
296      resolve('testAesGcm');
297    }, 10)
298  }).then(() => {
299    // Create a SymKeyGenerator instance.
300    let symAlgName = 'AES128';
301    let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);
302    if (symKeyGenerator == null) {
303      console.error('createSymKeyGenerator failed');
304      return;
305    }
306    console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`);
307    // Use the key generator to randomly generate a 128-bit symmetric key.
308    let promiseSymKey = symKeyGenerator.generateSymKey();
309    // Generate GCM parameter specifications.
310    globalGcmParams = genGcmParamsSpec();
311
312    // Create a Cipher instance.
313    let cipherAlgName = 'AES128|GCM|PKCS7';
314    try {
315      globalCipher = cryptoFramework.createCipher(cipherAlgName);
316      console.info(`cipher algName: ${globalCipher.algName}`);
317    } catch (error) {
318      console.error(`createCipher failed, ${error.code}, ${error.message}`);
319      return;
320    }
321    return promiseSymKey;
322  }).then(key => {
323      let encodedKey = key.getEncoded();
324      console.info('key hex:' + uint8ArrayToShowStr(encodedKey.data));
325      globalKey = key;
326      return key;
327  }).then(key => {
328      // Initialize the Cipher instance and start encryption.
329      let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
330      let promiseInit = globalCipher.init(mode, key, globalGcmParams);    // init
331      return promiseInit;
332  }).then(() => {
333      let plainText = {data : stringToUint8Array('this is test!')};
334      let promiseUpdate = globalCipher.update(plainText);   // update
335      return promiseUpdate;
336  }).then(updateOutput => {
337      globalCipherText = updateOutput;
338      let promiseFinal = globalCipher.doFinal(null);    // doFinal
339      return promiseFinal;
340  }).then(authTag => {
341      // In GCM mode, the encrypted authentication information needs to be obtained from the output of doFinal() and passed in globalGcmParams of init() in decryption.
342      globalGcmParams.authTag = authTag;
343      return;
344  }).then(() => {
345      // Initialize the Cipher instance and start decryption.
346      let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
347      let promiseInit = globalCipher.init(mode, globalKey, globalGcmParams);    // init
348      return promiseInit;
349  }).then(() => {
350      let promiseUpdate = globalCipher.update(globalCipherText);    // update
351      return promiseUpdate;
352  }).then(updateOutput => {
353      console.info('decrypt plainText: ' + uint8ArrayToString(updateOutput.data));
354      let promiseFinal = globalCipher.doFinal(null);    // doFinal
355      return promiseFinal;
356  }).then(finalOutput => {
357      if (finalOutput == null) {  // Check whether the result is null before using finalOutput.data.
358          console.info('GCM finalOutput is null');
359      }
360  }).catch(error => {
361      console.error(`catch error, ${error.code}, ${error.message}`);
362  })
363}
364```
365
366Example: Generate a key from the existing data to encrypt and decrypt data using 3DES ECB in callback mode.
367
368```js
369import cryptoFramework from '@ohos.security.cryptoFramework';
370
371var globalCipher;
372var globalGcmParams;
373var globalKey;
374var globalCipherText;
375
376// Convert strings in plaintext into byte streams.
377function stringToUint8Array(str) {
378  let arr = [];
379  for (let i = 0, j = str.length; i < j; ++i) {
380    arr.push(str.charCodeAt(i));
381  }
382  return new Uint8Array(arr);
383}
384
385// Output the byte streams in hexadecimal format.
386function uint8ArrayToShowStr(uint8Array) {
387  return Array.prototype.map
388    .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2))
389    .join('');
390}
391
392// Convert byte streams into strings in plaintext.
393function uint8ArrayToString(array) {
394  let arrayString = '';
395  for (let i = 0; i < array.length; i++) {
396    arrayString += String.fromCharCode(array[i]);
397  }
398  return arrayString;
399}
400
401function genKeyMaterialBlob() {
402  let arr = [
403    0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56,
404    0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c,
405    0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72];    // keyLen = 192 (24 bytes)
406  let keyMaterial = new Uint8Array(arr);
407  return {data : keyMaterial};
408}
409
410// Generate a 3DES ECB key from the existing data in callback mode.
411function test3DesEcb() {
412  // Create a SymKeyGenerator instance.
413  let symAlgName = '3DES192';
414  let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);
415  if (symKeyGenerator == null) {
416    console.error('createSymKeyGenerator failed');
417    return;
418  }
419  console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`);
420
421  // Create a Cipher instance.
422  let cipherAlgName = '3DES192|ECB|PKCS7';
423  try {
424    globalCipher = cryptoFramework.createCipher(cipherAlgName);
425    console.info(`cipher algName: ${globalCipher.algName}`);
426  } catch (error) {
427    console.error(`createCipher failed, ${error.code}, ${error.message}`);
428    return;
429  }
430
431  // Generate a symmetric key based on the specified data.
432  let keyMaterialBlob = genKeyMaterialBlob();
433  try {
434    symKeyGenerator.convertKey(keyMaterialBlob, (error, key) => {
435      if (error) {
436        console.error(`convertKey error, ${error.code}, ${error.message}`);
437        return;
438      }
439      console.info(`key algName: ${key.algName}`);
440      console.info(`key format: ${key.format}`);
441      let encodedKey = key.getEncoded();
442      console.info('key getEncoded hex: ' + uint8ArrayToShowStr(encodedKey.data));
443      globalKey = key;
444
445      // Initialize the Cipher instance and start encryption.
446      let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
447      // init
448      globalCipher.init(mode, key, null, (err, ) => {
449        let plainText = {data : stringToUint8Array('this is test!')};
450        // update
451        globalCipher.update(plainText, (err, updateOutput) => {
452          globalCipherText = updateOutput;
453          //doFinal
454          globalCipher.doFinal(null, (err, finalOutput) => {
455            if (error) {
456              console.error(`doFinal error, ${error.code}, ${error.message}`);
457              return;
458            }
459            if (finalOutput != null) {
460              globalCipherText = Array.from(globalCipherText.data);
461              finalOutput = Array.from(finalOutput.data);
462              globalCipherText = globalCipherText.concat(finalOutput);
463              globalCipherText = new Uint8Array(globalCipherText);
464              globalCipherText = {data : globalCipherText};
465            }
466            // Initialize the Cipher instance and start decryption.
467            let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
468            // init
469            globalCipher.init(mode, globalKey, null, (err, ) => {
470              // update
471              globalCipher.update(globalCipherText, (err, updateOutput) => {
472                console.info('decrypt plainText: ' + uint8ArrayToString(updateOutput.data));
473                // doFinal
474                globalCipher.doFinal(null, (error, finalOutput) => {
475                  if (finalOutput == null) {  // Check whether the result is null before using finalOutput.data.
476                    console.info("decrypt plainText:" + uint8ArrayToString(finalOutput.data));
477                  }
478                })
479              })
480            })
481          })
482        })
483      })
484    })
485  } catch (error) {
486    console.error(`convertKey failed, ${error.code}, ${error.message}`);
487    return;
488  }
489}
490```
491Example: Encrypt and decrypt a large amount in AES GCM mode by calling **update()** multiple times in promise mode.
492
493```javascript
494import cryptoFramework from '@ohos.security.cryptoFramework';
495
496var globalCipher;
497var globalGcmParams;
498var globalKey;
499var globalCipherText;
500var globalPlainText;
501
502function genGcmParamsSpec() {
503  let arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0 , 0, 0]; // 12 bytes
504  let dataIv = new Uint8Array(arr);
505  let ivBlob = {data : dataIv};
506
507  arr = [0, 0, 0, 0 , 0, 0, 0, 0]; // 8 bytes
508  let dataAad = new Uint8Array(arr);
509  let aadBlob = {data : dataAad};
510
511  arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0]; // 16 bytes
512  let dataTag = new Uint8Array(arr);
513  let tagBlob = {data : dataTag};
514  let gcmParamsSpec = {iv : ivBlob, aad : aadBlob, authTag : tagBlob, algName : "GcmParamsSpec"};
515  return gcmParamsSpec;
516}
517
518// Output the byte streams in hexadecimal format.
519function uint8ArrayToShowStr(uint8Array) {
520  return Array.prototype.map
521    .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2))
522    .join('');
523}
524
525// Convert byte streams into strings in plaintext.
526function uint8ArrayToString(array) {
527  let arrayString = '';
528  for (let i = 0; i < array.length; i++) {
529    arrayString += String.fromCharCode(array[i]);
530  }
531  return arrayString;
532}
533
534// 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.
535function testAesMultiUpdate() {
536  return new Promise((resolve, reject) => {
537    setTimeout(() => {
538      resolve('testAesMultiUpdate');
539    }, 10)
540  }).then(() => {
541    // Create a SymKeyGenerator instance.
542    let symAlgName = 'AES128';
543    let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName);
544    if (symKeyGenerator == null) {
545      console.error('createSymKeyGenerator failed');
546      return;
547    }
548    console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`);
549    // Use the key generator to randomly generate a 128-bit symmetric key.
550    let promiseSymKey = symKeyGenerator.generateSymKey();
551    // Generate GCM parameter specifications.
552    globalGcmParams = genGcmParamsSpec();
553
554    // Create a Cipher instance.
555    let cipherAlgName = 'AES128|GCM|PKCS7';
556    try {
557      globalCipher = cryptoFramework.createCipher(cipherAlgName);
558      console.info(`cipher algName: ${globalCipher.algName}`);
559    } catch (error) {
560      console.error(`createCipher failed, ${error.code}, ${error.message}`);
561      return;
562    }
563    return promiseSymKey;
564  }).then(key => {
565    let encodedKey = key.getEncoded();
566    console.info('key hex:' + uint8ArrayToShowStr(encodedKey.data));
567    globalKey = key;
568    return key;
569  }).then(key => {
570    // Initialize the Cipher instance and start encryption.
571    let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE;
572    let promiseInit = globalCipher.init(mode, key, globalGcmParams);    // init
573    return promiseInit;
574  }).then(async () => {
575    let plainText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // Assume that the plaintext is of 43 bytes.
576    let messageArr = [];
577    let updateLength = 20; // Pass in 20 bytes by update() each time.
578    globalCipherText = [];
579
580    for (let i = 0; i <= plainText.length; i++) {
581      if ((i % updateLength == 0 || i == plainText.length) && messageArr.length != 0) {
582        let message = new Uint8Array(messageArr);
583        let messageBlob = { data : message };
584        let updateOutput = await globalCipher.update(messageBlob); // Update by segment.
585        // 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
586        // 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.
587        globalCipherText = globalCipherText.concat(Array.from(updateOutput.data));
588        messageArr = [];
589      }
590      if (i < plainText.length) {
591        messageArr.push(plainText.charCodeAt(i));
592      }
593    }
594    return;
595  }).then(() => {
596    let promiseFinal = globalCipher.doFinal(null);    // doFinal
597    return promiseFinal;
598  }).then(authTag => {
599    // Obtain the authentication information after encryption.
600    globalGcmParams.authTag = authTag;
601    return;
602  }).then(() => {
603    // Initialize the Cipher instance and start decryption.
604    let mode = cryptoFramework.CryptoMode.DECRYPT_MODE;
605    let promiseInit = globalCipher.init(mode, globalKey, globalGcmParams);    // init
606    return promiseInit;
607  }).then(async () => {
608    let updateLength = 20;
609    let updateTimes = Math.ceil(globalCipherText.length / updateLength);  // Round up to the nearest integer.
610    globalPlainText = "";
611    for (let i = 0; i < updateTimes; i++) {
612      let messageArr = globalCipherText.slice(i * updateLength, (i + 1) * updateLength);
613      let message = new Uint8Array(messageArr);
614      let messageBlob = { data : message };
615      let updateOutput = await globalCipher.update(messageBlob); // Update by segment.
616      globalPlainText += uint8ArrayToString(updateOutput.data);     // Restore the original plaintext.
617    }
618    return;
619  }).then(() => {
620    let promiseFinal = globalCipher.doFinal(null);      // doFinal
621    return promiseFinal;
622  }).then(finalOutput => {
623    if (finalOutput == null) {
624      console.info('GCM finalOutput is null');
625    }
626    console.info(`decrypt output: ${globalPlainText}`);
627  }).catch(error => {
628      console.error(`catch error, ${error.code}, ${error.message}`);
629  })
630}
631```
632
633Encrypt and decrypt data using an asymmetric key pair.
634
6351. Generate an RSA key pair.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an RSA asymmetric key pair.
6362. Create a **Cipher** instance.<br>Call **createCipher()** to create a **Cipher** instance, and set the key and encryption/decryption mode.
6373. Encrypt and decrypt data.<br>Call **doFinal()** provided by the **Cipher** instance to encrypt data or decrypt data.
638
639```javascript
640import cryptoFramework from "@ohos.security.cryptoFramework"
641
642let plan = "This is cipher test.";
643
644function stringToUint8Array(str) {
645  var arr = [];
646  for (var i = 0, j = str.length; i < j; ++i) {
647    arr.push(str.charCodeAt(i));
648  }
649  var tmpArray = new Uint8Array(arr);
650  return tmpArray;
651}
652
653function encryptMessageProMise() {
654  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
655  let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
656  let keyGenPromise = rsaGenerator.generateKeyPair();
657  keyGenPromise.then(rsaKeyPair => {
658    let pubKey = rsaKeyPair.pubKey;
659    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null);
660  }).then(() => {
661    let input = { data : stringToUint8Array(plan) };
662    return cipher.doFinal(input);
663  }).then(dataBlob => {
664    console.info("EncryptOutPut is " + dataBlob.data);
665  });
666}
667
668function encryptMessageCallback() {
669  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
670  let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
671  rsaGenerator.generateKeyPair(function (err, keyPair) {
672    let pubKey = keyPair.pubKey;
673    cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null, function (err, data) {
674      let input = {data : stringToUint8Array(plan) };
675      cipher.doFinal(input, function (err, data) {
676        console.info("EncryptOutPut is " + data.data);
677      })
678    })
679  })
680}
681
682function decryptMessageProMise() {
683  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
684  let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
685  let decoder = cryptoFramework.createCipher("RSA1024|PKCS1");
686  let keyGenPromise = rsaGenerator.generateKeyPair();
687  let keyPair;
688  let cipherDataBlob;
689  let input = { data : stringToUint8Array(plan) };
690  keyGenPromise.then(rsaKeyPair => {
691    keyPair = rsaKeyPair;
692    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null);
693  }).then(() => {
694    return cipher.doFinal(input);
695  }).then(dataBlob => {
696    console.info("EncryptOutPut is " + dataBlob.data);
697    AlertDialog.show({message : "output" + dataBlob.data});
698    cipherDataBlob = dataBlob;
699    return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null);
700  }).then(() => {
701    return decoder.doFinal(cipherDataBlob);
702  }).then(decodeData => {
703    if (decodeData.data.toString() === input.data.toString()) {
704      AlertDialog.show({message : "decrypt success"});
705      return;
706    }
707    AlertDialog.show({message : "decrypt fail"});
708  });
709}
710
711function decryptMessageCallback() {
712  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
713  let cipher = cryptoFramework.createCipher("RSA1024|PKCS1");
714  let decoder = cryptoFramework.createCipher("RSA1024|PKCS1");
715  let plainText = "this is cipher text";
716  let input = {data : stringToUint8Array(plainText) };
717  let cipherData;
718  let keyPair;
719  rsaGenerator.generateKeyPair(function (err, newKeyPair) {
720    keyPair = newKeyPair;
721    cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null, function (err, data) {
722      cipher.doFinal(input, function (err, data) {
723        AlertDialog.show({ message : "EncryptOutPut is " + data.data} );
724        cipherData = data;
725        decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null, function (err, data) {
726          decoder.doFinal(cipherData, function (err, data) {
727            if (input.data.toString() === data.data.toString()) {
728              AlertDialog.show({ message : "decrype success"} );
729              return;
730            }
731            AlertDialog.show({ message : "decrype fail"} );
732          });
733        });
734      });
735    });
736  });
737}
738```
739Example: Use an RSA asymmetric key pair to encrypt and decrypt data. In this example, **doFinal()** is called multiple times to process data by segment.
740```javascript
741import cryptoFramework from "@ohos.security.cryptoFramework"
742
743function stringToUint8Array(str) {
744  var arr = [];
745  for (var i = 0, j = str.length; i < j; ++i) {
746    arr.push(str.charCodeAt(i));
747  }
748  var tmpArray = new Uint8Array(arr);
749  return tmpArray;
750}
751
752// Convert byte streams into strings in plaintext.
753function uint8ArrayToString(array) {
754  let arrayString = '';
755  for (let i = 0; i < array.length; i++) {
756    arrayString += String.fromCharCode(array[i]);
757  }
758  return arrayString;
759}
760
761function encryptLongMessagePromise() {
762  let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
763  "This is a long plainTest! 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  let globalCipherOutput;
771  let globalDecodeOutput;
772  var globalKeyPair;
773  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.
774  let cipherTextSplitLen = 128; // Length of the ciphertext = Number of key bits/8
775  let keyGenName = "RSA1024";
776  let cipherAlgName = "RSA1024|PKCS1";
777  let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // Create an AsyKeyGenerator object.
778  let cipher = cryptoFramework.createCipher(cipherAlgName); // Create a Cipher object.
779  let decoder = cryptoFramework.createCipher(cipherAlgName); // Create a Decoder object.
780  return new Promise((resolve, reject) => {
781    setTimeout(() => {
782      resolve("testRsaMultiDoFinal");
783    }, 10);
784  }).then(() => {
785    return asyKeyGenerator.generateKeyPair(); // Generate an RSA key pair.
786  }).then(keyPair => {
787    globalKeyPair = keyPair; // Save the key pair as a global variable.
788    return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, globalKeyPair.pubKey, null);
789  }).then(async () => {
790    globalCipherOutput = [];
791    // 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.
792    for (let i = 0; i < (globalPlainText.length / plainTextSplitLen); i++) {
793      let tempStr = globalPlainText.substr(i * plainTextSplitLen, plainTextSplitLen);
794      let tempBlob = { data : stringToUint8Array(tempStr) };
795      let tempCipherOutput = await cipher.doFinal(tempBlob);
796      globalCipherOutput = globalCipherOutput.concat(Array.from(tempCipherOutput.data));
797    }
798    console.info(`globalCipherOutput len is ${globalCipherOutput.length}, data is: ${globalCipherOutput.toString()}`);
799    return;
800  }).then(() =>{
801    return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, globalKeyPair.priKey, null);
802  }).then(async() => {
803    globalDecodeOutput = [];
804    // Split and decrypt the ciphertext by 128 bytes, and combine the plaintext obtained each time.
805    for (let i = 0; i < (globalCipherOutput.length / cipherTextSplitLen); i++) {
806      let tempBlobData = globalCipherOutput.slice(i * cipherTextSplitLen, (i + 1) * cipherTextSplitLen);
807      let message = new Uint8Array(tempBlobData);
808      let tempBlob = { data : message };
809      let tempDecodeOutput = await decoder.doFinal(tempBlob);
810      globalDecodeOutput += uint8ArrayToString(tempDecodeOutput.data);
811    }
812    if (globalDecodeOutput === globalPlainText) {
813      console.info(`encode and decode success`);
814    } else {
815      console.info(`encode and decode error`);
816    }
817    return;
818  }).catch(error => {
819    console.error(`catch error, ${error.code}, ${error.message}`);
820  })
821}
822```
823
824**NOTE**
825
826- In RSA encryption and decryption, **init()** cannot be repeatedly called to initialize a **Cipher** instance. You must create a **Cipher** instance for each encryption and decryption.
827- 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).
828- 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.
829
830## Signing and Signature Verification
831
832### When to Use
833
834A digital signature can be used to verify the authenticity of a message. Typical signing and signature verification operations involve the following:
8351. Use RSA to generate a signature and verify the signature.
8362. Use ECC to generate a signature and verify the signature.
837
838### Available APIs
839
840For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md). <br>Due to 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 to ensure correct use of these APIs.
841
842|Instance|API|Description|
843|---|---|---|
844|cryptoFramework|createSign(algName : string) : Sign|Creates a **Sign** instance.|
845|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.|
846|Sign|init(priKey : PriKey) : Promise\<void>|Sets a key and initializes the **Sign** instance. This API uses a promise to return the result.|
847|Sign|update(data : DataBlob, callback : AsyncCallback\<void>) : void|Updates the data for signing. This API uses an asynchronous callback to return the result.|
848|Sign|update(data : DataBlob) : Promise\<void>|Updates the data for signing. This API uses a promise to return the result.|
849|Sign|sign(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|Signs the data. This API uses an asynchronous callback to return the result.|
850|Sign|sign(data : DataBlob) : Promise\<DataBlob>|Signs the data. This API uses a promise to return the result.|
851|cryptoFramework|function createVerify(algName : string) : Verify|Creates a **Verify** instance.|
852|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.|
853|Verify|init(priKey : PriKey) : Promise\<void>|Sets a key and initializes the **Verify** instance. This API uses a promise to return the result.|
854|Verify|update(data : DataBlob, callback : AsyncCallback\<void>) : void|Updates the data for signature verification. This API uses an asynchronous callback to return the result.|
855|Verify|update(data : DataBlob) : Promise\<void>|Updates the data for signature verification. This API uses a promise to return the result.|
856|Verify|verify(data : DataBlob, signatureData : DataBlob, callback : AsyncCallback\<boolean>) : void|Verifies a signature. This API uses an asynchronous callback to return the result.|
857|Verify|verify(data : DataBlob, signatureData : DataBlob) : Promise\<boolean>|Verifies a signature. This API uses a promise to return the result.|
858
859### How to Develop
860
861Use RSA to sign data and verify the signature.
8621. Generate an RSA key pair.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an RSA asymmetric key pair.
8632. Create a **Sign** instance.<br>Call **createSign()** to create a **Sign** instance, initialize the **Sign** instance, and set a private key for signing.
8643. Generate a signature.<br>Call **update()** provided by the **Sign** class to pass in the data for signing and call **sign()** to generate a signature.
8654. Create a **Verify** instance.<br>Call **createVerify()** to create a **Verify** instance, initialize the instance, and set a public key for signature verification.
8665. Verify the signature.<br>Call **update()** provided by the **Verify** class to pass in the signature data and call **verify()** to verify the signature.
867```javascript
868import cryptoFramework from "@ohos.security.cryptoFramework"
869
870function stringToUint8Array(str) {
871	var arr = [];
872	for (var i = 0, j = str.length; i < j; ++i) {
873		arr.push(str.charCodeAt(i));
874	}
875	var tmpArray = new Uint8Array(arr);
876	return tmpArray;
877}
878
879let globalKeyPair;
880let SignMessageBlob;
881let plan1 = "This is Sign test plan1";
882let plan2 = "This is Sign test plan1";
883let input1 = { data : stringToUint8Array(plan1) };
884let input2 = { data : stringToUint8Array(plan2) };
885
886function signMessagePromise() {
887  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
888  let signer = cryptoFramework.createSign("RSA1024|PKCS1|SHA256");
889  let keyGenPromise = rsaGenerator.generateKeyPair();
890  keyGenPromise.then( keyPair => {
891    globalKeyPair = keyPair;
892    let priKey = globalKeyPair.priKey;
893    return signer.init(priKey);
894  }).then(() => {
895    return signer.update(input1);
896  }).then(() => {
897    return signer.sign(input2);
898  }).then(dataBlob => {
899    SignMessageBlob = dataBlob;
900    console.info("sign output is " + SignMessageBlob.data);
901  });
902}
903
904function verifyMessagePromise() {
905  let verifyer = cryptoFramework.createVerify("RSA1024|PKCS1|SHA256");
906  let verifyInitPromise = verifyer.init(globalKeyPair.pubKey);
907  verifyInitPromise.then(() => {
908    return verifyer.update(input1);
909  }).then(() => {
910    return verifyer.verify(input2, SignMessageBlob);
911  }).then(res => {
912    console.log("Verify result is " + res);
913  });
914}
915
916function signMessageCallback() {
917  let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2");
918  let signer = cryptoFramework.createSign("RSA1024|PKCS1|SHA256");
919  rsaGenerator.generateKeyPair(function (err, keyPair) {
920    globalKeyPair = keyPair;
921    let priKey = globalKeyPair.priKey;
922    signer.init(priKey, function (err, data) {
923      signer.update(input1, function (err, data) {
924        signer.sign(input2, function (err, data) {
925          SignMessageBlob = data;
926          console.info("sign output is " + SignMessageBlob.data);
927        });
928      });
929    });
930  });
931}
932
933function verifyMessageCallback() {
934  let verifyer = cryptoFramework.createVerify("RSA1024|PKCS1|SHA256");
935  verifyer.init(globalKeyPair.pubKey, function (err, data) {
936    verifyer.update(input1, function(err, data) {
937      verifyer.verify(input2, SignMessageBlob, function(err, data) {
938        console.info("verify result is " + data);
939      });
940    });
941  })
942}
943```
944
945Use ECDSA to sign data and verify the signature.
9461. Generate an ECC key.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an ECC asymmetric key pair.
9472. Create a **Sign** instance.<br>Call **createSign()** to create a **Sign** instance, initialize the **Sign** instance, and set a private key for signing.
9483. Generate a signature.<br>Call **update()** provided by the **Sign** class to pass in the data for signing and call **doFinal()** to generate a signature.
9494. Create a **Verify** instance.<br>Call **createVerify()** to create a **Verify** instance, initialize the instance, and set a public key for signature verification.
9505. Verify the signature.<br>Call **update()** provided by the **Verify** class to pass in the signature data and call **doFinal()** to verify the signature.
951
952```javascript
953import cryptoFramework from "@ohos.security.cryptoFramework"
954
955function stringToUint8Array(str) {
956	var arr = [];
957	for (var i = 0, j = str.length; i < j; ++i) {
958		arr.push(str.charCodeAt(i));
959	}
960	var tmpArray = new Uint8Array(arr);
961	return tmpArray;
962}
963
964let globalKeyPair;
965let SignMessageBlob;
966let plan1 = "This is Sign test plan1";
967let plan2 = "This is Sign test plan1";
968let input1 = { data : stringToUint8Array(plan1) };
969let input2 = { data : stringToUint8Array(plan2) };
970
971function signMessagePromise() {
972  let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
973  let signer = cryptoFramework.createSign("ECC256|SHA256");
974  let keyGenPromise = eccGenerator.generateKeyPair();
975  keyGenPromise.then( keyPair => {
976    globalKeyPair = keyPair;
977    let priKey = globalKeyPair.priKey;
978    return signer.init(priKey);
979  }).then(() => {
980    return signer.update(input1);
981  }).then(() => {
982    return signer.sign(input2);
983  }).then(dataBlob => {
984    SignMessageBlob = dataBlob;
985    console.info("sign output is " + SignMessageBlob.data);
986  });
987}
988
989function verifyMessagePromise() {
990  let verifyer = cryptoFramework.createVerify("ECC256|SHA256");
991  let verifyInitPromise = verifyer.init(globalKeyPair.pubKey);
992  verifyInitPromise.then(() => {
993    return verifyer.update(input1);
994  }).then(() => {
995    return verifyer.verify(input2, SignMessageBlob);
996  }).then(res => {
997    console.log("Verify result is " + res);
998  });
999}
1000
1001function signMessageCallback() {
1002  let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256");
1003  let signer = cryptoFramework.createSign("ECC256|SHA256");
1004  eccGenerator.generateKeyPair(function (err, keyPair) {
1005    globalKeyPair = keyPair;
1006    let priKey = globalKeyPair.priKey;
1007    signer.init(priKey, function (err, data) {
1008      signer.update(input1, function (err, data) {
1009        signer.sign(input2, function (err, data) {
1010          SignMessageBlob = data;
1011          console.info("sign output is " + SignMessageBlob.data);
1012        });
1013      });
1014    });
1015  });
1016}
1017
1018function verifyMessageCallback() {
1019  let verifyer = cryptoFramework.createVerify("ECC256|SHA256");
1020  verifyer.init(globalKeyPair.pubKey, function (err, data) {
1021    verifyer.update(input1, function(err, data) {
1022      verifyer.verify(input2, SignMessageBlob, function(err, data) {
1023        console.info("verify result is " + data);
1024      });
1025    });
1026  })
1027}
1028```
1029The following example presents how to call **update()** multiple times to implement signing and signature verification.
1030
1031```javascript
1032import cryptoFramework from "@ohos.security.cryptoFramework"
1033
1034function stringToUint8Array(str) {
1035  var arr = [];
1036  for (var i = 0, j = str.length; i < j; ++i) {
1037    arr.push(str.charCodeAt(i));
1038  }
1039  var tmpArray = new Uint8Array(arr);
1040  return tmpArray;
1041}
1042
1043function signLongMessagePromise() {
1044  let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" +
1045  "This is a long plainTest! 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  let globalSignData;
1053  let textSplitLen = 64; // Customized data splitting length.
1054  let keyGenName = "RSA1024";
1055  let signAlgName = "RSA1024|PKCS1|SHA256";
1056  let globalKeyPair;
1057  let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // Create an AsyKeyGenerator object.
1058  let signer = cryptoFramework.createSign(signAlgName); // Create a Signer instance.
1059  let verifier = cryptoFramework.createVerify(signAlgName); // Create a Verifier instance.
1060  return new Promise((resolve, reject) => {
1061    setTimeout(() => {
1062      resolve("testRsaMultiUpdate");
1063    }, 10);
1064  }).then(() => {
1065    return asyKeyGenerator.generateKeyPair(); // Generate an RSA key pair.
1066  }).then(keyPair => {
1067    globalKeyPair = keyPair; // Save the key pair as a global variable.
1068    return signer.init(globalKeyPair.priKey);
1069  }).then(async () => {
1070    // If the plaintext is too large, split the plaintext based on the specified length and cyclically call update() to pass in the plaintext.
1071    for (let i = 0; i < (globalPlainText.length / textSplitLen); i++) {
1072      let tempStr = globalPlainText.substr(i * textSplitLen, textSplitLen);
1073      let tempBlob = { data : stringToUint8Array(tempStr) };
1074      await signer.update(tempBlob);
1075    }
1076    return signer.sign(null);
1077  }).then(data =>{
1078    globalSignData = data.data;
1079    console.info(`globalSignOutput len is ${globalSignData.length}, data is: ${globalSignData.toString()}`);
1080    return verifier.init(globalKeyPair.pubKey);
1081  }).then(async() => {
1082    // Split and decrypt the ciphertext by 128 bytes, and combine the plaintext obtained each time.
1083    for (let i = 0; i < (globalPlainText.length / textSplitLen); i++) {
1084      let tempData = globalPlainText.slice(i * textSplitLen, (i + 1) * textSplitLen);
1085      let tempBlob = { data : stringToUint8Array(tempData) };
1086      await verifier.update(tempBlob);
1087    }
1088    return verifier.verify(null, { data : globalSignData});
1089  }).then(res => {
1090    console.info(`verify res is ${res}`);
1091  }).catch(error => {
1092    console.error(`catch error, ${error.code}, ${error.message}`);
1093  })
1094}
1095```
1096
1097## Message Digest
1098
1099### When to Use
1100
1101A message digest (MD) is a fixed size numeric representation of the content of a message, computed by a hash 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.
1102
1103Typical MD operations involve the following:
1104
11051. Create an **Md** instance.
11062. Add one or more segments of data for generating a digest.
11073. Compute a digest.
11084. Obtain the algorithm and length of a digest.
1109
1110### Available APIs
1111
1112For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
1113
1114| Instance         | API                                                      | Description                                              |
1115| --------------- | ------------------------------------------------------------ | -------------------------------------------------- |
1116| cryptoFramework | function createMd(algName : string) : Md;                    | Creates an **Md** instance.                  |
1117| Md              | update(input : DataBlob, callback : AsyncCallback\<void>) : void; | Updates the data for a digest. This API uses an asynchronous callback to return the result.|
1118| Md              | update(input : DataBlob) : Promise\<void>;                  | Updates the data for a digest. This API uses a promise to return the result. |
1119| Md              | digest(callback : AsyncCallback\<DataBlob>) : void;         | Generates the digest. This API uses an asynchronous callback to return the result.                      |
1120| Md              | digest() : Promise\<DataBlob>;                              | Generates the digest. This API uses a promise to return the result.                       |
1121| Md              | getMdLength() : number;                                      | Obtains the digest length based on the specified digest algorithm.            |
1122| Md              | readonly algName : string;                                   | Obtains the digest algorithm.                          |
1123
1124### How to Develop
1125
11261. Use **createMd()** to create an **Md** instance.
11272. Use **update()** to update the data for computing a digest. **update()** can be called multiple times to update the data by segment.
11283. Use **digest()** to compute a digest.
11294. Obtain the digest algorithm and length of the digest generated.
1130
1131```javascript
1132import cryptoFramework from "@ohos.security.cryptoFramework"
1133
1134// Convert strings in plaintext into byte streams.
1135function stringToUint8Array(str) {
1136  let arr = [];
1137  for (let i = 0, j = str.length; i < j; ++i) {
1138    arr.push(str.charCodeAt(i));
1139  }
1140  return new Uint8Array(arr);
1141}
1142
1143// Generate a digest in promise mode.
1144function doMdByPromise() {
1145  let mdAlgName = "SHA256"; // Digest algorithm name.
1146  let message = "mdTestMessgae"; // Data to be digested.
1147  let md;
1148  let mdOutput;
1149  try {
1150    md = cryptoFramework.createMd(mdAlgName);
1151  } catch (error) {
1152    console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
1153    return;
1154  }
1155  console.info("[Promise]: Md algName is: " + md.algName);
1156  // If the data volume is small, you can use update() once to pass in all data. There is no limit on the length of the input parameter.
1157  let promiseMdUpdate = md.update({ data: stringToUint8Array(message) });
1158  promiseMdUpdate.then(() => {
1159    // Call digest() to return the result.
1160    let PromiseMdDigest = md.digest();
1161    return PromiseMdDigest;
1162  }).then(digestOutput => {
1163    mdOutput = digestOutput;
1164    console.info("[Promise]: MD result: " + mdOutput.data);
1165    let mdLen = md.getMdLength();
1166    console.info("[Promise]: MD len: " + mdLen);
1167  }).catch(error => {
1168    console.error("[Promise]: error: " + error.message);
1169  });
1170}
1171
1172// Generate a digest in callback mode.
1173function doMdByCallback() {
1174  let mdAlgName = "SHA256"; // Digest algorithm name.
1175  let message = "mdTestMessgae"; // Data to be digested.
1176  let md;
1177  let mdOutput;
1178  try {
1179    md = cryptoFramework.createMd(mdAlgName);
1180  } catch (error) {
1181    console.error("[Callback]: error code: " + error.code + ", message is: " + error.message);
1182  }
1183  console.info("[Callback]: Md algName is: " + md.algName);
1184  // If the data volume is small, you can use update() once to pass in all data. There is no limit on the length of the input parameter.
1185  md.update({ data: stringToUint8Array(message) }, (err,) => {
1186    if (err) {
1187      console.error("[Callback]: err: " + err.code);
1188    }
1189    md.digest((err1, digestOutput) => {
1190      if (err1) {
1191        console.error("[Callback]: err: " + err1.code);
1192      } else {
1193        mdOutput = digestOutput;
1194        console.info("[Callback]: MD result: " + mdOutput.data);
1195        let mdLen = md.getMdLength();
1196        console.info("[Callback]: MD len: " + mdLen);
1197      }
1198    });
1199  });
1200}
1201```
1202The following example presents how to call **update()** multiple times to update the MD.
1203```javascript
1204import cryptoFramework from "@ohos.security.cryptoFramework"
1205
1206// Convert strings in plaintext into byte streams.
1207function stringToUint8Array(str) {
1208  let arr = [];
1209  for (let i = 0, j = str.length; i < j; ++i) {
1210    arr.push(str.charCodeAt(i));
1211  }
1212  return new Uint8Array(arr);
1213}
1214
1215
1216// Generate a digest by segment in promise mode.
1217async function doLoopMdPromise() {
1218  let mdAlgName = "SHA256"; // Digest algorithm name.
1219  let md;
1220  let mdOutput;
1221  try {
1222    md = cryptoFramework.createMd(mdAlgName);
1223  } catch (error) {
1224    console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
1225    return;
1226  }
1227  console.info("[Promise]: Md algName is: " + md.algName);
1228  let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // Assume that the message is of 43 bytes.
1229  let messageArr = [];
1230  let updateLength = 20; // For example, pass in 20 bytes in each update().
1231
1232  for (let i = 0; i <= messageText.length; i++) {
1233    if ((i % updateLength == 0 || i == messageText.length) && messageArr.length != 0) {
1234      let message = new Uint8Array(messageArr);
1235      let messageBlob = { data : message };
1236      // Use await to process the update() in the for() loop.
1237      try {
1238        await md.update (messageBlob); // Use update() to process data by segment.
1239      } catch (error) {
1240        console.error("await update error code: " + error.code + ", message is: " + error.message);
1241        return;
1242      }
1243      messageArr = [];
1244    }
1245    // Pad messageArr based on the segment length.
1246    if (i < messageText.length) {
1247      messageArr.push(messageText.charCodeAt(i));
1248    }
1249  }
1250  let PromiseMdDigest = md.digest();
1251  PromiseMdDigest.then(digestOutput => {
1252    mdOutput = digestOutput;
1253    console.info("[Promise]: MD result: " + mdOutput.data);
1254    let mdLen = md.getMdLength();
1255    console.info("[Promise]: MD len: " + mdLen);
1256  }).catch(error => {
1257    console.error("[Promise]: error: " + error.message);
1258  });
1259}
1260```
1261
1262## Key Agreement
1263
1264### When to Use
1265
1266
1267Key agreement allows two parties to establish a shared secret over an insecure channel.
1268
1269### Available APIs
1270
1271For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
1272
1273|Instance|API|Description|
1274|---|---|---|
1275|cryptoFramework|createKeyAgreement(algName : string) : KeyAgreement|Creates a **KeyAgreement** instance.|
1276|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey, callback : AsyncCallback\<DataBlob>) : void|Generates a shared secret. This API uses an asynchronous callback to return the result.|
1277|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey) : Promise\<DataBlob>|Generates a shared secret. This API uses a promise to return the result.|
1278
1279### How to Develop
1280
12811. Use **createKeyAgreement()** to create a **KeyAgreement** instance for subsequent key agreement operations.
12822. Use **generateSecret()** provided by **KeyAgreement** to pass in the peer ECC public key object and the ECC private key object generated locally.
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## HMAC
1330
1331### When to Use
1332
1333A hash-based message authentication code (HMAC) can be used to verify both the integrity and authenticity of a message using a shared secret.
1334
1335Typical MAC operations involve the following:
1336
13371. Create a **Mac** instance.
13382. Initialize the **Mac** instance, add one or more segments of data for generating a MAC, and generate an HMAC.
13393. Obtain the algorithm and length of an HMAC.
1340
1341### Available APIs
1342
1343For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
1344
1345| Instance         | API                                                      | Description                                               |
1346| --------------- | ------------------------------------------------------------ | --------------------------------------------------- |
1347| cryptoFramework | function createMac(algName : string) : Mac;                  | Creates a **Mac** instance.                |
1348| Mac             | init(key : SymKey, callback : AsyncCallback\<void>) : void; | Initializes the **Mac** instance. This API uses an asynchronous callback to return the result.|
1349| Mac             | init(key : SymKey) : Promise\<void>;                        | Initializes the **Mac** instance. This API uses a promise to return the result. |
1350| 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.      |
1351| Mac             | update(input : DataBlob) : Promise\<void>;                  | Updates the data for the MAC operation. This API uses a promise to return the result.       |
1352| Mac             | doFinal(callback : AsyncCallback\<DataBlob>) : void;        | Finalizes the MAC operation to generate a MAC. This API uses an asynchronous callback to return the result.                |
1353| Mac             | doFinal() : Promise\<DataBlob>;                             | Finalizes the MAC operation to generate a MAC. This API uses a promise to return the result.                 |
1354| Mac             | getMacLength() : number;                                     | Obtains the length of the MAC based on the specified algorithm.              |
1355| Mac             | readonly algName : string;                                   | Obtains the digest algorithm.                           |
1356
1357### How to Develop
1358
13591. Call **createMac()** to create a **Mac** instance.
13602. Call **init()** to initialize the **Mac** instance with the symmetric key passed in.
13613. Call **update()** one or more times to add the data for computing a MAC.
13624. Call **doFinal()** to generate a MAC.
13635. Obtain the algorithm and length of the MAC.
1364
1365```javascript
1366import cryptoFramework from "@ohos.security.cryptoFramework"
1367
1368// Convert strings in plaintext into byte streams.
1369function stringToUint8Array(str) {
1370  let arr = [];
1371  for (let i = 0, j = str.length; i < j; ++i) {
1372    arr.push(str.charCodeAt(i));
1373  }
1374  return new Uint8Array(arr);
1375}
1376
1377// Generate an HMAC in promise mode.
1378function doHmacByPromise() {
1379  let macAlgName = "SHA256"; // Digest algorithm name.
1380  let message = "hmacTestMessgae"; // Data used to generate an HMAC.
1381  let macOutput;
1382  let mac;
1383  try {
1384    mac = cryptoFramework.createMac(macAlgName);
1385  } catch (error) {
1386    console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
1387  }
1388  console.info("[Promise]: Mac algName is: " + mac.algName);
1389  let KeyBlob = {
1390    // 128-bit key
1391    data : stringToUint8Array("12345678abcdefgh")
1392  }
1393  let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128");
1394  // Convert the binary data into a key.
1395  let promiseConvertKey = symKeyGenerator.convertKey(KeyBlob);
1396  promiseConvertKey.then(symKey => {
1397    let promiseMacInit = mac.init(symKey);
1398    return promiseMacInit;
1399  }).then(() => {
1400    // If the data volume is small, you can use update() once to pass in all data. There is no limit on the length of the input parameter.
1401    let promiseMacUpdate = mac.update({ data: stringToUint8Array(message) });
1402    return promiseMacUpdate;
1403  }).then(() => {
1404    let PromiseMacDoFinal = mac.doFinal();
1405    return PromiseMacDoFinal;
1406  }).then(output => {
1407    macOutput = output;
1408    console.info("[Promise]: HMAC result: " + macOutput.data);
1409    let macLen = mac.getMacLength();
1410    console.info("[Promise]: MAC len: " + macLen);
1411  }).catch(error => {
1412    console.error("[Promise]: error: " + error.message);
1413  });
1414}
1415
1416// Generate an HMAC in callback mode.
1417function doHmacByCallback() {
1418  let macAlgName = "SHA256"; // Digest algorithm name.
1419  let message = "hmacTestMessgae"; // Data used to generate an HMAC.
1420  let macOutput;
1421  let mac;
1422  try {
1423    mac = cryptoFramework.createMac(macAlgName);
1424  } catch (error) {
1425    console.error("[Callback]: error code: " + error.code + ", message is: " + error.message);
1426  }
1427  console.info("[Promise]: Mac algName is: " + mac.algName);
1428  let KeyBlob = {
1429    // 128-bit key
1430    data : stringToUint8Array("12345678abcdefgh")
1431  }
1432  let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128");
1433  // Convert the binary data into a key.
1434  symKeyGenerator.convertKey(KeyBlob, (err, symKey) => {
1435    if (err) {
1436      console.error("[Callback]: err: " + err.code);
1437    }
1438    mac.init(symKey, (err1, ) => {
1439      if (err1) {
1440        console.error("[Callback]: err: " + err1.code);
1441      }
1442      // If the data volume is small, you can use update() once to pass in all data. There is no limit on the length of the input parameter.
1443      mac.update({ data: stringToUint8Array(message) }, (err2, ) => {
1444        if (err2) {
1445          console.error("[Callback]: err: " + err2.code);
1446        }
1447        mac.doFinal((err3, output) => {
1448          if (err3) {
1449            console.error("[Callback]: err: " + err3.code);
1450          } else {
1451            macOutput = output;
1452            console.info("[Callback]: HMAC result: " + macOutput.data);
1453            let macLen = mac.getMacLength();
1454            console.info("[Callback]: MAC len: " + macLen);
1455          }
1456        });
1457      });
1458    });
1459  });
1460}
1461```
1462Generate an HMAC by segment.
1463```javascript
1464import cryptoFramework from "@ohos.security.cryptoFramework"
1465
1466function stringToUint8Array(str) {
1467  let arr = [];
1468  for (let i = 0, j = str.length; i < j; ++i) {
1469    arr.push(str.charCodeAt(i));
1470  }
1471  return new Uint8Array(arr);
1472}
1473
1474function doLoopHmacPromise() {
1475  let macAlgName = "SHA256"; // Digest algorithm name.
1476  let macOutput;
1477  let mac;
1478  try {
1479    mac = cryptoFramework.createMac(macAlgName);
1480  } catch (error) {
1481    console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
1482    return;
1483  }
1484  console.info("[Promise]: Mac algName is: " + mac.algName);
1485  let KeyBlob = {
1486    // 128-bit key
1487    data : stringToUint8Array("12345678abcdefgh")
1488  }
1489  let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // Assume that the message is of 43 bytes.
1490  let updateLength = 20; // For example, pass in 20 bytes in each update().
1491  let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128");
1492  // Convert the binary data into a key.
1493  let promiseConvertKey = symKeyGenerator.convertKey(KeyBlob);
1494  promiseConvertKey.then(symKey => {
1495    let promiseMacInit = mac.init(symKey);
1496    return promiseMacInit;
1497  }).then(async () => {
1498    let promiseMacUpdate;
1499    let messageArr = [];
1500    for (let i = 0; i <= messageText.length; i++) {
1501      if ((i % updateLength == 0 || i == messageText.length) && messageArr.length != 0) {
1502        let message = new Uint8Array(messageArr);
1503        let messageBlob = { data : message };
1504        // Use await to process the update() in the for() loop.
1505        try {
1506          promiseMacUpdate = await mac.update(messageBlob); // Invoke update() multiple times.
1507        } catch (error) {
1508          console.error("await update error code: " + error.code + ", message is: " + error.message);
1509          return;
1510        }
1511        messageArr = [];
1512      }
1513      // Pad messageArr based on the segment length.
1514      if (i < messageText.length) {
1515        messageArr.push(messageText.charCodeAt(i));
1516      }
1517    }
1518    return promiseMacUpdate;
1519  }).then(() => {
1520    let PromiseMacDoFinal = mac.doFinal();
1521    return PromiseMacDoFinal;
1522  }).then(output => {
1523    macOutput = output;
1524    console.log("[Promise]: HMAC result: " + macOutput.data);
1525    let macLen = mac.getMacLength();
1526    console.log("[Promise]: MAC len: " + macLen);
1527  }).catch(error => {
1528    console.error("[Promise]: error: " + error.message);
1529  });
1530}
1531```
1532
1533
1534## Random Number
1535
1536### When to Use
1537
1538Typical random number operations involve the following:
1539
15401. Generate a random number of the specified length.
15412. Set a seed based on the random number generated.
1542
1543### Available APIs
1544
1545For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md).
1546
1547| Instance         | API                                                      | Description                                          |
1548| --------------- | ------------------------------------------------------------ | ---------------------------------------------- |
1549| cryptoFramework | function createRandom() : Random;                            | Creates a **Random** instance.                          |
1550| Random          | generateRandom(len : number, callback: AsyncCallback\<DataBlob>) : void; | Generates a random number. This API uses an asynchronous callback to return the result.  |
1551| Random          | generateRandom(len : number) : Promise\<DataBlob>;          | Generates a random number. This API uses a promise to return the result.     |
1552| Random          | setSeed(seed : DataBlob) : void;                            | Sets a seed. |
1553
1554### How to Develop
1555
15561. Call **createRandom()** to create a **Random** instance.
15572. Call **generateRandom()** to generate a random number of the given length.
15583. Call **setSeed()** to set a seed.
1559
1560```javascript
1561import cryptoFramework from "@ohos.security.cryptoFramework"
1562
1563// Generate a random number and set a seed in promise mode.
1564function doRandByPromise(len) {
1565  var rand;
1566  try {
1567    rand = cryptoFramework.createRandom();
1568  } catch (error) {
1569    console.error("[Promise]: error code: " + error.code + ", message is: " + error.message);
1570  }
1571  var promiseGenerateRand = rand.generateRandom(len);
1572  promiseGenerateRand.then(randData => {
1573    console.error("[Promise]: rand result: " + randData.data);
1574      try {
1575          rand.setSeed(randData);
1576      } catch (error) {
1577          console.log("setSeed failed, errCode: " + error.code + ", errMsg: " + error.message);
1578      }
1579  }).catch(error => {
1580    console.error("[Promise]: error: " + error.message);
1581  });
1582}
1583
1584// Generate a random number and set a seed in callback mode.
1585function doRandByCallback(len) {
1586  var rand;
1587  try {
1588    rand = cryptoFramework.createRandom();
1589  } catch (error) {
1590    console.error("[Callback]: error code: " + error.code + ", message is: " + error.message);
1591  }
1592  rand.generateRandom(len, (err, randData) => {
1593    if (err) {
1594      console.error("[Callback]: err: " + err.code);
1595    } else {
1596      console.error("[Callback]: generate random result: " + randData.data);
1597      try {
1598          rand.setSeed(randData);
1599      } catch (error) {
1600          console.log("setSeed failed, errCode: " + error.code + ", errMsg: " + error.message);
1601      }
1602    }
1603  });
1604}
1605```
1606