1# Crypto Framework Development 2 3> **NOTE** 4> 5> This guide applies only to JavaScript development using the SDK of API version 9 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. Create a key object based on the specified key parameters for subsequent encryption and decryption. 153. Convert external or internal binary data into a key object for subsequent encryption and decryption. 164. Obtain the binary data of a key object for storage or transmission. 175. Obtain the parameter properties of an asymmetric key object for storage or transmission. 18 19> **NOTE** 20> 21> The key object can be a symmetric key object (**SymKey**) or an asymmetric key pair object (**KeyPair**). The **KeyPair** object consists a public key (**PubKey**) and a private key (**PriKey**). For details about the relationship between the keys, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md). 22 23### Available APIs 24 25The following table describes the APIs used in typical key generation operations. For more information about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md). 26 27 28|Instance|API|Description| 29|---|---|---| 30|cryptoFramework|createAsyKeyGenerator(algName : string) : AsyKeyGenerator|Creates an **AsyKeyGenerator** instance based on the asymmetric key pair specifications specified by **algName**.| 31|cryptoFramework|createAsyKeyGeneratorBySpec(asyKeySpec: AsyKeySpec): AsyKeyGeneratorBySpec;|Creates an **AsyKeyGenerator** instance based on the asymmetric key specifications specified by the key parameter.| 32|cryptoFramework|createSymKeyGenerator(algName : string) : SymKeyGenerator|Creates a **SymKeyGenerator** instance.| 33|AsyKeyGenerator|generateKeyPair(callback : AsyncCallback\<KeyPair>) : void|Generates an asymmetric key pair randomly. This API uses an asynchronous callback to return the result.| 34|AsyKeyGenerator|generateKeyPair() : Promise\<KeyPair>|Generates an asymmetric key pair randomly. This API uses a promise to return the result.| 35|SymKeyGenerator|generateSymKey(callback : AsyncCallback\<SymKey>) : void|Generates a symmetric key randomly. This API uses an asynchronous callback to return the result.| 36|SymKeyGenerator|generateSymKey() : Promise\<SymKey>|Generates a symmetric key randomly. This API uses a promise to return the result.| 37| 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.)| 38| 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.)| 39| 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.| 40| SymKeyGenerator |convertKey(pubKey : DataBlob, priKey : DataBlob) : Promise\<KeyPair>| Converts binary data into a symmetric key. This API uses a promise to return the result.| 41| Key | getEncoded() : DataBlob; | Obtains the binary data of a key. (The child class instances of **Key** include **SymKey**, **PubKey**, and **PriKey**.)| 42 43### Randomly Generating an RSA Key Pair and Obtaining the Binary Data 44 45Randomly generate an asymmetric key pair and obtain its binary data. 46 471. Create an **AsyKeyGenerator** instance. 482. Randomly generate an asymmetric key pair using **AsyKeyGenerator**. 493. Obtain the binary data of the key pair generated. 50 51Example: Randomly generate an RSA key (1024 bits and two primes) in promise mode. 52 53```ts 54import cryptoFramework from '@ohos.security.cryptoFramework'; 55import { BusinessError } from '@ohos.base'; 56 57function generateAsyKey() { 58 // Create an AsyKeyGenerator instance. 59 let rsaGenerator = cryptoFramework.createAsyKeyGenerator('RSA1024|PRIMES_2'); 60 // Use the key generator to randomly generate an asymmetric key pair. 61 let keyGenPromise = rsaGenerator.generateKeyPair(); 62 keyGenPromise.then(keyPair => { 63 let pubKey = keyPair.pubKey; 64 let priKey = keyPair.priKey; 65 // Obtain the binary data of the asymmetric key pair. 66 let pkBlob = pubKey.getEncoded(); 67 let skBlob = priKey.getEncoded(); 68 AlertDialog.show({ message: 'pk bin data' + pkBlob.data }); 69 AlertDialog.show({ message: 'sk bin data' + skBlob.data }); 70 }) 71} 72``` 73 74### Randomly Generating an AES Key and Obtaining the Binary Data 75 76Randomly generate a symmetric key and obtain its binary data. 77 781. Create a **SymKeyGenerator** instance. 792. Randomly generate a symmetric key using **SymKeyGenerator**. 803. Obtain the binary data of the key generated. 81 82Example: Randomly generate an AES key (256 bits) in promise mode. 83 84```ts 85import cryptoFramework from '@ohos.security.cryptoFramework'; 86import { BusinessError } from '@ohos.base'; 87 88function testGenerateAesKey() { 89 // Create a SymKeyGenerator instance. 90 let symKeyGenerator = cryptoFramework.createSymKeyGenerator('AES256'); 91 // Use the key generator to randomly generate a symmetric key. 92 let promiseSymKey = symKeyGenerator.generateSymKey(); 93 promiseSymKey.then(key => { 94 // Obtain the binary data of the symmetric key and output the 256-bit key. The length is 32 bytes. 95 let encodedKey = key.getEncoded(); 96 console.info('key hex:' + encodedKey.data); 97 }) 98} 99``` 100 101### Converting Binary Data into an RSA Key Pair 102 103Generate an RSA asymmetric key pair from the binary data. 104 1051. 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. 1062. 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. 107 108```ts 109import cryptoFramework from '@ohos.security.cryptoFramework'; 110import { BusinessError } from '@ohos.base'; 111 112function convertAsyKey() { 113 let rsaGenerator = cryptoFramework.createAsyKeyGenerator('RSA1024'); 114 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]); 115 let pkBlob: cryptoFramework.DataBlob = { data: pkVal }; 116 rsaGenerator.convertKey(pkBlob, null, (err, keyPair) => { 117 if (err) { 118 AlertDialog.show({ message: 'Convert keyPair fail' }); 119 return; 120 } 121 AlertDialog.show({ message: 'Convert keyPair success' }); 122 }) 123} 124``` 125 126> **NOTE** 127> 128> 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. 129 130### Converting Binary Data into an ECC Key Pair 131 132Generate an ECC asymmetric key pair from the binary data. 133 1341. Obtain the ECC binary key data and encapsulate it into a **DataBlob** instance. 1352. Use **convertKey()** to convert the binary data (data of the private or public key, or both) into a **KeyPair** instance. 136 137```ts 138import cryptoFramework from '@ohos.security.cryptoFramework'; 139import { BusinessError } from '@ohos.base'; 140 141function convertEccAsyKey() { 142 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]); 143 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]); 144 let pubKeyBlob: cryptoFramework.DataBlob = { data: pubKeyArray }; 145 let priKeyBlob: cryptoFramework.DataBlob = { data: priKeyArray }; 146 let generator = cryptoFramework.createAsyKeyGenerator('ECC256'); 147 generator.convertKey(pubKeyBlob, priKeyBlob, (error, data) => { 148 if (error) { 149 AlertDialog.show({ message: 'Convert keyPair fail' }); 150 return; 151 } 152 AlertDialog.show({ message: 'Convert keyPair success' }); 153 }) 154} 155``` 156 157### Converting Binary Data into a 3DES Key 158 159Generate a symmetric key from the binary key data. 160 1611. Create a **SymKeyGenerator** instance. 1622. Convert the binary data into a **SymKey** instance. 1633. Obtain the binary data of the key instance generated. 164 165Example: Generate a 3DES key (192 bits only) in callback mode. 166 167```ts 168import cryptoFramework from '@ohos.security.cryptoFramework'; 169import { BusinessError } from '@ohos.base'; 170 171function genKeyMaterialBlob(): cryptoFramework.DataBlob { 172 let arr = [ 173 0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56, 174 0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c, 175 0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72]; // keyLen = 192 (24 bytes) 176 let keyMaterial = new Uint8Array(arr); 177 return { data: keyMaterial }; 178} 179 180function testConvertSymKey() { 181 // Create a SymKeyGenerator instance. 182 let symKeyGenerator = cryptoFramework.createSymKeyGenerator('3DES192'); 183 // Generate a symmetric key based on the specified data. 184 let keyMaterialBlob = genKeyMaterialBlob(); 185 try { 186 symKeyGenerator.convertKey(keyMaterialBlob, (error, key) => { 187 if (error) { // If the service logic fails to be executed, the first parameter of callback returns error information, that is, an exception is thrown asynchronously. 188 let e: BusinessError = error as BusinessError; 189 console.error(`convertKey error, ${e.code}, ${e.message}`); 190 return; 191 } 192 console.info(`key algName: ${key.algName}`); 193 console.info(`key format: ${key.format}`); 194 let encodedKey = key.getEncoded(); // Obtain the binary data of the symmetric key and output in bytes array. The length is 24 bytes. 195 console.info('key getEncoded hex: ' + encodedKey.data); 196 }) 197 } catch (error) { // Throw an exception immediately when an error is detected in parameter check. 198 let e: BusinessError = error as BusinessError; 199 console.error(`convertKey failed, ${e.code}, ${e.message}`); 200 return; 201 } 202} 203``` 204 205### Randomly Generating an SM2 Key Pair and Obtaining the Binary Data 206 207> **NOTE** 208> 209> SM2 asymmetric keys can be randomly generated from API version 10. 210 211Randomly generate an asymmetric key pair and obtain its binary data. 212 2131. Create an **AsyKeyGenerator** instance. 2142. Randomly generate an asymmetric key pair using **AsyKeyGenerator**. 2153. Obtain the binary data of the key pair generated. 216 217Example: Randomly generate an SM2 key (256 bits) in promise mode. 218 219```ts 220import cryptoFramework from '@ohos.security.cryptoFramework'; 221import { BusinessError } from '@ohos.base'; 222 223function generateSM2Key() { 224 // Create an AsyKeyGenerator instance. 225 let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256"); 226 // Use the key generator to randomly generate an asymmetric key pair. 227 let keyGenPromise = sm2Generator.generateKeyPair(); 228 keyGenPromise.then(keyPair => { 229 let pubKey = keyPair.pubKey; 230 let priKey = keyPair.priKey; 231 // Obtain the binary data of the asymmetric key pair. 232 let pkBlob = pubKey.getEncoded(); 233 let skBlob = priKey.getEncoded(); 234 AlertDialog.show({ message: "pk bin data" + pkBlob.data }); 235 AlertDialog.show({ message: "sk bin data" + skBlob.data }); 236 }) 237} 238``` 239 240### Randomly Generating an SM4 Key and Obtaining the Binary Data 241 242 > **NOTE** 243 > 244 > SM4 keys can be randomly generated from API version 10. 245 246Randomly generate a symmetric key and obtain its binary data. 247 2481. Create a **SymKeyGenerator** instance. 2492. Randomly generate a symmetric key using **SymKeyGenerator**. 2503. Obtain the binary data of the key generated. 251 252Example: Randomly generate an SM4 key (128 bits) in promise mode. 253 254```ts 255import cryptoFramework from '@ohos.security.cryptoFramework'; 256import { BusinessError } from '@ohos.base'; 257 258function testGenerateSM4Key() { 259 // Create a SymKeyGenerator instance. 260 let symKeyGenerator = cryptoFramework.createSymKeyGenerator("SM4_128"); 261 // Use the key generator to randomly generate a symmetric key. 262 let promiseSymKey = symKeyGenerator.generateSymKey(); 263 promiseSymKey.then(key => { 264 // Obtain the binary data of the symmetric key and output a 128-bit byte stream. The length is 16 bytes. 265 let encodedKey = key.getEncoded(); 266 console.info('key hex:' + encodedKey.data); 267 }) 268} 269``` 270 271### Converting Binary Data into an SM2 Key Pair 272 273 > **NOTE** 274 > 275 > SM2 key conversion is supported from API version 10. 276 277Generate an SM2 asymmetric key pair from the given binary key data. 278 2791. Obtain the SM2 binary key data and encapsulate it into a **DataBlob** instance. 2802. Call **convertKey()** to convert the binary data (data of the private or public key, or both) into a **KeyPair** instance. 281 282```ts 283import cryptoFramework from '@ohos.security.cryptoFramework'; 284import { BusinessError } from '@ohos.base'; 285 286function convertSM2AsyKey() { 287 let pubKeyArray = new Uint8Array([48, 89, 48, 19, 6, 7, 42, 134, 72, 206, 61, 2, 1, 6, 8, 42, 129, 28, 207, 85, 1, 130, 45, 3, 66, 0, 4, 90, 3, 58, 157, 190, 248, 76, 7, 132, 200, 151, 208, 112, 230, 96, 140, 90, 238, 211, 155, 128, 109, 248, 40, 83, 214, 78, 42, 104, 106, 55, 148, 249, 35, 61, 32, 221, 135, 143, 100, 45, 97, 194, 176, 52, 73, 136, 174, 40, 70, 70, 34, 103, 103, 161, 99, 27, 187, 13, 187, 109, 244, 13, 7]); 288 let priKeyArray = new Uint8Array([48, 49, 2, 1, 1, 4, 32, 54, 41, 239, 240, 63, 188, 134, 113, 31, 102, 149, 203, 245, 89, 15, 15, 47, 202, 170, 60, 38, 154, 28, 169, 189, 100, 251, 76, 112, 223, 156, 159, 160, 10, 6, 8, 42, 129, 28, 207, 85, 1, 130, 45]); 289 let pubKeyBlob: cryptoFramework.DataBlob = { data: pubKeyArray }; 290 let priKeyBlob: cryptoFramework.DataBlob = { data: priKeyArray }; 291 let generator = cryptoFramework.createAsyKeyGenerator("SM2_256"); 292 generator.convertKey(pubKeyBlob, priKeyBlob, (error, data) => { 293 if (error) { 294 AlertDialog.show({ message: "Convert keypair fail" }); 295 return; 296 } 297 AlertDialog.show({ message: "Convert KeyPair success" }); 298 }) 299} 300``` 301 302## Generating an Asymmetric Key Object and Obtaining Key Parameters 303 304### When to Use 305 306Typical key generation operations involve the following: 3071. Create a key object based on the specified asymmetric key parameters for subsequent encryption and decryption. 3082. Obtain the parameter properties of an asymmetric key object for storage or transmission. 309 310> **NOTE** 311> 312> - Key parameters can be used to generate asymmetric keys from API version 10. 313> - Asymmetric systems use a public key (**PubKey**) to encrypt data and a related private key (**PriKey**) to decrypt it. The public key and private key form a key pair (**KeyPair**). For details about asymmetric key parameters, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md). 314 315### Available APIs 316 317The following table describes the APIs used in typical key generation operations. For more information about the APIs, see [AsyKeyGeneratorBySpec](../reference/apis/js-apis-cryptoFramework.md#asykeygeneratorbyspec10). 318 319|Instance|API|Description| 320|---|---|---| 321|AsyKeyGeneratorBySpec|generateKeyPair(callback: AsyncCallback\<KeyPair>): void;|Generates a **KeyPair** instance based on the key parameters. This API uses an asynchronous callback to return the result.| 322|AsyKeyGeneratorBySpec|generateKeyPair(): Promise\<KeyPair>;|Generates a **KeyPair** instance based on the key parameters. This API uses a promise to return the result.| 323|AsyKeyGeneratorBySpec|generatePriKey(callback: AsyncCallback\<KeyPair>): void;|Generates a **PriKey** instance based on the key parameters. This API uses an asynchronous callback to return the result.| 324|AsyKeyGeneratorBySpec|generatePriKey(): Promise\<KeyPair>;|Generates a **PriKey** instance based on the key parameters. This API uses a promise to return the result.| 325|AsyKeyGeneratorBySpec|generatePubKey(callback: AsyncCallback\<KeyPair>): void;|Generates a **PubKey** instance based on the key parameters. This API uses an asynchronous callback to return the result.| 326|AsyKeyGeneratorBySpec|generatePubKey(): Promise\<KeyPair>;|Generates a **PubKey** instance based on the key parameters. This API uses a promise to return the result.| 327| PriKey | getAsyKeySpec(itemType: AsyKeySpecItem): bigint \| string \| number; | Obtains the key specifications of a **PriKey** instance.| 328| PubKey | getAsyKeySpec(itemType: AsyKeySpecItem): bigint \| string \| number; | Obtains the key specifications of a **PubKey** instance.| 329 330### Generating an ECC Key Pair and Obtaining Key Specifications 331 332Generate an ECC key pair based on parameters and obtain the key specifications. 333 3341. Create an **AsyKeyGenerator** based on key parameters. 3352. Use the **AsyKeyGenerator** to generate an asymmetric key pair based on the specified key parameters. 3363. Obtain the key specifications of a key object. 337 338Example: Generate an ECC key based on key parameters in promise mode. 339 340```ts 341import cryptoFramework from '@ohos.security.cryptoFramework'; 342import { BusinessError } from '@ohos.base'; 343 344// Print bigint information. 345function showBigIntInfo(bnName: string, bnValue: bigint | string | number) { 346 if (typeof bnValue === 'string') { 347 console.error('type is string'); 348 return; 349 } 350 if (typeof bnValue === 'number') { 351 console.error('type is number'); 352 return; 353 } 354 console.info(bnName + ":"); 355 console.info(". Decimal: " + bnValue.toString()); 356 console.info(". Hexadecimal: " + bnValue.toString(16)); 357 console.info(". Length (bits): " + bnValue.toString(2).length); 358} 359 360// Construct the EccCommonSpec struct based on the key specifications. The EccCommonSpec struct defines the common parameters of the ECC private key and public key. 361function genEccCommonSpec(): cryptoFramework.ECCCommonParamsSpec { 362 let fieldFp: cryptoFramework.ECFieldFp = { 363 fieldType: "Fp", 364 p: BigInt("0xffffffffffffffffffffffffffffffff000000000000000000000001") 365 } 366 367 let G: cryptoFramework.Point = { 368 x: BigInt("0xb70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21"), 369 y: BigInt("0xbd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34") 370 } 371 372 let eccCommonSpec: cryptoFramework.ECCCommonParamsSpec = { 373 algName: "ECC", 374 specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC, 375 field: fieldFp, 376 a: BigInt("0xfffffffffffffffffffffffffffffffefffffffffffffffffffffffe"), 377 b: BigInt("0xb4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4"), 378 g: G, 379 n: BigInt("0xffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d"), 380 h: 1 381 } 382 return eccCommonSpec; 383} 384 385// Print the ECC key specifications. 386function showEccSpecDetailInfo(key: cryptoFramework.PubKey | cryptoFramework.PriKey, keyType: string) { 387 console.info("show detail of " + keyType + ":"); 388 try { 389 let p = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FP_P_BN); 390 showBigIntInfo("--- p", p); // length is 224, hex : ffffffffffffffffffffffffffffffff000000000000000000000001 391 392 let a = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_A_BN); 393 showBigIntInfo("--- a", a); // length is 224, hex : fffffffffffffffffffffffffffffffefffffffffffffffffffffffe 394 395 let b = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_B_BN); 396 showBigIntInfo("--- b", b); // length is 224, hex : b4050a850c04b3abf54132565044b0b7d7bfd8ba270b39432355ffb4 397 398 let gX = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_G_X_BN); 399 showBigIntInfo("--- gX", gX); // length is 224, hex : b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21 400 401 let gY = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_G_Y_BN); 402 showBigIntInfo("--- gY", gY); // length is 224, hex : bd376388b5f723fb4c22dfe6cd4375a05a07476444d5819985007e34 403 404 let n = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_N_BN); 405 showBigIntInfo("--- n", n); // length is 224, hex : ffffffffffffffffffffffffffff16a2e0b8f03e13dd29455c5c2a3d 406 407 let h = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_H_NUM); 408 console.warn("--- h: " + h); // key h: 1 409 410 let fieldType = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FIELD_TYPE_STR); 411 console.warn("--- field type: " + fieldType); // key field type: Fp 412 413 let fieldSize = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_FIELD_SIZE_NUM); 414 console.warn("--- field size: " + fieldSize); // key field size: 224 415 416 let curveName = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_CURVE_NAME_STR); 417 console.warn("--- curve name: " + curveName); // key curve name: NID_secp224r1 418 419 if (keyType == "priKey") { 420 let sk = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_SK_BN); 421 showBigIntInfo("--- sk", sk); 422 } else if (keyType == "pubKey") { 423 let pkX = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_PK_X_BN); 424 showBigIntInfo("--- pkX", pkX); 425 let pkY = key.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.ECC_PK_Y_BN); 426 showBigIntInfo("--- pkY", pkY); 427 } 428 } catch (error) { 429 console.error("getAsyKeySpec error"); 430 let e: BusinessError = error as BusinessError; 431 console.error(`getAsyKeySpec failed, ${e.code}, ${e.message}`); 432 } 433} 434 435// Generate an ECC key pair based on the EccCommonSpec instance and obtain the key specifications. 436function testEccUseCommKeySpecGet() { 437 try { 438 let commKeySpec = genEccCommonSpec(); // Construct the EccCommonSpec object. 439 let generatorBySpec = cryptoFramework.createAsyKeyGeneratorBySpec(commKeySpec); // Create an AsyKeyGenerator instance based on the EccCommonSpec object. 440 let keyPairPromise = generatorBySpec.generateKeyPair(); // Generate an ECC key pair. 441 keyPairPromise.then(keyPair => { 442 showEccSpecDetailInfo(keyPair.priKey, "priKey"); // Obtain the ECC specifications of the private key. 443 showEccSpecDetailInfo(keyPair.pubKey, "pubKey"); // Obtain the ECC specifications of the public key. 444 }).catch((error: BusinessError) => { 445 // Capture exceptions such as logic errors asynchronously here. 446 console.error("generateComm error"); 447 console.error("error code: " + error.code + ", message is: " + error.message); 448 }) 449 } catch (error) { 450 // Capture parameter errors synchronously here. 451 console.error("testEccUseCommSpec error"); 452 let e: BusinessError = error as BusinessError; 453 console.error(`ecc comm spec failed, ${e.code}, ${e.message}`); 454 } 455} 456``` 457 458### Generating an RSA Public Key and Obtaining Key Specifications 459 460Generate an RSA public key based on parameters and obtain key specifications. 461 4621. Create an **AsyKeyGenerator** based on key parameters. 4632. Use the **AsyKeyGenerator** to generate the public key of an asymmetric key pair. 4643. Obtain the key specifications of the public key object. 465 466Example: Generate an RSA public key based on key parameters in callback mode. 467```ts 468import cryptoFramework from '@ohos.security.cryptoFramework'; 469import { BusinessError } from '@ohos.base'; 470// Generate RSA public key specifications. 471function genRsaPubKeySpec(nIn: bigint, eIn: bigint): cryptoFramework.RSAPubKeySpec { 472 let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = { 473 n: nIn, 474 algName: "RSA", 475 specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC 476 }; 477 let rsaPubKeySpec: cryptoFramework.RSAPubKeySpec = { 478 params: rsaCommSpec, 479 pk: eIn, 480 algName: "RSA", 481 specType: cryptoFramework.AsyKeySpecType.PUBLIC_KEY_SPEC 482 }; 483 return rsaPubKeySpec; 484} 485 486// Construct an RSA public key specifications object based on the key parameters. 487function genRsa2048PubKeySpec() { 488 let nIn = BigInt("0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25"); 489 let eIn = BigInt("0x010001"); 490 return genRsaPubKeySpec(nIn, eIn); 491} 492 493// Compare the RSA public key specifications with the expected values. 494function compareRsaPubKeyBySpec(rsaKeySpec: cryptoFramework.RSAPubKeySpec, n: bigint | string | number, e: bigint | string | number) { 495 if (typeof n === 'string' || typeof e === 'string') { 496 console.error('type is string'); 497 return false; 498 } 499 if (typeof n === 'number' || typeof e === 'number') { 500 console.error('type is number'); 501 return false; 502 } 503 if (rsaKeySpec.params.n != n) { 504 return false; 505 } 506 if (rsaKeySpec.pk != e) { 507 return false; 508 } 509 return true; 510} 511 512// Generate an RSA public key based on the RSA public key specifications, obtain the key specifications, and compare the key specifications with the expected values. 513function rsaUsePubKeySpecGetCallback() { 514 let rsaPubKeySpec = genRsa2048PubKeySpec(); 515 let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaPubKeySpec); 516 rsaGeneratorSpec.generatePubKey((error, key) => { 517 let pubKey = key; 518 let nBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_N_BN); 519 let eBN = pubKey.getAsyKeySpec(cryptoFramework.AsyKeySpecItem.RSA_PK_BN); 520 if (compareRsaPubKeyBySpec(rsaPubKeySpec, nBN, eBN) != true) { 521 AlertDialog.show({ message: "error pub key big number" }); 522 } else { 523 console.info("n, e in the pubKey are same as the spec."); 524 } 525 if (error) { 526 console.error("generate pubKey error" + "error code: " + error.code + "error message" + error.message); 527 } 528 }); 529} 530``` 531 532## Encryption and Decryption 533 534### When to Use 535 536Important data needs to be encrypted in data storage or transmission for security purposes. Typical encryption and decryption operations involve the following: 5371. Encrypt and decrypt data using a symmetric key. 5382. Encrypt and decrypt data using an asymmetric key pair. 5393. Obtain and set the **CipherSpecItem** parameter when the PKCS1_OAEP padding mode is used in RSA. 540 541> **NOTE** 542> 543> - From API version 10, [CipherSpecItem](../reference/apis/js-apis-cryptoFramework.md#cipherspecitem10) can be obtained and set when the PKCS1_OAEP padding mode is used in RSA. 544> - From API version 10, the string parameter without the key length is supported in encryption and decryption. 545 546### Available APIs 547 548The following table describes the APIs used in the typical encryption and decryption operations. For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md). 549> **NOTE** 550> 551> Due to complexity of cryptographic algorithms, the implementation varies depending on the key 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. 552 553 554 555|Instance|API|Description| 556|---|---|---| 557|cryptoFramework|createCipher(transformation : string) : Cipher|Creates a **Cipher** instance.| 558|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.| 559|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.| 560|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.| 561|Cipher|update(data : DataBlob) : Promise\<DataBlob>|Updates the data for encryption and decryption. This API uses a promise to return the result.| 562|Cipher|doFinal(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|Finalizes the encryption or decryption. This API uses an asynchronous callback to return the result.| 563|Cipher|doFinal(data : DataBlob) : Promise\<DataBlob>|Finalizes the encryption or decryption. This API uses a promise to return the result.| 564|Cipher|getCipherSpec(itemType: CipherSpecItem): string \| Uint8Array|Obtains cipher specifications. Currently, only the RSA is supported.| 565|Cipher|setCipherSpec(itemType: CipherSpecItem, itemValue: Uint8Array): void|Sets cipher specifications. Currently, only the RSA is supported.| 566 567### Encrypting and Decrypting Data Using AES GCM (Promise) 568 569Encrypt and decrypt data using an AES symmetric key. 570 5711. Create a **SymKeyGenerator** instance. 5722. Use the **SymKeyGenerator** to randomly generate a symmetric key. 5733. Create a **Cipher** instance. 5744. Encrypt or decrypt data. 575 576```ts 577import cryptoFramework from '@ohos.security.cryptoFramework'; 578import { BusinessError } from '@ohos.base'; 579 580function genGcmParamsSpec() { 581 let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 12 bytes 582 let dataIv = new Uint8Array(arr); 583 let ivBlob: cryptoFramework.DataBlob = { data: dataIv }; 584 585 arr = [0, 0, 0, 0, 0, 0, 0, 0]; // 8 bytes 586 let dataAad = new Uint8Array(arr); 587 let aadBlob: cryptoFramework.DataBlob = { data: dataAad }; 588 589 arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 16 bytes 590 let dataTag = new Uint8Array(arr); 591 let tagBlob: cryptoFramework.DataBlob = { 592 data: dataTag 593 }; // The GCM authTag is obtained by doFinal() in encryption and passed in params of init() in decryption. 594 595 let gcmParamsSpec: cryptoFramework.GcmParamsSpec = { 596 iv: ivBlob, 597 aad: aadBlob, 598 authTag: tagBlob, 599 algName: "GcmParamsSpec" 600 }; 601 return gcmParamsSpec; 602} 603 604// Convert strings in plaintext into byte streams. 605function stringToUint8Array(str: string) { 606 let arr = new Uint8Array(str.length); 607 for (let i = 0, j = str.length; i < j; ++i) { 608 arr[i] = str.charCodeAt(i); 609 } 610 return arr; 611} 612 613// Convert byte streams into strings in plaintext. 614function uint8ArrayToString(array: Uint8Array) { 615 let arrayString = ''; 616 for (let i = 0; i < array.length; i++) { 617 arrayString += String.fromCharCode(array[i]); 618 } 619 return arrayString; 620} 621 622// Automatically generate an AES GCM key in promise mode. 623function testAesGcm() { 624 let symAlgName = 'AES128'; 625 let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName); 626 console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`); 627 // Generate GCM parameter specifications. 628 let globalGcmParams = genGcmParamsSpec(); 629 // Create a Cipher instance. 630 let cipherAlgName = 'AES128|GCM|PKCS7'; 631 let globalCipher = cryptoFramework.createCipher(cipherAlgName); 632 console.info(`cipher algName: ${globalCipher.algName}`); 633 // Use the key generator to randomly generate a 128-bit symmetric key. 634 let globalCipherText: cryptoFramework.DataBlob; 635 let globalKey: cryptoFramework.SymKey; 636 let promiseSymKey = symKeyGenerator.generateSymKey(); 637 promiseSymKey.then(key => { 638 // Initialize the Cipher instance and start encryption. 639 globalKey = key; 640 let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE; 641 return globalCipher.init(mode, globalKey, globalGcmParams); 642 }) 643 .then(() => { 644 let plainText: cryptoFramework.DataBlob = { data: stringToUint8Array('this is test!') }; 645 return globalCipher.update(plainText); 646 }) 647 .then((updateOutput: cryptoFramework.DataBlob): Promise<cryptoFramework.DataBlob> => { 648 globalCipherText = updateOutput; 649 return globalCipher.doFinal(null); 650 }) 651 .then(tag => { 652 // In GCM mode, the encrypted authentication information needs to be obtained from the output of doFinal() and passed in globalGcmParams of init() in decryption. 653 globalGcmParams.authTag = tag; 654 return; 655 }) 656 .then(() => { 657 // Initialize the Cipher instance and start decryption. 658 let mode = cryptoFramework.CryptoMode.DECRYPT_MODE; 659 return globalCipher.init(mode, globalKey, globalGcmParams); 660 }) 661 .then(() => { 662 return globalCipher.update(globalCipherText); // update 663 }) 664 .then((updateOutput: cryptoFramework.DataBlob): Promise<cryptoFramework.DataBlob> => { 665 console.info('decrypt plainText: ' + uint8ArrayToString(updateOutput.data)); 666 return globalCipher.doFinal(null); 667 }) 668 .then(finalOutput => { 669 if (finalOutput == null) { // Check whether the result is null before using finalOutput.data. 670 console.info('GCM finalOutput is null'); 671 } 672 }) 673 .catch((error: BusinessError) => { 674 console.error(`catch error, ${error.code}, ${error.message}`); 675 }) 676} 677``` 678 679### Encrypting and Decrypting Data Using a 3DES ECB Symmetric Key (Callback) 680 681Encrypt and decrypt data using a 3DES symmetric key. 682 6831. Create a **SymKeyGenerator** instance. 6842. Generate a key based on the existing binary data. 6853. Create a **Cipher** instance. 6864. Encrypt or decrypt data. 687 688```ts 689import cryptoFramework from '@ohos.security.cryptoFramework'; 690import { BusinessError } from '@ohos.base'; 691 692// Convert strings in plaintext into byte streams. 693function stringToUint8Array(str: string) { 694 let arr = new Uint8Array(str.length); 695 for (let i = 0, j = str.length; i < j; ++i) { 696 arr[i] = str.charCodeAt(i); 697 } 698 return arr; 699} 700 701// Convert byte streams into strings in plaintext. 702function uint8ArrayToString(array: Uint8Array) { 703 let arrayString = ''; 704 for (let i = 0; i < array.length; i++) { 705 arrayString += String.fromCharCode(array[i]); 706 } 707 return arrayString; 708} 709 710function genKeyMaterialBlob(): cryptoFramework.DataBlob { 711 let arr = [ 712 0xba, 0x3d, 0xc2, 0x71, 0x21, 0x1e, 0x30, 0x56, 713 0xad, 0x47, 0xfc, 0x5a, 0x46, 0x39, 0xee, 0x7c, 714 0xba, 0x3b, 0xc2, 0x71, 0xab, 0xa0, 0x30, 0x72]; // keyLen = 192 (24 bytes) 715 let keyMaterial = new Uint8Array(arr); 716 return { data: keyMaterial }; 717} 718 719// Generate a 3DES ECB key from the existing data in callback mode. 720function test3DesEcb() { 721 // Create a SymKeyGenerator instance. 722 let symAlgName = '3DES192'; 723 let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName); 724 if (symKeyGenerator == null) { 725 console.error('createSymKeyGenerator failed'); 726 return; 727 } 728 console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`); 729 730 // Create a Cipher instance. 731 let cipherAlgName = '3DES192|ECB|PKCS7'; 732 let globalCipher = cryptoFramework.createCipher(cipherAlgName); 733 734 // Generate a symmetric key based on the specified data. 735 let keyMaterialBlob = genKeyMaterialBlob(); 736 try { 737 symKeyGenerator.convertKey(keyMaterialBlob, (error, key) => { 738 if (error) { 739 console.error(`convertKey error, ${error.code}, ${error.message}`); 740 return; 741 } 742 console.info(`key algName: ${key.algName}`); 743 console.info(`key format: ${key.format}`); 744 let encodedKey = key.getEncoded(); 745 console.info('key getEncoded: ' + encodedKey.data); 746 let globalKey = key; 747 748 // Initialize the Cipher instance and start encryption. 749 let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE; 750 // init 751 globalCipher.init(mode, key, null, (err,) => { 752 let plainText: cryptoFramework.DataBlob = { data: stringToUint8Array('this is test!') }; 753 // update 754 globalCipher.update(plainText, (err, updateOutput) => { 755 let globalCipherText = updateOutput; 756 //doFinal 757 globalCipher.doFinal(null, (err, finalOutput) => { 758 if (err) { 759 console.error(`doFinal error, ${err.code}, ${err.message}`); 760 return; 761 } 762 if (finalOutput != null) { 763 let tmpCipherText = Array.from(globalCipherText.data); 764 let tmpFinalOutput = Array.from(finalOutput.data); 765 tmpCipherText = tmpCipherText.concat(tmpFinalOutput); 766 globalCipherText = { data: new Uint8Array(tmpCipherText) }; 767 } 768 // Initialize the Cipher instance and start decryption. 769 let mode = cryptoFramework.CryptoMode.DECRYPT_MODE; 770 // init 771 globalCipher.init(mode, globalKey, null, (err,) => { 772 // update 773 globalCipher.update(globalCipherText, (err, updateOutput) => { 774 console.info('decrypt plainText: ' + uint8ArrayToString(updateOutput.data)); 775 // doFinal 776 globalCipher.doFinal(null, (error, finalOutput) => { 777 if (finalOutput != null) { // Check whether the result is null before using finalOutput.data. 778 console.info('decrypt plainText: ' + uint8ArrayToString(finalOutput.data)); 779 } 780 }) 781 }) 782 }) 783 }) 784 }) 785 }) 786 }) 787 } catch (error) { 788 let e: BusinessError = error as BusinessError; 789 console.error(`3des failed, ${e.code}, ${e.message}`); 790 return; 791 } 792} 793``` 794 795### Encrypting and Decrypting Data Using an AES GCM Symmetric Key by Segment (Promise) 796 797Use an AES symmetric key to encrypt and decrypt a large amount of data by segment using **update()**. 798 7991. Create a **SymKeyGenerator** instance. 8002. Generate a key based on the existing binary data. 8013. Create a **Cipher** instance. 8024. Encrypt or decrypt data. 803 804Example: Encrypt and decrypt a large amount in AES GCM mode by calling **update()** multiple times in promise mode. 805 806```ts 807import cryptoFramework from '@ohos.security.cryptoFramework'; 808import { BusinessError } from '@ohos.base'; 809 810function genGcmParamsSpec() { 811 let arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 12 bytes 812 let dataIv = new Uint8Array(arr); 813 let ivBlob: cryptoFramework.DataBlob = { data: dataIv }; 814 815 arr = [0, 0, 0, 0, 0, 0, 0, 0]; // 8 bytes 816 let dataAad = new Uint8Array(arr); 817 let aadBlob: cryptoFramework.DataBlob = { data: dataAad }; 818 819 arr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // 16 bytes 820 let dataTag = new Uint8Array(arr); 821 let tagBlob: cryptoFramework.DataBlob = { 822 data: dataTag 823 }; // The GCM authTag is obtained by doFinal() in encryption and passed in params of init() in decryption. 824 825 let gcmParamsSpec: cryptoFramework.GcmParamsSpec = { 826 iv: ivBlob, 827 aad: aadBlob, 828 authTag: tagBlob, 829 algName: "GcmParamsSpec" 830 }; 831 return gcmParamsSpec; 832} 833 834// Convert strings in plaintext into byte streams. 835function stringToUint8Array(str: string) { 836 let arr = new Uint8Array(str.length); 837 for (let i = 0, j = str.length; i < j; ++i) { 838 arr[i] = str.charCodeAt(i); 839 } 840 return arr; 841} 842 843// Convert byte streams into strings in plaintext. 844function uint8ArrayToString(array: Uint8Array) { 845 let arrayString = ''; 846 for (let i = 0; i < array.length; i++) { 847 arrayString += String.fromCharCode(array[i]); 848 } 849 return arrayString; 850} 851 852function testAesMultiUpdate() { 853 let symAlgName = 'AES128'; 854 let symKeyGenerator = cryptoFramework.createSymKeyGenerator(symAlgName); 855 console.info(`symKeyGenerator algName: ${symKeyGenerator.algName}`); 856 // Generate GCM parameter specifications. 857 let globalGcmParams = genGcmParamsSpec(); 858 // Create a Cipher instance. 859 let cipherAlgName = 'AES128|GCM|PKCS7'; 860 let globalCipher = cryptoFramework.createCipher(cipherAlgName); 861 console.info(`cipher algName: ${globalCipher.algName}`); 862 // Use the key generator to randomly generate a 128-bit symmetric key. 863 let globalCipherText: cryptoFramework.DataBlob; 864 let globalKey: cryptoFramework.SymKey; 865 let globalPlainText = ''; 866 let promiseSymKey = symKeyGenerator.generateSymKey(); 867 promiseSymKey.then(key => { 868 // Initialize the Cipher instance and start encryption. 869 globalKey = key; 870 let mode = cryptoFramework.CryptoMode.ENCRYPT_MODE; 871 return globalCipher.init(mode, globalKey, globalGcmParams); 872 }) 873 .then(async () => { 874 let plainText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // Assume that the plaintext is of 43 bytes. 875 let messageArr: number[] = []; 876 let updateLength = 20; // Pass in 20 bytes by update() each time. 877 let tmpCipherText = new Uint8Array(); 878 879 for (let i = 0; i <= plainText.length; i++) { 880 if ((i % updateLength == 0 || i == plainText.length) && messageArr.length != 0) { 881 let message = new Uint8Array(messageArr); 882 let messageBlob: cryptoFramework.DataBlob = { data: message }; 883 let updateOutput = await globalCipher.update(messageBlob); // Update by segment. 884 // 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 885 // 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. 886 let mergeText = new Uint8Array(tmpCipherText.length + updateOutput.data.length); 887 mergeText.set(tmpCipherText); 888 mergeText.set(updateOutput.data, tmpCipherText.length); 889 tmpCipherText = mergeText; 890 // tmpCipherText = tmpCipherText.concat(Array.from(updateOutput.data)); 891 messageArr = []; 892 } 893 if (i < plainText.length) { 894 messageArr.push(plainText.charCodeAt(i)); 895 } 896 } 897 globalCipherText = { data: tmpCipherText }; 898 return; 899 }) 900 .then((): Promise<cryptoFramework.DataBlob> => { 901 return globalCipher.doFinal(null); 902 }) 903 .then(tag => { 904 // In GCM mode, the encrypted authentication information needs to be obtained from the output of doFinal() and passed in globalGcmParams of init() in decryption. 905 globalGcmParams.authTag = tag; 906 return; 907 }) 908 .then(() => { 909 // Initialize the Cipher instance and start decryption. 910 let mode = cryptoFramework.CryptoMode.DECRYPT_MODE; 911 return globalCipher.init(mode, globalKey, globalGcmParams); 912 }) 913 .then(async () => { 914 let updateLength = 20; 915 let updateTimes = Math.ceil(globalCipherText.data.length / updateLength); // Round up to the nearest integer. 916 for (let i = 0; i < updateTimes; i++) { 917 let messageArr = globalCipherText.data.slice(i * updateLength, (i + 1) * updateLength); 918 let message = new Uint8Array(messageArr); 919 let messageBlob: cryptoFramework.DataBlob = { data: message }; 920 let updateOutput = await globalCipher.update(messageBlob); // Update by segment. 921 globalPlainText += uint8ArrayToString(updateOutput.data); // Restore the original plaintext. 922 } 923 return; 924 }) 925 .then((): Promise<cryptoFramework.DataBlob> => { 926 return globalCipher.doFinal(null); 927 }) 928 .then(finalOutput => { 929 if (finalOutput == null) { // Check whether the result is null before using finalOutput.data. 930 console.info('GCM finalOutput is null'); 931 } 932 console.info(`decrypt output: ${globalPlainText}`); 933 }) 934 .catch((error: BusinessError) => { 935 console.error(`catch error, ${error.code}, ${error.message}`); 936 }) 937} 938``` 939 940### Encrypting and Decrypting Data Using RSA 941 942Encrypt and decrypt data using an RSA asymmetric key pair. 943 9441. Generate an RSA key pair.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an RSA asymmetric key pair. 9452. Create a **Cipher** instance.<br>Call **createCipher()** to create a **Cipher** instance, and set the key and encryption/decryption mode. 9463. Encrypt and decrypt data.<br>Call **doFinal()** provided by the **Cipher** instance to encrypt data or decrypt data. 947 948```ts 949import cryptoFramework from '@ohos.security.cryptoFramework'; 950import { BusinessError } from '@ohos.base'; 951 952let plan = "This is cipher test."; 953 954// Convert strings in plaintext into byte streams. 955function stringToUint8Array(str: string) { 956 let arr = new Uint8Array(str.length); 957 for (let i = 0, j = str.length; i < j; ++i) { 958 arr[i] = str.charCodeAt(i); 959 } 960 return arr; 961} 962 963// Encrypt the message in promise mode. 964function encryptMessagePromise() { 965 // Create an AsyKeyGenerator instance. 966 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 967 // Create a Cipher instance. 968 let cipher = cryptoFramework.createCipher("RSA1024|PKCS1"); 969 // Generate an asymmetric key pair using the AsyKeyGenerator instance. 970 let keyGenPromise = rsaGenerator.generateKeyPair(); 971 keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => { 972 let pubKey = rsaKeyPair.pubKey; 973 // Initialize the Cipher instance and use the public key to encrypt the data. 974 return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null); 975 }).then(() => { 976 // doFinal 977 let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) }; 978 return cipher.doFinal(input); 979 }).then(dataBlob => { 980 // Obtain the encrypted data. 981 console.info("EncryptOutPut is " + dataBlob.data); 982 }); 983} 984 985// Encrypt the message in callback mode. 986function encryptMessageCallback() { 987 // Create an AsyKeyGenerator instance. 988 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 989 // Create a Cipher instance. 990 let cipher = cryptoFramework.createCipher("RSA1024|PKCS1"); 991 // Generate an asymmetric key pair using the AsyKeyGenerator instance. 992 rsaGenerator.generateKeyPair((err, keyPair) => { 993 let pubKey = keyPair.pubKey; 994 // Initialize the Cipher instance and use the public key to encrypt the data. 995 cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null, (err, data) => { 996 let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) }; 997 // doFinal 998 cipher.doFinal(input, (err, data) => { 999 // Obtain the encrypted data. 1000 console.info("EncryptOutPut is " + data.data); 1001 }) 1002 }) 1003 }) 1004} 1005 1006// Encrypt and decrypt the message in promise mode. 1007function decryptMessagePromise() { 1008 // Create an AsyKeyGenerator instance. 1009 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 1010 // Create a Cipher instance for encryption. 1011 let cipher = cryptoFramework.createCipher("RSA1024|PKCS1"); 1012 // Create a Cipher instance for decryption. 1013 let decoder = cryptoFramework.createCipher("RSA1024|PKCS1"); 1014 // Generate an asymmetric key pair using the AsyKeyGenerator instance. 1015 let keyGenPromise = rsaGenerator.generateKeyPair(); 1016 let keyPair: cryptoFramework.KeyPair; 1017 let cipherDataBlob: cryptoFramework.DataBlob; 1018 let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) }; 1019 keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => { 1020 keyPair = rsaKeyPair; 1021 // Initialize the Cipher instance and use the public key to encrypt the message. 1022 return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null); 1023 }) 1024 .then(() => { 1025 // Call doFinal() to encrypt data. 1026 return cipher.doFinal(input); 1027 }) 1028 .then((dataBlob: cryptoFramework.DataBlob): Promise<void> => { 1029 // Obtain the encrypted information and use it as the input parameter for decryption. 1030 console.info("EncryptOutPut is " + dataBlob.data); 1031 AlertDialog.show({ message: "output" + dataBlob.data }); 1032 cipherDataBlob = dataBlob; 1033 // Initialize the Cipher instance and use the private key to decrypt the message. 1034 return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null); 1035 }) 1036 .then(() => { 1037 // Call doFinal() to decrypt the data. 1038 return decoder.doFinal(cipherDataBlob); 1039 }) 1040 .then(decodeData => { 1041 // Check whether the decrypted data is consistent with the original data. 1042 if (decodeData.data.toString() === input.data.toString()) { 1043 AlertDialog.show({ message: "decrypt success" }); 1044 return; 1045 } 1046 AlertDialog.show({ message: "decrypt fail" }); 1047 }); 1048} 1049 1050// Encrypt and decrypt the message in callback mode. 1051function decryptMessageCallback() { 1052 // Create an AsyKeyGenerator instance. 1053 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 1054 // Create a Cipher instance for encryption. 1055 let cipher = cryptoFramework.createCipher("RSA1024|PKCS1"); 1056 // Create a Cipher instance for decryption. 1057 let decoder = cryptoFramework.createCipher("RSA1024|PKCS1"); 1058 let plainText = "this is cipher text"; 1059 let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plainText) }; 1060 // Generate an asymmetric key pair using the AsyKeyGenerator instance. 1061 rsaGenerator.generateKeyPair((err, newKeyPair) => { 1062 let keyPair = newKeyPair; 1063 // Initialize the Cipher instance and use the public key to encrypt the message. 1064 cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null, (err, data) => { 1065 // Call doFinal() to encrypt the message. 1066 cipher.doFinal(input, (err, data) => { 1067 // Obtain the encrypted information and use it as the input parameter for decryption. 1068 AlertDialog.show({ message: "EncryptOutPut is " + data.data }); 1069 let cipherData = data; 1070 // Initialize the Cipher instance and use the private key to decrypt the message. 1071 decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null, (err, data) => { 1072 // Call doFinal() to decrypt the message. 1073 decoder.doFinal(cipherData, (err, data) => { 1074 // Check whether the decrypted data is consistent with the original data. 1075 if (input.data.toString() === data.data.toString()) { 1076 AlertDialog.show({ message: "decryption success" }); 1077 return; 1078 } 1079 AlertDialog.show({ message: "decryption fail" }); 1080 }); 1081 }); 1082 }); 1083 }); 1084 }); 1085} 1086``` 1087 1088### Encrypting and Decrypting Data Using RSA by Segment 1089 1090Use an RSA asymmetric key pair to encrypt and decrypt a large amount of data by segment. 1091 10921. Generate an RSA key pair.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an RSA asymmetric key pair. 10932. Create a **Cipher** instance.<br>Call **createCipher()** to create a **Cipher** instance, and set the key and encryption/decryption mode. 10943. Encrypt and decrypt data.<br>Call **doFinal()** provided by the **Cipher** instance multiple times to encrypt and decrypt data. 1095 1096```ts 1097import cryptoFramework from '@ohos.security.cryptoFramework'; 1098import { BusinessError } from '@ohos.base'; 1099 1100// Convert strings in plaintext into byte streams. 1101function stringToUint8Array(str: string) { 1102 let arr = new Uint8Array(str.length); 1103 for (let i = 0, j = str.length; i < j; ++i) { 1104 arr[i] = str.charCodeAt(i); 1105 } 1106 return arr; 1107} 1108 1109// Convert byte streams into strings in plaintext. 1110function uint8ArrayToString(array: Uint8Array) { 1111 let arrayString = ''; 1112 for (let i = 0; i < array.length; i++) { 1113 arrayString += String.fromCharCode(array[i]); 1114 } 1115 return arrayString; 1116} 1117 1118function encryptLongMessagePromise() { 1119 let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1120 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1121 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1122 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1123 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1124 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1125 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1126 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!"; 1127 let globalKeyPair: cryptoFramework.KeyPair; 1128 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. 1129 let cipherTextSplitLen = 128; // Length of the ciphertext = Number of key bits/8 1130 let keyGenName = "RSA1024"; 1131 let cipherAlgName = "RSA1024|PKCS1"; 1132 let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // Create an AsyKeyGenerator object. 1133 let cipher = cryptoFramework.createCipher(cipherAlgName); // Create a Cipher object. 1134 let decoder = cryptoFramework.createCipher(cipherAlgName); // Create a Decoder object. 1135 let keyGenPromise = asyKeyGenerator.generateKeyPair(); // Generate an RSA key pair. 1136 let globalCipherText: cryptoFramework.DataBlob; 1137 1138 keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => { 1139 globalKeyPair = rsaKeyPair; // Save the key pair as a global variable. 1140 return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, globalKeyPair.pubKey, null); 1141 }) 1142 .then(async () => { 1143 let tmpCipherText = new Uint8Array(); 1144 // 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. 1145 for (let i = 0; i < (globalPlainText.length / plainTextSplitLen); i++) { 1146 let tempStr = globalPlainText.substr(i * plainTextSplitLen, plainTextSplitLen); 1147 let tempBlob: cryptoFramework.DataBlob = { data: stringToUint8Array(tempStr) }; 1148 let tempCipherOutput = await cipher.doFinal(tempBlob); 1149 let mergeText = new Uint8Array(tmpCipherText.length + tempCipherOutput.data.length); 1150 mergeText.set(tmpCipherText); 1151 mergeText.set(tempCipherOutput.data, tmpCipherText.length); 1152 tmpCipherText = mergeText; 1153 } 1154 globalCipherText = { data: tmpCipherText }; 1155 console.info(`globalCipherOutput len is ${tmpCipherText.length}, data is: ${tmpCipherText.toString()}`); 1156 return; 1157 }) 1158 .then((): Promise<void> => { 1159 return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, globalKeyPair.priKey, null); 1160 }) 1161 .then(async () => { 1162 let tmpDecodeText = new Uint8Array(); 1163 // Split and decrypt the ciphertext by 128 bytes, and combine the plaintext obtained each time. 1164 for (let i = 0; i < (globalCipherText.data.length / cipherTextSplitLen); i++) { 1165 let tempBlobData = globalCipherText.data.slice(i * cipherTextSplitLen, (i + 1) * cipherTextSplitLen); 1166 let message = new Uint8Array(tempBlobData); 1167 let tempBlob: cryptoFramework.DataBlob = { data: message }; 1168 let tempDecodeOutput = await decoder.doFinal(tempBlob); 1169 let mergeText = new Uint8Array(tmpDecodeText.length + tempDecodeOutput.data.length); 1170 mergeText.set(tmpDecodeText); 1171 mergeText.set(tempDecodeOutput.data, tmpDecodeText.length); 1172 tmpDecodeText = mergeText; 1173 } 1174 let globalDecodeOutput = uint8ArrayToString(tmpDecodeText); 1175 if (globalDecodeOutput === globalPlainText) { 1176 console.info(`encode and decode success`); 1177 } else { 1178 console.info(`encode and decode error`); 1179 } 1180 return; 1181 }) 1182 .catch((error: BusinessError) => { 1183 console.error(`catch error, ${error.code}, ${error.message}`); 1184 }) 1185} 1186``` 1187 1188> **NOTE** 1189> 1190> - 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. 1191> - The RSA encryption has a limit on the length of the plaintext to be encrypted. For details, see [Encryption and Decryption](cryptoFramework-overview.md#encryption-and-decryption). 1192> - 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. 1193 1194### Using PKCS1_OAEP in RSA Encryption and Decryption 1195 1196Use the PKCS1_OAEP padding mode in RSA encryption and decryption in promise mode. 1197 11981. Generate an RSA key pair based on the key parameters.<br>Call **createAsyKeyGeneratorBySpec()** to create an **AsyKeyGeneratorBySpec** object and generate an RSA asymmetric key pair. (You can also use **createAsyKeyGenerator()** to randomly generate or convert an RSA key object.) 11992. Create a **Cipher** instance.<br>Call **createCipher()** to create a cipher instance, initialize the cipher instance, set the key and encryption/decryption mode, use **setCipherSpec()** to set PKCS1_OAEP **pSource**, and use **update()** to pass in data. 12003. Encrypt and decrypt data.<br>Call the **doFinal()** API provided by the **Cipher** class to perform encryption or decryption. The **pSource** of the **Cipher** instance to be encrypted must be the same as that decrypted. 1201 1202```ts 1203import cryptoFramework from '@ohos.security.cryptoFramework'; 1204import { BusinessError } from '@ohos.base'; 1205 1206// Convert strings in plaintext into byte streams. 1207function stringToUint8Array(str: string) { 1208 let arr = new Uint8Array(str.length); 1209 for (let i = 0, j = str.length; i < j; ++i) { 1210 arr[i] = str.charCodeAt(i); 1211 } 1212 return arr; 1213} 1214 1215// Construct the key parameters of the RSA asymmetric key pair based on the key pair specifications. 1216function genRsaKeyPairSpec(nIn: bigint, eIn: bigint, dIn: bigint) { 1217 let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = { 1218 n: nIn, 1219 algName: "RSA", 1220 specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC 1221 }; 1222 let rsaKeyPairSpec: cryptoFramework.RSAKeyPairSpec = { 1223 params: rsaCommSpec, 1224 sk: dIn, 1225 pk: eIn, 1226 algName: "RSA", 1227 specType: cryptoFramework.AsyKeySpecType.KEY_PAIR_SPEC 1228 }; 1229 return rsaKeyPairSpec; 1230} 1231 1232// Generate RSA2048 key pair parameters. 1233function genRsa2048KeyPairSpec(): cryptoFramework.RSAKeyPairSpec { 1234 let nIn = BigInt("0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25"); 1235 let eIn = BigInt("0x010001"); 1236 let dIn = BigInt("0x6a7df2ca63ead4dda191d614b6b385e0d9056a3d6d5cfe07db1daabee022db08212d97613d3328e0267c9dd23d787abde2afcb306aeb7dfce69246cc73f5c87fdf06030179a2114b767db1f083ff841c025d7dc00cd82435b9a90f695369e94df23d2ce458bc3b3283ad8bba2b8fa1ba62e2dce9accff3799aae7c840016f3ba8e0048c0b6cc4339af7161003a5beb864a0164b2c1c9237b64bc87556994351b27506c33d4bcdfce0f9c491a7d6b0628c7c852be4f0a9c3132b2ed3a2c8881e9aab07e20e17deb074691be677776a78b5c502e05d9bdde72126b3738695e2dd1a0a98a14247c65d8a7ee79432a092cb0721a12df798e44f7cfce0c498147a9b1"); 1237 return genRsaKeyPairSpec(nIn, eIn, dIn); 1238} 1239 1240function rsaUseSpecDecryptOAEPPromise() { 1241 let plan = "This is cipher test."; 1242 // Obtain the key parameter object of the RSA key pair. 1243 let rsaKeyPairSpec = genRsa2048KeyPairSpec(); 1244 // Generate an RSA key pair based on the RSA key parameters. 1245 let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaKeyPairSpec); 1246 let keyGenPromise = rsaGeneratorSpec.generateKeyPair(); 1247 let cipher = cryptoFramework.createCipher("RSA|PKCS1_OAEP|SHA256|MGF1_SHA1"); 1248 let decoder = cryptoFramework.createCipher("RSA|PKCS1_OAEP|SHA256|MGF1_SHA1"); 1249 let keyPair: cryptoFramework.KeyPair; 1250 let cipherDataBlob: cryptoFramework.DataBlob; 1251 // Set the pSource, which defines the encoding input P filled by OAEP. 1252 let pSource = new Uint8Array([1, 2, 3, 4]); 1253 let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) }; 1254 // Generate the key pair. 1255 keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => { 1256 keyPair = rsaKeyPair; 1257 // Initialize the Cipher instance for encryption. 1258 return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null); 1259 }) 1260 .then(() => { 1261 // Set and obtain the cipher specifications after the initialization. 1262 cipher.setCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_PSRC_UINT8ARR, pSource); 1263 let retP = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_PSRC_UINT8ARR); 1264 // Check whether the obtained PSource is the same as the PSource set. 1265 if (retP.toString() != pSource.toString()) { 1266 AlertDialog.show({ message: "error init pSource" + retP }); 1267 } else { 1268 console.info("pSource changed ==" + retP); 1269 } 1270 // Obtain other OAEP parameters. 1271 let md = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MD_NAME_STR); 1272 console.info("md == " + md); 1273 let mgf = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF_NAME_STR); 1274 console.info("mgf == " + mgf); 1275 let mgf1Md = cipher.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_MD_STR); 1276 console.info("mgf1Md == " + mgf1Md); 1277 return cipher.doFinal(input); 1278 }) 1279 .then((dataBlob: cryptoFramework.DataBlob): Promise<void> => { 1280 console.info("EncryptOutPut is " + dataBlob.data); 1281 cipherDataBlob = dataBlob; 1282 // The get() and set() operations can be performed before the init() operation of the Cipher object and are equivalent to those after the init() operation. For example, set and get the decoder. 1283 decoder.setCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_PSRC_UINT8ARR, pSource); 1284 let retP = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_PSRC_UINT8ARR); 1285 // Check whether the obtained PSource is the same as the PSource set. 1286 if (retP.toString() != pSource.toString()) { 1287 AlertDialog.show({ message: "error init pSource" + retP }); 1288 } else { 1289 console.info("pSource changed ==" + retP); 1290 } 1291 // Obtain other OAEP parameters. 1292 let md = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MD_NAME_STR); 1293 console.info("md == " + md); 1294 let mgf = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF_NAME_STR); 1295 console.info("mgf == " + mgf); 1296 let mgf1Md = decoder.getCipherSpec(cryptoFramework.CipherSpecItem.OAEP_MGF1_MD_STR); 1297 console.info("mgf1Md == " + mgf1Md); 1298 // Initialize the decryption operation. 1299 return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null); 1300 }) 1301 .then(() => { 1302 return decoder.doFinal(cipherDataBlob); 1303 }) 1304 .then(decodeData => { 1305 // The decryption is successful. 1306 if (decodeData.data.toString() === input.data.toString()) { 1307 console.info("oaep decrypt success"); 1308 AlertDialog.show({ message: " oaep decrypt success" }); 1309 } else { 1310 AlertDialog.show({ message: "oeap decrypt fail" }); 1311 } 1312 }); 1313} 1314``` 1315 1316### Encrypting and Decrypting Data Using SM2 1317 1318> **NOTE** 1319> 1320> SM2 encryption and decryption are supported from API version 10. 1321 1322Use an SM2 asymmetric key pair to encrypt and decrypt data. 1323 13241. Generate an SM2 key pair. Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an SM2 asymmetric key pair. 13252. Create a **Cipher** instance.<br>Call **createCipher()** to create a **Cipher** instance, and set the key and encryption/decryption mode. 13263. Encrypt and decrypt data.<br>Call **doFinal()** provided by the **Cipher** instance to encrypt data or decrypt data. 1327 1328```ts 1329import cryptoFramework from '@ohos.security.cryptoFramework'; 1330import { BusinessError } from '@ohos.base'; 1331 1332let plan = "This is cipher test."; 1333 1334// Convert strings in plaintext into byte streams. 1335function stringToUint8Array(str: string) { 1336 let arr = new Uint8Array(str.length); 1337 for (let i = 0, j = str.length; i < j; ++i) { 1338 arr[i] = str.charCodeAt(i); 1339 } 1340 return arr; 1341} 1342 1343// Encrypt the message in promise mode. 1344function encryptMessagePromise() { 1345 // Create an AsyKeyGenerator instance. 1346 let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256"); 1347 // Create a Cipher instance. 1348 let cipher = cryptoFramework.createCipher("SM2_256|SM3"); 1349 // Generate an asymmetric key pair using the AsyKeyGenerator instance. 1350 let keyGenPromise = sm2Generator.generateKeyPair(); 1351 keyGenPromise.then((sm2KeyPair: cryptoFramework.KeyPair): Promise<void> => { 1352 let pubKey = sm2KeyPair.pubKey; 1353 // Initialize the Cipher instance and use the public key to encrypt the message. 1354 return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null); 1355 }).then(() => { 1356 // doFinal 1357 let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) }; 1358 return cipher.doFinal(input); 1359 }).then(dataBlob => { 1360 // Obtain the encrypted data. 1361 console.info("EncryptOutPut is " + dataBlob.data); 1362 }); 1363} 1364 1365// Encrypt the message in callback mode. 1366function encryptMessageCallback() { 1367 // Create an AsyKeyGenerator instance. 1368 let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256"); 1369 // Create a Cipher instance. 1370 let cipher = cryptoFramework.createCipher("SM2_256|SM3"); 1371 // Generate an asymmetric key pair using the AsyKeyGenerator instance. 1372 sm2Generator.generateKeyPair((err, keyPair) => { 1373 let pubKey = keyPair.pubKey; 1374 // Initialize the Cipher instance and use the public key to encrypt the message. 1375 cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, pubKey, null, (err, data) => { 1376 let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) }; 1377 // doFinal 1378 cipher.doFinal(input, (err, data) => { 1379 // Obtain the encrypted data. 1380 console.info("EncryptOutPut is " + data.data); 1381 }) 1382 }) 1383 }) 1384} 1385 1386// Encrypt and decrypt data in promise mode. 1387function decryptMessagePromise() { 1388 // Create an AsyKeyGenerator instance. 1389 let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256"); 1390 // Create a Cipher instance for encryption. 1391 let cipher = cryptoFramework.createCipher("SM2_256|SM3"); 1392 // Create a Cipher instance for decryption. 1393 let decoder = cryptoFramework.createCipher("SM2_256|SM3"); 1394 // Generate an asymmetric key pair using the AsyKeyGenerator instance. 1395 let keyGenPromise = sm2Generator.generateKeyPair(); 1396 let keyPair: cryptoFramework.KeyPair; 1397 let cipherDataBlob: cryptoFramework.DataBlob; 1398 let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plan) }; 1399 keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => { 1400 keyPair = rsaKeyPair; 1401 // Initialize the Cipher instance and use the public key to encrypt the data. 1402 return cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null); 1403 }) 1404 .then(() => { 1405 // Call doFinal() to encrypt data. 1406 return cipher.doFinal(input); 1407 }) 1408 .then((dataBlob: cryptoFramework.DataBlob): Promise<void> => { 1409 // Obtain the encrypted information and use it as the input parameter for decryption. 1410 console.info("EncryptOutPut is " + dataBlob.data); 1411 AlertDialog.show({ message: "output" + dataBlob.data }); 1412 cipherDataBlob = dataBlob; 1413 // Initialize the Cipher instance and use the private key to decrypt the data. 1414 return decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null); 1415 }) 1416 .then(() => { 1417 // Call doFinal() to decrypt data. 1418 return decoder.doFinal(cipherDataBlob); 1419 }) 1420 .then(decodeData => { 1421 // Check whether the decrypted data is consistent with the original data. 1422 if (decodeData.data.toString() === input.data.toString()) { 1423 AlertDialog.show({ message: "decrypt success" }); 1424 return; 1425 } 1426 AlertDialog.show({ message: "decrypt fail" }); 1427 }); 1428} 1429 1430// Encrypt and decrypt data in callback mode. 1431function decryptMessageCallback() { 1432 // Create an AsyKeyGenerator instance. 1433 let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256"); 1434 // Create a Cipher instance for encryption. 1435 let cipher = cryptoFramework.createCipher("SM2_256|SM3"); 1436 // Create a Cipher instance for decryption. 1437 let decoder = cryptoFramework.createCipher("SM2_256|SM3"); 1438 let plainText = "this is cipher text"; 1439 let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plainText) }; 1440 let cipherData: cryptoFramework.DataBlob; 1441 let keyPair: cryptoFramework.KeyPair; 1442 // Generate an asymmetric key pair using the AsyKeyGenerator instance. 1443 sm2Generator.generateKeyPair((err, newKeyPair) => { 1444 keyPair = newKeyPair; 1445 // Initialize the Cipher instance and use the public key to encrypt the data. 1446 cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, keyPair.pubKey, null, (err, data) => { 1447 // Call doFinal() to encrypt data. 1448 cipher.doFinal(input, (err, data) => { 1449 // Obtain the encrypted information and use it as the input parameter for decryption. 1450 AlertDialog.show({ message: "EncryptOutPut is " + data.data }); 1451 cipherData = data; 1452 // Initialize the Cipher instance and use the private key to decrypt the data. 1453 decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, keyPair.priKey, null, (err, data) => { 1454 // Call doFinal() to decrypt data. 1455 decoder.doFinal(cipherData, (err, data) => { 1456 // Check whether the decrypted data is consistent with the original data. 1457 if (input.data.toString() === data.data.toString()) { 1458 AlertDialog.show({ message: "decrypt success" }); 1459 return; 1460 } 1461 AlertDialog.show({ message: "decrypt fail" }); 1462 }); 1463 }); 1464 }); 1465 }); 1466 }); 1467} 1468``` 1469 1470### Encrypting and Decrypting Data Using an SM4 ECB Symmetric Key (Callback) 1471 1472> **NOTE** 1473> 1474> SM4 encryption and decryption are supported from API version 10. 1475 1476Use an SM4 symmetric key to encrypt and decrypt data. 1477 14781. Create a **SymKeyGenerator** instance. 14792. Generate a key based on the existing binary data. 14803. Create a **Cipher** instance. 14814. Encrypt or decrypt data. 1482 1483```ts 1484import cryptoFramework from '@ohos.security.cryptoFramework'; 1485import { BusinessError } from '@ohos.base'; 1486 1487// Convert strings in plaintext into byte streams. 1488function stringToUint8Array(str: string) { 1489 let arr = new Uint8Array(str.length); 1490 for (let i = 0, j = str.length; i < j; ++i) { 1491 arr[i] = str.charCodeAt(i); 1492 } 1493 return arr; 1494} 1495 1496// Convert byte streams into strings in plaintext. 1497function uint8ArrayToString(array: Uint8Array) { 1498 let arrayString = ''; 1499 for (let i = 0; i < array.length; i++) { 1500 arrayString += String.fromCharCode(array[i]); 1501 } 1502 return arrayString; 1503} 1504 1505// Use SM4 ECB to encrypt and decrypt a message in callback mode. 1506function testSM4Ecb() { 1507 // Create an AsyKeyGenerator instance. 1508 let sm4Generator = cryptoFramework.createSymKeyGenerator('SM4_128'); 1509 // Create a Cipher instance for encryption. 1510 let cipher = cryptoFramework.createCipher("SM4_128|ECB|PKCS7"); 1511 // Create a Cipher instance for decryption. 1512 let decoder = cryptoFramework.createCipher("SM4_128|ECB|PKCS7"); 1513 let plainText = "this is cipher text"; 1514 let input: cryptoFramework.DataBlob = { data: stringToUint8Array(plainText) }; 1515 let cipherData: cryptoFramework.DataBlob; 1516 let key: cryptoFramework.SymKey; 1517 // Generate an asymmetric key pair using the AsyKeyGenerator instance. 1518 sm4Generator.generateSymKey((err, newKey) => { 1519 key = newKey; 1520 // Initialize the Cipher instance and use the public key to encrypt the data. 1521 cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, key, null, (err, data) => { 1522 // Call doFinal() to encrypt data. 1523 cipher.doFinal(input, (err, data) => { 1524 // Obtain the encrypted information and use it as the input parameter for decryption. 1525 AlertDialog.show({ message: "EncryptOutPut is " + data.data }); 1526 cipherData = data; 1527 // Initialize the Cipher instance and use the private key to decrypt the data. 1528 decoder.init(cryptoFramework.CryptoMode.DECRYPT_MODE, key, null, (err, data) => { 1529 // Call doFinal() to decrypt data. 1530 decoder.doFinal(cipherData, (err, data) => { 1531 // Check whether the decrypted data is consistent with the original data. 1532 if (input.data.toString() === data.data.toString()) { 1533 AlertDialog.show({ message: "decrypt success" }); 1534 return; 1535 } 1536 AlertDialog.show({ message: "decrypt fail" }); 1537 }); 1538 }); 1539 }); 1540 }); 1541 }); 1542} 1543``` 1544 1545## Signing and Signature Verification 1546 1547### When to Use 1548 1549A digital signature can be used to verify the authenticity of a message. Typical signing and signature verification operations involve the following: 15501. Use RSA to generate a signature and verify the signature. 15512. Use ECC to generate a signature and verify the signature. 15523. Use RSA to generate a signature and verify the signature. Obtain and set **SignSpecItem** when the PSS padding mode is used. 15534. Use SM2 to generate a signature and verify the signature. 1554 1555> **NOTE** 1556> 1557> - From API version 10, [SignSpecItem](../reference/apis/js-apis-cryptoFramework.md#signspecitem10) can be set and obtained when the PSS padding mode is used. 1558> - From API version 10, the string parameter without the key length is supported in signature verification. 1559 1560### Available APIs 1561 1562The following table describes the APIs used in typical signing and signature verification operations. For more information about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md). 1563> **NOTE** 1564> 1565> 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. 1566 1567|Instance|API|Description| 1568|---|---|---| 1569|cryptoFramework|createSign(algName : string) : Sign|Creates a **Sign** instance.| 1570|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.| 1571|Sign|init(priKey : PriKey) : Promise\<void>|Sets a key and initializes the **Sign** instance. This API uses a promise to return the result.| 1572|Sign|update(data : DataBlob, callback : AsyncCallback\<void>) : void|Updates the data for signing. This API uses an asynchronous callback to return the result.| 1573|Sign|update(data : DataBlob) : Promise\<void>|Updates the data for signing. This API uses a promise to return the result.| 1574|Sign|sign(data : DataBlob, callback : AsyncCallback\<DataBlob>) : void|Signs the data. This API uses an asynchronous callback to return the result.| 1575|Sign|sign(data : DataBlob) : Promise\<DataBlob>|Signs the data. This API uses a promise to return the result.| 1576|Sign|getSignSpec(itemType: SignSpecItem): string \| number|Obtains signing specifications. Currently, only the RSA is supported.| 1577|Sign|setSignSpec(itemType: SignSpecItem, itemValue: number): void|Sets signing specifications. Currently, only the RSA is supported.| 1578|cryptoFramework|function createVerify(algName : string) : Verify|Creates a **Verify** instance.| 1579|Verify|init(pubKey : PubKey, callback : AsyncCallback\<void>) : void|Sets a key and initializes the **Verify** instance. This API uses an asynchronous callback to return the result.| 1580|Verify|init(pubKey : PubKey) : Promise\<void>|Sets a key and initializes the **Verify** instance. This API uses a promise to return the result.| 1581|Verify|update(data : DataBlob, callback : AsyncCallback\<void>) : void|Updates the data for signature verification. This API uses an asynchronous callback to return the result.| 1582|Verify|update(data : DataBlob) : Promise\<void>|Updates the data for signature verification. This API uses a promise to return the result.| 1583|Verify|verify(data : DataBlob, signatureData : DataBlob, callback : AsyncCallback\<boolean>) : void|Verifies a signature. This API uses an asynchronous callback to return the result.| 1584|Verify|verify(data : DataBlob, signatureData : DataBlob) : Promise\<boolean>|Verifies a signature. This API uses a promise to return the result.| 1585|Verify|getVerifySpec(itemType: SignSpecItem): string \| number|Obtains signature verification specifications. Currently, only the RSA is supported.| 1586|Verify|setVerifySpec(itemType: SignSpecItem, itemValue: number): void|Sets signature verification specifications. Currently, only the RSA is supported.| 1587 1588### Signing and Signature Verification Using RSA 1589 1590Use RSA to sign data and verify the signature. 1591 15921. Generate an RSA key pair.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an RSA asymmetric key pair. 15932. Create a **Sign** instance.<br>Call **createSign()** to create a **Sign** instance, initialize the **Sign** instance, and set a private key for signing. 15943. 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. 15954. Create a **Verify** instance.<br>Call **createVerify()** to create a **Verify** instance, initialize the instance, and set a public key for signature verification. 15965. Verify the signature.<br>Call **update()** provided by the **Verify** class to pass in the signature data and call **verify()** to verify the signature. 1597 1598```ts 1599import cryptoFramework from '@ohos.security.cryptoFramework'; 1600import { BusinessError } from '@ohos.base'; 1601 1602// Convert strings in plaintext into byte streams. 1603function stringToUint8Array(str: string) { 1604 let arr = new Uint8Array(str.length); 1605 for (let i = 0, j = str.length; i < j; ++i) { 1606 arr[i] = str.charCodeAt(i); 1607 } 1608 return arr; 1609} 1610 1611let globalKeyPair: cryptoFramework.KeyPair; 1612let signMessageBlob: cryptoFramework.DataBlob; 1613let plan1 = "This is Sign test plan1"; 1614let plan2 = "This is Sign test plan1"; 1615let input1: cryptoFramework.DataBlob = { data: stringToUint8Array(plan1) }; 1616let input2: cryptoFramework.DataBlob = { data: stringToUint8Array(plan2) }; 1617 1618function signMessagePromise() { 1619 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 1620 let signer = cryptoFramework.createSign("RSA1024|PKCS1|SHA256"); // From API version 10, a Sign instance can be created by specifying a string parameter defining the key specifications. 1621 let keyGenPromise = rsaGenerator.generateKeyPair(); 1622 keyGenPromise.then(keyPair => { 1623 globalKeyPair = keyPair; 1624 let priKey = globalKeyPair.priKey; 1625 return signer.init(priKey); 1626 }).then(() => { 1627 return signer.update(input1); 1628 }).then(() => { 1629 return signer.sign(input2); 1630 }).then(dataBlob => { 1631 signMessageBlob = dataBlob; 1632 console.info("sign output is " + signMessageBlob.data); 1633 }); 1634} 1635 1636// Call verify() after sign() is called. 1637function verifyMessagePromise() { 1638 let verifyer = cryptoFramework.createVerify("RSA1024|PKCS1|SHA256"); 1639 let verifyInitPromise = verifyer.init(globalKeyPair.pubKey); 1640 verifyInitPromise.then(() => { 1641 return verifyer.update(input1); 1642 }).then(() => { 1643 return verifyer.verify(input2, signMessageBlob); 1644 }).then(res => { 1645 console.log("Verify result is " + res); 1646 }); 1647} 1648 1649function signMessageCallback() { 1650 let rsaGenerator = cryptoFramework.createAsyKeyGenerator("RSA1024|PRIMES_2"); 1651 let signer = cryptoFramework.createSign("RSA1024|PKCS1|SHA256"); // From API version 10, a Sign instance can be created by specifying a string parameter defining the key specifications. 1652 rsaGenerator.generateKeyPair((err, keyPair) => { 1653 globalKeyPair = keyPair; 1654 let priKey = globalKeyPair.priKey; 1655 signer.init(priKey, err => { 1656 signer.update(input1, err => { 1657 signer.sign(input2, (err, data) => { 1658 signMessageBlob = data; 1659 console.info("sign output is " + signMessageBlob.data); 1660 }); 1661 }); 1662 }); 1663 }); 1664} 1665 1666// Call verify() after sign() is called. 1667function verifyMessageCallback() { 1668 let verifyer = cryptoFramework.createVerify("RSA1024|PKCS1|SHA256"); 1669 verifyer.init(globalKeyPair.pubKey, err => { 1670 verifyer.update(input1, err => { 1671 verifyer.verify(input2, signMessageBlob, (err, data) => { 1672 console.info("verify result is " + data); 1673 }); 1674 }); 1675 }) 1676} 1677``` 1678 1679### Signing and Signature Verification Using ECDSA 1680 1681Use ECDSA to sign data and verify the signature. 1682 16831. Generate an ECC key.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an ECC asymmetric key pair. 16842. Create a **Sign** instance.<br>Call **createSign()** to create a **Sign** instance, initialize the **Sign** instance, and set a private key for signing. 16853. 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. 16864. Create a **Verify** instance.<br>Call **createVerify()** to create a **Verify** instance, initialize the instance, and set a public key for signature verification. 16875. Verify the signature.<br>Call **update()** provided by the **Verify** class to pass in the signature data and call **doFinal()** to verify the signature. 1688 1689```ts 1690import cryptoFramework from '@ohos.security.cryptoFramework'; 1691import { BusinessError } from '@ohos.base'; 1692 1693// Convert strings in plaintext into byte streams. 1694function stringToUint8Array(str: string) { 1695 let arr = new Uint8Array(str.length); 1696 for (let i = 0, j = str.length; i < j; ++i) { 1697 arr[i] = str.charCodeAt(i); 1698 } 1699 return arr; 1700} 1701 1702let globalKeyPair: cryptoFramework.KeyPair; 1703let signMessageBlob: cryptoFramework.DataBlob; 1704let plan1 = "This is Sign test plan1"; 1705let plan2 = "This is Sign test plan1"; 1706let input1: cryptoFramework.DataBlob = { data: stringToUint8Array(plan1) }; 1707let input2: cryptoFramework.DataBlob = { data: stringToUint8Array(plan2) }; 1708 1709function signMessagePromise() { 1710 let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256"); 1711 let signer = cryptoFramework.createSign("ECC256|SHA256"); 1712 let keyGenPromise = eccGenerator.generateKeyPair(); 1713 keyGenPromise.then(keyPair => { 1714 globalKeyPair = keyPair; 1715 let priKey = globalKeyPair.priKey; 1716 return signer.init(priKey); 1717 }).then(() => { 1718 return signer.update(input1); 1719 }).then(() => { 1720 return signer.sign(input2); 1721 }).then(dataBlob => { 1722 signMessageBlob = dataBlob; 1723 console.info("sign output is " + signMessageBlob.data); 1724 }); 1725} 1726 1727function verifyMessagePromise() { 1728 let verifyer = cryptoFramework.createVerify("ECC256|SHA256"); 1729 let verifyInitPromise = verifyer.init(globalKeyPair.pubKey); 1730 verifyInitPromise.then(() => { 1731 return verifyer.update(input1); 1732 }).then(() => { 1733 return verifyer.verify(input2, signMessageBlob); 1734 }).then(res => { 1735 console.log("Verify result is " + res); 1736 }); 1737} 1738 1739function signMessageCallback() { 1740 let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256"); 1741 let signer = cryptoFramework.createSign("ECC256|SHA256"); 1742 eccGenerator.generateKeyPair((err, keyPair) => { 1743 globalKeyPair = keyPair; 1744 let priKey = globalKeyPair.priKey; 1745 signer.init(priKey, err => { 1746 signer.update(input1, err => { 1747 signer.sign(input2, (err, data) => { 1748 signMessageBlob = data; 1749 console.info("sign output is " + signMessageBlob.data); 1750 }); 1751 }); 1752 }); 1753 }); 1754} 1755 1756function verifyMessageCallback() { 1757 let verifyer = cryptoFramework.createVerify("ECC256|SHA256"); 1758 verifyer.init(globalKeyPair.pubKey, err => { 1759 verifyer.update(input1, err => { 1760 verifyer.verify(input2, signMessageBlob, (err, data) => { 1761 console.info("verify result is " + data); 1762 }); 1763 }); 1764 }) 1765} 1766``` 1767 1768### Signing and Signature Verification Using RSA by Segment 1769 1770Use RSA to sign data and verify the signature by segment. 1771 17721. Generate an RSA key pair.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an RSA asymmetric key pair. 17732. Create a **Sign** instance.<br>Call **createSign()** to create a **Sign** instance, initialize the **Sign** instance, and set a private key for signing. 17743. Generate a signature.<br>Call the **update()** provided by the **Sign** class multiple times to pass in data by segment and call **sign()** to generate a signature. 17754. Create a **Verify** instance.<br>Call **createVerify()** to create a **Verify** instance, initialize the instance, and set a public key for signature verification. 17765. Verify the signature.<br>Call the **update()** method provided by the **Verify** class multiple times to pass in data by segment and call **verify()** to verify the signature. 1777 1778```ts 1779import cryptoFramework from '@ohos.security.cryptoFramework'; 1780import { BusinessError } from '@ohos.base'; 1781 1782// Convert strings in plaintext into byte streams. 1783function stringToUint8Array(str: string) { 1784 let arr = new Uint8Array(str.length); 1785 for (let i = 0, j = str.length; i < j; ++i) { 1786 arr[i] = str.charCodeAt(i); 1787 } 1788 return arr; 1789} 1790 1791function signLongMessagePromise() { 1792 let globalPlainText = "This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1793 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1794 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1795 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1796 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1797 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1798 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!" + 1799 "This is a long plainTest! This is a long plainTest! This is a long plainTest! This is a long plainTest!"; 1800 let globalSignData: Uint8Array; 1801 let textSplitLen = 64; // Customized data splitting length. 1802 let keyGenName = "RSA1024"; 1803 let signAlgName = "RSA1024|PKCS1|SHA256"; 1804 let globalKeyPair: cryptoFramework.KeyPair; 1805 let asyKeyGenerator = cryptoFramework.createAsyKeyGenerator(keyGenName); // Create an AsyKeyGenerator object. 1806 let signer = cryptoFramework.createSign(signAlgName); // Create a Signer instance. 1807 let verifier = cryptoFramework.createVerify(signAlgName); // Create a Verifier instance. 1808 let keyGenPromise = asyKeyGenerator.generateKeyPair(); 1809 keyGenPromise.then((rsaKeyPair: cryptoFramework.KeyPair): Promise<void> => { 1810 globalKeyPair = rsaKeyPair; // Save the key pair as a global variable. 1811 return signer.init(globalKeyPair.priKey); 1812 }) 1813 .then(async (): Promise<void> => { 1814 // If the plaintext is too large, split the plaintext based on the specified length and cyclically call update() to pass in the plaintext. 1815 for (let i = 0; i < (globalPlainText.length / textSplitLen); i++) { 1816 let tempStr = globalPlainText.substr(i * textSplitLen, textSplitLen); 1817 let tempBlob: cryptoFramework.DataBlob = { data: stringToUint8Array(tempStr) }; 1818 await signer.update(tempBlob); 1819 } 1820 }) 1821 .then((): Promise<cryptoFramework.DataBlob> => { 1822 return signer.sign(null); 1823 }) 1824 .then((signData: cryptoFramework.DataBlob): Promise<void> => { 1825 globalSignData = signData.data; 1826 console.info(`globalSignOutput len is ${globalSignData.length}, data is: ${globalSignData.toString()}`); 1827 return verifier.init(globalKeyPair.pubKey); 1828 }) 1829 .then(async () => { 1830 // If the plaintext is too large, split the plaintext based on the specified length and cyclically call update() to pass in the plaintext. 1831 for (let i = 0; i < (globalPlainText.length / textSplitLen); i++) { 1832 let tempData = globalPlainText.slice(i * textSplitLen, (i + 1) * textSplitLen); 1833 let tempBlob: cryptoFramework.DataBlob = { data: stringToUint8Array(tempData) }; 1834 await verifier.update(tempBlob); 1835 } 1836 return; 1837 }) 1838 .then((): Promise<boolean> => { 1839 return verifier.verify(null, { data: globalSignData }); 1840 }) 1841 .then(res => { 1842 console.info(`verify res is ${res}`); 1843 }) 1844 .catch((error: BusinessError) => { 1845 console.error(`catch error, ${error.code}, ${error.message}`); 1846 }) 1847} 1848``` 1849 1850### Using PSS in RSA Signing and Signature Verification 1851 1852Use the PSS padding mode in RSA signing and signature verification in callback mode. 1853 18541. Generate an RSA key pair based on the key parameters.<br>Call **createAsyKeyGeneratorBySpec** to create an **AsyKeyGeneratorBySpec** object and generate an RSA asymmetric key pair. 18552. Create a **Sign** instance.<br>Call **createSign()** to create a **Sign** object, initialize the **Sign** object, set the private key for signing, and set and obtain PSS parameters. 18563. 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. 18574. Create a **Verify** instance.<br>Call **createVerify()** to create a **Verify** object, initialize the object, set the public key for signature verification, and set and obtain PSS parameters. The signature verification is successful if the salt length is the same. 18585. Verify the signature.<br>Call **update()** provided by the **Verify** class to pass in the signature data and call **verify()** to verify the signature. 1859 1860```ts 1861import cryptoFramework from '@ohos.security.cryptoFramework'; 1862import { BusinessError } from '@ohos.base'; 1863 1864// Convert strings in plaintext into byte streams. 1865function stringToUint8Array(str: string) { 1866 let arr = new Uint8Array(str.length); 1867 for (let i = 0, j = str.length; i < j; ++i) { 1868 arr[i] = str.charCodeAt(i); 1869 } 1870 return arr; 1871} 1872 1873// Convert byte streams into strings in plaintext. 1874function uint8ArrayToString(array: Uint8Array) { 1875 let arrayString = ''; 1876 for (let i = 0; i < array.length; i++) { 1877 arrayString += String.fromCharCode(array[i]); 1878 } 1879 return arrayString; 1880} 1881 1882// Construct the key parameters of the RSA asymmetric key pair based on the key pair specifications. 1883function genRsaKeyPairSpec(nIn: bigint, eIn: bigint, dIn: bigint) { 1884 let rsaCommSpec: cryptoFramework.RSACommonParamsSpec = { 1885 n: nIn, 1886 algName: "RSA", 1887 specType: cryptoFramework.AsyKeySpecType.COMMON_PARAMS_SPEC 1888 }; 1889 let rsaKeyPairSpec: cryptoFramework.RSAKeyPairSpec = { 1890 params: rsaCommSpec, 1891 sk: dIn, 1892 pk: eIn, 1893 algName: "RSA", 1894 specType: cryptoFramework.AsyKeySpecType.KEY_PAIR_SPEC 1895 }; 1896 return rsaKeyPairSpec; 1897} 1898 1899// Generate RSA2048 key pair parameters. 1900function genRsa2048KeyPairSpec(): cryptoFramework.RSAKeyPairSpec { 1901 let nIn = BigInt("0x9260d0750ae117eee55c3f3deaba74917521a262ee76007cdf8a56755ad73a1598a1408410a01434c3f5bc54a88b57fa19fc4328daea0750a4c44e88cff3b2382621b80f670464433e4336e6d003e8cd65bff211da144b88291c2259a00a72b711c116ef7686e8fee34e4d933c868187bdc26f7be071493c86f7a5941c3510806ad67b0f94d88f5cf5c02a092821d8626e8932b65c5bd8c92049c210932b7afa7ac59c0e886ae5c1edb00d8ce2c57633db26bd6639bff73cee82be9275c402b4cf2a4388da8cf8c64eefe1c5a0f5ab8057c39fa5c0589c3e253f0960332300f94bea44877b588e1edbde97cf2360727a09b775262d7ee552b3319b9266f05a25"); 1902 let eIn = BigInt("0x010001"); 1903 let dIn = BigInt("0x6a7df2ca63ead4dda191d614b6b385e0d9056a3d6d5cfe07db1daabee022db08212d97613d3328e0267c9dd23d787abde2afcb306aeb7dfce69246cc73f5c87fdf06030179a2114b767db1f083ff841c025d7dc00cd82435b9a90f695369e94df23d2ce458bc3b3283ad8bba2b8fa1ba62e2dce9accff3799aae7c840016f3ba8e0048c0b6cc4339af7161003a5beb864a0164b2c1c9237b64bc87556994351b27506c33d4bcdfce0f9c491a7d6b0628c7c852be4f0a9c3132b2ed3a2c8881e9aab07e20e17deb074691be677776a78b5c502e05d9bdde72126b3738695e2dd1a0a98a14247c65d8a7ee79432a092cb0721a12df798e44f7cfce0c498147a9b1"); 1904 return genRsaKeyPairSpec(nIn, eIn, dIn); 1905} 1906 1907function verifyMessageCallbackPSS() { 1908 let plan1 = "This is Sign test plan1"; 1909 let plan2 = "This is Sign test plan1"; 1910 let input1: cryptoFramework.DataBlob = { data: stringToUint8Array(plan1) }; 1911 let input2: cryptoFramework.DataBlob = { data: stringToUint8Array(plan2) }; 1912 let globalKeyPair: cryptoFramework.KeyPair; 1913 let signMessageBlob: cryptoFramework.DataBlob; 1914 // Obtain the key parameter object of the RSA key pair. 1915 let rsaKeyPairSpec = genRsa2048KeyPairSpec(); 1916 // Create an RSA key pair generator. 1917 let rsaGeneratorSpec = cryptoFramework.createAsyKeyGeneratorBySpec(rsaKeyPairSpec); 1918 // Both sign() and verify() support the RSA key with or without the length. 1919 let signer = cryptoFramework.createSign("RSA|PSS|SHA256|MGF1_SHA256"); 1920 let verifyer = cryptoFramework.createVerify("RSA2048|PSS|SHA256|MGF1_SHA256"); 1921 rsaGeneratorSpec.generateKeyPair((err, keyPair) => { 1922 globalKeyPair = keyPair; 1923 signer.init(globalKeyPair.priKey, err => { 1924 // After the initialization, set and obtain the PSS parameters. 1925 let setN = 32; 1926 signer.setSignSpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM, setN); 1927 let saltLen = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM); 1928 console.info("SaltLen == " + saltLen); 1929 let tf = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_TRAILER_FIELD_NUM); 1930 console.info("trailer field == " + tf); 1931 let md = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MD_NAME_STR); 1932 console.info("md == " + md); 1933 let mgf = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MGF_NAME_STR); 1934 console.info("mgf == " + mgf); 1935 let mgf1Md = signer.getSignSpec(cryptoFramework.SignSpecItem.PSS_MGF1_MD_STR); 1936 console.info("mgf1Md == " + mgf1Md); 1937 signer.update(input1, err => { 1938 signer.sign(input2, (err, data) => { 1939 // Before signature verification initialization, set and obtain PSS parameters. The functions are the same as those after initialization. 1940 signMessageBlob = data; 1941 AlertDialog.show({ message: "res" + signMessageBlob.data }); 1942 let setN = 32; 1943 verifyer.setVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM, setN); 1944 let saltLen = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_SALT_LEN_NUM); 1945 console.info("SaltLen == " + saltLen); 1946 let tf = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_TRAILER_FIELD_NUM); 1947 console.info("trailer field == " + tf); 1948 let md = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MD_NAME_STR); 1949 console.info("md == " + md); 1950 let mgf = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF_NAME_STR); 1951 console.info("mgf == " + mgf); 1952 let mgf1Md = verifyer.getVerifySpec(cryptoFramework.SignSpecItem.PSS_MGF1_MD_STR); 1953 console.info("mgf1Md == " + mgf1Md); 1954 verifyer.init(globalKeyPair.pubKey, err => { 1955 verifyer.update(input1, err => { 1956 verifyer.verify(input2, signMessageBlob, (err, data) => { 1957 AlertDialog.show({ message: "res " + data }); 1958 }) 1959 }); 1960 }); 1961 }); 1962 }); 1963 }); 1964 }); 1965} 1966``` 1967 1968### Signing and Signature Verification Using SM2 1969 1970> **NOTE** 1971> 1972> SM2 signing and signature verification are supported from API version 10. 1973 1974Use SM2 to sign data and verify the signature. 1975 19761. Generate an SM2 key pair. Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an SM2 asymmetric key pair. 19772. Create a **Sign** instance.<br>Call **createSign()** to create a **Sign** instance, initialize the **Sign** instance, and set a private key for signing. 19783. 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. 19794. Create a **Verify** instance.<br>Call **createVerify()** to create a **Verify** instance, initialize the instance, and set a public key for signature verification. 19805. Verify the signature.<br>Call **update()** provided by the **Verify** class to pass in the signature data and call **doFinal()** to verify the signature. 1981 1982```ts 1983import cryptoFramework from '@ohos.security.cryptoFramework'; 1984import { BusinessError } from '@ohos.base'; 1985 1986// Convert strings in plaintext into byte streams. 1987function stringToUint8Array(str: string) { 1988 let arr = new Uint8Array(str.length); 1989 for (let i = 0, j = str.length; i < j; ++i) { 1990 arr[i] = str.charCodeAt(i); 1991 } 1992 return arr; 1993} 1994 1995let plan1 = "This is Sign test plan1"; 1996let plan2 = "This is Sign test plan2"; 1997let input1: cryptoFramework.DataBlob = { data: stringToUint8Array(plan1) }; 1998let input2: cryptoFramework.DataBlob = { data: stringToUint8Array(plan2) }; 1999 2000function signAndVerify() { 2001 let signMessageBlob: cryptoFramework.DataBlob; 2002 let sm2Generator = cryptoFramework.createAsyKeyGenerator("SM2_256"); 2003 let signer = cryptoFramework.createSign("SM2_256|SM3"); 2004 sm2Generator.generateKeyPair((err, keyPair) => { 2005 let priKey = keyPair.priKey; 2006 signer.init(priKey, err => { 2007 signer.update(input1, err => { 2008 signer.sign(input2, (err, data) => { 2009 signMessageBlob = data; 2010 console.info("sign output is " + signMessageBlob.data); 2011 let verifyer = cryptoFramework.createVerify("SM2_256|SM3"); 2012 verifyer.init(keyPair.pubKey, err => { 2013 verifyer.update(input1, err => { 2014 verifyer.verify(input2, signMessageBlob, (err, data) => { 2015 console.info("verify result is " + data); 2016 AlertDialog.show({ message: "verify success" }) 2017 }); 2018 }); 2019 }) 2020 }); 2021 }); 2022 }); 2023 }); 2024} 2025``` 2026 2027## Key Agreement 2028 2029### When to Use 2030 2031 2032Key agreement allows two parties to establish a shared secret over an insecure channel. 2033 2034> **NOTE** 2035> 2036> From API version 10, the string parameter without the key length is supported in key agreement. 2037 2038### Available APIs 2039 2040For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md). 2041 2042|Instance|API|Description| 2043|---|---|---| 2044|cryptoFramework|createKeyAgreement(algName : string) : KeyAgreement|Creates a **KeyAgreement** instance.| 2045|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey, callback : AsyncCallback\<DataBlob>) : void|Generates a shared secret. This API uses an asynchronous callback to return the result.| 2046|KeyAgreement|generateSecret(priKey : PriKey, pubKey : PubKey) : Promise\<DataBlob>|Generates a shared secret. This API uses a promise to return the result.| 2047 2048### How to Develop 2049 20501. Generate an ECC key.<br>Call **createAsyKeyGenerator()** to create an **AsyKeyGenerator** instance and generate an ECC asymmetric key pair. 20512. Generate a shared secret by using the private and public ECC keys. 2052 2053```ts 2054import cryptoFramework from '@ohos.security.cryptoFramework'; 2055import { BusinessError } from '@ohos.base'; 2056 2057let globalKeyPair: cryptoFramework.KeyPair; 2058 2059function ecdhPromise() { 2060 let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256"); 2061 let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256"); // ECC is supported for key agreement from API version 10. 2062 let keyGenPromise = eccGenerator.generateKeyPair(); 2063 keyGenPromise.then(keyPair => { 2064 globalKeyPair = keyPair; 2065 return eccKeyAgreement.generateSecret(keyPair.priKey, keyPair.pubKey); 2066 }).then((secret) => { 2067 console.info("ecdh output is " + secret.data); 2068 }).catch((error: BusinessError) => { 2069 console.error("ecdh error."); 2070 }); 2071} 2072 2073function ecdhCallback() { 2074 let eccGenerator = cryptoFramework.createAsyKeyGenerator("ECC256"); 2075 let eccKeyAgreement = cryptoFramework.createKeyAgreement("ECC256"); 2076 eccGenerator.generateKeyPair((err, keyPair) => { 2077 globalKeyPair = keyPair; 2078 eccKeyAgreement.generateSecret(keyPair.priKey, keyPair.pubKey, (err, secret) => { 2079 if (err) { 2080 console.error("ecdh error."); 2081 return; 2082 } 2083 console.info("ecdh output is " + secret.data); 2084 }); 2085 }); 2086} 2087``` 2088 2089## Message Digest 2090 2091### When to Use 2092 2093A 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. 2094 2095Typical MD operations involve the following: 2096 20971. Create an **Md** instance with the specified digest algorithm (such as SHA-256). 20982. Pass in one or more messages for generating a digest, and generate a digest. 20993. Obtain the digest algorithm and digest length (in bytes). 2100 2101### Available APIs 2102 2103For more information about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md). 2104 2105| Instance | API | Description | 2106| --------------- | ------------------------------------------------------------ | -------------------------------------------------- | 2107| cryptoFramework | function createMd(algName : string) : Md; | Creates an **Md** instance with the specified algorithm. | 2108| Md | update(input : DataBlob, callback : AsyncCallback\<void>) : void; | Updates the data for a digest. This API uses an asynchronous callback to return the result.| 2109| Md | update(input : DataBlob) : Promise\<void>; | Updates the data for a digest. This API uses a promise to return the result. | 2110| Md | digest(callback : AsyncCallback\<DataBlob>) : void; | Generates the digest. This API uses an asynchronous callback to return the result. | 2111| Md | digest() : Promise\<DataBlob>; | Generates the digest. This API uses a promise to return the result. | 2112| Md | getMdLength() : number; | Obtains the digest length based on the specified digest algorithm. | 2113| Md | readonly algName : string; | Obtains the digest algorithm. | 2114 2115### Generating a Digest 2116 21171. Use **createMd()** to create an **Md** instance. 21182. Use **update()** to pass in data. **update()** can be called multiple times. The algorithm library does not limit the data length of a single **update()**. 21193. Use **digest()** to compute a digest. 21204. Obtain the digest algorithm and length of the digest generated. 2121 2122```ts 2123import cryptoFramework from '@ohos.security.cryptoFramework'; 2124import { BusinessError } from '@ohos.base'; 2125 2126// Convert strings in plaintext into byte streams. 2127function stringToUint8Array(str: string) { 2128 let arr = new Uint8Array(str.length); 2129 for (let i = 0, j = str.length; i < j; ++i) { 2130 arr[i] = str.charCodeAt(i); 2131 } 2132 return arr; 2133} 2134 2135// Generate a digest in promise mode. 2136function doMdByPromise() { 2137 let mdAlgName = "SHA256"; // Digest algorithm name. 2138 let message = "mdTestMessgae"; // Data to be digested. 2139 let md = cryptoFramework.createMd(mdAlgName); 2140 ; 2141 console.info("[Promise]: Md algName is: " + md.algName); 2142 // 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. 2143 let promiseMdUpdate = md.update({ data: stringToUint8Array(message) }); 2144 promiseMdUpdate.then(() => { 2145 // Call digest() to return the result. 2146 let PromiseMdDigest = md.digest(); 2147 return PromiseMdDigest; 2148 }).then(digestOutput => { 2149 let mdOutput = digestOutput; 2150 console.info("[Promise]: MD result: " + mdOutput.data); 2151 let mdLen = md.getMdLength(); 2152 console.info("[Promise]: MD len: " + mdLen); 2153 }).catch((error: BusinessError) => { 2154 console.error("[Promise]: error: " + error.message); 2155 }); 2156} 2157 2158// Generate a digest in callback mode. 2159function doMdByCallback() { 2160 let mdAlgName = "SHA256"; // Digest algorithm name. 2161 let message = "mdTestMessgae"; // Data to be digested. 2162 let md = cryptoFramework.createMd(mdAlgName); 2163 console.info("[Callback]: Md algName is: " + md.algName); 2164 // 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. 2165 md.update({ data: stringToUint8Array(message) }, (err,) => { 2166 if (err) { 2167 console.error("[Callback]: err: " + err.code); 2168 } 2169 md.digest((err1, digestOutput) => { 2170 if (err1) { 2171 console.error("[Callback]: err: " + err1.code); 2172 } else { 2173 let mdOutput = digestOutput; 2174 console.info("[Callback]: MD result: " + mdOutput.data); 2175 let mdLen = md.getMdLength(); 2176 console.info("[Callback]: MD len: " + mdLen); 2177 } 2178 }); 2179 }); 2180} 2181``` 2182 2183### Generating a Digest by Segment 2184 21851. Use **createMd()** to create an **Md** instance. 21862. Use **update()** multiple times to pass in by segment. 21873. Use **digest()** to compute a digest. 21884. Obtain the digest algorithm and length of the digest generated. 2189 2190```ts 2191import cryptoFramework from '@ohos.security.cryptoFramework'; 2192import { BusinessError } from '@ohos.base'; 2193 2194// Convert strings in plaintext into byte streams. 2195function stringToUint8Array(str: string) { 2196 let arr = new Uint8Array(str.length); 2197 for (let i = 0, j = str.length; i < j; ++i) { 2198 arr[i] = str.charCodeAt(i); 2199 } 2200 return arr; 2201} 2202 2203// Generate a digest by segment in promise mode. 2204async function doLoopMdPromise() { 2205 let mdAlgName = "SHA256"; // Digest algorithm name. 2206 let md = cryptoFramework.createMd(mdAlgName); 2207 ; 2208 console.info("[Promise]: Md algName is: " + md.algName); 2209 let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // Assume that the message is of 43 bytes. 2210 let messageArr: number[] = []; 2211 let updateLength = 20; // For example, pass in 20 bytes in each update(). 2212 2213 for (let i = 0; i <= messageText.length; i++) { 2214 if ((i % updateLength == 0 || i == messageText.length) && messageArr.length != 0) { 2215 let message = new Uint8Array(messageArr); 2216 let messageBlob: cryptoFramework.DataBlob = { data: message }; 2217 // Use await to process the update() in the for() loop. 2218 try { 2219 await md.update(messageBlob); // Use update() to process data by segment. 2220 } catch (error) { 2221 let e: BusinessError = error as BusinessError; 2222 console.error(`await update error, ${e.code}, ${e.message}`); 2223 return; 2224 } 2225 messageArr = []; 2226 } 2227 // Pad messageArr based on the segment length. 2228 if (i < messageText.length) { 2229 messageArr.push(messageText.charCodeAt(i)); 2230 } 2231 } 2232 let PromiseMdDigest = md.digest(); 2233 PromiseMdDigest.then(digestOutput => { 2234 let mdOutput = digestOutput; 2235 console.info("[Promise]: MD result: " + mdOutput.data); 2236 let mdLen = md.getMdLength(); 2237 console.info("[Promise]: MD len: " + mdLen); 2238 }).catch((error: BusinessError) => { 2239 console.error("[Promise]: error: " + error.message); 2240 }); 2241} 2242``` 2243 2244## HMAC 2245 2246### When to Use 2247 2248A hash-based message authentication code (HMAC) can be used to verify both the integrity and authenticity of a message using a shared secret. 2249 2250Typical MAC operations involve the following: 2251 22521. Create a **Mac** instance. 22532. Initialize the **Mac** instance, add one or more segments of data for generating a MAC, and generate a MAC. 22543. Obtain the algorithm and length of a MAC. 2255 2256### Available APIs 2257 2258For details about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md). 2259 2260| Instance | API | Description | 2261| --------------- | ------------------------------------------------------------ | --------------------------------------------------- | 2262| cryptoFramework | function createMac(algName : string) : Mac; | Creates a **Mac** instance. | 2263| Mac | init(key : SymKey, callback : AsyncCallback\<void>) : void; | Initializes the **Mac** instance. This API uses an asynchronous callback to return the result.| 2264| Mac | init(key : SymKey) : Promise\<void>; | Initializes the **Mac** instance. This API uses a promise to return the result. | 2265| 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. | 2266| Mac | update(input : DataBlob) : Promise\<void>; | Updates the data for the MAC operation. This API uses a promise to return the result. | 2267| Mac | doFinal(callback : AsyncCallback\<DataBlob>) : void; | Finalizes the MAC operation to generate a MAC. This API uses an asynchronous callback to return the result. | 2268| Mac | doFinal() : Promise\<DataBlob>; | Finalizes the MAC operation to generate a MAC. This API uses a promise to return the result. | 2269| Mac | getMacLength() : number; | Obtains the length of the MAC based on the specified algorithm. | 2270| Mac | readonly algName : string; | Obtains the digest algorithm. | 2271 2272### Generating an HMAC 2273 22741. Use **createMac()** to create a **Mac** instance. 22752. Use **init()** to initialize the **Mac** instance with the symmetric key passed in. 22763. Use **update()** to pass in the data for computing an HMAC. 22774. Use **doFinal()** to generate an HMAC. 22785. Obtain the algorithm and length of the HMAC. 2279 2280```ts 2281import cryptoFramework from '@ohos.security.cryptoFramework'; 2282import { BusinessError } from '@ohos.base'; 2283 2284// Convert strings in plaintext into byte streams. 2285function stringToUint8Array(str: string) { 2286 let arr = new Uint8Array(str.length); 2287 for (let i = 0, j = str.length; i < j; ++i) { 2288 arr[i] = str.charCodeAt(i); 2289 } 2290 return arr; 2291} 2292 2293// Generate an HMAC in promise mode. 2294function doHmacByPromise() { 2295 let macAlgName = "SHA256"; // Digest algorithm name. 2296 let message = "hmacTestMessgae"; // Data used to generate an HMAC. 2297 let mac = cryptoFramework.createMac(macAlgName); 2298 console.info("[Promise]: Mac algName is: " + mac.algName); 2299 let KeyBlob: cryptoFramework.DataBlob = { 2300 // 128-bit key 2301 data: stringToUint8Array("12345678abcdefgh") 2302 } 2303 let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128"); 2304 // Convert the binary data into a key. 2305 let promiseConvertKey = symKeyGenerator.convertKey(KeyBlob); 2306 promiseConvertKey.then(symKey => { 2307 let promiseMacInit = mac.init(symKey); 2308 return promiseMacInit; 2309 }) 2310 .then(() => { 2311 // 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. 2312 let promiseMacUpdate = mac.update({ data: stringToUint8Array(message) }); 2313 return promiseMacUpdate; 2314 }) 2315 .then(() => { 2316 let PromiseMacDoFinal = mac.doFinal(); 2317 return PromiseMacDoFinal; 2318 }) 2319 .then(output => { 2320 let macOutput = output; 2321 console.info("[Promise]: HMAC result: " + macOutput.data); 2322 let macLen = mac.getMacLength(); 2323 console.info("[Promise]: MAC len: " + macLen); 2324 }) 2325 .catch((error: BusinessError) => { 2326 console.error("[Promise]: error: " + error.message); 2327 }); 2328} 2329 2330// Generate an HMAC in callback mode. 2331function doHmacByCallback() { 2332 let macAlgName = "SHA256"; // Digest algorithm name. 2333 let message = "hmacTestMessgae"; // Data used to generate an HMAC. 2334 let mac = cryptoFramework.createMac(macAlgName); 2335 console.info("[Promise]: Mac algName is: " + mac.algName); 2336 let KeyBlob: cryptoFramework.DataBlob = { 2337 // 128-bit key 2338 data: stringToUint8Array("12345678abcdefgh") 2339 } 2340 let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128"); 2341 // Convert the binary data into a key. 2342 symKeyGenerator.convertKey(KeyBlob, (err, symKey) => { 2343 if (err) { 2344 console.error("[Callback]: err: " + err.code); 2345 } 2346 mac.init(symKey, (err1,) => { 2347 if (err1) { 2348 console.error("[Callback]: err: " + err1.code); 2349 } 2350 // 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. 2351 mac.update({ data: stringToUint8Array(message) }, (err2,) => { 2352 if (err2) { 2353 console.error("[Callback]: err: " + err2.code); 2354 } 2355 mac.doFinal((err3, output) => { 2356 if (err3) { 2357 console.error("[Callback]: err: " + err3.code); 2358 } else { 2359 let macOutput = output; 2360 console.error("[Callback]: HMAC result: " + macOutput.data); 2361 let macLen = mac.getMacLength(); 2362 console.error("[Callback]: MAC len: " + macLen); 2363 } 2364 }); 2365 }); 2366 }); 2367 }); 2368} 2369``` 2370 2371### Generating an HMAC by Segment 2372 2373Generate an HMAC by segment. 2374 23751. Use **createMac()** to create a **Mac** instance. 23762. Use **init()** to initialize the **Mac** instance with the symmetric key passed in. 23773. Call **update()** multiple times to pass in data by segment. 23784. Use **doFinal()** to generate an HMAC. 23795. Obtain the algorithm and length of the HMAC. 2380 2381```ts 2382import cryptoFramework from '@ohos.security.cryptoFramework'; 2383import { BusinessError } from '@ohos.base'; 2384 2385function stringToUint8Array(str: string) { 2386 let arr = new Uint8Array(str.length); 2387 for (let i = 0, j = str.length; i < j; ++i) { 2388 arr[i] = str.charCodeAt(i); 2389 } 2390 return arr; 2391} 2392 2393function doLoopHmacPromise() { 2394 let macAlgName = "SHA256"; // Digest algorithm name. 2395 let mac = cryptoFramework.createMac(macAlgName); 2396 console.info("[Promise]: Mac algName is: " + mac.algName); 2397 let KeyBlob: cryptoFramework.DataBlob = { 2398 // 128-bit key 2399 data: stringToUint8Array("12345678abcdefgh") 2400 } 2401 let messageText = "aaaaa.....bbbbb.....ccccc.....ddddd.....eee"; // Assume that the message is of 43 bytes. 2402 let updateLength = 20; // For example, pass in 20 bytes in each update(). 2403 let symKeyGenerator = cryptoFramework.createSymKeyGenerator("AES128"); 2404 // Convert the binary data into a key. 2405 let promiseConvertKey = symKeyGenerator.convertKey(KeyBlob); 2406 promiseConvertKey.then((symKey: cryptoFramework.SymKey): Promise<void> => { 2407 let promiseMacInit = mac.init(symKey); 2408 return promiseMacInit; 2409 }) 2410 .then(async () => { 2411 let messageArr: number[] = []; 2412 for (let i = 0; i <= messageText.length; i++) { 2413 if ((i % updateLength == 0 || i == messageText.length) && messageArr.length != 0) { 2414 let message = new Uint8Array(messageArr); 2415 let messageBlob: cryptoFramework.DataBlob = { data: message }; 2416 // Use await to process the update() in the for() loop. 2417 try { 2418 await mac.update(messageBlob); // Invoke update() multiple times. 2419 } catch (error) { 2420 let e: BusinessError = error as BusinessError; 2421 console.error(`await update error, ${e.code}, ${e.message}`); 2422 return; 2423 } 2424 messageArr = []; 2425 } 2426 // Pad messageArr based on the segment length. 2427 if (i < messageText.length) { 2428 messageArr.push(messageText.charCodeAt(i)); 2429 } 2430 } 2431 return; 2432 }) 2433 .then(() => { 2434 let PromiseMacDoFinal = mac.doFinal(); 2435 return PromiseMacDoFinal; 2436 }) 2437 .then(output => { 2438 let macOutput = output; 2439 console.log("[Promise]: HMAC result: " + macOutput.data); 2440 let macLen = mac.getMacLength(); 2441 console.log("[Promise]: MAC len: " + macLen); 2442 }) 2443 .catch((error: BusinessError) => { 2444 console.error("[Promise]: error: " + error.message); 2445 }); 2446} 2447``` 2448 2449## Random Number 2450 2451### When to Use 2452 2453Typical random number operations involve the following: 2454 24551. Create a **Random** instance and specify the length (in bytes) of the random number to generate a secure random number of the specified length (ranging from **1** to **INT_MAX**). 24562. Set a seed based on the random number generated. 2457 2458### Available APIs 2459 2460For more information about the APIs, see [Crypto Framework](../reference/apis/js-apis-cryptoFramework.md). 2461 2462| Instance | API | Description | 2463| --------------- | ------------------------------------------------------------ | ------------------------------------------ | 2464| cryptoFramework | function createRandom() : Random; | Creates a **Random** instance. | 2465| Random | generateRandom(len : number, callback: AsyncCallback\<DataBlob>) : void; | Generates a random number. This API uses an asynchronous callback to return the result.| 2466| Random | generateRandom(len : number) : Promise\<DataBlob>; | Generates a random number. This API uses a promise to return the result. | 2467| Random | generateRandomSync(len: number): DataBlob; | Generates a random number of the specified length synchronously. | 2468| Random | setSeed(seed : DataBlob) : void; | Sets a seed. | 2469 2470### How to Develop 2471 24721. Use **createRandom()** to create a **Random** instance. 24732. Use **generateRandom()** to generate a random number of the given length. 24743. Use **setSeed()** to set a seed. 2475 2476```ts 2477import cryptoFramework from '@ohos.security.cryptoFramework'; 2478import { BusinessError } from '@ohos.base'; 2479 2480// Generate a random number in promise mode. 2481function doRandByPromise() { 2482 let rand = cryptoFramework.createRandom(); 2483 let len = 4; // Generate a 4-byte random number. 2484 let promiseGenerateRand = rand.generateRandom(len); 2485 promiseGenerateRand.then(randData => { 2486 console.info("[Promise]: rand result: " + randData.data); 2487 try { 2488 rand.setSeed(randData); 2489 } catch (error) { 2490 let e: BusinessError = error as BusinessError; 2491 console.error(`setSeed failed, ${e.code}, ${e.message}`); 2492 } 2493 }).catch((error: BusinessError) => { 2494 console.error("[Promise]: error: " + error.message); 2495 }); 2496} 2497 2498// Generate a random number in callback mode. 2499function doRandByCallback() { 2500 let rand = cryptoFramework.createRandom(); 2501 let len = 4; // Generate a 4-byte random number. 2502 rand.generateRandom(len, (err, randData) => { 2503 if (err) { 2504 console.error("[Callback]: err: " + err.code); 2505 } else { 2506 console.info("[Callback]: generate random result: " + randData.data); 2507 try { 2508 rand.setSeed(randData); 2509 } catch (error) { 2510 let e: BusinessError = error as BusinessError; 2511 console.error(`setSeed failed, ${e.code}, ${e.message}`); 2512 } 2513 } 2514 }); 2515} 2516 2517// Generate a random number synchronously. 2518function doRandBySync() { 2519 let rand = cryptoFramework.createRandom(); 2520 let len = 24; // Generate a 24-byte random number. 2521 try { 2522 let randData = rand.generateRandomSync(len); 2523 if (randData != null) { 2524 console.info("[Sync]: rand result: " + randData.data); 2525 } else { 2526 console.error("[Sync]: get rand result fail!"); 2527 } 2528 } catch (error) { 2529 let e: BusinessError = error as BusinessError; 2530 console.error(`do rand failed, ${e.code}, ${e.message}`); 2531 } 2532} 2533``` 2534