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