• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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![huks_import_wrapped_key](figures/huks_import_wrapped_key.png)
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![huks_key_user_auth_work_flow](./figures/huks_key_user_auth_work_flow.png)
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.