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