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