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 131. Randomly create a key instance for subsequent encryption and decryption. 142. Convert external or stored binary data into a key instance for subsequent encryption and decryption. 153. 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 19**Available APIs** 20 21For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md). 22 23The table below describes the APIs used in this guide. 24 25|Instance|API|Description| 26|---|---|---| 27|cryptoFramework|createAsyKeyGenerator(algName : string) : AsyKeyGenerator|Creates an **AsyKeyGenerator** instance.| 28|cryptoFramework|createSymKeyGenerator(algName : string) : SymKeyGenerator|Creates a **SymKeyGenerator** instance.| 29|AsyKeyGenerator|generateKeyPair(callback : AsyncCallback\<KeyPair>) : void|Generates an asymmetric key pair randomly. This API uses an asynchronous callback to return the result.| 30|AsyKeyGenerator|generateKeyPair() : Promise\<KeyPair>|Generates an asymmetric key pair randomly. This API uses a promise to return the result.| 31|SymKeyGenerator|generateSymKey(callback : AsyncCallback\<SymKey>) : void|Generates a symmetric key randomly. This API uses an asynchronous callback to return the result.| 32|SymKeyGenerator|generateSymKey() : Promise\<SymKey>|Generates a symmetric key randomly. This API uses a promise to return the result.| 33| 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.)| 34| 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.)| 35| 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.| 36| SymKeyGenerator |convertKey(pubKey : DataBlob, priKey : DataBlob) : Promise\<KeyPair>| Converts binary data into a symmetric key. This API uses a promise to return the result.| 37| Key | getEncoded() : DataBlob; | Obtains the binary data of a key. (The child class instances of **Key** include **SymKey**, **PubKey**, and **PriKey**.)| 38 39**How to Develop** 40 41Example 1: Randomly generate an asymmetric key pair and obtain its binary data. 42 431. Create an **AsyKeyGenerator** instance. 442. Randomly generate an asymmetric key pair using **AsyKeyGenerator**. 453. Obtain binary data of the key pair generated. 46 47The following sample code demonstrates how to randomly generate an RSA key (1024 bits and two primes) using promise-based APIs. 48 49```javascript 50import cryptoFramework from '@ohos.security.cryptoFramework'; 51 52function generateAsyKey() { 53 // Create an AsyKeyGenerator instance. 54 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 55 // Use the key generator to randomly generate an asymmetric key pair. 56 let keyGenPromise = rsaGenerator.generateKeyPair(); 57 keyGenPromise.then( keyPair => { 58 globalKeyPair = keyPair; 59 let pubKey = globalKeyPair.pubKey; 60 let priKey = globalKeyPair.priKey; 61 // Obtain the binary data of the asymmetric key pair. 62 pkBlob = pubKey.getEncoded(); 63 skBlob = priKey.getEncoded(); 64 AlertDialog.show({ message : "pk bin data" + pkBlob.data} ); 65 AlertDialog.show({ message : "sk bin data" + skBlob.data} ); 66 }) 67} 68``` 69 70Example 2: Randomly generate a symmetric key and obtain its binary data. 71 721. Create a **SymKeyGenerator** instance. 732. Randomly generate a symmetric key using **SymKeyGenerator**. 743. Obtain binary data of the key generated. 75 76The following example demonstrates how to randomly generate a 256-bit AES key using promise-based APIs. 77 78```javascript 79import cryptoFramework from '@ohos.security.cryptoFramework'; 80 81// Output the byte streams in hexadecimal format. 82function uint8ArrayToShowStr(uint8Array) { 83 return Array.prototype.map 84 .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2)) 85 .join(''); 86} 87 88function testGenerateAesKey() { 89 // Create a SymKeyGenerator instance. 90 let symKeyGenerator = cryptoFramework.createSymKeyGenerator('AES256'); 91 // Use the key generator to randomly generate a symmetric key. 92 let promiseSymKey = symKeyGenerator.generateSymKey(); 93 promiseSymKey.then( key => { 94 // Obtain the binary data of the symmetric key and output a 256-bit byte stream. 95 let encodedKey = key.getEncoded(); 96 console.info('key hex:' + uint8ArrayToShowStr(encodedKey.data)); 97 }) 98} 99``` 100 101Example 3: Generate an asymmetric key pair from the binary RSA key data. 102 1031. 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. 1042. 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. 105 106```javascript 107import cryptoFramework from '@ohos.security.cryptoFramework'; 108 109function convertAsyKey() { 110 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024"); 111 let pkval = new Uint8Array([48,129,159,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,129,141,0,48,129,137,2,129,129,0,174,203,113,83,113,3,143,213,194,79,91,9,51,142,87,45,97,65,136,24,166,35,5,179,42,47,212,79,111,74,134,120,73,67,21,19,235,80,46,152,209,133,232,87,192,140,18,206,27,106,106,169,106,46,135,111,118,32,129,27,89,255,183,116,247,38,12,7,238,77,151,167,6,102,153,126,66,28,253,253,216,64,20,138,117,72,15,216,178,37,208,179,63,204,39,94,244,170,48,190,21,11,73,169,156,104,193,3,17,100,28,60,50,92,235,218,57,73,119,19,101,164,192,161,197,106,105,73,2,3,1,0,1]); 112 let pkBlob = {data : pkval}; 113 rsaGenerator.convertKey(pkBlob, null, function(err, keyPair) { 114 if (keyPair == null) { 115 AlertDialog.show({message : "Convert keypair fail"}); 116 } 117 AlertDialog.show({message : "Convert KeyPair success"}); 118 }) 119} 120``` 121 122> **NOTE** 123> 124> 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. 125 126Example 4: Generate an asymmetric key pair from the binary ECC key data. 127 1281. Obtain the ECC binary key data and encapsulate it into a **DataBlob** instance. 1292. Call **convertKey()** to convert the key binary data (data of the private or public key, or both) into a **KeyPair** instance. 130 131```javascript 132import cryptoFramework from "@ohos.security.cryptoFramework" 133 134function convertEccAsyKey() { 135 let pubKeyArray = new Uint8Array([48,89,48,19,6,7,42,134,72,206,61,2,1,6,8,42,134,72,206,61,3,1,7,3,66,0,4,83,96,142,9,86,214,126,106,247,233,92,125,4,128,138,105,246,162,215,71,81,58,202,121,26,105,211,55,130,45,236,143,55,16,248,75,167,160,167,106,2,152,243,44,68,66,0,167,99,92,235,215,159,239,28,106,124,171,34,145,124,174,57,92]); 136 let priKeyArray = new Uint8Array([48,49,2,1,1,4,32,115,56,137,35,207,0,60,191,90,61,136,105,210,16,27,4,171,57,10,61,123,40,189,28,34,207,236,22,45,223,10,189,160,10,6,8,42,134,72,206,61,3,1,7]); 137 let pubKeyBlob = { data: pubKeyArray }; 138 let priKeyBlob = { data: priKeyArray }; 139 let generator = cryptoFramework.createAsyKeyGenerator("ECC256"); 140 generator.convertKey(pubKeyBlob, priKeyBlob, (error, data) => { 141 if (error) { 142 AlertDialog.show({message : "Convert keypair fail"}); 143 } 144 AlertDialog.show({message : "Convert KeyPair success"}); 145 }) 146} 147``` 148 149Example 5: Generate a symmetric key from binary data. 150 1511. Create a **SymKeyGenerator** instance. 1522. Generate a symmetric key from the binary data passed in. 1533. Obtain binary data of the key generated. 154 155The following example demonstrates how to generate a 3DES key (192 bits only) using callback-based APIs. 156 157```javascript 158import cryptoFramework from '@ohos.security.cryptoFramework'; 159 160// Output the byte streams in hexadecimal format. 161function uint8ArrayToShowStr(uint8Array) { 162 return Array.prototype.map 163 .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2)) 164 .join(''); 165} 166 167function genKeyMaterialBlob() { 168 let arr = [ 169 0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56, 170 0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c, 171 0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72]; // keyLen = 192 (24 bytes) 172 let keyMaterial = new Uint8Array(arr); 173 return {data : keyMaterial}; 174} 175 176function testConvertAesKey() { 177 // Create a SymKeyGenerator instance. 178 let symKeyGenerator = cryptoFramework.createSymKeyGenerator('3DES192'); 179 // Generate a symmetric key based on the specified data. 180 let keyMaterialBlob = genKeyMaterialBlob(); 181 try { 182 symKeyGenerator.convertKey(keyMaterialBlob, (error, key) => { 183 if (error) { // If the service logic fails to be executed, return the error information in the first parameter of the callback. 184 console.error(`convertKey error, ${error.code}, ${error.message}`); 185 return; 186 } 187 console.info(`key algName: ${key.algName}`); 188 console.info(`key format: ${key.format}`); 189 let encodedKey = key.getEncoded(); // Obtain the binary data of the symmetric key and output a 192-bit byte stream. 190 console.info('key getEncoded hex: ' + uint8ArrayToShowStr(encodedKey.data)); 191 }) 192 } catch (error) { // Throw an exception immediately in synchronous mode when an error is detected during the parameter check. 193 console.error(`convertKey failed, ${error.code}, ${error.message}`); 194 return; 195 } 196} 197``` 198 199## Encrypting and Decrypting Data 200 201**When to Use** 202 203Important data needs to be encrypted in data storage or transmission for security purposes. Typical encryption and decryption operations involve the following: 2041. Encrypt and decrypt data using a symmetric key. 2052. Encrypt and decrypt data using an asymmetric key pair. 206 207**Available APIs** 208 209For 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. 210 211The table below describes the APIs used in this guide. 212 213|Instance|API|Description| 214|---|---|---| 215|cryptoFramework|createCipher(transformation : string) : Cipher|Creates a **Cipher** instance.| 216|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.| 217|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.| 218|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.| 219|Cipher|update(data : DataBlob) : Promise\<DataBlob>|Updates the data for encryption and decryption. This API uses a promise to return the result.| 220|Cipher|doFinal(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|Finalizes the encryption or decryption. This API uses an asynchronous callback to return the result.| 221|Cipher|doFinal(data : DataBlob) : Promise\<DataBlob>|Finalizes the encryption or decryption. This API uses a promise to return the result.| 222 223**How to Develop** 224 225Example 1: Encrypt and decrypt data using a symmetric key. 226 2271. Create a **SymKeyGenerator** instance. 2282. Use the key generator to generate a symmetric key. 2293. Create a **Cipher** instance. 2304. Encrypt or decrypt data. 231 232The following example demonstrates how to use the AES-GCM to encrypt and decrypt data with promise-based APIs. 233 234```js 235import cryptoFramework from '@ohos.security.cryptoFramework'; 236 237var globalCipher; 238var globalGcmParams; 239var globalKey; 240var globalCipherText; 241 242function genGcmParamsSpec() { 243 let arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0 , 0, 0]; // 12 bytes 244 let dataIv = new Uint8Array(arr); 245 let ivBlob = {data : dataIv}; 246 247 arr = [0, 0, 0, 0 , 0, 0, 0, 0]; // 8 bytes 248 let dataAad = new Uint8Array(arr); 249 let aadBlob = {data : dataAad}; 250 251 arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0]; // 16 bytes 252 let dataTag = new Uint8Array(arr); 253 let tagBlob = {data : dataTag}; // The authTag of GCM is obtained by doFinal() in encryption and passed in params of init() in decryption. 254 255 let gcmParamsSpec = {iv : ivBlob, aad : aadBlob, authTag : tagBlob, algName : "GcmParamsSpec"}; 256 return gcmParamsSpec; 257} 258 259// Convert strings in plaintext into byte streams. 260function stringToUint8Array(str) { 261 let arr = []; 262 for (let i = 0, j = str.length; i < j; ++i) { 263 arr.push(str.charCodeAt(i)); 264 } 265 return new Uint8Array(arr); 266} 267 268// Output the byte streams in hexadecimal format. 269function uint8ArrayToShowStr(uint8Array) { 270 return Array.prototype.map 271 .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2)) 272 .join(''); 273} 274 275// Convert byte streams into strings in plaintext. 276function uint8ArrayToString(array) { 277 let arrayString = ''; 278 for (let i = 0; i < array.length; i++) { 279 arrayString += String.fromCharCode(array[i]); 280 } 281 return arrayString; 282} 283 284function genKeyMaterialBlob() { 285 let arr = [ 286 0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56, 287 0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c, 288 0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72]; // keyLen = 192 (24 bytes) 289 let keyMaterial = new Uint8Array(arr); 290 return {data : keyMaterial}; 291} 292 293 294// Automatically generate a key in AES GCM mode and return the result in a promise. 295function testAesGcm() { 296 return new Promise((resolve, reject) => { 297 setTimeout(() => { 298 resolve('testAesGcm'); 299 }, 10) 300 }).then(() => { 301 // Create a SymKeyGenerator instance. 302 let symAlgName = 'AES128'; 303 let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName); 304 if (symKeyGenerator == null) { 305 console.error('createSymKeyGenerator failed'); 306 return; 307 } 308 console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`); 309 // Use the key generator to randomly generate a 128-bit symmetric key. 310 let promiseSymKey = symKeyGenerator.generateSymKey(); 311 // Constructor 312 globalGcmParams = genGcmParamsSpec(); 313 314 // Create a Cipher instance. 315 let cipherAlgName = 'AES128|GCM|PKCS7'; 316 try { 317 globalCipher = cryptoFramework.createCipher(cipherAlgName); 318 console.info(`cipher algName: ${globalCipher.algName}`); 319 } catch (error) { 320 console.error(`createCipher failed, ${error.code}, ${error.message}`); 321 return; 322 } 323 return promiseSymKey; 324 }).then(key => { 325 let encodedKey = key.getEncoded(); 326 console.info('key hex:' + uint8ArrayToShowStr(encodedKey.data)); 327 globalKey = key; 328 return key; 329 }).then(key => { 330 // Initialize the cipher environment and start encryption. 331 let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE; 332 let promiseInit = globalCipher.init(mode, key, globalGcmParams); // init 333 return promiseInit; 334 }).then(() => { 335 let plainText = {data : stringToUint8Array('this is test!')}; 336 let promiseUpdate = globalCipher.update(plainText); // update 337 return promiseUpdate; 338 }).then(updateOutput => { 339 globalCipherText = updateOutput; 340 let promiseFinal = globalCipher.doFinal(null); // doFinal 341 return promiseFinal; 342 }).then(authTag => { 343 // In GCM mode, the encrypted authentication information needs to be obtained from the output of doFinal() and passed in globalGcmParams of init() in decryption. 344 globalGcmParams.authTag = authTag; 345 return; 346 }).then(() => { 347 // Initialize the cipher environment and start decryption. 348 let mode = cryptoFramework.CryptoMode.DECRYPT_MODE; 349 let promiseInit = globalCipher.init(mode, globalKey, globalGcmParams); // init 350 return promiseInit; 351 }).then(() => { 352 let promiseUpdate = globalCipher.update(globalCipherText); // update 353 return promiseUpdate; 354 }).then(updateOutput => { 355 console.info('decrypt plainText: ' + uint8ArrayToString(updateOutput.data)); 356 let promiseFinal = globalCipher.doFinal(null); // doFinal 357 return promiseFinal; 358 }).then(finalOutput => { 359 if (finalOutput == null) { // Check whether the result is null before using finalOutput.data. 360 console.info('GCM finalOutput is null'); 361 } 362 }).catch(error => { 363 console.error(`catch error, ${error.code}, ${error.message}`); 364 }) 365} 366``` 367 368The following example demonstrates how to use the the 3DES ECB to convert existing data into a key and encrypt and decrypt data using callback-based APIs. 369 370```js 371import cryptoFramework from '@ohos.security.cryptoFramework'; 372 373var globalCipher; 374var globalGcmParams; 375var globalKey; 376var globalCipherText; 377 378// Convert strings in plaintext into byte streams. 379function stringToUint8Array(str) { 380 let arr = []; 381 for (let i = 0, j = str.length; i < j; ++i) { 382 arr.push(str.charCodeAt(i)); 383 } 384 return new Uint8Array(arr); 385} 386 387// Output the byte streams in hexadecimal format. 388function uint8ArrayToShowStr(uint8Array) { 389 return Array.prototype.map 390 .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2)) 391 .join(''); 392} 393 394// Convert byte streams into strings in plaintext. 395function uint8ArrayToString(array) { 396 let arrayString = ''; 397 for (let i = 0; i < array.length; i++) { 398 arrayString += String.fromCharCode(array[i]); 399 } 400 return arrayString; 401} 402 403function genKeyMaterialBlob() { 404 let arr = [ 405 0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56, 406 0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c, 407 0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72]; // keyLen = 192 (24 bytes) 408 let keyMaterial = new Uint8Array(arr); 409 return {data : keyMaterial}; 410} 411 412// Use the 3DES ECB to Generate a key from the existing data and encrypt and decrypt data using callback-based APIs. 413function test3DesEcb() { 414 // Create a SymKeyGenerator instance. 415 let symAlgName = '3DES192'; 416 let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName); 417 if (symKeyGenerator == null) { 418 console.error('createSymKeyGenerator failed'); 419 return; 420 } 421 console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`); 422 423 // Create a Cipher instance. 424 let cipherAlgName = '3DES192|ECB|PKCS7'; 425 try { 426 globalCipher = cryptoFramework.createCipher(cipherAlgName); 427 console.info(`cipher algName: ${globalCipher.algName}`); 428 } catch (error) { 429 console.error(`createCipher failed, ${error.code}, ${error.message}`); 430 return; 431 } 432 433 // Generate a symmetric key based on the specified data. 434 let keyMaterialBlob = genKeyMaterialBlob(); 435 try { 436 symKeyGenerator.convertKey(keyMaterialBlob, (error, key) => { 437 if (error) { 438 console.error(`convertKey error, ${error.code}, ${error.message}`); 439 return; 440 } 441 console.info(`key algName: ${key.algName}`); 442 console.info(`key format: ${key.format}`); 443 let encodedKey = key.getEncoded(); 444 console.info('key getEncoded hex: ' + uint8ArrayToShowStr(encodedKey.data)); 445 globalKey = key; 446 447 // Initialize the cipher environment and start encryption. 448 let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE; 449 // init 450 globalCipher.init(mode, key, null, (err, ) => { 451 let plainText = {data : stringToUint8Array('this is test!')}; 452 // update 453 globalCipher.update(plainText, (err, updateOutput) => { 454 globalCipherText = updateOutput; 455 //doFinal 456 globalCipher.doFinal(null, (err, finalOutput) => { 457 if (error) { 458 console.error(`doFinal error, ${error.code}, ${error.message}`); 459 return; 460 } 461 if (finalOutput != null) { 462 globalCipherText = Array.from(globalCipherText.data); 463 finalOutput = Array.from(finalOutput.data); 464 globalCipherText = globalCipherText.concat(finalOutput); 465 globalCipherText = new Uint8Array(globalCipherText); 466 globalCipherText = {data : globalCipherText}; 467 } 468 // Initialize the cipher environment and start decryption. 469 let mode = cryptoFramework.CryptoMode.DECRYPT_MODE; 470 // init 471 globalCipher.init(mode, globalKey, null, (err, ) => { 472 // update 473 globalCipher.update(globalCipherText, (err, updateOutput) => { 474 console.info('decrypt plainText: ' + uint8ArrayToString(updateOutput.data)); 475 // doFinal 476 globalCipher.doFinal(null, (error, finalOutput) => { 477 if (finalOutput == null) { // Check whether the result is null before using finalOutput.data. 478 console.info("decrypt plainText:" + uint8ArrayToString(finalOutput.data)); 479 } 480 }) 481 }) 482 }) 483 }) 484 }) 485 }) 486 }) 487 } catch (error) { 488 console.error(`convertKey failed, ${error.code}, ${error.message}`); 489 return; 490 } 491} 492``` 493The following example demonstrates how to call **update()** multiple times to implement AES GCM encryption and decryption by using promise-based APIs. 494 495```javascript 496import cryptoFramework from '@ohos.security.cryptoFramework'; 497 498var globalCipher; 499var globalGcmParams; 500var globalKey; 501var globalCipherText; 502var globalPlainText; 503 504function genGcmParamsSpec() { 505 let arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0 , 0, 0]; // 12 bytes 506 let dataIv = new Uint8Array(arr); 507 let ivBlob = {data : dataIv}; 508 509 arr = [0, 0, 0, 0 , 0, 0, 0, 0]; // 8 bytes 510 let dataAad = new Uint8Array(arr); 511 let aadBlob = {data : dataAad}; 512 513 arr = [0, 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0, 0 , 0, 0, 0, 0]; // 16 bytes 514 let dataTag = new Uint8Array(arr); 515 let tagBlob = {data : dataTag}; 516 let gcmParamsSpec = {iv : ivBlob, aad : aadBlob, authTag : tagBlob, algName : "GcmParamsSpec"}; 517 return gcmParamsSpec; 518} 519 520// Output the byte streams in hexadecimal format. 521function uint8ArrayToShowStr(uint8Array) { 522 return Array.prototype.map 523 .call(uint8Array, (x) => ('00' + x.toString(16)).slice(-2)) 524 .join(''); 525} 526 527// Convert byte streams into strings in plaintext. 528function uint8ArrayToString(array) { 529 let arrayString = ''; 530 for (let i = 0; i < array.length; i++) { 531 arrayString += String.fromCharCode(array[i]); 532 } 533 return arrayString; 534} 535 536// 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. 537function testAesMultiUpdate() { 538 return new Promise((resolve, reject) => { 539 setTimeout(() => { 540 resolve('testAesMultiUpdate'); 541 }, 10) 542 }).then(() => { 543 // Create a SymKeyGenerator instance. 544 let symAlgName = 'AES128'; 545 let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName); 546 if (symKeyGenerator == null) { 547 console.error('createSymKeyGenerator failed'); 548 return; 549 } 550 console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`); 551 // Use the key generator to randomly generate a 128-bit symmetric key. 552 let promiseSymKey = symKeyGenerator.generateSymKey(); 553 // Constructor 554 globalGcmParams = genGcmParamsSpec(); 555 556 // Create a Cipher instance. 557 let cipherAlgName = 'AES128|GCM|PKCS7'; 558 try { 559 globalCipher = cryptoFramework.createCipher(cipherAlgName); 560 console.info(`cipher algName: ${globalCipher.algName}`); 561 } catch (error) { 562 console.error(`createCipher failed, ${error.code}, ${error.message}`); 563 return; 564 } 565 return promiseSymKey; 566 }).then(key => { 567 let encodedKey = key.getEncoded(); 568 console.info('key hex:' + uint8ArrayToShowStr(encodedKey.data)); 569 globalKey = key; 570 return key; 571 }).then(key => { 572 // Initialize the cipher environment and start encryption. 573 let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE; 574 let promiseInit = globalCipher.init(mode, key, globalGcmParams); // init 575 return promiseInit; 576 }).then(async () => { 577 let plainText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // Assume that the plaintext contains 43 bytes. 578 let messageArr = []; 579 let updateLength = 20; // Pass in 20 bytes by update() each time. 580 globalCipherText = []; 581 582 for (let i = 0; i <= plainText.length; i++) { 583 if ((i % updateLength == 0 || i == plainText.length) && messageArr.length != 0) { 584 let message = new Uint8Array(messageArr); 585 let messageBlob = { data : message }; 586 let updateOutput = await globalCipher.update(messageBlob); // Update by segment. 587 // 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 588 // 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. 589 globalCipherText = globalCipherText.concat(Array.from(updateOutput.data)); 590 messageArr = []; 591 } 592 if (i < plainText.length) { 593 messageArr.push(plainText.charCodeAt(i)); 594 } 595 } 596 return; 597 }).then(() => { 598 let promiseFinal = globalCipher.doFinal(null); // doFinal 599 return promiseFinal; 600 }).then(authTag => { 601 // Obtain the authentication information after encryption. 602 globalGcmParams.authTag = authTag; 603 return; 604 }).then(() => { 605 // Initialize the cipher environment and start decryption. 606 let mode = cryptoFramework.CryptoMode.DECRYPT_MODE; 607 let promiseInit = globalCipher.init(mode, globalKey, globalGcmParams); // init 608 return promiseInit; 609 }).then(async () => { 610 let updateLength = 20; 611 let updateTimes = Math.ceil(globalCipherText.length / updateLength); // Round up to the nearest integer. 612 globalPlainText = ""; 613 for (let i = 0; i < updateTimes; i++) { 614 let messageArr = globalCipherText.slice(i * updateLength, (i + 1) * updateLength); 615 let message = new Uint8Array(messageArr); 616 let messageBlob = { data : message }; 617 let updateOutput = await globalCipher.update(messageBlob); // Pass in data by segment. 618 globalPlainText += uint8ArrayToString(updateOutput.data); // Restore the original plaintext. 619 } 620 return; 621 }).then(() => { 622 let promiseFinal = globalCipher.doFinal(null); // doFinal 623 return promiseFinal; 624 }).then(finalOutput => { 625 if (finalOutput == null) { 626 console.info('GCM finalOutput is null'); 627 } 628 console.info(`decrypt output: ${globalPlainText}`); 629 }).catch(error => { 630 console.error(`catch error, ${error.code}, ${error.message}`); 631 }) 632} 633``` 634 635Example 2: Encrypt and decrypt data using an asymmetric key pair. 636 6371. Generate an RSA key pair.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an RSA asymmetric key pair. 6382. Create a **Cipher** instance.<br>Call **createCipher()** to create a **Cipher** instance, and set the key and encryption/decryption mode. 6393. Perform encryption and decryption operations.<br>Call **doFinal()** provided by the **Cipher** instance to encrypt data or decrypt data. 640 641```javascript 642import cryptoFramework from "@ohos.security.cryptoFramework" 643 644let plan = "This is cipher test."; 645 646function stringToUint8Array(str) { 647 var arr = []; 648 for (var i = 0, j = str.length; i < j; ++i) { 649 arr.push(str.charCodeAt(i)); 650 } 651 var tmpArray = new Uint8Array(arr); 652 return tmpArray; 653} 654 655function encryptMessageProMise() { 656 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 657 let cipher = cryptoFramework.createCipher("RSA1024|PKCS1"); 658 let keyGenPromise = rsaGenerator.generateKeyPair(); 659 keyGenPromise.then(rsaKeyPair => { 660 let pubKey = rsaKeyPair.pubKey; 661 return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null); 662 }).then(() => { 663 let input = { data : stringToUint8Array(plan) }; 664 return cipher.doFinal(input); 665 }).then(dataBlob => { 666 console.info("EncryptOutPut is " + dataBlob.data); 667 }); 668} 669 670function encryptMessageCallback() { 671 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 672 let cipher = cryptoFramework.createCipher("RSA1024|PKCS1"); 673 rsaGenerator.generateKeyPair(function (err, keyPair) { 674 let pubKey = keyPair.pubKey; 675 cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null, function (err, data) { 676 let input = {data : stringToUint8Array(plan) }; 677 cipher.doFinal(input, function (err, data) { 678 console.info("EncryptOutPut is " + data.data); 679 }) 680 }) 681 }) 682} 683 684function decryptMessageProMise() { 685 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 686 let cipher = cryptoFramework.createCipher("RSA1024|PKCS1"); 687 let decoder = cryptoFramework.createCipher("RSA1024|PKCS1"); 688 let keyGenPromise = rsaGenerator.generateKeyPair(); 689 let keyPair; 690 let cipherDataBlob; 691 let input = { data : stringToUint8Array(plan) }; 692 keyGenPromise.then(rsaKeyPair => { 693 keyPair = rsaKeyPair; 694 return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null); 695 }).then(() => { 696 return cipher.doFinal(input); 697 }).then(dataBlob => { 698 console.info("EncryptOutPut is " + dataBlob.data); 699 AlertDialog.show({message : "output" + dataBlob.data}); 700 cipherDataBlob = dataBlob; 701 return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null); 702 }).then(() => { 703 return decoder.doFinal(cipherDataBlob); 704 }).then(decodeData => { 705 if (decodeData.data.toString() === input.data.toString()) { 706 AlertDialog.show({message : "decrypt success"}); 707 return; 708 } 709 AlertDialog.show({message : "decrypt fail"}); 710 }); 711} 712 713function decryptMessageCallback() { 714 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 715 let cipher = cryptoFramework.createCipher("RSA1024|PKCS1"); 716 let decoder = cryptoFramework.createCipher("RSA1024|PKCS1"); 717 let plainText = "this is cipher text"; 718 let input = {data : stringToUint8Array(plainText) }; 719 let cipherData; 720 let keyPair; 721 rsaGenerator.generateKeyPair(function (err, newKeyPair) { 722 keyPair = newKeyPair; 723 cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null, function (err, data) { 724 cipher.doFinal(input, function (err, data) { 725 AlertDialog.show({ message : "EncryptOutPut is " + data.data} ); 726 cipherData = data; 727 decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null, function (err, data) { 728 decoder.doFinal(cipherData, function (err, data) { 729 if (input.data.toString() === data.data.toString()) { 730 AlertDialog.show({ message : "decrype success"} ); 731 return; 732 } 733 AlertDialog.show({ message : "decrype fail"} ); 734 }); 735 }); 736 }); 737 }); 738 }); 739} 740``` 741The following example demonstrates how to implement RSA asymmetric encryption and decryption (**doFinal()** is called multiple times). 742```javascript 743import cryptoFramework from "@ohos.security.cryptoFramework" 744 745function stringToUint8Array(str) { 746 var arr = []; 747 for (var i = 0, j = str.length; i < j; ++i) { 748 arr.push(str.charCodeAt(i)); 749 } 750 var tmpArray = new Uint8Array(arr); 751 return tmpArray; 752} 753 754// Convert byte streams into strings in plaintext. 755function uint8ArrayToString(array) { 756 let arrayString = ''; 757 for (let i = 0; i < array.length; i++) { 758 arrayString += String.fromCharCode(array[i]); 759 } 760 return arrayString; 761} 762 763function encryptLongMessagePromise() { 764 let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 765 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 766 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 767 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 768 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 769 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 770 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 771 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!"; 772 let globalCipherOutput; 773 let globalDecodeOutput; 774 var globalKeyPair; 775 let plainTextSplitLen = 64; // 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. 776 let cipherTextSplitLen = 128; // Length of the ciphertext = Number of key bits/8 777 let keyGenName = "RSA1024"; 778 let cipherAlgName = "RSA1024|PKCS1"; 779 let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // Create an AsyKeyGenerator object. 780 let cipher = cryptoFramework.createCipher(cipherAlgName); // Create a Cipher object. 781 let decoder = cryptoFramework.createCipher(cipherAlgName); // Create a Decoder object. 782 return new Promise((resolve, reject) => { 783 setTimeout(() => { 784 resolve("testRsaMultiDoFinal"); 785 }, 10); 786 }).then(() => { 787 return asyKeyGenerator.generateKeyPair(); // Generate an RSA key. 788 }).then(keyPair => { 789 globalKeyPair = keyPair; // Save the key to global variables. 790 return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, globalKeyPair.pubKey, null); 791 }).then(async () => { 792 globalCipherOutput = []; 793 // 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. 794 for (let i = 0; i < (globalPlainText.length / plainTextSplitLen); i++) { 795 let tempStr = globalPlainText.substr(i * plainTextSplitLen, plainTextSplitLen); 796 let tempBlob = { data : stringToUint8Array(tempStr) }; 797 let tempCipherOutput = await cipher.doFinal(tempBlob); 798 globalCipherOutput = globalCipherOutput.concat(Array.from(tempCipherOutput.data)); 799 } 800 console.info(`globalCipherOutput len is ${globalCipherOutput.length}, data is: ${globalCipherOutput.toString()}`); 801 return; 802 }).then(() =>{ 803 return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, globalKeyPair.priKey, null); 804 }).then(async() => { 805 globalDecodeOutput = []; 806 // Split and decrypt the ciphertext by 128 bytes, and combine the plaintext obtained each time. 807 for (let i = 0; i < (globalCipherOutput.length / cipherTextSplitLen); i++) { 808 let tempBlobData = globalCipherOutput.slice(i * cipherTextSplitLen, (i + 1) * cipherTextSplitLen); 809 let message = new Uint8Array(tempBlobData); 810 let tempBlob = { data : message }; 811 let tempDecodeOutput = await decoder.doFinal(tempBlob); 812 globalDecodeOutput += uint8ArrayToString(tempDecodeOutput.data); 813 } 814 if (globalDecodeOutput === globalPlainText) { 815 console.info(`encode and decode success`); 816 } else { 817 console.info(`encode and decode error`); 818 } 819 return; 820 }).catch(error => { 821 console.error(`catch error, ${error.code}, ${error.message}`); 822 }) 823} 824``` 825 826> **NOTE** 827> 828> - 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. 829> - 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). 830> - 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. 831 832## Generating and Verifying a Signature 833 834**When to Use** 835 836A digital signature can be used to verify the authenticity of a message. Typical signing and signature verification operations involve the following: 837- Use the RSA to generate and verify a signature. 838- Use the ECC to generate and verify a signature. 839 840**Available APIs** 841 842For 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. 843 844|Instance|API|Description| 845|---|---|---| 846|cryptoFramework|createSign(algName : string) : Sign|Creates a **Sign** instance.| 847|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.| 848|Sign|init(priKey : PriKey) : Promise\<void>|Sets a key and initializes the **Sign** instance. This API uses a promise to return the result.| 849|Sign|update(data : DataBlob, callback : AsyncCallback\<void>) : void|Updates the data for signing. This API uses an asynchronous callback to return the result.| 850|Sign|update(data : DataBlob) : Promise\<void>|Updates the data for signing. This API uses a promise to return the result.| 851|Sign|sign(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|Signs the data. This API uses an asynchronous callback to return the result.| 852|Sign|sign(data : DataBlob) : Promise\<DataBlob>|Signs the data. This API uses a promise to return the result.| 853|cryptoFramework|function createVerify(algName : string) : Verify|Creates a **Verify** instance.| 854|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.| 855|Verify|init(priKey : PriKey) : Promise\<void>|Sets a key and initializes the **Verify** instance. This API uses a promise to return the result.| 856|Verify|update(data : DataBlob, callback : AsyncCallback\<void>) : void|Updates the data for signature verification. This API uses an asynchronous callback to return the result.| 857|Verify|update(data : DataBlob) : Promise\<void>|Updates the data for signature verification. This API uses a promise to return the result.| 858|Verify|verify(data : DataBlob, signatureData : DataBlob, callback : AsyncCallback\<boolean>) : void|Verifies the signature. This API uses an asynchronous callback to return the result.| 859|Verify|verify(data : DataBlob, signatureData : DataBlob) : Promise\<boolean>|Verifies the signature. This API uses a promise to return the result.| 860 861**How to Develop** 862 863Example 1: Use the RSA to generate and verify a signature. 8641. Generate an RSA key pair.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an RSA asymmetric key pair. 8652. Create a **Sign** instance.<br>Call **createSign()** to create a **Sign** instance, initialize the **Sign** instance, and set a private key for signing. 8663. Generate a signature.<br>Call **update()** provided by the **Sign** class to add the data for signing and call **sign()** to generate a signature. 8674. Create a **Verify** instance.<br>Call **createVerify()** to create a **Verify** instance, initialize the instance, and set a public key for signature verification. 8685. Verify the signature.<br>Call **update()** provided by the **Verify** class to add signature data and call **verify()** to verify the signature. 869```javascript 870import cryptoFramework from "@ohos.security.cryptoFramework" 871 872function stringToUint8Array(str) { 873 var arr = []; 874 for (var i = 0, j = str.length; i < j; ++i) { 875 arr.push(str.charCodeAt(i)); 876 } 877 var tmpArray = new Uint8Array(arr); 878 return tmpArray; 879} 880 881let globalKeyPair; 882let SignMessageBlob; 883let plan1 = "This is Sign test plan1"; 884let plan2 = "This is Sign test plan1"; 885let input1 = { data : stringToUint8Array(plan1) }; 886let input2 = { data : stringToUint8Array(plan2) }; 887 888function signMessagePromise() { 889 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 890 let signer = cryptoFramework.createSign("RSA1024|PKCS1|SHA256"); 891 let keyGenPromise = rsaGenerator.generateKeyPair(); 892 keyGenPromise.then( keyPair => { 893 globalKeyPair = keyPair; 894 let priKey = globalKeyPair.priKey; 895 return signer.init(priKey); 896 }).then(() => { 897 return signer.update(input1); 898 }).then(() => { 899 return signer.sign(input2); 900 }).then(dataBlob => { 901 SignMessageBlob = dataBlob; 902 console.info("sign output is " + SignMessageBlob.data); 903 }); 904} 905 906function verifyMessagePromise() { 907 let verifyer = cryptoFramework.createVerify("RSA1024|PKCS1|SHA256"); 908 let verifyInitPromise = verifyer.init(globalKeyPair.pubKey); 909 verifyInitPromise.then(() => { 910 return verifyer.update(input1); 911 }).then(() => { 912 return verifyer.verify(input2, SignMessageBlob); 913 }).then(res => { 914 console.log("Verify result is " + res); 915 }); 916} 917 918function signMessageCallback() { 919 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 920 let signer = cryptoFramework.createSign("RSA1024|PKCS1|SHA256"); 921 rsaGenerator.generateKeyPair(function (err, keyPair) { 922 globalKeyPair = keyPair; 923 let priKey = globalKeyPair.priKey; 924 signer.init(priKey, function (err, data) { 925 signer.update(input1, function (err, data) { 926 signer.sign(input2, function (err, data) { 927 SignMessageBlob = data; 928 console.info("sign output is " + SignMessageBlob.data); 929 }); 930 }); 931 }); 932 }); 933} 934 935function verifyMessageCallback() { 936 let verifyer = cryptoFramework.createVerify("RSA1024|PKCS1|SHA256"); 937 verifyer.init(globalKeyPair.pubKey, function (err, data) { 938 verifyer.update(input1, function(err, data) { 939 verifyer.verify(input2, SignMessageBlob, function(err, data) { 940 console.info("verify result is " + data); 941 }); 942 }); 943 }) 944} 945``` 946 947Example 2: Use the ECDSA to generate and verify a signature. 9481. Generate an ECC key.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an ECC asymmetric key pair. 9492. Create a **Sign** instance.<br>Call **createSign()** to create a **Sign** instance, initialize the **Sign** instance, and set a private key for signing. 9503. Generate a signature.<br>Call **update()** provided by the **Sign** class to add the data for signing and call **doFinal()** to generate a signature. 9514. Create a **Verify** instance.<br>Call **createVerify()** to create a **Verify** instance, initialize the instance, and set a public key for signature verification. 9525. Verify the signature.<br>Call **update()** provided by the **Verify** class to add signature data and call **doFinal()** to verify the signature. 953 954```javascript 955import cryptoFramework from "@ohos.security.cryptoFramework" 956 957function stringToUint8Array(str) { 958 var arr = []; 959 for (var i = 0, j = str.length; i < j; ++i) { 960 arr.push(str.charCodeAt(i)); 961 } 962 var tmpArray = new Uint8Array(arr); 963 return tmpArray; 964} 965 966let globalKeyPair; 967let SignMessageBlob; 968let plan1 = "This is Sign test plan1"; 969let plan2 = "This is Sign test plan1"; 970let input1 = { data : stringToUint8Array(plan1) }; 971let input2 = { data : stringToUint8Array(plan2) }; 972 973function signMessagePromise() { 974 let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256"); 975 let signer = cryptoFramework.createSign("ECC256|SHA256"); 976 let keyGenPromise = eccGenerator.generateKeyPair(); 977 keyGenPromise.then( keyPair => { 978 globalKeyPair = keyPair; 979 let priKey = globalKeyPair.priKey; 980 return signer.init(priKey); 981 }).then(() => { 982 return signer.update(input1); 983 }).then(() => { 984 return signer.sign(input2); 985 }).then(dataBlob => { 986 SignMessageBlob = dataBlob; 987 console.info("sign output is " + SignMessageBlob.data); 988 }); 989} 990 991function verifyMessagePromise() { 992 let verifyer = cryptoFramework.createVerify("ECC256|SHA256"); 993 let verifyInitPromise = verifyer.init(globalKeyPair.pubKey); 994 verifyInitPromise.then(() => { 995 return verifyer.update(input1); 996 }).then(() => { 997 return verifyer.verify(input2, SignMessageBlob); 998 }).then(res => { 999 console.log("Verify result is " + res); 1000 }); 1001} 1002 1003function signMessageCallback() { 1004 let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256"); 1005 let signer = cryptoFramework.createSign("ECC256|SHA256"); 1006 eccGenerator.generateKeyPair(function (err, keyPair) { 1007 globalKeyPair = keyPair; 1008 let priKey = globalKeyPair.priKey; 1009 signer.init(priKey, function (err, data) { 1010 signer.update(input1, function (err, data) { 1011 signer.sign(input2, function (err, data) { 1012 SignMessageBlob = data; 1013 console.info("sign output is " + SignMessageBlob.data); 1014 }); 1015 }); 1016 }); 1017 }); 1018} 1019 1020function verifyMessageCallback() { 1021 let verifyer = cryptoFramework.createVerify("ECC256|SHA256"); 1022 verifyer.init(globalKeyPair.pubKey, function (err, data) { 1023 verifyer.update(input1, function(err, data) { 1024 verifyer.verify(input2, SignMessageBlob, function(err, data) { 1025 console.info("verify result is " + data); 1026 }); 1027 }); 1028 }) 1029} 1030``` 1031The following example demonstrates how to call **update()** multiple times to implement signing and signature verification. 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 example demonstrates 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. Use **createKeyAgreement()** to create a **KeyAgreement** object for subsequent key agreement operations. 12932. Use **generateSecret()** provided by **KeyAgreement** to pass in the peer ECC public key object and the ECC private key object generated locally. 1294 1295```javascript 1296import cryptoFramework from "@ohos.security.cryptoFramework" 1297 1298let globalSelfPriKey; 1299let globalPeerPubKey; 1300 1301function ecdhPromise() { 1302 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]); 1303 let peerPubKeyBlob = { data: peerPubKeyArray }; 1304 let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256"); 1305 let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256"); 1306 eccGenerator.convertKey(peerPubKeyBlob, null).then((peerKeyPair) => { 1307 globalPeerPubKey = peerKeyPair.pubKey; 1308 return eccGenerator.generateKeyPair(); 1309 }).then((keyPair) => { 1310 globalSelfPriKey = keyPair.priKey; 1311 return eccKeyAgreement.generateSecret(globalSelfPriKey, globalPeerPubKey); 1312 }).then((secret) => { 1313 console.info("ecdh promise output is " + secret.data); 1314 }).catch((error) => { 1315 console.error("ecdh error."); 1316 }); 1317} 1318 1319function ecdhCallback() { 1320 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]); 1321 let peerPubKeyBlob = { data: peerPubKeyArray }; 1322 let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256"); 1323 let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256"); 1324 eccGenerator.convertKey(peerPubKeyBlob, null, function (err, peerKeyPair) { 1325 globalPeerPubKey = peerKeyPair.pubKey; 1326 eccGenerator.generateKeyPair(function (err, keyPair) { 1327 globalSelfPriKey = keyPair.priKey; 1328 eccKeyAgreement.generateSecret(globalSelfPriKey, globalPeerPubKey, function (err, secret) { 1329 if (err) { 1330 console.error("ecdh error."); 1331 return; 1332 } 1333 console.info("ecdh callback output is " + secret.data); 1334 }); 1335 }); 1336 }) 1337} 1338``` 1339 1340## Generating a MAC 1341 1342**When to Use** 1343 1344A message authentication code (MAC) can be used to verify both the integrity and authenticity of a message using a shared secret. 1345 1346Typical MAC operations involve the following: 1347 13481. Create a **Mac** instance. 13492. Initialize the **Mac** instance, add one or more segments of data for generating a MAC, and generate a MAC. 13503. Obtain the algorithm and length of a MAC. 1351 1352**Available APIs** 1353 1354For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md). 1355 1356| Instance | API | Description | 1357| --------------- | ------------------------------------------------------------ | --------------------------------------------------- | 1358| cryptoFramework | function createMac(algName : string) : Mac; | Creates a **Mac** instance. | 1359| Mac | init(key : SymKey, callback : AsyncCallback\<void>) : void; | Initializes the MAC operation. This API uses an asynchronous callback to return the result.| 1360| Mac | init(key : SymKey) : Promise\<void>; | Initializes the MAC operation. This API uses a promise to return the result. | 1361| 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. | 1362| Mac | update(input : DataBlob) : Promise\<void>; | Updates the data for the MAC operation. This API uses a promise to return the result. | 1363| Mac | doFinal(callback : AsyncCallback\<DataBlob>) : void; | Finalizes the MAC operation to generate a MAC. This API uses an asynchronous callback to return the result. | 1364| Mac | doFinal() : Promise\<DataBlob>; | Finalizes the MAC operation to generate a MAC. This API uses a promise to return the result. | 1365| Mac | getMacLength() : number; | Obtains the length of the MAC based on the specified algorithm. | 1366| Mac | readonly algName : string; | Obtains the digest algorithm. | 1367 1368**How to Develop** 1369 13701. Call **createMac()** to create a **Mac** instance. 13712. Call **init()** to initialize the **Mac** instance with the symmetric key passed in. 13723. Call **update()** one or more times to add the data for computing a MAC. 13734. Call **doFinal()** to generate a MAC. 13745. Obtain the algorithm and length of the MAC. 1375 1376```javascript 1377import cryptoFramework from "@ohos.security.cryptoFramework" 1378 1379// Convert string into uint8Arr. 1380function stringToUint8Array(str) { 1381 var arr = []; 1382 for (var i = 0, j = str.length; i < j; ++i) { 1383 arr.push(str.charCodeAt(i)); 1384 } 1385 var tmpUint8Array = new Uint8Array(arr); 1386 return tmpUint8Array; 1387} 1388 1389// Generate a blob. 1390function GenDataBlob(dataBlobLen) { 1391 var dataBlob; 1392 if (dataBlobLen == 12) { 1393 dataBlob = {data: stringToUint8Array("my test data")}; 1394 } else { 1395 console.error("GenDataBlob: dataBlobLen is invalid"); 1396 dataBlob = {data: stringToUint8Array("my test data")}; 1397 } 1398 return dataBlob; 1399} 1400 1401function doHmacByPromise(algName) { 1402 var mac; 1403 try { 1404 mac = cryptoFramework.createMac(algName); 1405 } catch (error) { 1406 console.error("[Promise]: error code: " + error.code + ", message is: " + error.message); 1407 } 1408 console.error("[Promise]: Mac algName is: " + mac.algName); 1409 var KeyBlob = { 1410 data : stringToUint8Array("12345678abcdefgh") 1411 } 1412 var symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128"); 1413 var promiseConvertKey = symKeyGenerator.convertKey(KeyBlob); 1414 promiseConvertKey.then(symKey => { 1415 var promiseMacInit = mac.init(symKey); 1416 return promiseMacInit; 1417 }).then(() => { 1418 // Initial update(). 1419 var promiseMacUpdate = mac.update(GenDataBlob(12)); 1420 return promiseMacUpdate; 1421 }).then(() => { 1422 // Call update() multiple times based on service requirements. 1423 var promiseMacUpdate = mac.update(GenDataBlob(12)); 1424 return promiseMacUpdate; 1425 }).then(() => { 1426 var PromiseMacDoFinal = mac.doFinal(); 1427 return PromiseMacDoFinal; 1428 }).then(macOutput => { 1429 console.error("[Promise]: HMAC result: " + macOutput.data); 1430 var macLen = mac.getMacLength(); 1431 console.error("[Promise]: MAC len: " + macLen); 1432 }).catch(error => { 1433 console.error("[Promise]: error: " + error.message); 1434 }); 1435} 1436 1437// Generate a MAC using callback-based APIs. 1438function doHmacByCallback(algName) { 1439 var mac; 1440 try { 1441 mac = cryptoFramework.createMac(algName); 1442 } catch (error) { 1443 AlertDialog.show({message: "[Callback]: error code: " + error.code + ", message is: " + error.message}); 1444 console.error("[Callback]: error code: " + error.code + ", message is: " + error.message); 1445 } 1446 var KeyBlob = { 1447 data : stringToUint8Array("12345678abcdefgh") 1448 } 1449 var symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128"); 1450 symKeyGenerator.convertKey(KeyBlob, (err, symKey) => { 1451 if (err) { 1452 console.error("[Callback]: err: " + err.code); 1453 } 1454 mac.init(symKey, (err1, ) => { 1455 if (err1) { 1456 console.error("[Callback]: err: " + err1.code); 1457 } 1458 // Initial update(). 1459 mac.update(GenDataBlob(12), (err2, ) => { 1460 if (err2) { 1461 console.error("[Callback]: err: " + err2.code); 1462 } 1463 // Call update() multiple times based on service requirements. 1464 mac.update(GenDataBlob(12), (err3, ) => { 1465 if (err3) { 1466 console.error("[Callback]: err: " + err3.code); 1467 } 1468 mac.doFinal((err4, macOutput) => { 1469 if (err4) { 1470 console.error("[Callback]: err: " + err4.code); 1471 } else { 1472 console.error("[Callback]: HMAC result: " + macOutput.data); 1473 var macLen = mac.getMacLength(); 1474 console.error("[Callback]: MAC len: " + macLen); 1475 } 1476 }); 1477 }); 1478 }); 1479 }); 1480 }); 1481} 1482``` 1483The following example demonstrates how to call **update()** multiple times to update the MAC. 1484```javascript 1485import cryptoFramework from "@ohos.security.cryptoFramework" 1486 1487async function updateData(index, obj, data) { 1488 console.error("update " + (index + 1) + " MB data..."); 1489 return obj.update(data); 1490} 1491 1492function stringToUint8Array(str) { 1493 var arr = []; 1494 for (var i = 0, j = str.length; i < j; ++i) { 1495 arr.push(str.charCodeAt(i)); 1496 } 1497 var tmpUint8Array = new Uint8Array(arr); 1498 return tmpUint8Array; 1499} 1500 1501function GenDataBlob(dataBlobLen) { 1502 var dataBlob; 1503 if (dataBlobLen == 12) { 1504 dataBlob = {data: stringToUint8Array("my test data")}; 1505 } else { 1506 console.error("GenDataBlob: dataBlobLen is invalid"); 1507 dataBlob = {data: stringToUint8Array("my test data")}; 1508 } 1509 return dataBlob; 1510} 1511 1512function LoopHmacPromise(algName, loopSize) { 1513 var mac; 1514 try { 1515 mac = cryptoFramework.createMac(algName); 1516 } catch (error) { 1517 console.error("[Promise]: error code: " + error.code + ", message is: " + error.message); 1518 return; 1519 } 1520 console.error("[Promise]: Mac algName is: " + mac.algName); 1521 var KeyBlob = { 1522 data : stringToUint8Array("12345678abcdefgh") 1523 } 1524 var symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128"); 1525 var promiseConvertKey = symKeyGenerator.convertKey(KeyBlob); 1526 promiseConvertKey.then(symKey => { 1527 var promiseMacInit = mac.init(symKey); 1528 return promiseMacInit; 1529 }).then(async () => { 1530 for (var i = 0; i < loopSize; i++) { 1531 await updateData(i, mac, GenDataBlob(12)); 1532 } 1533 var promiseMacUpdate = mac.update(GenDataBlob(12)); 1534 return promiseMacUpdate; 1535 }).then(() => { 1536 var PromiseMacDoFinal = mac.doFinal(); 1537 return PromiseMacDoFinal; 1538 }).then(macOutput => { 1539 console.error("[Promise]: HMAC result: " + macOutput.data); 1540 var macLen = mac.getMacLength(); 1541 console.error("[Promise]: MAC len: " + macLen); 1542 }).catch(error => { 1543 console.error("[Promise]: error: " + error.message); 1544 }); 1545} 1546``` 1547 1548 1549## Generating a Random Number 1550 1551**When to Use** 1552 1553Typical random number operations involve the following: 1554 1555- Generate a random number. 1556- Set a seed based on the random number generated. 1557 1558**Available APIs** 1559 1560For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md). 1561 1562| Instance | API | Description | 1563| --------------- | ------------------------------------------------------------ | ---------------------------------------------- | 1564| cryptoFramework | function createRandom() : Random; | Creates a **Random** instance. | 1565| Random | generateRandom(len : number, callback: AsyncCallback\<DataBlob>) : void; | Generates a random number. This API uses an asynchronous callback to return the result. | 1566| Random | generateRandom(len : number) : Promise\<DataBlob>; | Generates a random number. This API uses a promise to return the result. | 1567| Random | setSeed(seed : DataBlob) : void; | Sets a seed. | 1568 1569**How to Develop** 1570 15711. Call **createRandom()** to create a **Random** instance. 15722. Call **generateRandom()** to generate a random number of the given length. 15733. Call **setSeed()** to set a seed. 1574 1575```javascript 1576import cryptoFramework from "@ohos.security.cryptoFramework" 1577 1578// Generate a random number and set a seed using promise-based APIs. 1579function doRandByPromise(len) { 1580 var rand; 1581 try { 1582 rand = cryptoFramework.createRandom(); 1583 } catch (error) { 1584 console.error("[Promise]: error code: " + error.code + ", message is: " + error.message); 1585 } 1586 var promiseGenerateRand = rand.generateRandom(len); 1587 promiseGenerateRand.then(randData => { 1588 console.error("[Promise]: rand result: " + randData.data); 1589 try { 1590 rand.setSeed(randData); 1591 } catch (error) { 1592 console.log("setSeed failed, errCode: " + error.code + ", errMsg: " + error.message); 1593 } 1594 }).catch(error => { 1595 console.error("[Promise]: error: " + error.message); 1596 }); 1597} 1598 1599// Generate a random number and set a seed using callback-based APIs. 1600function doRandByCallback(len) { 1601 var rand; 1602 try { 1603 rand = cryptoFramework.createRandom(); 1604 } catch (error) { 1605 console.error("[Callback]: error code: " + error.code + ", message is: " + error.message); 1606 } 1607 rand.generateRandom(len, (err, randData) => { 1608 if (err) { 1609 console.error("[Callback]: err: " + err.code); 1610 } else { 1611 console.error("[Callback]: generate random result: " + randData.data); 1612 try { 1613 rand.setSeed(randData); 1614 } catch (error) { 1615 console.log("setSeed failed, errCode: " + error.code + ", errMsg: " + error.message); 1616 } 1617 } 1618 }); 1619} 1620``` 1621