1 2# HUKS Development (ArkTS) 3 4> **NOTE** 5> 6> The SDK of API version 9 or later must be used. 7 8## Key Generation 9 10The OpenHarmony Universal KeyStore (HUKS) provides key management and cryptography operations for services. For a key generated by the HUKS, the plaintext will never be exposed outside throughout the lifecycle. No one can obtain the key in plaintext. Even the service itself can call APIs provided by the HUKS to perform operations on the key and obtain the operation result, but cannot access the key. 11 12**How to Develop** 13 14Use [huks.generateKeyItem(keyAlias,options,callback)](../reference/apis/js-apis-huks.md#huksgeneratekeyitem9) to generate a key. You need to pass in the key alias in **keyAlias**, key property set in **options**, and **callback** to return the result asynchronously. For details about the APIs, see [HUKS](../reference/apis/js-apis-huks.md). 15 16**Procedure** 171. Set the key alias. 182. Initialize the key property set.<br>Use [HuksParam](../reference/apis/js-apis-huks.md#huksparam) to encapsulate key properties and use a **HuksParam** array to assign values to the **properties** field of [HuksOptions](../reference/apis/js-apis-huks.md#huksoptions). The parameters [HuksKeyAlg](../reference/apis/js-apis-huks.md#hukskeyalg), [HuksKeySize](../reference/apis/js-apis-huks.md#hukskeysize), and [HuksKeyPurpose](../reference/apis/js-apis-huks.md#hukskeypurpose) are mandatory. 193. Pass in the key alias and key parameter set to generate a key. 20 21> **NOTE** 22> 23> The key alias cannot exceed 64 bytes. 24 25**Sample code** 26 27```ts 28/* 29 * Generate a DH key using callback-based APIs. 30 */ 31import huks from '@ohos.security.huks'; 32import { BusinessError } from '@ohos.base'; 33 34class HuksProperties { 35 tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM; 36 value: huks.HuksKeyAlg | huks.HuksKeySize | huks.HuksKeyPurpose | huks.HuksKeyDigest = huks.HuksKeyAlg.HUKS_ALG_ECC; 37} 38 39/* 40 * Set the key alias and encapsulate the key properties. 41 */ 42let keyAlias = 'dh_key'; 43let properties1: HuksProperties[] = [ 44 { 45 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 46 value: huks.HuksKeyAlg.HUKS_ALG_DH 47 }, 48 { 49 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 50 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE 51 }, 52 { 53 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 54 value: huks.HuksKeySize.HUKS_DH_KEY_SIZE_2048 55 }, 56 { 57 tag: huks.HuksTag.HUKS_TAG_DIGEST, 58 value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256 59 } 60]; 61 62let huksOptions: huks.HuksOptions = { 63 properties: properties1, 64 inData: new Uint8Array(new Array()) 65} 66 67/* 68 * Generate a key. 69 */ 70function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions){ 71 return new Promise<void>((resolve, reject) => { 72 try { 73 huks.generateKeyItem(keyAlias, huksOptions, (error, data) => { 74 if (error) { 75 reject(error); 76 } else { 77 resolve(data); 78 } 79 }); 80 } catch (error) { 81 throw (error as Error); 82 } 83 }); 84} 85 86async function publicGenKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 87 console.info(`enter callback generateKeyItem`); 88 try { 89 await generateKeyItem(keyAlias, huksOptions) 90 .then((data) => { 91 console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`); 92 }) 93 .catch((error: BusinessError) => { 94 console.error(`callback: generateKeyItem failed`); 95 }); 96 } catch (error) { 97 console.error(`callback: generateKeyItem input arg invalid`); 98 } 99} 100 101async function TestGenKey() { 102 await publicGenKeyFunc(keyAlias, huksOptions); 103} 104``` 105 106## Key Import 107 108A key generated outside the HUKS (for example, generated through key agreement or by a server) can be imported to the HUKS for management. The HUKS supports import of keys in plaintext. However, if a key is imported in plaintext, the key is exposed in the Rich Execution Environment (REE) memory. This type of import applies to lightweight devices or security-insensitive services. For security-sensitive services, use the secure import feature provided by the HUKS. Secure import allows the keys generated for services to be transferred to the HUKS through an end-to-end encrypted transmission channel. 109 110Once a key is imported to the HUKS, its plaintext will never be exposed outside the HUKS throughout the lifecycle of the key. 111 112### Importing a Key in Plaintext 113 114Use [huks.importKeyItem(keyAlias,options,callback)](../reference/apis/js-apis-huks.md#huksimportkeyitem9) to import a key in plaintext. You need to pass in the key alias in **keyAlias**, key material and property set in **options**, and **callback** to return the result asynchronously. For details about the APIs, see [HUKS](../reference/apis/js-apis-huks.md). 115 1161. Set the key alias. 1172. Encapsulate the key material and key property set.<br>The key material must comply with [HUKS key material formats](./huks-appendix.md#key-material-formats). The **inData** value of [HuksOptions](../reference/apis/js-apis-huks.md#huksoptions) must be in the Uint8Array format. Encapsulate key properties in [HuksParam](../reference/apis/js-apis-huks.md#huksparam), and use a **HuksParam** array to assign values to the **properties** field. The key properties must contain [HuksKeyAlg](../reference/apis/js-apis-huks.md#hukskeyalg), [HuksKeySize](../reference/apis/js-apis-huks.md#hukskeysize), and [HuksKeyPurpose](../reference/apis/js-apis-huks.md#hukskeypurpose). 1183. Import the key. 119 120**Sample code** 121 122```ts 123import huks from '@ohos.security.huks' 124 125/* 126 /* Import an AES key of 256 bits. */ 127 */ 128 129/* Key */ 130let plainTextSize32 = new Uint8Array([ 131 0xfb, 0x8b, 0x9f, 0x12, 0xa0, 0x83, 0x19, 0xbe, 0x6a, 0x6f, 0x63, 0x2a, 0x7c, 0x86, 0xba, 0xca, 132 0x64, 0x0b, 0x88, 0x96, 0xe2, 0xfa, 0x77, 0xbc, 0x71, 0xe3, 0x0f, 0x0f, 0x9e, 0x3c, 0xe5, 0xf9 133]); 134 135/* 136 * Set the key alias. 137 */ 138let keyAlias = 'AES256Alias_sample'; 139 140/* 141 * Encapsulate the key properties and key material. 142 */ 143class propertyType { 144 tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM; 145 value: huks.HuksKeyAlg | huks.HuksKeySize | huks.HuksKeyPurpose = huks.HuksKeyAlg.HUKS_ALG_RSA; 146} 147 148let properties: propertyType[] = [ 149 { 150 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 151 value:huks.HuksKeyAlg.HUKS_ALG_AES 152 }, 153 { 154 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 155 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 156 }, 157 { 158 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 159 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT 160 }, 161] 162 163let options: huks.HuksOptions = { 164 properties: properties, 165 inData: plainTextSize32 166}; 167 168/* 169 * Import the key. 170 */ 171try { 172 huks.importKeyItem(keyAlias, options, (error, data) => { 173 if (error) { 174 console.error(`callback: importKeyItem failed`); 175 } else { 176 console.info(`callback: importKeyItem success`); 177 } 178 }); 179} catch (error) { 180 console.error(`callback: importKeyItem input arg invalid`); 181} 182``` 183 184**Verification** 185 186Check whether the key exists. If yes, the key is imported successfully. 187 188**Sample code** 189 190```ts 191import huks from '@ohos.security.huks'; 192 193let keyAlias = 'AES256Alias_sample'; 194let isKeyExist = false; 195 196class keyPropertyType { 197 tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM; 198 value: huks.HuksKeyAlg = huks.HuksKeyAlg.HUKS_ALG_RSA; 199} 200 201let keyProperties: keyPropertyType[] = [ 202 { 203 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 204 value: huks.HuksKeyAlg.HUKS_ALG_AES 205 }, 206] 207 208let huksOptions: huks.HuksOptions = { 209 properties: keyProperties, // It cannot be empty. 210 inData: new Uint8Array(new Array()) // It cannot be empty. 211} 212try { 213 huks.isKeyItemExist(keyAlias, huksOptions, (error, data) => { 214 if (error) { 215 console.error(`callback: isKeyItemExist failed`); 216 } else { 217 if (data !== null && data.valueOf() !== null) { 218 isKeyExist = data.valueOf(); 219 console.info(`callback: isKeyItemExist success, isKeyExist = ${isKeyExist}`); 220 } 221 } 222 }); 223} catch (error) { 224 console.error(`callback: isKeyItemExist input arg invalid`); 225} 226``` 227 228### Importing a Key Securely 229 230Compared with import of a key in plaintext, secure import involves more complex key material and operations. The following figure illustrates the basic development process of secure import. 231 232**Figure 1** Development process of secure import 233 234 235 236**Available APIs** 237 238You need to use the APIs listed in the following table in sequence. 239 240**Table 1** APIs for importing a key securely 241 242| API | Description | 243| -------------------------------------- | ----------------------------| 244|generateKeyItem(keyAlias: string, options: HuksOptions, callback: AsyncCallback\<void>) : void| Generates a key.| 245|exportKeyItem(keyAlias: string, options: HuksOptions, callback: AsyncCallback\<HuksReturnResult>) : void| Exports the public key of a key pair.| 246|importWrappedKeyItem(keyAlias: string, wrappingKeyAlias: string, options: HuksOptions, callback: AsyncCallback\<void>) : void|Imports a wrapped key.| 247|deleteKeyItem(keyAlias: string, options: HuksOptions, callback: AsyncCallback\<void>) : void|Deletes a key.| 248 249>**NOTE** 250> 251>The public key plaintext material returned by **exportKeyItem()** is encapsulated in X.509 format, and the key material to be imported by **importWrappedKeyItem()** must be encapsulated in **Length<sub>Data</sub>-Data** format. Specifically, the application needs to request a Uint8Array and encapsulate the Uint8Array in the sequence listed in the following table. 252 253**Table 2** Format of the encrypted key material 254 255| Content| Public Key Length (L<sub>pk2</sub>)| Public Key (pk2)| k2 AAD Length (L<sub>AAD2</sub>)| k2 AAD (AAD2)| k2 Nonce Length (L<sub>Nonce2</sub>)| k2 Nonce (Nonce2)| 256| :--: |:----:|:----: |:----: | :----: | :----:|:----:| 257|Length| 4 bytes|L<sub>pk2</sub> bytes| 4 bytes| L<sub>AAD2</sub> bytes| 4 bytes| L<sub>Nonce2</sub> bytes| 258| Content| k2 AEAD Length (L<sub>AEAD2</sub>)| k2 AEAD (AEAD2)| k3 Ciphertext Length (L<sub>k3_enc</sub>)| k3 Ciphertext (k3_enc)| k3 AAD Length (L<sub>AAD3</sub>)| k3 AAD (AAD3)| 259|Length| 4 bytes|L<sub>AEAD2</sub> bytes| 4 bytes| L<sub>k3_enc</sub> bytes| 4 bytes| L<sub>AAD3</sub> bytes| 260| Content| k3 Nonce Length (L<sub>Nonce3</sub>)| k3 Nonce (Nonce3)| k3 AEAD Length (L<sub>AEAD3</sub>)| k3 AEAD (AEAD3)| Length of **k1'_size** (L<sub>k1'_size</sub>)| Key Plaintext Material Length (k1'_size)| 261|Length| 4 bytes|L<sub>Nonce3</sub> bytes| 4 bytes| L<sub>AEAD3</sub> bytes| 4 bytes| L<sub>k1'_size</sub> bytes| 262|Content|k1' Ciphertext Length (L<sub>k1'_enc</sub>)| k1' ciphertext (k1'_enc) | | | | | 263|Length| 4 bytes|L<sub>k1'_enc</sub> bytes| | | | | 264 265**How to Develop** 266 267The following example presents the development involving HUKS APIs (using the ECDH key agreement suite). The operations performed by the service are not included. 268 2691. Generate the **Caller_Key** and **Wrapping_Key** asymmetric key pairs. 2702. Export the public key material. 2713. Generate a symmetric key **Caller_Kek**. 2724. Perform key agreement using the public keys of **Caller_Key** and **Wrapping_Key** to obtain the **Agree_Key**. 2735. Use **Caller_Kek** to encrypt the key to be imported. 2746. Use **Agree_Key** to encrypt **Caller_Kek**. 2757. Encapsulate the key material to be imported. 2768. Import the encapsulated key material. 2779. Delete the keys that are used for secure import. 278 279**Sample code** 280 281```ts 282import { expect } from '@ohos/hypium'; 283import huks from '@ohos.security.huks'; 284import { BusinessError } from '@ohos.base'; 285 286let IV = '0000000000000000'; 287let AAD = "abababababababab"; 288let NONCE = "hahahahahaha"; 289let TAG_SIZE = 16; 290let FILED_LENGTH = 4; 291let importedAes192PlainKey = "The aes192 key to import"; 292let callerAes256Kek = "The is kek to encrypt aes192 key"; 293 294let callerKeyAlias = "test_caller_key_ecdh_aes192"; 295let callerKekAliasAes256 = "test_caller_kek_ecdh_aes256"; 296let callerAgreeKeyAliasAes256 = "test_caller_agree_key_ecdh_aes256"; 297let importedKeyAliasAes192 = "test_import_key_ecdh_aes192"; 298 299let huksPubKey: Uint8Array; 300let callerSelfPublicKey: Uint8Array; 301let outSharedKey: Uint8Array; 302let outPlainKeyEncData: Uint8Array; 303let outKekEncData: Uint8Array; 304let outKekEncTag: Uint8Array; 305let outAgreeKeyEncTag: Uint8Array; 306 307let mask = [0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000]; 308function subUint8ArrayOf(arrayBuf: Uint8Array, start: number, end: number) { 309 let arr: number[] = []; 310 for (let i = start; i < end && i < arrayBuf.length; ++i) { 311 arr.push(arrayBuf[i]); 312 } 313 return new Uint8Array(arr); 314} 315 316function stringToUint8Array(str: string) { 317 let arr: number[] = []; 318 for (let i = 0, j = str.length; i < j; ++i) { 319 arr.push(str.charCodeAt(i)); 320 } 321 return new Uint8Array(arr); 322} 323 324function assignLength(length: number, arrayBuf: Uint8Array, startIndex: number) { 325 let index = startIndex; 326 for (let i = 0; i < 4; i++) { 327 arrayBuf[index++] = (length & mask[i]) >> (i * 8); 328 } 329 return 4; 330} 331 332function assignData(data: Uint8Array, arrayBuf: Uint8Array, startIndex: number) { 333 let index = startIndex; 334 for (let i = 0; i < data.length; i++) { 335 arrayBuf[index++] = data[i]; 336 } 337 return data.length; 338} 339 340 341let genWrappingKeyParams:huks.HuksOptions = { 342 properties: new Array<huks.HuksParam>( 343 { 344 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 345 value: huks.HuksKeyAlg.HUKS_ALG_ECC 346 }, 347 { 348 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 349 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_UNWRAP 350 }, 351 { 352 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 353 value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256 354 }, 355 { 356 tag: huks.HuksTag.HUKS_TAG_PADDING, 357 value: huks.HuksKeyPadding.HUKS_PADDING_NONE 358 } 359 ) 360} 361 362let genCallerEcdhParams:huks.HuksOptions = { 363 properties: new Array<huks.HuksParam>( 364 { 365 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 366 value: huks.HuksKeyAlg.HUKS_ALG_ECC 367 }, 368 { 369 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 370 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE 371 }, 372 { 373 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 374 value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256 375 } 376 ) 377} 378 379let importParamsCallerKek: huks.HuksOptions = { 380 properties: new Array<huks.HuksParam>( 381 { 382 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 383 value: huks.HuksKeyAlg.HUKS_ALG_AES 384 }, 385 { 386 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 387 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT 388 }, 389 { 390 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 391 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 392 }, 393 { 394 tag: huks.HuksTag.HUKS_TAG_PADDING, 395 value: huks.HuksKeyPadding.HUKS_PADDING_NONE 396 }, 397 { 398 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 399 value: huks.HuksCipherMode.HUKS_MODE_GCM 400 }, 401 { 402 tag: huks.HuksTag.HUKS_TAG_DIGEST, 403 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE 404 }, 405 { 406 tag: huks.HuksTag.HUKS_TAG_IV, 407 value: stringToUint8Array(IV) 408 } 409 ), 410 inData: stringToUint8Array(callerAes256Kek) 411} 412 413let importParamsAgreeKey: huks.HuksOptions = { 414 properties: new Array<huks.HuksParam>( 415 { 416 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 417 value: huks.HuksKeyAlg.HUKS_ALG_AES 418 }, 419 { 420 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 421 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT 422 }, 423 { 424 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 425 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 426 }, 427 { 428 tag: huks.HuksTag.HUKS_TAG_PADDING, 429 value: huks.HuksKeyPadding.HUKS_PADDING_NONE 430 }, 431 { 432 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 433 value: huks.HuksCipherMode.HUKS_MODE_GCM 434 }, 435 { 436 tag: huks.HuksTag.HUKS_TAG_DIGEST, 437 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE 438 }, 439 { 440 tag: huks.HuksTag.HUKS_TAG_IV, 441 value: stringToUint8Array(IV) 442 } 443 ), 444} 445 446let callerAgreeParams: huks.HuksOptions = { 447 properties: new Array<huks.HuksParam>( 448 { 449 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 450 value: huks.HuksKeyAlg.HUKS_ALG_ECDH 451 }, 452 { 453 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 454 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE 455 }, 456 { 457 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 458 value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256 459 } 460 ) 461} 462 463let encryptKeyCommonParams: huks.HuksOptions = { 464 properties: new Array<huks.HuksParam>( 465 { 466 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 467 value: huks.HuksKeyAlg.HUKS_ALG_AES 468 }, 469 { 470 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 471 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT 472 }, 473 { 474 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 475 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 476 }, 477 { 478 tag: huks.HuksTag.HUKS_TAG_PADDING, 479 value: huks.HuksKeyPadding.HUKS_PADDING_NONE 480 }, 481 { 482 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 483 value: huks.HuksCipherMode.HUKS_MODE_GCM 484 }, 485 { 486 tag: huks.HuksTag.HUKS_TAG_NONCE, 487 value: stringToUint8Array(NONCE) 488 }, 489 { 490 tag: huks.HuksTag.HUKS_TAG_ASSOCIATED_DATA, 491 value: stringToUint8Array(AAD) 492 } 493 ), 494} 495 496let importWrappedAes192Params: huks.HuksOptions = { 497 properties: new Array<huks.HuksParam>( 498 { 499 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 500 value: huks.HuksKeyAlg.HUKS_ALG_AES 501 }, 502 { 503 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 504 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | 505 huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT 506 }, 507 { 508 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 509 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_192 510 }, 511 { 512 tag: huks.HuksTag.HUKS_TAG_PADDING, 513 value: huks.HuksKeyPadding.HUKS_PADDING_NONE 514 }, 515 { 516 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 517 value: huks.HuksCipherMode.HUKS_MODE_CBC 518 }, 519 { 520 tag: huks.HuksTag.HUKS_TAG_DIGEST, 521 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE 522 }, 523 { 524 tag: huks.HuksTag.HUKS_TAG_UNWRAP_ALGORITHM_SUITE, 525 value: huks.HuksUnwrapSuite.HUKS_UNWRAP_SUITE_ECDH_AES_256_GCM_NOPADDING 526 }, 527 { 528 tag: huks.HuksTag.HUKS_TAG_IV, 529 value: stringToUint8Array(IV) 530 } 531 ) 532} 533 534async function publicGenerateItemFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 535 console.info(`enter promise generateKeyItem`); 536 try { 537 await huks.generateKeyItem(keyAlias, huksOptions) 538 .then(data => { 539 console.info(`promise: generateKeyItem success, data = ${JSON.stringify(data)}`); 540 }) 541 .catch((err: BusinessError) => { 542 console.error(`callback: generateKeyItem failed`); 543 expect(null).assertFail(); 544 }) 545 } catch (err) { 546 console.error(`callback: generateKeyItem invalid`); 547 expect(null).assertFail(); 548 } 549} 550 551async function publicImportKeyItemFunc(keyAlias: string, HuksOptions: huks.HuksOptions) { 552 console.info(`enter promise importKeyItem`); 553 try { 554 await huks.importKeyItem(keyAlias, HuksOptions) 555 .then(data => { 556 console.info(`promise: importKeyItem success, data = ${JSON.stringify(data)}`); 557 }).catch((err: BusinessError) => { 558 console.error(`promise: importKeyItem failed`); 559 expect(null).assertFail(); 560 }) 561 } catch (err) { 562 console.error(`promise: importKeyItem input arg invalid`); 563 expect(null).assertFail(); 564 } 565} 566 567async function publicDeleteKeyItemFunc(KeyAlias: string, HuksOptions: huks.HuksOptions) { 568 console.info(`enter promise deleteKeyItem`); 569 try { 570 await huks.deleteKeyItem(KeyAlias, HuksOptions) 571 .then(data => { 572 console.info(`promise: deleteKeyItem key success, data = ${JSON.stringify(data)}`); 573 }) 574 .catch((err: BusinessError) => { 575 console.error(`promise: deleteKeyItem failed`); 576 expect(null).assertFail(); 577 }) 578 } catch (err) { 579 console.error(`promise: deleteKeyItem input arg invalid`); 580 expect(null).assertFail(); 581 } 582} 583 584function importWrappedKeyItem(keyAlias: string, wrappingKeyAlias: string, huksOptions: huks.HuksOptions) { 585 return new Promise<void>((resolve, reject) => { 586 try { 587 huks.importWrappedKeyItem(keyAlias, wrappingKeyAlias, huksOptions, (error, data) => { 588 if (error) { 589 reject(error); 590 } else { 591 resolve(data); 592 } 593 }); 594 } catch (error) { 595 expect(null).assertFail(); 596 } 597 }); 598} 599 600async function publicImportWrappedKeyFunc(keyAlias: string, wrappingKeyAlias: string, huksOptions: huks.HuksOptions) { 601 console.info(`enter callback importWrappedKeyItem`); 602 for (let i = 0; i < huksOptions.inData!.length; i++) { 603 console.error(`${i}: ${huksOptions.inData![i]}`); 604 } 605 try { 606 await importWrappedKeyItem(keyAlias, wrappingKeyAlias, huksOptions) 607 .then((data) => { 608 console.info(`callback: importWrappedKeyItem success, data = ${JSON.stringify(data)}`); 609 }) 610 .catch((error: BusinessError) => { 611 console.error(`callback: importWrappedKeyItem failed`); 612 expect(null).assertFail(); 613 }); 614 } catch (error) { 615 console.error(`callback: importWrappedKeyItem input arg invalid`); 616 expect(null).assertFail(); 617 } 618} 619 620async function publicImportWrappedKeyPromise(keyAlias: string, wrappingKeyAlias: string, huksOptions: huks.HuksOptions) { 621 console.info(`enter callback importWrappedKeyItem`); 622 try { 623 await huks.importWrappedKeyItem(keyAlias, wrappingKeyAlias, huksOptions) 624 .then((data) => { 625 console.info(`callback: importWrappedKeyItem success, data = ${JSON.stringify(data)}`); 626 }) 627 .catch((error: BusinessError) => { 628 console.error(`callback: importWrappedKeyItem failed`); 629 expect(null).assertFail(); 630 }); 631 } catch (error) { 632 console.error(`callback: importWrappedKeyItem input arg invalid`); 633 expect(null).assertFail(); 634 } 635} 636 637async function publicInitFunc(srcKeyAlias: string, HuksOptions: huks.HuksOptions) { 638 let handle: number = 0; 639 console.info(`enter promise doInit`); 640 try { 641 await huks.initSession(srcKeyAlias, HuksOptions) 642 .then((data) => { 643 console.info(`promise: doInit success, data = ${JSON.stringify(data)}`); 644 handle = data.handle; 645 }) 646 .catch((error: BusinessError) => { 647 console.error(`promise: doInit key failed`); 648 expect(null).assertFail(); 649 }); 650 } catch (error) { 651 console.error(`promise: doInit input arg invalid`); 652 expect(null).assertFail(); 653 } 654 return handle; 655} 656 657async function publicUpdateSessionFunction(handle: number, HuksOptions: huks.HuksOptions) { 658 const maxUpdateSize = 64; 659 const inData = HuksOptions.inData!; 660 const lastInDataPosition = inData.length - 1; 661 let inDataSegSize = maxUpdateSize; 662 let inDataSegPosition = 0; 663 let isFinished = false; 664 let outData: number[] = []; 665 666 while (inDataSegPosition <= lastInDataPosition) { 667 if (inDataSegPosition + maxUpdateSize > lastInDataPosition) { 668 isFinished = true; 669 inDataSegSize = lastInDataPosition - inDataSegPosition + 1; 670 console.error(`enter promise doUpdate`); 671 break; 672 } 673 HuksOptions.inData = new Uint8Array( 674 Array.from(inData).slice(inDataSegPosition, inDataSegPosition + inDataSegSize) 675 ); 676 console.error(`enter promise doUpdate`); 677 try { 678 await huks.updateSession(handle, HuksOptions) 679 .then((data) => { 680 console.error(`promise: doUpdate success, data = ${JSON.stringify(data)}`); 681 outData = outData.concat(Array.from(data.outData!)); 682 }) 683 .catch((error: BusinessError) => { 684 console.error(`promise: doUpdate failed`); 685 expect(null).assertFail(); 686 }); 687 } catch (error) { 688 console.error(`promise: doUpdate input arg invalid`); 689 expect(null).assertFail(); 690 } 691 if ((!isFinished) && (inDataSegPosition + maxUpdateSize > lastInDataPosition)) { 692 console.log(`update size invalid isFinished = ${isFinished}`); 693 console.log(`inDataSegPosition = ${inDataSegPosition}`); 694 console.log(`lastInDataPosition = ${lastInDataPosition}`); 695 expect(null).assertFail(); 696 return; 697 } 698 inDataSegPosition += maxUpdateSize; 699 } 700 return outData; 701} 702 703async function publicFinishSession(handle: number, HuksOptions: huks.HuksOptions, inData: number[]) { 704 let outData: number[] = []; 705 console.info(`enter promise doFinish`); 706 try { 707 await huks.finishSession(handle, HuksOptions) 708 .then((data) => { 709 console.info(`promise: doFinish success, data = ${JSON.stringify(data)}`); 710 outData = inData.concat(Array.from(data.outData!)); 711 }) 712 .catch((error: BusinessError) => { 713 console.error(`promise: doFinish key failed`); 714 expect(null).assertFail(); 715 }); 716 } catch (error) { 717 console.error(`promise: doFinish input arg invalid`); 718 expect(null).assertFail(); 719 } 720 return new Uint8Array(outData); 721} 722 723async function cipherFunction(keyAlias: string, HuksOptions: huks.HuksOptions) { 724 let handle = await publicInitFunc(keyAlias, HuksOptions); 725 let tmpData = await publicUpdateSessionFunction(handle, HuksOptions); 726 let outData = await publicFinishSession(handle, HuksOptions, tmpData!); 727 return outData; 728} 729 730async function agreeFunction(keyAlias: string, HuksOptions: huks.HuksOptions, huksPublicKey: Uint8Array) { 731 let handle = await publicInitFunc(keyAlias, HuksOptions); 732 let outSharedKey: Uint8Array = new Uint8Array; 733 HuksOptions.inData = huksPublicKey; 734 console.error(`enter promise doUpdate`); 735 try { 736 await huks.updateSession(handle, HuksOptions) 737 .then((data) => { 738 console.error(`promise: doUpdate success, data = ${JSON.stringify(data)}`); 739 }) 740 .catch((error: BusinessError) => { 741 console.error(`promise: doUpdate failed`); 742 expect(null).assertFail(); 743 }); 744 } catch (error) { 745 console.error(`promise: doUpdate input arg invalid`); 746 expect(null).assertFail(); 747 } 748 console.info(`enter promise doInit`); 749 try { 750 await huks.finishSession(handle, HuksOptions) 751 .then((data) => { 752 console.info(`promise: doInit success, data = ${JSON.stringify(data)}`); 753 outSharedKey = data.outData as Uint8Array; 754 }) 755 .catch((error: BusinessError) => { 756 console.error(`promise: doInit key failed`); 757 expect(null).assertFail(); 758 }); 759 } catch (error) { 760 console.error(`promise: doInit input arg invalid`); 761 expect(null).assertFail(); 762 } 763 return outSharedKey; 764} 765 766async function ImportKekAndAgreeSharedSecret(callerKekAlias: string, importKekParams: huks.HuksOptions, callerKeyAlias: string, huksPublicKey: Uint8Array, agreeParams: huks.HuksOptions) { 767 await publicImportKeyItemFunc(callerKekAlias, importKekParams); 768 outSharedKey = await agreeFunction(callerKeyAlias, agreeParams, huksPublicKey); 769 770 importParamsAgreeKey.inData = outSharedKey; 771 await publicImportKeyItemFunc(callerAgreeKeyAliasAes256, importParamsAgreeKey); 772} 773 774async function generateAndExportPublicKey(keyAlias: string, HuksOptions: huks.HuksOptions, caller: Boolean) { 775 await publicGenerateItemFunc(keyAlias, HuksOptions); 776 try { 777 await huks.exportKeyItem(keyAlias, HuksOptions) 778 .then((data) => { 779 console.info(`promise: exportKeyItem success, data = ${JSON.stringify(data)}`); 780 if (caller) { 781 callerSelfPublicKey = data.outData as Uint8Array; 782 } else { 783 huksPubKey = data.outData as Uint8Array; 784 } 785 }) 786 .catch((error: BusinessError) => { 787 console.error(`promise: exportKeyItem failed`); 788 expect(null).assertFail(); 789 }); 790 } catch (e) { 791 console.error(`promise: generate pubKey failed`); 792 expect(null).assertFail(); 793 } 794} 795 796async function EncryptImportedPlainKeyAndKek(keyAlias: string) { 797 encryptKeyCommonParams.inData = stringToUint8Array(keyAlias) 798 let plainKeyEncData = await cipherFunction(callerKekAliasAes256, encryptKeyCommonParams); 799 outKekEncTag = subUint8ArrayOf(plainKeyEncData, plainKeyEncData.length - TAG_SIZE, plainKeyEncData.length) 800 outPlainKeyEncData = subUint8ArrayOf(plainKeyEncData, 0, plainKeyEncData.length - TAG_SIZE) 801 802 encryptKeyCommonParams.inData = stringToUint8Array(callerAes256Kek) 803 let kekEncData = await cipherFunction(callerAgreeKeyAliasAes256, encryptKeyCommonParams) 804 outAgreeKeyEncTag = subUint8ArrayOf(kekEncData, kekEncData.length - TAG_SIZE, kekEncData.length) 805 outKekEncData = subUint8ArrayOf(kekEncData, 0, kekEncData.length - TAG_SIZE) 806} 807 808async function BuildWrappedDataAndImportWrappedKey(plainKey: string) { 809 let plainKeySizeBuff = new Uint8Array(4); 810 assignLength(plainKey.length, plainKeySizeBuff, 0); 811 812 let wrappedData = new Uint8Array( 813 FILED_LENGTH + huksPubKey.length + 814 FILED_LENGTH + AAD.length + 815 FILED_LENGTH + NONCE.length + 816 FILED_LENGTH + TAG_SIZE + 817 FILED_LENGTH + outKekEncData.length + 818 FILED_LENGTH + AAD.length + 819 FILED_LENGTH + NONCE.length + 820 FILED_LENGTH + TAG_SIZE + 821 FILED_LENGTH + plainKeySizeBuff.length + 822 FILED_LENGTH + outPlainKeyEncData.length 823 ); 824 let index = 0; 825 let AADUint8Array = stringToUint8Array(AAD); 826 let NonceArray = stringToUint8Array(NONCE); 827 828 index += assignLength(callerSelfPublicKey.length, wrappedData, index); // 4 829 index += assignData(callerSelfPublicKey, wrappedData, index); // 91 830 index += assignLength(AADUint8Array.length, wrappedData, index); // 4 831 index += assignData(AADUint8Array, wrappedData, index); // 16 832 index += assignLength(NonceArray.length, wrappedData, index); // 4 833 index += assignData(NonceArray, wrappedData, index); // 12 834 index += assignLength(outAgreeKeyEncTag.length, wrappedData, index); // 4 835 index += assignData(outAgreeKeyEncTag, wrappedData, index); // 16 836 index += assignLength(outKekEncData.length, wrappedData, index); // 4 837 index += assignData(outKekEncData, wrappedData, index); // 32 838 index += assignLength(AADUint8Array.length, wrappedData, index); // 4 839 index += assignData(AADUint8Array, wrappedData, index); // 16 840 index += assignLength(NonceArray.length, wrappedData, index); // 4 841 index += assignData(NonceArray, wrappedData, index); // 12 842 index += assignLength(outKekEncTag.length, wrappedData, index); // 4 843 index += assignData(outKekEncTag, wrappedData, index); // 16 844 index += assignLength(plainKeySizeBuff.length, wrappedData, index); // 4 845 index += assignData(plainKeySizeBuff, wrappedData, index); // 4 846 index += assignLength(outPlainKeyEncData.length, wrappedData, index); // 4 847 index += assignData(outPlainKeyEncData, wrappedData, index); // 24 848 849 return wrappedData; 850} 851 852async function ImportWrappedKey() { 853 const srcKeyAliesWrap = 'HUKS_Basic_Capability_Import_0200'; 854 /* 855 * Generate Caller_Key and Wrapping_Key, which are used to agree on a key for encrypting the key to be imported, and export the public key materials. 856 */ 857 await generateAndExportPublicKey(srcKeyAliesWrap, genWrappingKeyParams, false); 858 await generateAndExportPublicKey(callerKeyAlias, genCallerEcdhParams, true); 859 860 /** 861 * Generate a symmetric key **Caller_Kek**. 862 * Perform key agreement using the public keys of **Caller_Key** and **Wrapping_Key** to obtain the **Agree_Key**. 863 */ 864 await ImportKekAndAgreeSharedSecret(callerKekAliasAes256, importParamsCallerKek, callerKeyAlias, huksPubKey, callerAgreeParams); 865 866 /** 867 * Use **Caller_Kek** to encrypt the key to be imported. 868 * Use **Agree_Key** to encrypt **Caller_Kek**. 869 */ 870 await EncryptImportedPlainKeyAndKek(importedAes192PlainKey); 871 872 /** 873 * Encapsulate the key materials to be imported. 874 */ 875 let wrappedData = await BuildWrappedDataAndImportWrappedKey(importedAes192PlainKey); 876 importWrappedAes192Params.inData = wrappedData; 877 878 /** 879 * Import the encapsulated key material. 880 */ 881 await publicImportWrappedKeyFunc(importedKeyAliasAes192, srcKeyAliesWrap, importWrappedAes192Params); 882 883 /** 884 * Delete the key used for secure import. 885 */ 886 await publicDeleteKeyItemFunc(srcKeyAliesWrap, genWrappingKeyParams); 887 await publicDeleteKeyItemFunc(callerKeyAlias, genCallerEcdhParams); 888 await publicDeleteKeyItemFunc(importedKeyAliasAes192, importWrappedAes192Params); 889 await publicDeleteKeyItemFunc(callerKekAliasAes256, callerAgreeParams); 890} 891``` 892 893**Verification** 894 895Check whether the key exists. If yes, the key is imported successfully. 896 897**Sample code** 898 899```ts 900import huks from '@ohos.security.huks'; 901 902/* 903 * Set the key alias and encapsulate the key properties. 904 */ 905let keyAlias = 'test_import_key_ecdh_aes192'; 906let isKeyExist:Boolean; 907 908let keyProperties: Array<huks.HuksParam> = new Array(); 909keyProperties[0] = { 910 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 911 value: huks.HuksKeyAlg.HUKS_ALG_AES, 912} 913let huksOptions:huks.HuksOptions = { 914 properties: keyProperties, // It cannot be empty. 915 inData: new Uint8Array(new Array()) // It cannot be empty. 916} 917try { 918 huks.isKeyItemExist(keyAlias, huksOptions, (error, data)=> { 919 if (error) { 920 console.error(`callback: isKeyItemExist failed`); 921 } else { 922 if (data !== null && data.valueOf() !== null) { 923 isKeyExist = data.valueOf(); 924 console.info(`callback: isKeyItemExist success, isKeyExist = ${isKeyExist}`); 925 } 926 } 927 }); 928} catch (error) { 929 console.error(`callback: isKeyItemExist input arg invalid`); 930} 931``` 932 933## Common Key Operations 934 935**When to Use** 936 937To ensure data confidentiality and integrity, you may need to encrypt or decrypt data, generate or verify a signature, perform key agreement, and derive a key. The following describes common key operations. The following examples do not involve secondary identity access control. If secondary identity access control is involved, see [Key Access Control](#key-access-control). 938 939**General Development Process** 940 941The HUKS operates data based on key sessions. The general process is as follows: 942 9431. (Mandatory) Use [huks.initSession()](../reference/apis/js-apis-huks.md#huksinitsession9) to initialize a key session.<br>You need to pass in the key alias and key operation parameters to initialize a key session, and obtain the session handle. The key operation parameters must contain the parameters required by the cipher algorithm, including the cipher algorithm, key size, key purpose, working mode, padding mode, hash mode, IV, nonce, and AAD. If access control is set for the key, other parameters are required. For details, see [Key Access Control](#key-access-control). 9442. (Optional) Use [huks.updateSession()](../reference/apis/js-apis-huks.md#huksupdatesession9) to pass in data by segment. Perform this step only if the data exceeds 100 KB or the cryptographic algorithm requires operations by data segment. Otherwise, skip this step. 9453. (Mandatory) Use [huks.finishSession()](../reference/apis/js-apis-huks.md#huksfinishsession9) to complete the key session operation.<br>Pass in the last data segment and complete the key session operation. If an error occurs during the process or the data passed in is not required, use [huks.abortSession()](../reference/apis/js-apis-huks.md#huksabortsession9) to abort the session. 946 947### Encryption and Decryption 948 949```ts 950/* 951 * The following uses an AES 128-bit key and callback-based APIs as an example. 952 */ 953import huks from '@ohos.security.huks'; 954import { BusinessError } from '@ohos.base'; 955 956let aesKeyAlias = 'test_aesKeyAlias'; 957let handle:number; 958let plainText = '123456'; 959let IV = '001122334455'; 960let cipherData:Uint8Array; 961 962function StringToUint8Array(str: String) { 963 let arr:number[]=new Array(); 964 for (let i = 0, j = str.length; i < j; ++i) { 965 arr.push(str.charCodeAt(i)); 966 } 967 return new Uint8Array(arr); 968} 969 970function Uint8ArrayToString(fileData:Uint8Array) { 971 let dataString = ''; 972 for (let i = 0; i < fileData.length; i++) { 973 dataString += String.fromCharCode(fileData[i]); 974 } 975 return dataString; 976} 977 978function GetAesGenerateProperties() { 979 let properties: Array<huks.HuksParam> = new Array(); 980 let index = 0; 981 properties[index++] = { 982 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 983 value: huks.HuksKeyAlg.HUKS_ALG_AES 984 }; 985 properties[index++] = { 986 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 987 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_128 988 }; 989 properties[index++] = { 990 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 991 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | 992 huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT 993 } 994 return properties; 995} 996 997function GetAesEncryptProperties() { 998 let properties: Array<huks.HuksParam> = new Array(); 999 let index = 0; 1000 properties[index++] = { 1001 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 1002 value: huks.HuksKeyAlg.HUKS_ALG_AES 1003 }; 1004 properties[index++] = { 1005 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 1006 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_128 1007 }; 1008 properties[index++] = { 1009 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 1010 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT 1011 } 1012 properties[index++] = { 1013 tag: huks.HuksTag.HUKS_TAG_PADDING, 1014 value: huks.HuksKeyPadding.HUKS_PADDING_PKCS7 1015 } 1016 properties[index++] = { 1017 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 1018 value: huks.HuksCipherMode.HUKS_MODE_CBC 1019 } 1020 properties[index++] = { 1021 tag: huks.HuksTag.HUKS_TAG_IV, 1022 value: StringToUint8Array(IV) 1023 } 1024 return properties; 1025} 1026 1027function GetAesDecryptProperties() { 1028 let properties: Array<huks.HuksParam> = new Array(); 1029 let index = 0; 1030 properties[index++] = { 1031 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 1032 value: huks.HuksKeyAlg.HUKS_ALG_AES 1033 }; 1034 properties[index++] = { 1035 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 1036 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_128 1037 }; 1038 properties[index++] = { 1039 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 1040 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT 1041 } 1042 properties[index++] = { 1043 tag: huks.HuksTag.HUKS_TAG_PADDING, 1044 value: huks.HuksKeyPadding.HUKS_PADDING_PKCS7 1045 } 1046 properties[index++] = { 1047 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 1048 value: huks.HuksCipherMode.HUKS_MODE_CBC 1049 } 1050 properties[index++] = { 1051 tag: huks.HuksTag.HUKS_TAG_IV, 1052 value: StringToUint8Array(IV) 1053 } 1054 return properties; 1055} 1056 1057async function GenerateAesKey() { 1058 let genProperties = GetAesGenerateProperties(); 1059 let options: huks.HuksOptions = { 1060 properties: genProperties 1061 } 1062 await huks.generateKeyItem(aesKeyAlias, options) 1063 .then((data) => { 1064 console.info(`callback: generate AES Key success, data = ${JSON.stringify(data)}`); 1065 }).catch((error: BusinessError)=>{ 1066 console.error(`callback: generate AES Key failed`); 1067 }) 1068} 1069 1070 1071async function EncryptData() { 1072 let encryptProperties = GetAesEncryptProperties(); 1073 let options: huks.HuksOptions = { 1074 properties: encryptProperties, 1075 inData: StringToUint8Array(plainText) 1076 } 1077 await huks.initSession(aesKeyAlias, options) 1078 .then((data) => { 1079 handle = data.handle; 1080 }).catch((error: BusinessError)=>{ 1081 console.error(`callback: init encryptdata failed`); 1082 }) 1083 await huks.finishSession(handle, options) 1084 .then((data) => { 1085 console.info(`callback: encrypt data success, data is `+ Uint8ArrayToString(data.outData as Uint8Array)); 1086 cipherData = data.outData as Uint8Array; 1087 }).catch((error: BusinessError)=>{ 1088 console.error(`callback: encrypt data failed`); 1089 }) 1090} 1091 1092async function DecryptData() { 1093 let decryptOptions = GetAesDecryptProperties() 1094 let options: huks.HuksOptions = { 1095 properties: decryptOptions, 1096 inData: cipherData 1097 } 1098 await huks.initSession(aesKeyAlias, options) 1099 .then((data) => { 1100 handle = data.handle; 1101 }).catch((error: BusinessError)=>{ 1102 console.error(`callback: init decryptdata failed`); 1103 }) 1104 await huks.finishSession(handle, options) 1105 .then((data) => { 1106 console.info(`callback: decrypt data success, data is ` + Uint8ArrayToString(data.outData as Uint8Array)); 1107 }).catch((error: BusinessError)=>{ 1108 console.error(`callback: decrypt data failed`); 1109 }) 1110} 1111 1112async function DeleteKey() { 1113 let emptyOptions: huks.HuksOptions = { 1114 properties: [] 1115 } 1116 await huks.deleteKeyItem(aesKeyAlias, emptyOptions) 1117 .then((data) => { 1118 console.info(`callback: delete data success`); 1119 }).catch((error: BusinessError)=>{ 1120 console.error(`callback: delete data failed`); 1121 }) 1122} 1123``` 1124 1125### Key Agreement 1126 1127You are advised to pass in [HuksKeyStorageType](../reference/apis/js-apis-huks.md#hukskeystoragetype) to specify the storage type in key agreement. From API version 10, only **HUKS_STORAGE_ONLY_USED_IN_HUKS** or **HUKS_STORAGE_KEY_EXPORT_ALLOWED** can be used. If **HuksKeyStorageType** is not passed in, the key can be stored or exported by default, which poses security risks. 1128 1129```ts 1130/* 1131 * Perform key agreement using an X25519 256-bit TEMP key and return the result in a callback. 1132 */ 1133import huks from '@ohos.security.huks'; 1134import { BusinessError } from '@ohos.base'; 1135 1136/* 1137 * Set the key alias and encapsulate the key properties. 1138 */ 1139let srcKeyAliasFirst = "AgreeX25519KeyFirstAlias"; 1140let srcKeyAliasSecond = "AgreeX25519KeySecondAlias"; 1141let agreeX25519InData = 'AgreeX25519TestIndata'; 1142let finishOutData : Uint8Array; 1143let handle: number; 1144let exportKey : Uint8Array; 1145let exportKeyFrist: Uint8Array; 1146let exportKeySecond : Uint8Array; 1147 1148/* Configure the parameter set used for generating the key. */ 1149let properties : Array<huks.HuksParam> = new Array(); 1150properties[0] = { 1151 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 1152 value: huks.HuksKeyAlg.HUKS_ALG_X25519, 1153} 1154properties[1] = { 1155 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 1156 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE, 1157} 1158properties[2] = { 1159 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 1160 value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256, 1161} 1162properties[3] = { 1163 tag: huks.HuksTag.HUKS_TAG_DIGEST, 1164 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE, 1165} 1166properties[4] = { 1167 tag: huks.HuksTag.HUKS_TAG_PADDING, 1168 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 1169} 1170properties[5] = { 1171 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 1172 value: huks.HuksCipherMode.HUKS_MODE_CBC, 1173} 1174properties[6] = { 1175 tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, 1176 value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS, 1177} 1178let HuksOptions : huks.HuksOptions = { 1179 properties: properties, 1180 inData: new Uint8Array(new Array()) 1181} 1182 1183/* Configure parameters for the first key agreement. */ 1184let finishProperties : Array<huks.HuksParam> = new Array(); 1185finishProperties[0] = { 1186 tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, 1187 value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS, 1188} 1189finishProperties[1] = { 1190 tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS, 1191 value: true 1192} 1193finishProperties[2] = { 1194 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 1195 value: huks.HuksKeyAlg.HUKS_ALG_AES, 1196} 1197finishProperties[3] = { 1198 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 1199 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256, 1200} 1201finishProperties[4] = { 1202 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 1203 value: 1204 huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | 1205 huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT, 1206} 1207finishProperties[5] = { 1208 tag: huks.HuksTag.HUKS_TAG_DIGEST, 1209 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE, 1210} 1211finishProperties[6] = { 1212 tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS, 1213 value: StringToUint8Array(srcKeyAliasFirst+ 'final'), 1214} 1215finishProperties[7] = { 1216 tag: huks.HuksTag.HUKS_TAG_PADDING, 1217 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 1218} 1219finishProperties[8] = { 1220 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 1221 value: huks.HuksCipherMode.HUKS_MODE_ECB, 1222} 1223let finishOptionsFrist : huks.HuksOptions = { 1224 properties: finishProperties, 1225 inData: StringToUint8Array(agreeX25519InData) 1226} 1227/* Configure parameters for the second key agreement. */ 1228let finishOptionsSecond : huks.HuksOptions = { 1229 properties: finishProperties, 1230 inData: StringToUint8Array(agreeX25519InData) 1231} 1232finishOptionsSecond.properties!.splice(6, 1, { 1233 tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS, 1234 value: StringToUint8Array(srcKeyAliasSecond + 'final'), 1235}) 1236 1237function StringToUint8Array(str:string) { 1238 let arr: number[] = new Array(); 1239 for (let i = 0, j = str.length; i < j; ++i) { 1240 arr.push(str.charCodeAt(i)); 1241 } 1242return new Uint8Array(arr); 1243} 1244class throwObject { 1245 isThrow: boolean = false 1246} 1247function generateKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1248 return new Promise<void>((resolve, reject) => { 1249 try { 1250 huks.generateKeyItem(keyAlias, huksOptions, (error, data) => { 1251 if (error) { 1252 reject(error); 1253 } else { 1254 resolve(data); 1255 } 1256 }); 1257 } catch (error) { 1258 throwObject.isThrow = true; 1259 throw(error as Error); 1260 } 1261 }); 1262} 1263 1264async function publicGenKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) { 1265 console.info(`enter callback generateKeyItem`); 1266 let throwObject :throwObject = {isThrow: false}; 1267 try { 1268 await generateKeyItem(keyAlias, huksOptions, throwObject) 1269 .then((data) => { 1270 console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`); 1271 }) 1272 .catch((error : BusinessError) => { 1273 if (throwObject.isThrow) { 1274 throw(error as Error); 1275 } else { 1276 console.error(`callback: generateKeyItem failed`); 1277 } 1278 }); 1279 } catch (error) { 1280 console.error(`callback: generateKeyItem input arg invalid`); 1281 } 1282} 1283 1284function initSession(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1285 return new Promise<huks.HuksSessionHandle>((resolve, reject) => { 1286 try { 1287 huks.initSession(keyAlias, huksOptions, (error, data) => { 1288 if (error) { 1289 reject(error); 1290 } else { 1291 resolve(data); 1292 } 1293 }); 1294 } catch (error) { 1295 throwObject.isThrow = true; 1296 throw(error as Error); 1297 } 1298 }); 1299} 1300 1301async function publicInitFunc(keyAlias:string, huksOptions:huks.HuksOptions) { 1302 console.info(`enter callback doInit`); 1303 let throwObject:throwObject = {isThrow: false}; 1304 try { 1305 await initSession(keyAlias, huksOptions, throwObject) 1306 .then ((data) => { 1307 console.info(`callback: doInit success, data = ${JSON.stringify(data)}`); 1308 handle = data.handle; 1309 }) 1310 .catch((error : BusinessError) => { 1311 if (throwObject.isThrow) { 1312 throw(error as Error); 1313 } else { 1314 console.error(`callback: doInit failed`); 1315 } 1316 }); 1317 } catch (error) { 1318 console.error(`callback: doInit input arg invalid`); 1319 } 1320} 1321 1322function updateSession(handle:number, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1323 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 1324 try { 1325 huks.updateSession(handle, huksOptions, (error, data) => { 1326 if (error) { 1327 reject(error); 1328 } else { 1329 resolve(data); 1330 } 1331 }); 1332 } catch (error) { 1333 throwObject.isThrow = true; 1334 throw(error as Error); 1335 } 1336 }); 1337} 1338 1339async function publicUpdateFunc(handle:number, huksOptions:huks.HuksOptions) { 1340 console.info(`enter callback doUpdate`); 1341 let throwObject:throwObject = {isThrow: false}; 1342 try { 1343 await updateSession(handle, huksOptions, throwObject) 1344 .then ((data) => { 1345 console.info(`callback: doUpdate success, data = ${JSON.stringify(data)}`); 1346 }) 1347 .catch((error : BusinessError) => { 1348 if (throwObject.isThrow) { 1349 throw(error as Error); 1350 } else { 1351 console.error(`callback: doUpdate failed`); 1352 } 1353 }); 1354 } catch (error) { 1355 console.error(`callback: doUpdate input arg invalid`); 1356 } 1357} 1358 1359function finishSession(handle:number, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1360 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 1361 try { 1362 huks.finishSession(handle, huksOptions, (error, data) =>{ 1363 if (error) { 1364 reject(error); 1365 } else { 1366 resolve(data); 1367 } 1368 }); 1369 } catch (error) { 1370 throwObject.isThrow = true; 1371 throw(error as Error); 1372 } 1373 }); 1374} 1375 1376async function publicFinishFunc(handle:number, huksOptions:huks.HuksOptions) { 1377 console.info(`enter callback doFinish`); 1378 let throwObject:throwObject = {isThrow: false}; 1379 try { 1380 await finishSession(handle, huksOptions, throwObject) 1381 .then ((data) => { 1382 finishOutData = data.outData as Uint8Array; 1383 console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`); 1384 }) 1385 .catch((error : BusinessError) => { 1386 if (throwObject.isThrow) { 1387 throw(error as Error); 1388 } else { 1389 console.error(`callback: doFinish failed`); 1390 } 1391 }); 1392 } catch (error) { 1393 console.error(`callback: doFinish input arg invalid`); 1394 } 1395} 1396 1397function exportKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1398 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 1399 try { 1400 huks.exportKeyItem(keyAlias, huksOptions, (error, data) => { 1401 if (error) { 1402 reject(error); 1403 } else { 1404 resolve(data); 1405 } 1406 }); 1407 } catch (error) { 1408 throwObject.isThrow = true; 1409 throw(error as Error); 1410 } 1411 }); 1412} 1413 1414async function publicExportKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) { 1415 console.info(`enter callback export`); 1416 let throwObject:throwObject = {isThrow: false}; 1417 try { 1418 await exportKeyItem(keyAlias, huksOptions, throwObject) 1419 .then ((data) => { 1420 console.info(`callback: exportKeyItem success, data = ${JSON.stringify(data)}`); 1421 exportKey = data.outData as Uint8Array; 1422 }) 1423 .catch((error : BusinessError) => { 1424 if (throwObject.isThrow) { 1425 throw(error as Error); 1426 } else { 1427 console.error(`callback: exportKeyItem failed`); 1428 } 1429 }); 1430 } catch (error) { 1431 console.error(`callback: exportKeyItem input arg invalid`); 1432 } 1433} 1434 1435function deleteKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1436 return new Promise<void>((resolve, reject) => { 1437 try { 1438 huks.deleteKeyItem(keyAlias, huksOptions, (error, data) => { 1439 if (error) { 1440 reject(error); 1441 } else { 1442 resolve(data); 1443 } 1444 }); 1445 } catch (error) { 1446 throwObject.isThrow = true; 1447 throw(error as Error); 1448 } 1449 }); 1450} 1451 1452async function publicDeleteKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) { 1453 console.info(`enter callback deleteKeyItem`); 1454 let throwObject : throwObject = {isThrow: false}; 1455 try { 1456 await deleteKeyItem(keyAlias, huksOptions, throwObject) 1457 .then ((data) => { 1458 console.info(`callback: deleteKeyItem key success, data = ${JSON.stringify(data)}`); 1459 }) 1460 .catch((error :BusinessError) => { 1461 if (throwObject.isThrow) { 1462 throw(error as Error); 1463 } else { 1464 console.error(`callback: deleteKeyItem failed`); 1465 } 1466 }); 1467 } catch (error) { 1468 console.error(`callback: deletKeeyItem input arg invalid`); 1469 } 1470} 1471 1472async function testAgree() { 1473 /* 1. Generate two keys and export them. */ 1474 await publicGenKeyFunc(srcKeyAliasFirst, HuksOptions); 1475 await publicGenKeyFunc(srcKeyAliasSecond, HuksOptions); 1476 1477 await publicExportKeyFunc(srcKeyAliasFirst, HuksOptions); 1478 exportKeyFrist = exportKey; 1479 await publicExportKeyFunc(srcKeyAliasFirst, HuksOptions); 1480 exportKeySecond = exportKey; 1481 1482 /* Perform key agreement for the first. */ 1483 await publicInitFunc(srcKeyAliasFirst, HuksOptions); 1484 HuksOptions.inData = exportKeySecond; 1485 await publicUpdateFunc(handle, HuksOptions); 1486 await publicFinishFunc(handle, finishOptionsFrist); 1487 1488 /* Perform key agreement for the second key. */ 1489 await publicInitFunc(srcKeyAliasSecond, HuksOptions); 1490 HuksOptions.inData = exportKeyFrist; 1491 await publicUpdateFunc(handle, HuksOptions); 1492 await publicFinishFunc(handle, finishOptionsSecond); 1493 1494 await publicDeleteKeyFunc(srcKeyAliasFirst, HuksOptions); 1495 await publicDeleteKeyFunc(srcKeyAliasSecond, HuksOptions); 1496} 1497``` 1498 1499### Key Derivation 1500 1501You are advised to pass in [HuksKeyStorageType](../reference/apis/js-apis-huks.md#hukskeystoragetype) to specify the storage type in key derivation. From API version 10, only **HUKS_STORAGE_ONLY_USED_IN_HUKS** or **HUKS_STORAGE_KEY_EXPORT_ALLOWED** can be used. If **HuksKeyStorageType** is not passed in, the key can be stored or exported by default, which poses security risks. 1502 1503```ts 1504/* 1505 * The following uses an HKDF256 key and promise-based APIs as an example. 1506 */ 1507import huks from '@ohos.security.huks'; 1508import { BusinessError } from '@ohos.base'; 1509 1510/* 1511 * Set the key alias and encapsulate the key properties. 1512 */ 1513let srcKeyAlias = "hkdf_Key"; 1514let deriveHkdfInData = "deriveHkdfTestIndata"; 1515let handle:number; 1516let finishOutData:Uint8Array; 1517let HuksKeyDeriveKeySize = 32; 1518 1519/* Configure the parameter set used for generating the key. */ 1520let properties:Array<huks.HuksParam> = new Array(); 1521properties[0] = { 1522 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 1523 value: huks.HuksKeyAlg.HUKS_ALG_AES, 1524} 1525properties[1] = { 1526 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 1527 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DERIVE, 1528} 1529properties[2] = { 1530 tag: huks.HuksTag.HUKS_TAG_DIGEST, 1531 value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256, 1532} 1533properties[3] = { 1534 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 1535 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_128, 1536} 1537properties[4] = { 1538 tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, 1539 value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS, 1540} 1541let huksOptions:huks.HuksOptions = { 1542 properties: properties, 1543 inData: new Uint8Array(new Array()) 1544} 1545 1546/* Configure the parameter set used for init(). */ 1547let initProperties:Array<huks.HuksParam> = new Array(); 1548initProperties[0] = { 1549 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 1550 value: huks.HuksKeyAlg.HUKS_ALG_HKDF, 1551} 1552initProperties[1] = { 1553 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 1554 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DERIVE, 1555} 1556initProperties[2] = { 1557 tag: huks.HuksTag.HUKS_TAG_DIGEST, 1558 value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256, 1559} 1560initProperties[3] = { 1561 tag: huks.HuksTag.HUKS_TAG_DERIVE_KEY_SIZE, 1562 value: HuksKeyDeriveKeySize, 1563} 1564let initOptions:huks.HuksOptions = { 1565 properties: initProperties, 1566 inData: new Uint8Array(new Array()) 1567} 1568 1569/* Configure the parameter set used for finish(). */ 1570let finishProperties:Array<huks.HuksParam> = new Array(); 1571finishProperties[0] = { 1572 tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, 1573 value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS, 1574} 1575finishProperties[1] = { 1576 tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS, 1577 value: true, 1578} 1579finishProperties[2] = { 1580 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 1581 value: huks.HuksKeyAlg.HUKS_ALG_AES, 1582} 1583finishProperties[3] = { 1584 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 1585 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256, 1586} 1587finishProperties[4] = { 1588 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 1589 value: 1590 huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | 1591 huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT, 1592} 1593finishProperties[5] = { 1594 tag: huks.HuksTag.HUKS_TAG_DIGEST, 1595 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE, 1596} 1597finishProperties[6] = { 1598 tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS, 1599 value: StringToUint8Array(srcKeyAlias), 1600} 1601finishProperties[7] = { 1602 tag: huks.HuksTag.HUKS_TAG_PADDING, 1603 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 1604} 1605finishProperties[8] = { 1606 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 1607 value: huks.HuksCipherMode.HUKS_MODE_ECB, 1608} 1609let finishOptions:huks.HuksOptions = { 1610 properties: finishProperties, 1611 inData: new Uint8Array(new Array()) 1612} 1613 1614function StringToUint8Array(str:String) { 1615 let arr:number[]=new Array(); 1616 for (let i = 0, j = str.length; i < j; ++i) { 1617 arr.push(str.charCodeAt(i)); 1618 } 1619 return new Uint8Array(arr); 1620} 1621 1622class throwObject{ 1623 isThrow=false; 1624} 1625 1626function generateKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1627 return new Promise<void>((resolve, reject) => { 1628 try { 1629 huks.generateKeyItem(keyAlias, huksOptions, (error, data)=> { 1630 if (error) { 1631 reject(error); 1632 } else { 1633 resolve(data); 1634 } 1635 }); 1636 } catch (error) { 1637 throwObject.isThrow = true; 1638 throw(error as Error); 1639 } 1640 }); 1641} 1642 1643async function publicGenKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) { 1644 console.info(`enter callback generateKeyItem`); 1645 let throwObject:throwObject = {isThrow: false}; 1646 try { 1647 await generateKeyItem(keyAlias, huksOptions, throwObject) 1648 .then((data) => { 1649 console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`); 1650 }) 1651 .catch((error:BusinessError) => { 1652 if (throwObject.isThrow) { 1653 throw(error as Error); 1654 } else { 1655 console.error(`callback: generateKeyItem failed`); 1656 } 1657 }); 1658 } catch (error) { 1659 console.error(`callback: generateKeyItem input arg invalid`); 1660 } 1661} 1662 1663function initSession(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1664 return new Promise<huks.HuksSessionHandle>((resolve, reject) => { 1665 try { 1666 huks.initSession(keyAlias, huksOptions, (error, data)=> { 1667 if (error) { 1668 reject(error); 1669 } else { 1670 resolve(data); 1671 } 1672 }); 1673 } catch (error) { 1674 throwObject.isThrow = true; 1675 throw(error as Error); 1676 } 1677 }); 1678} 1679 1680async function publicInitFunc(keyAlias:string, huksOptions:huks.HuksOptions) { 1681 console.info(`enter callback doInit`); 1682 let throwObject:throwObject = {isThrow: false}; 1683 try { 1684 await initSession(keyAlias, huksOptions, throwObject) 1685 .then ((data) => { 1686 console.info(`callback: doInit success, data = ${JSON.stringify(data)}`); 1687 handle = data.handle; 1688 }) 1689 .catch((error:BusinessError) => { 1690 if (throwObject.isThrow) { 1691 throw(error as Error); 1692 } else { 1693 console.error(`callback: doInit failed`); 1694 } 1695 }); 1696 } catch (error) { 1697 console.error(`callback: doInit input arg invalid`); 1698 } 1699} 1700 1701function updateSession(handle:number, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1702 return new Promise<huks.HuksOptions>((resolve, reject) => { 1703 try { 1704 huks.updateSession(handle, huksOptions, (error, data)=> { 1705 if (error) { 1706 reject(error); 1707 } else { 1708 resolve(data); 1709 } 1710 }); 1711 } catch (error) { 1712 throwObject.isThrow = true; 1713 throw(error as Error); 1714 } 1715 }); 1716} 1717 1718async function publicUpdateFunc(handle:number, huksOptions:huks.HuksOptions) { 1719 console.info(`enter callback doUpdate`); 1720 let throwObject:throwObject = {isThrow: false}; 1721 try { 1722 await updateSession(handle, huksOptions, throwObject) 1723 .then ((data) => { 1724 console.info(`callback: doUpdate success, data = ${JSON.stringify(data)}`); 1725 }) 1726 .catch((error:BusinessError) => { 1727 if (throwObject.isThrow) { 1728 throw(error as Error); 1729 } else { 1730 console.error(`callback: doUpdate failed`); 1731 } 1732 }); 1733 } catch (error) { 1734 console.error(`callback: doUpdate input arg invalid`); 1735 } 1736} 1737 1738function finishSession(handle:number, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1739 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 1740 try { 1741 huks.finishSession(handle, huksOptions, (error, data)=> { 1742 if (error) { 1743 reject(error); 1744 } else { 1745 resolve(data); 1746 } 1747 }); 1748 } catch (error) { 1749 throwObject.isThrow = true; 1750 throw(error as Error); 1751 } 1752 }); 1753} 1754 1755async function publicFinishFunc(handle:number, huksOptions:huks.HuksOptions) { 1756 console.info(`enter callback doFinish`); 1757 let throwObject:throwObject = {isThrow: false}; 1758 try { 1759 await finishSession(handle, huksOptions, throwObject) 1760 .then ((data) => { 1761 finishOutData = data.outData as Uint8Array; 1762 console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`); 1763 }) 1764 .catch((error:BusinessError) => { 1765 if (throwObject.isThrow) { 1766 throw(error as Error); 1767 } else { 1768 console.error(`callback: doFinish failed`); 1769 } 1770 }); 1771 } catch (error) { 1772 console.error(`callback: doFinish input arg invalid`); 1773 } 1774} 1775 1776function deleteKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1777 return new Promise<void>((resolve, reject) => { 1778 try { 1779 huks.deleteKeyItem(keyAlias, huksOptions, (error, data)=> { 1780 if (error) { 1781 reject(error); 1782 } else { 1783 resolve(data); 1784 } 1785 }); 1786 } catch (error) { 1787 throwObject.isThrow = true; 1788 throw(error as Error); 1789 } 1790 }); 1791} 1792 1793async function publicDeleteKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) { 1794 console.info(`enter callback deleteKeyItem`); 1795 let throwObject:throwObject = {isThrow: false}; 1796 try { 1797 await deleteKeyItem(keyAlias, huksOptions, throwObject) 1798 .then ((data) => { 1799 console.info(`callback: deleteKeyItem key success, data = ${JSON.stringify(data)}`); 1800 }) 1801 .catch((error:BusinessError) => { 1802 if (throwObject.isThrow) { 1803 throw(error as Error); 1804 } else { 1805 console.error(`callback: deleteKeyItem failed`); 1806 } 1807 }); 1808 } catch (error) { 1809 console.error(`callback: deletKeeyItem input arg invalid`); 1810 } 1811} 1812 1813async function testDerive() { 1814 /* Generate a key. */ 1815 await publicGenKeyFunc(srcKeyAlias, huksOptions); 1816 1817 /* Derive a key. */ 1818 await publicInitFunc(srcKeyAlias, initOptions); 1819 1820 initOptions.inData = StringToUint8Array(deriveHkdfInData); 1821 await publicUpdateFunc(handle, initOptions); 1822 await publicFinishFunc(handle, finishOptions); 1823 1824 await publicDeleteKeyFunc(srcKeyAlias, huksOptions); 1825} 1826``` 1827 1828## Key Access Control 1829 1830The HUKS provides comprehensive key access control to prevent unauthorized access. 1831 1832Services can access only their own keys, that is, the keys generated or imported through HUKS. 1833In addition, the HUKS supports user identity authentication for security-sensitive services. Users can use the service keys only after the authentication (PIN or biometric authentication) is successful. 1834The HUKS also restricts the key usage. For example, the AES keys can only be used for encryption and decryption, and the RSA keys can only be used for signing and signature verification. 1835 1836### User Identity Authentication 1837 1838During the key generation or import process, user identity authentication can be enabled to allow the use of the key only after the authentication is successful. You can specify a subset of credentials (lock screen password, fingerprint, and face) for user identity authentication. After a key is generated or imported, unauthorized key access can be prevented even if the application process is attacked. Key access control applies to security-sensitive scenarios, such as password-free login, password-free payment, and automatic password filling. 1839 1840In addition to user identity authentication, the HUKS provides the following modes for automatically invalidating a key: 1841 1842- Invalidate the key when the screen lock password is cleared.<br>This mode takes effect only when a screen lock password has been set. If the screen lock password is cleared, the key becomes invalid permanently. The key will not be invalidated if the screen lock password is modified. This mode applies to user-related data protection or access based on screen lock passwords. 1843- Invalidate the key when new biometric enrollments are added.<br>This mode takes effect only when at least one biometric feature (such as fingerprint) has been enrolled. The key becomes invalid permanently once a new biometric feature is enrolled. The key will not be invalidated if the biometric feature is deleted. This mode applies to scenarios, such as password-free login or payment. 1844 1845To ensure the validity of the user authentication result, the HUKS supports challenge verification. Before user identity authentication, obtain the challenge (in [HuksSessionHandle](../reference/apis/js-apis-huks.md#hukssessionhandle9) returned by [huks.initSession()](../reference/apis/js-apis-huks.md#huksinitsession9)) from the HUKS and pass in the challenge in **userIAM_userAuth.getAuthInstance**. The challenge of the authentication token is then verified during key operations. 1846 1847**How to Develop** 1848 1849If secondary user identity authentication is enabled for a key, initialize the key session and obtain the challenge. Then, pass the challenge to **userIAM_userAuth.getAuthInstance()** for user identity authentication. After the authentication is successful, an authentication token is obtained. The authentication token can be used to perform key operations. 1850 1851 1852 1853**Available APIs** 1854 1855When a key is generated or imported, [HuksUserAuthType](../reference/apis/js-apis-huks.md#huksuserauthtype9), [HuksAuthAccessType](../reference/apis/js-apis-huks.md#huksauthaccesstype9), and [HuksChallengeType](../reference/apis/js-apis-huks.md#hukschallengetype9) in the key properties are mandatory. 1856 1857**Table 3** User authentication types 1858 1859| Name | Value | Description | 1860| ------------------------------- |---|------------------------ | 1861| HUKS_USER_AUTH_TYPE_FINGERPRINT |0x0001 | Fingerprint authentication, which can be enabled with facial authentication and PIN authentication at the same time. | 1862| HUKS_USER_AUTH_TYPE_FACE |0x0002 | Facial authentication, whch can be enabled with fingerprint authentication and PIN authentication at the same time.| 1863| HUKS_USER_AUTH_TYPE_PIN |0x0004 | PIN authentication, which can be enabled with fingerprint authentication and facial authenticationat the same time.| 1864 1865**Table 4** Secure access types 1866 1867| Name | Value | Description | 1868| --------------------------------------- | ---- | ------------------------------------------------ | 1869| HUKS_AUTH_ACCESS_INVALID_CLEAR_PASSWORD | 1 | Invalidates the key after the screen lock password is cleared. | 1870| HUKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL | 2 | Invalidates the key after a biometric enrollment is added. The user authentication types must include the biometric authentication.| 1871 1872**Table 5** Challenge types 1873 1874| Name | Value | Description | 1875| ------------------------------- | ---- | ------------------------------ | 1876| HUKS_CHALLENGE_TYPE_NORMAL | 0 | Normal challenge, which requires an independent user authentication for each use of the key.| 1877| HUKS_CHALLENGE_TYPE_CUSTOM | 1 | Custom challenge, which supports only one user authentication for multiple keys.| 1878| HUKS_CHALLENGE_TYPE_NONE | 2 | No challenge is required during user authentication.| 1879 1880 > **NOTICE** 1881 > 1882 > If the challenge type is **HUKS_CHALLENGE_TYPE_NONE**, no challenge is required. However, the key can be accessed within a specified time period (set by **HUKS_TAG_AUTH_TIMEOUT**) after a successful authentication. The maximum value of **HUKS_TAG_AUTH_TIMEOUT** is 60 seconds. 1883 1884To use a key, initialize the key session, and determine whether a challenge is required based on the challenge type specified when the key is generated or imported. 1885 1886**Table 6** APIs for using a key 1887| API | Description | 1888| -------------------------------------- | ----------------------------| 1889|initSession(keyAlias: string, options: HuksOptions, callback: AsyncCallback\<HuksSessionHandle>) : void| Initializes the key session and obtains the challenge.| 1890|updateSession(handle: number, options: HuksOptions, token: Uint8Array, callback: AsyncCallback\<HuksReturnResult>) : void| Operates data by segment and passes the authentication token.| 1891|finishSession(handle: number, options: HuksOptions, token: Uint8Array, callback: AsyncCallback\<HuksReturnResult>) : void| Finishes the key session.| 1892 1893**How to Develop** 1894 18951. Generate a key and specify user authentication properties. 1896 1897```ts 1898import huks from '@ohos.security.huks'; 1899import { BusinessError } from '@ohos.base'; 1900 1901/* 1902 * Set the key alias and encapsulate the key properties. 1903 */ 1904let keyAlias = 'dh_key_fingerprint_access'; 1905let properties : Array<huks.HuksParam> = new Array(); 1906properties[0] = { 1907 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 1908 value: huks.HuksKeyAlg.HUKS_ALG_SM4, 1909} 1910properties[1] = { 1911 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 1912 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT, 1913} 1914properties[2] = { 1915 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 1916 value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, 1917} 1918properties[3] = { 1919 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 1920 value: huks.HuksCipherMode.HUKS_MODE_CBC, 1921} 1922properties[4] = { 1923 tag: huks.HuksTag.HUKS_TAG_PADDING, 1924 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 1925} 1926// Enable fingerprint authentication. 1927properties[5] = { 1928 tag: huks.HuksTag.HUKS_TAG_USER_AUTH_TYPE, 1929 value: huks.HuksUserAuthType.HUKS_USER_AUTH_TYPE_FINGERPRINT 1930} 1931// Set the key expiration type. Invalidate the key when a new biometric feature (fingerprint) is enrolled. 1932properties[6] = { 1933 tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_ACCESS_TYPE, 1934 value: huks.HuksAuthAccessType.HUKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL 1935} 1936// Use the default challenge type. 1937properties[7] = { 1938 tag: huks.HuksTag.HUKS_TAG_CHALLENGE_TYPE, 1939 value: huks.HuksChallengeType.HUKS_CHALLENGE_TYPE_NORMAL 1940} 1941let huksOptions : huks.HuksOptions = { 1942 properties: properties, 1943 inData: new Uint8Array(new Array()) 1944} 1945 1946/* 1947 * Generate a key. 1948 */ 1949class throwObject { 1950 isThrow:boolean = false 1951} 1952function generateKeyItem(keyAlias : string, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1953 return new Promise<void>((resolve, reject) => { 1954 try { 1955 huks.generateKeyItem(keyAlias, huksOptions, (error, data) => { 1956 if (error) { 1957 reject(error); 1958 } else { 1959 resolve(data); 1960 } 1961 }); 1962 } catch (error) { 1963 throwObject.isThrow = true; 1964 throw(error as Error); 1965 } 1966 }); 1967} 1968 1969async function publicGenKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) { 1970 console.info(`enter callback generateKeyItem`); 1971 let throwObject : throwObject = {isThrow: false}; 1972 try { 1973 await generateKeyItem(keyAlias, huksOptions, throwObject) 1974 .then((data) => { 1975 console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`); 1976 }) 1977 .catch((error : BusinessError) => { 1978 if (throwObject.isThrow) { 1979 throw(error as Error); 1980 } else { 1981 console.error(`callback: generateKeyItem failed`); 1982 } 1983 }); 1984 } catch (error) { 1985 console.error(`callback: generateKeyItem input arg invalid`); 1986 } 1987} 1988 1989async function TestGenKeyForFingerprintAccessControl() { 1990 await publicGenKeyFunc(keyAlias, huksOptions); 1991} 1992``` 1993 19942. Initialize the key session to obtain a challenge, and initiate fingerprint authentication to obtain an authentication token. 1995 1996```ts 1997import huks from '@ohos.security.huks'; 1998import userIAM_userAuth from '@ohos.userIAM.userAuth'; 1999import { BusinessError } from '@ohos.base'; 2000 2001/* 2002 * Set the key alias and encapsulate the key properties. 2003 */ 2004let srcKeyAlias = 'sm4_key_fingerprint_access'; 2005let handle : number; 2006let challenge : Uint8Array; 2007let fingerAuthToken : Uint8Array; 2008let authType = userIAM_userAuth.UserAuthType.FINGERPRINT; 2009let authTrustLevel = userIAM_userAuth.AuthTrustLevel.ATL1; 2010 2011/* Configure the key generation parameter set and key encryption parameter set. */ 2012let properties : Array<huks.HuksParam> = new Array(); 2013properties[0] = { 2014 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 2015 value: huks.HuksKeyAlg.HUKS_ALG_SM4, 2016} 2017properties[1] = { 2018 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 2019 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT, 2020} 2021properties[2] = { 2022 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 2023 value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, 2024} 2025properties[3] = { 2026 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 2027 value: huks.HuksCipherMode.HUKS_MODE_CBC, 2028} 2029properties[4] = { 2030 tag: huks.HuksTag.HUKS_TAG_PADDING, 2031 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 2032} 2033let huksOptions : huks.HuksOptions = { 2034 properties: properties, 2035 inData: new Uint8Array(new Array()) 2036} 2037 2038class throwObject { 2039 isThrow:boolean=false 2040} 2041 2042function initSession(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) { 2043 return new Promise<huks.HuksSessionHandle>((resolve, reject) => { 2044 try { 2045 huks.initSession(keyAlias, huksOptions, (error, data) =>{ 2046 if (error) { 2047 reject(error); 2048 } else { 2049 resolve(data); 2050 } 2051 }); 2052 } catch (error) { 2053 throwObject.isThrow = true; 2054 throw(error as Error); 2055 } 2056 }); 2057} 2058 2059async function publicInitFunc(keyAlias:string, huksOptions:huks.HuksOptions) { 2060 console.info(`enter callback doInit`); 2061 let throwObject : throwObject = {isThrow: false}; 2062 try { 2063 await initSession(keyAlias, huksOptions, throwObject) 2064 .then ((data) => { 2065 console.info(`callback: doInit success, data = ${JSON.stringify(data)}`); 2066 handle = data.handle; 2067 challenge = data.challenge as Uint8Array; 2068 }) 2069 .catch((error : BusinessError) => { 2070 if (throwObject.isThrow) { 2071 throw(error as Error); 2072 } else { 2073 console.error(`callback: doInit failed`); 2074 } 2075 }); 2076 } catch (error) { 2077 console.error(`callback: doInit input arg invalid`); 2078 } 2079} 2080 2081function userIAMAuthFinger(huksChallenge:Uint8Array) { 2082 // Obtain an authentication object. 2083 let auth : userIAM_userAuth.AuthInstance; 2084 try { 2085 auth = userIAM_userAuth.getAuthInstance(huksChallenge, authType, authTrustLevel); 2086 console.log("get auth instance success"); 2087 } catch (error) { 2088 console.log("get auth instance failed" + error); 2089 return; 2090 } 2091 2092 // Subscribe to the authentication result. 2093 try { 2094 auth.on("result", { 2095 callback: (result:userIAM_userAuth.AuthResultInfo) => { 2096 /* The authentication is successful, and the authentication token is obtained. */ 2097 fingerAuthToken = result.token as Uint8Array; 2098 } 2099 }); 2100 console.log("subscribe authentication event success"); 2101 } catch (error) { 2102 console.log("subscribe authentication event failed " + error); 2103 } 2104 2105 // Start user authentication. 2106 try { 2107 auth.start(); 2108 console.info("authV9 start auth success"); 2109 } catch (error) { 2110 console.info("authV9 start auth failed, error = " + error); 2111 } 2112} 2113 2114async function testInitAndAuthFinger() { 2115 /* Initialize the key session to obtain a challenge. */ 2116 await publicInitFunc(srcKeyAlias, huksOptions); 2117 /* Invoke userIAM to perform user identity authentication. */ 2118 userIAMAuthFinger(challenge); 2119} 2120``` 2121 21223. Pass in the authentication token to perform data operations. 2123 2124```ts 2125/* 2126* The following uses an SM4 128-bit key and callback-based APIs as an example. 2127*/ 2128import huks from '@ohos.security.huks'; 2129import { BusinessError } from '@ohos.base'; 2130 2131/* 2132* Set the key alias and encapsulate the key properties. 2133*/ 2134let srcKeyAlias = 'sm4_key_fingerprint_access'; 2135let IV = '1234567890123456'; 2136let cipherInData = 'Hks_SM4_Cipher_Test_101010101010101010110_string'; 2137let handle: number; 2138let fingerAuthToken: Uint8Array; 2139let finishOutData: Uint8Array; 2140 2141class throwObject { 2142 isThrow: boolean = false; 2143} 2144 2145/* Configure the key generation parameter set and key encryption parameter set. */ 2146class propertyEncryptType { 2147 tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM; 2148 value: huks.HuksKeyAlg | huks.HuksKeyPurpose | huks.HuksKeySize | huks.HuksKeyPadding | huks.HuksCipherMode 2149 | Uint8Array = huks.HuksKeyAlg.HUKS_ALG_SM4; 2150} 2151 2152let propertiesEncrypt: propertyEncryptType[] = [ 2153 { 2154 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 2155 value: huks.HuksKeyAlg.HUKS_ALG_SM4, 2156 }, 2157 { 2158 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 2159 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT, 2160 }, 2161 { 2162 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 2163 value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, 2164 }, 2165 { 2166 tag: huks.HuksTag.HUKS_TAG_PADDING, 2167 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 2168 }, 2169 { 2170 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 2171 value: huks.HuksCipherMode.HUKS_MODE_CBC, 2172 }, 2173 { 2174 tag: huks.HuksTag.HUKS_TAG_IV, 2175 value: StringToUint8Array(IV), 2176 } 2177] 2178 2179let encryptOptions: huks.HuksOptions = { 2180 properties: propertiesEncrypt, 2181 inData: new Uint8Array(new Array()) 2182} 2183 2184function StringToUint8Array(str: string) { 2185 let arr: number[] = []; 2186 for (let i = 0, j = str.length; i < j; ++i) { 2187 arr.push(str.charCodeAt(i)); 2188 } 2189 return new Uint8Array(arr); 2190} 2191 2192function updateSession(handle: number, huksOptions: huks.HuksOptions, token: Uint8Array, throwObject: throwObject) { 2193 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 2194 try { 2195 huks.updateSession(handle, huksOptions, token, (error, data) => { 2196 if (error) { 2197 reject(error); 2198 } else { 2199 resolve(data); 2200 } 2201 }); 2202 } catch (error) { 2203 throwObject.isThrow = true; 2204 throw(error as Error); 2205 } 2206 }); 2207} 2208 2209async function publicUpdateFunc(handle: number, token: Uint8Array, huksOptions: huks.HuksOptions) { 2210 console.info(`enter callback doUpdate`); 2211 let throwObject: throwObject = {isThrow: false}; 2212 try { 2213 await updateSession(handle, huksOptions, token, throwObject) 2214 .then ((data) => { 2215 console.info(`callback: doUpdate success, data = ${JSON.stringify(data)}`); 2216 }) 2217 .catch((error: BusinessError) => { 2218 if (throwObject.isThrow) { 2219 throw(error as Error); 2220 } else { 2221 console.error(`callback: doUpdate failed`); 2222 } 2223 }); 2224 } catch (error) { 2225 console.error(`callback: doUpdate input arg invalid`); 2226 } 2227} 2228 2229function finishSession(handle: number, huksOptions: huks.HuksOptions, token: Uint8Array, throwObject: throwObject) { 2230 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 2231 try { 2232 huks.finishSession(handle, huksOptions, token, (error, data) => { 2233 if (error) { 2234 reject(error); 2235 } else { 2236 resolve(data); 2237 } 2238 }); 2239 } catch (error) { 2240 throwObject.isThrow = true; 2241 throw(error as Error); 2242 } 2243 }); 2244} 2245 2246async function publicFinishFunc(handle: number, token: Uint8Array, huksOptions: huks.HuksOptions) { 2247 console.info(`enter callback doFinish`); 2248 let throwObject: throwObject = {isThrow: false}; 2249 try { 2250 await finishSession(handle, huksOptions, token, throwObject) 2251 .then ((data) => { 2252 finishOutData = data.outData as Uint8Array; 2253 console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`); 2254 }) 2255 .catch((error: BusinessError) => { 2256 if (throwObject.isThrow) { 2257 throw(error as Error); 2258 } else { 2259 console.error(`callback: doFinish failed`); 2260 } 2261 }); 2262 } catch (error) { 2263 console.error(`callback: doFinish input arg invalid`); 2264 } 2265} 2266 2267async function testSm4Cipher() { 2268 encryptOptions.inData = StringToUint8Array(cipherInData); 2269 /* Pass in the authentication token. */ 2270 await publicUpdateFunc(handle, fingerAuthToken, encryptOptions); 2271 encryptOptions.inData = new Uint8Array(new Array()); 2272 /* Pass in the authentication token. */ 2273 await publicFinishFunc(handle, fingerAuthToken, encryptOptions); 2274 if (finishOutData === StringToUint8Array(cipherInData)) { 2275 console.info('test finish encrypt err '); 2276 } else { 2277 console.info('test finish encrypt success'); 2278 } 2279} 2280``` 2281 2282### Refined User Identity Authentication 2283 2284As an extension to [Key Access Control](#key-access-control), the refined access control allows secondary user identity authentication (biometric authentication and lock screen password) to be performed for key access in one or more scenarios, such as encryption, decryption, signing, signature verification, key agreement, and key derivation. For example, a service needs to use a HUKS key to encrypt the account password information. In this scenario, identity authentication is not required in encryption but required in decryption. To achieve this purpose, you can use the refined user identity authentication feature provided by the HUKS. 2285 2286**How to Develop** 2287 22881. Specify [HUKS_TAG_KEY_AUTH_PURPOSE](../reference/apis/js-apis-huks.md#hukstag) in key generation to allow refined user identity authentication to be performed when a specific algorithm is used. 22892. The **HUKS_TAG_KEY_AUTH_PURPOSE** does not need to be specified for the key usage process. The development process is the same as that of the user identity authentication process. 2290 2291**Available APIs** 2292 2293You can use the [HUKS_TAG_KEY_AUTH_PURPOSE](../reference/apis/js-apis-huks.md#hukstag) tag to specify the scenarios, for which the refined user identity authentication is performed. The value range of this tag is [HuksKeyAlg](../reference/apis/js-apis-huks.md#hukskeyalg). 2294 2295**Table 7** HUKS_TAG_KEY_AUTH_PURPOSE 2296| Name | Description | 2297| -------------------------------------- | ----------------------------| 2298|HUKS_TAG_KEY_AUTH_PURPOSE| Purpose of the user identity authentication, that is, perform the user identity authentication when a specific algorithm is used.| 2299 2300> **NOTICE** 2301> 2302> - If [**HuksUserAuthType**](../reference/apis/js-apis-huks.md#huksuserauthtype9) is not specified, no user identity authentication is performed by default. In this case, the setting of **HUKS_TAG_KEY_AUTH_PURPOSE** is invalid by default. If **HuksUserAuthType** is specified and **HUKS_TAG_KEY_AUTH_PURPOSE** is not specified, user identity authentication will still be performed by default before the key is used with the algorithm that is specified in the key generation process. 2303> - If the AES or SM4 symmetric algorithm is used for encryption and decryption, only the CBC mode supports refined user identity authentication. 2304 2305 2306 2307**How to Develop** 2308 2309Scenario: When generating keys for encryption and decryption, enable user identity authentication only for decryption. Enable user identity authentication for decryption but not for encryption. 2310 23111. Generate a key, set fingerprint authentication for key access control and related properties, and set **HUKS_TAG_KEY_AUTH_PURPOSE**. 2312 2313```ts 2314import huks from '@ohos.security.huks'; 2315import { BusinessError } from '@ohos.base'; 2316 2317/* 2318 * Set the key alias and encapsulate the key properties. 2319 */ 2320let keyAlias = 'dh_key_fingerprint_access'; 2321 2322class throwObject { 2323 isThrow: boolean = false; 2324} 2325 2326class propertyType { 2327 tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM; 2328 value: huks.HuksKeyAlg | huks.HuksKeyPurpose | huks.HuksKeySize | huks.HuksCipherMode | huks.HuksKeyPadding 2329 | huks.HuksUserAuthType | huks.HuksAuthAccessType | huks.HuksChallengeType = huks.HuksKeyAlg.HUKS_ALG_SM4 2330} 2331let properties: propertyType[] = [ 2332 { 2333 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 2334 value: huks.HuksKeyAlg.HUKS_ALG_SM4, 2335 }, 2336 { 2337 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 2338 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT, 2339 }, 2340 { 2341 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 2342 value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, 2343 }, 2344 { 2345 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 2346 value: huks.HuksCipherMode.HUKS_MODE_CBC, 2347 }, 2348 { 2349 tag: huks.HuksTag.HUKS_TAG_PADDING, 2350 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 2351 }, 2352 { 2353 tag: huks.HuksTag.HUKS_TAG_USER_AUTH_TYPE, 2354 value: huks.HuksUserAuthType.HUKS_USER_AUTH_TYPE_FINGERPRINT 2355 }, 2356 { 2357 tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_ACCESS_TYPE, 2358 value: huks.HuksAuthAccessType.HUKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL 2359 }, 2360 { 2361 tag: huks.HuksTag.HUKS_TAG_CHALLENGE_TYPE, 2362 value: huks.HuksChallengeType.HUKS_CHALLENGE_TYPE_NORMAL 2363 }, 2364 { 2365 tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_PURPOSE, 2366 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT 2367 } 2368] 2369 2370let huksOptions: huks.HuksOptions = { 2371 properties: properties, 2372 inData: new Uint8Array(new Array()) 2373} 2374 2375/* 2376 * Generate a key. 2377 */ 2378async function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) { 2379 return new Promise<void>((resolve, reject) => { 2380 try { 2381 huks.generateKeyItem(keyAlias, huksOptions, (error, data) => { 2382 if (error) { 2383 reject(error); 2384 } else { 2385 resolve(data); 2386 } 2387 }); 2388 } catch (error) { 2389 throwObject.isThrow = true; 2390 throw(error as Error); 2391 } 2392 }); 2393} 2394 2395async function publicGenKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 2396 console.info(`enter callback generateKeyItem`); 2397 let throwObject: throwObject = {isThrow: false}; 2398 try { 2399 await generateKeyItem(keyAlias, huksOptions, throwObject) 2400 .then((data) => { 2401 console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`); 2402 }) 2403 .catch((error: BusinessError) => { 2404 if (throwObject.isThrow) { 2405 throw(error as Error); 2406 } else { 2407 console.error(`callback: generateKeyItem failed`); 2408 } 2409 }); 2410 } catch (error) { 2411 console.error(`callback: generateKeyItem input arg invalid`); 2412 } 2413} 2414 2415async function TestGenKeyForFingerprintAccessControl() { 2416 await publicGenKeyFunc(keyAlias, huksOptions); 2417} 2418``` 2419 24202. Disable user identity authentication when the key is used for encryption. 2421 2422```ts 2423import huks from '@ohos.security.huks'; 2424import { BusinessError } from '@ohos.base'; 2425 2426class HuksProperties { 2427 tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM; 2428 value: huks.HuksKeyAlg | huks.HuksKeySize | huks.HuksKeyPurpose | huks.HuksKeyPadding | huks.HuksCipherMode 2429 | Uint8Array = huks.HuksKeyAlg.HUKS_ALG_ECC; 2430} 2431 2432/* 2433 * Set the key alias and encapsulate the key properties. 2434 */ 2435let srcKeyAlias = 'sm4_key_fingerprint_access'; 2436let cipherInData = 'Hks_SM4_Cipher_Test_101010101010101010110_string'; // Plaintext 2437let IV = '1234567890123456'; 2438let handle = 0; 2439let cipherText: Uint8Array; // Ciphertext data after encryption. 2440 2441function StringToUint8Array(str: string) { 2442 let arr: number[] = []; 2443 for (let i = 0, j = str.length; i < j; ++i) { 2444 arr.push(str.charCodeAt(i)); 2445 } 2446 return new Uint8Array(arr); 2447} 2448 2449/* Configure the key generation parameter set and key encryption parameter set. */ 2450let propertiesEncrypt: HuksProperties[] = [ 2451 { 2452 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 2453 value: huks.HuksKeyAlg.HUKS_ALG_SM4, 2454 }, 2455 { 2456 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 2457 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT, 2458 }, 2459 { 2460 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 2461 value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, 2462 }, 2463 { 2464 tag: huks.HuksTag.HUKS_TAG_PADDING, 2465 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 2466 }, 2467 { 2468 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 2469 value: huks.HuksCipherMode.HUKS_MODE_CBC, 2470 }, 2471 { 2472 tag: huks.HuksTag.HUKS_TAG_IV, 2473 value: StringToUint8Array(IV), 2474 } 2475]; 2476let encryptOptions: huks.HuksOptions = { 2477 properties: propertiesEncrypt, 2478 inData: new Uint8Array(new Array()) 2479} 2480class throwObject1{ 2481 isThrow: boolean = false; 2482} 2483function initSession(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject1) { 2484 return new Promise<huks.HuksSessionHandle>((resolve, reject) => { 2485 try { 2486 huks.initSession(keyAlias, huksOptions, (error, data) => { 2487 if (error) { 2488 reject(error); 2489 } else { 2490 resolve(data); 2491 } 2492 }); 2493 } catch (error) { 2494 throwObject.isThrow = true; 2495 throw (error as Error); 2496 } 2497 }); 2498} 2499 2500async function publicInitFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 2501 console.info(`enter callback doInit`); 2502 let throwObject: throwObject1 = { isThrow: false }; 2503 try { 2504 await initSession(keyAlias, huksOptions, throwObject) 2505 .then((data) => { 2506 console.info(`callback: doInit success, data = ${JSON.stringify(data)}`); 2507 handle = data.handle as number; 2508 }) 2509 .catch((error: BusinessError) => { 2510 if (throwObject.isThrow) { 2511 throw (error as Error); 2512 } else { 2513 console.error(`callback: doInit failed`); 2514 } 2515 }); 2516 } catch (error) { 2517 console.error(`callback: doInit input arg invalid`); 2518 } 2519} 2520 2521function finishSession(handle: number, huksOptions: huks.HuksOptions, throwObject: throwObject1) { 2522 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 2523 try { 2524 huks.finishSession(handle, huksOptions, (error, data) => { 2525 if (error) { 2526 reject(error); 2527 } else { 2528 resolve(data); 2529 } 2530 }); 2531 } catch (error) { 2532 throwObject.isThrow = true; 2533 throw (error as Error); 2534 } 2535 }); 2536} 2537 2538async function publicFinishFunc(handle: number, huksOptions: huks.HuksOptions) { 2539 console.info(`enter callback doFinish`); 2540 let throwObject: throwObject1 = { isThrow: false }; 2541 try { 2542 await finishSession(handle, huksOptions, throwObject) 2543 .then((data) => { 2544 cipherText = data.outData as Uint8Array; 2545 console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`); 2546 }) 2547 .catch((error: BusinessError) => { 2548 if (throwObject.isThrow) { 2549 throw (error as Error); 2550 } else { 2551 console.error(`callback: doFinish failed`); 2552 } 2553 }); 2554 } catch (error) { 2555 console.error(`callback: doFinish input arg invalid`); 2556 } 2557} 2558 2559async function testSm4Cipher() { 2560 /* Initialize the key session to obtain a challenge. */ 2561 await publicInitFunc(srcKeyAlias, encryptOptions); 2562 2563 /** Encryption */ 2564 encryptOptions.inData = StringToUint8Array(cipherInData); 2565 await publicFinishFunc(handle, encryptOptions); 2566} 2567``` 2568 25693. Enable user identity authentication when the key is used for decryption. 2570 2571```ts 2572import huks from '@ohos.security.huks'; 2573import userIAM_userAuth from '@ohos.userIAM.userAuth'; 2574import { BusinessError } from '@ohos.base'; 2575 2576/* 2577 * Set the key alias and encapsulate the key properties. 2578 */ 2579let srcKeyAlias = 'sm4_key_fingerprint_access'; 2580let cipherText = 'r56ywtTJUQC6JFJ2VV2kZw=='; // Ciphertext obtained, which may vary in actual situation. 2581let IV = '1234567890123456'; 2582let handle: number; 2583let finishOutData: Uint8Array; // Plaintext data after decryption. 2584let fingerAuthToken: Uint8Array; 2585let challenge: Uint8Array; 2586let authType = userIAM_userAuth.UserAuthType.FINGERPRINT; 2587let authTrustLevel = userIAM_userAuth.AuthTrustLevel.ATL1; 2588 2589class throwObject { 2590 isThrow: boolean = false; 2591} 2592 2593function StringToUint8Array(str: string) { 2594 let arr: number[] = []; 2595 for (let i = 0, j = str.length; i < j; ++i) { 2596 arr.push(str.charCodeAt(i)); 2597 } 2598 return new Uint8Array(arr); 2599} 2600 2601/* Configure the key generation parameter set and key encryption parameter set. */ 2602class propertyDecryptType { 2603 tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM 2604 value: huks.HuksKeyAlg | huks.HuksKeyPurpose | huks.HuksKeySize | huks.HuksKeyPadding | huks.HuksCipherMode 2605 | Uint8Array = huks.HuksKeyAlg.HUKS_ALG_SM4 2606} 2607 2608let propertiesDecrypt: propertyDecryptType[] = [ 2609 { 2610 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 2611 value: huks.HuksKeyAlg.HUKS_ALG_SM4, 2612 }, 2613 { 2614 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 2615 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT, 2616 }, 2617 { 2618 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 2619 value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, 2620 }, 2621 { 2622 tag: huks.HuksTag.HUKS_TAG_PADDING, 2623 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 2624 }, 2625 { 2626 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 2627 value: huks.HuksCipherMode.HUKS_MODE_CBC, 2628 }, 2629 { 2630 tag: huks.HuksTag.HUKS_TAG_IV, 2631 value: StringToUint8Array(IV), 2632 } 2633] 2634 2635let decryptOptions: huks.HuksOptions = { 2636 properties: propertiesDecrypt, 2637 inData: new Uint8Array(new Array()) 2638} 2639 2640function initSession(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) { 2641 return new Promise<huks.HuksSessionHandle>((resolve, reject) => { 2642 try { 2643 huks.initSession(keyAlias, huksOptions, (error, data) => { 2644 if (error) { 2645 reject(error); 2646 } else { 2647 resolve(data); 2648 } 2649 }); 2650 } catch (error) { 2651 throwObject.isThrow = true; 2652 throw(error as Error); 2653 } 2654 }); 2655} 2656 2657async function publicInitFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 2658 console.info(`enter callback doInit`); 2659 let throwObject: throwObject = {isThrow: false}; 2660 try { 2661 await initSession(keyAlias, huksOptions, throwObject) 2662 .then ((data) => { 2663 console.info(`callback: doInit success, data = ${JSON.stringify(data)}`); 2664 handle = data.handle; 2665 challenge = data.challenge as Uint8Array; 2666 }) 2667 .catch((error: BusinessError) => { 2668 if (throwObject.isThrow) { 2669 throw(error as Error); 2670 } else { 2671 console.error(`callback: doInit failed`); 2672 } 2673 }); 2674 } catch (error) { 2675 console.error(`callback: doInit input arg invalid`); 2676 } 2677} 2678 2679function userIAMAuthFinger(huksChallenge: Uint8Array) { 2680 // Obtain an authentication object. 2681 let auth: userIAM_userAuth.AuthInstance ; 2682 try { 2683 auth = userIAM_userAuth.getAuthInstance(huksChallenge, authType, authTrustLevel); 2684 console.log("get auth instance success"); 2685 } catch (error) { 2686 console.log("get auth instance failed" + error); 2687 return; 2688 } 2689 2690 // Subscribe to the authentication result. 2691 try { 2692 auth.on("result", { 2693 callback: (result) => { 2694 /* The authentication is successful, and the authentication token is obtained. */ 2695 fingerAuthToken = (result as userIAM_userAuth.AuthResultInfo).token as Uint8Array; 2696 } 2697 }); 2698 console.log("subscribe authentication event success"); 2699 } catch (error) { 2700 console.log("subscribe authentication event failed " + error); 2701 } 2702 2703 // Start user authentication. 2704 try { 2705 auth.start(); 2706 console.info("authV9 start auth success"); 2707 } catch (error) { 2708 console.info("authV9 start auth failed, error = " + error); 2709 } 2710} 2711 2712function finishSession(handle: number, huksOptions: huks.HuksOptions, token: Uint8Array, throwObject: throwObject) { 2713 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 2714 try { 2715 huks.finishSession(handle, huksOptions, token, (error, data) => { 2716 if (error) { 2717 reject(error); 2718 } else { 2719 resolve(data); 2720 } 2721 }); 2722 } catch (error) { 2723 throwObject.isThrow = true; 2724 throw(error as Error); 2725 } 2726 }); 2727} 2728 2729async function publicFinishFunc(handle: number, token: Uint8Array, huksOptions: huks.HuksOptions) { 2730 console.info(`enter callback doFinish`); 2731 let throwObject: throwObject = {isThrow: false}; 2732 try { 2733 await finishSession(handle, huksOptions, token, throwObject) 2734 .then ((data) => { 2735 finishOutData = data.outData as Uint8Array; 2736 console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`); 2737 }) 2738 .catch((error: BusinessError) => { 2739 if (throwObject.isThrow) { 2740 throw(error as Error); 2741 } else { 2742 console.error(`callback: doFinish failed`); 2743 } 2744 }); 2745 } catch (error) { 2746 console.error(`callback: doFinish input arg invalid`); 2747 } 2748} 2749 2750async function testSm4Cipher() { 2751 /* Initialize the key session to obtain a challenge. */ 2752 await publicInitFunc(srcKeyAlias, decryptOptions); 2753 2754 /* Invoke userIAM to perform user identity authentication. */ 2755 userIAMAuthFinger(challenge); 2756 2757 /* Perform decryption after the authentication is successful. The **authToken** value obtained by Auth needs to be passed in. */ 2758 decryptOptions.inData = StringToUint8Array(cipherText); 2759 await publicFinishFunc(handle, fingerAuthToken, decryptOptions); 2760} 2761``` 2762 2763## Key Attestation 2764 2765The HUKS provides attestation for the public keys of asymmetric key pairs. The HUKS can issue a certificate for the public key of an asymmetric key pair stored in the HUKS using the public key infrastructure (PKI) certificate chain technology. The certificate can prove the validity of the public key. The service can use the root CA certificate provided by the OpenHarmony to verify the key certificate issued by the HUKS level by level to ensure that the public key and private key in the certificate are from a trusted hardware device and stored in the HUKS. 2766 2767**How to Develop** 2768 27691. Pass in the key alias and the property tag of the key to be attested. 27702. Call a HUKS API to generate an X.509 certificate chain, which consists of the root CA certificate, device CA certificate, device certificate, and key certificate in sequence, for the application. 27713. Send the certificate chain to a trusted server. The server parses and verifies the validity of the certificate chain and whether a single certificate is revoked. 2772 2773**Available APIs** 2774 2775**Table 8** API for key attestation 2776| API | Description | 2777| -------------------------------------- | ----------------------------| 2778|attestKeyItem(keyAlias: string, options: HuksOptions, callback: AsyncCallback\<HuksReturnResult>) : void| Attests a key.| 2779 2780**How to Develop** 2781 2782```ts 2783/* 2784 * Attest a key and return the result in a callback. 2785 */ 2786import huks from '@ohos.security.huks'; 2787import { BusinessError } from '@ohos.base'; 2788 2789/* 2790 * Set the key alias and encapsulate the key properties. 2791 */ 2792let keyAliasString = "key attest"; 2793let aliasString = keyAliasString; 2794let aliasUint8 = StringToUint8Array(keyAliasString); 2795let securityLevel = StringToUint8Array('sec_level'); 2796let challenge = StringToUint8Array('challenge_data'); 2797let versionInfo = StringToUint8Array('version_info'); 2798let attestCertChain: Array<string>; 2799 2800class throwObject { 2801 isThrow: boolean = false; 2802} 2803 2804class genKeyPropertyType { 2805 tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM; 2806 value: huks.HuksKeyAlg | huks.HuksKeyStorageType | huks.HuksKeySize | huks.HuksKeyPurpose | huks.HuksKeyDigest 2807 | huks.HuksKeyPadding | huks.HuksKeyGenerateType | huks.HuksCipherMode = huks.HuksKeyAlg.HUKS_ALG_RSA 2808} 2809 2810let genKeyProperties: genKeyPropertyType[] = [ 2811 { 2812 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 2813 value: huks.HuksKeyAlg.HUKS_ALG_RSA 2814 }, 2815 { 2816 tag: huks.HuksTag.HUKS_TAG_KEY_STORAGE_FLAG, 2817 value: huks.HuksKeyStorageType.HUKS_STORAGE_PERSISTENT 2818 }, 2819 { 2820 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 2821 value: huks.HuksKeySize.HUKS_RSA_KEY_SIZE_2048 2822 }, 2823 { 2824 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 2825 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_VERIFY 2826 }, 2827 { 2828 tag: huks.HuksTag.HUKS_TAG_DIGEST, 2829 value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256 2830 }, 2831 { 2832 tag: huks.HuksTag.HUKS_TAG_PADDING, 2833 value: huks.HuksKeyPadding.HUKS_PADDING_PSS 2834 }, 2835 { 2836 tag: huks.HuksTag.HUKS_TAG_KEY_GENERATE_TYPE, 2837 value: huks.HuksKeyGenerateType.HUKS_KEY_GENERATE_TYPE_DEFAULT 2838 }, 2839 { 2840 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 2841 value: huks.HuksCipherMode.HUKS_MODE_ECB 2842 } 2843] 2844 2845let genOptions: huks.HuksOptions = { 2846 properties: genKeyProperties 2847}; 2848 2849class attestKeypropertyType { 2850 tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ATTESTATION_ID_SEC_LEVEL_INFO; 2851 value: Uint8Array = securityLevel; 2852} 2853 2854let attestKeyproperties: attestKeypropertyType[] = [ 2855 { 2856 tag: huks.HuksTag.HUKS_TAG_ATTESTATION_ID_SEC_LEVEL_INFO, 2857 value: securityLevel 2858 }, 2859 { 2860 tag: huks.HuksTag.HUKS_TAG_ATTESTATION_CHALLENGE, 2861 value: challenge 2862 }, 2863 { 2864 tag: huks.HuksTag.HUKS_TAG_ATTESTATION_ID_VERSION_INFO, 2865 value: versionInfo 2866 }, 2867 { 2868 tag: huks.HuksTag.HUKS_TAG_ATTESTATION_ID_ALIAS, 2869 value: aliasUint8 2870 } 2871] 2872 2873let huksOptions: huks.HuksOptions = { 2874 properties: attestKeyproperties 2875}; 2876 2877function StringToUint8Array(str: string) { 2878 let arr: number[] = []; 2879 for (let i = 0, j = str.length; i < j; ++i) { 2880 arr.push(str.charCodeAt(i)); 2881 } 2882 return new Uint8Array(arr); 2883} 2884 2885function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) { 2886 return new Promise<void>((resolve, reject) => { 2887 try { 2888 huks.generateKeyItem(keyAlias, huksOptions, (error, data) => { 2889 if (error) { 2890 reject(error); 2891 } else { 2892 resolve(data); 2893 } 2894 }); 2895 } catch (error) { 2896 throwObject.isThrow = true; 2897 throw(error as Error); 2898 } 2899 }); 2900} 2901 2902async function publicGenKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 2903 console.info(`enter callback generateKeyItem`); 2904 let throwObject: throwObject = {isThrow: false}; 2905 try { 2906 await generateKeyItem(keyAlias, huksOptions, throwObject) 2907 .then((data) => { 2908 console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`); 2909 }) 2910 .catch((error: BusinessError) => { 2911 if (throwObject.isThrow) { 2912 throw(error as Error); 2913 } else { 2914 console.error(`callback: generateKeyItem failed`); 2915 } 2916 }); 2917 } catch (error) { 2918 console.error(`callback: generateKeyItem input arg invalid`); 2919 } 2920} 2921 2922function attestKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) { 2923 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 2924 try { 2925 huks.attestKeyItem(keyAlias, huksOptions, (error, data) => { 2926 if (error) { 2927 reject(error); 2928 } else { 2929 resolve(data); 2930 } 2931 }); 2932 } catch (error) { 2933 throwObject.isThrow = true; 2934 throw(error as Error); 2935 } 2936 }); 2937} 2938 2939async function publicAttestKey(keyAlias: string, huksOptions: huks.HuksOptions) { 2940 console.info(`enter callback attestKeyItem`); 2941 let throwObject: throwObject = {isThrow: false}; 2942 try { 2943 await attestKeyItem(keyAlias, huksOptions, throwObject) 2944 .then ((data) => { 2945 console.info(`callback: attestKeyItem success, data = ${JSON.stringify(data)}`); 2946 if (data !== null && data.certChains !== null) { 2947 attestCertChain = data.certChains as string[]; 2948 } 2949 }) 2950 .catch((error: BusinessError) => { 2951 if (throwObject.isThrow) { 2952 throw(error as Error); 2953 } else { 2954 console.error(`callback: attestKeyItem failed`); 2955 } 2956 }); 2957 } catch (error) { 2958 console.error(`callback: attestKeyItem input arg invalid`); 2959 } 2960} 2961 2962async function AttestKeyTest() { 2963 await publicGenKeyFunc(aliasString, genOptions); 2964 2965 await publicAttestKey(aliasString, huksOptions); 2966 console.info('attest certChain data: ' + attestCertChain) 2967} 2968``` 2969 2970## FAQs 2971 2972### Cannot find name 'huks'. 2973 2974**security.huks.d.ts** is not imported. To solve the problem, add **import huks from '@ohos.security.huks'**. 2975 2976### Property 'finishSession' does not exist on type 'typeof huks'. Did you mean 'finish'? 2977 2978 **finishSession()** is supported from API version 9. Update the SDK version or use the latest **security.huks.d.ts** file.