• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1
2# 通用密钥库开发指导(ArkTS)
3
4> **说明**
5>
6> 本开发指导需使用API version 9及以上版本SDK。
7
8## 生成新密钥
9
10HUKS提供为业务安全随机生成密钥的能力。通过HUKS生成的密钥,密钥的全生命周期明文不会出安全环境,能保证任何人都无法接触获取到密钥的明文。即使生成密钥的业务自身,后续也只能通过HUKS提供的接口请求执行密钥操作,获取操作结果,但无法接触到密钥自身。
11
12**开发步骤**
13
14生成密钥时使用[huks.generateKeyItem(keyAlias,options,callback)](../reference/apis/js-apis-huks.md#huksgeneratekeyitem9)方法,传入keyAlias作为密钥别名,传入options包含该密钥的属性集,传入callback用于回调异步结果。关于接口的具体信息,可在[API参考文档](../reference/apis/js-apis-huks.md)中查看。
15
161. 确定密钥别名;
172. 初始化密钥属性集:通过[HuksParam](../reference/apis/js-apis-huks.md#huksparam)封装密钥属性,搭配Array组成密钥属性集,并赋值给[HuksOptions](../reference/apis/js-apis-huks.md#huksoptions)(properties字段),其中必须包含[HuksKeyAlg](../reference/apis/js-apis-huks.md#hukskeyalg),[HuksKeySize](../reference/apis/js-apis-huks.md#hukskeysize),[HuksKeyPurpose](../reference/apis/js-apis-huks.md#hukskeypurpose)属性;
183. 将密钥别名与密钥参数集作为参数传入,生成密钥。
19
20> **说明**
21>
22> 存储的 keyAlias 密钥别名最大为64字节
23
24**代码示例:**
25
26```ts
27/*
28 * 以下以生成DH密钥的Callback操作使用为例
29 */
30import huks from '@ohos.security.huks';
31import { BusinessError } from '@ohos.base';
32
33class HuksProperties {
34    tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM;
35    value: huks.HuksKeyAlg | huks.HuksKeySize | huks.HuksKeyPurpose | huks.HuksKeyDigest = huks.HuksKeyAlg.HUKS_ALG_ECC;
36}
37
38/*
39 * 确定密钥别名和封装密钥属性参数集
40 */
41let keyAlias = 'dh_key';
42let properties1: HuksProperties[] = [
43    {
44        tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
45        value: huks.HuksKeyAlg.HUKS_ALG_DH
46    },
47    {
48        tag: huks.HuksTag.HUKS_TAG_PURPOSE,
49        value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE
50    },
51    {
52        tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
53        value: huks.HuksKeySize.HUKS_DH_KEY_SIZE_2048
54    },
55    {
56        tag: huks.HuksTag.HUKS_TAG_DIGEST,
57        value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256
58    }
59];
60
61let huksOptions: huks.HuksOptions = {
62    properties: properties1,
63    inData: new Uint8Array(new Array())
64}
65
66/*
67 * 生成密钥
68 */
69function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions){
70    return new Promise<void>((resolve, reject) => {
71        try {
72            huks.generateKeyItem(keyAlias, huksOptions, (error, data) => {
73                if (error) {
74                    reject(error);
75                } else {
76                    resolve(data);
77                }
78            });
79        } catch (error) {
80            throw (error as Error);
81        }
82    });
83}
84
85async function publicGenKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
86    console.info(`enter callback generateKeyItem`);
87    try {
88        await generateKeyItem(keyAlias, huksOptions)
89        .then((data) => {
90            console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`);
91        })
92        .catch((error: BusinessError) => {
93            console.error(`callback: generateKeyItem failed`);
94        });
95    } catch (error) {
96        console.error(`callback: generateKeyItem input arg invalid`);
97    }
98}
99
100async function TestGenKey() {
101    await publicGenKeyFunc(keyAlias, huksOptions);
102}
103```
104
105## 导入外部密钥
106
107如果密钥是在HUKS外部生成(比如应用间协商生成、服务器端生成),应用可以将密钥导入到HUKS托管。HUKS支持直接将密钥明文导入到HUKS,但是明文导入会导致密钥暴露在REE内存中,一般适用于轻量级设备或低安业务。对于高安敏感业务,HUKS还提供了安全导入密钥的能力,允许业务自己生成密钥,并通过与处于安全环境中的HUKS建立端到端的加密传输通道,将密钥安全加密导入到HUKS中,确保导入传入过程中密钥不被泄露。
108
109与生成密钥一样,密钥一旦导入到HUKS中,密钥的生命周期明文不出安全环境,同样能保证任何人都无法接触获取到密钥的明文。
110
111### 明文导入
112
113导入明文密钥时使用[huks.importKeyItem(keyAlias,options,callback)](../reference/apis/js-apis-huks.md#huksimportkeyitem9)方法,传入keyAlias作为密钥别名,传入options,其中必须包含密钥材料和密钥属性集,传入callback用于回调异步结果。关于接口的具体信息,可在[API参考文档](../reference/apis/js-apis-huks.md)中查看。
114
1151. 确定密钥别名;
1162. 封装密钥材料和密钥属性集:密钥材料须符合[HUKS密钥材料格式](./huks-appendix.md#密钥材料格式)并以Uint8Array形式赋值给[HuksOptions](../reference/apis/js-apis-huks.md#huksoptions)的inData字段;另外,通过[HuksParam](../reference/apis/js-apis-huks.md#huksparam)封装密钥属性,搭配Array组成密钥属性集赋值给properties字段,属性集中必须包含[HuksKeyAlg](../reference/apis/js-apis-huks.md#hukskeyalg),[HuksKeySize](../reference/apis/js-apis-huks.md#hukskeysize),[HuksKeyPurpose](../reference/apis/js-apis-huks.md#hukskeypurpose)属性;
1173. 导入密钥。
118
119**代码示例:**
120
121```ts
122import huks from '@ohos.security.huks'
123
124/*
125 * 以导入AES256密钥为例
126 */
127
128/* 密钥 */
129let plainTextSize32 = new Uint8Array([
130    0xfb, 0x8b, 0x9f, 0x12, 0xa0, 0x83, 0x19, 0xbe, 0x6a, 0x6f, 0x63, 0x2a, 0x7c, 0x86, 0xba, 0xca,
131    0x64, 0x0b, 0x88, 0x96, 0xe2, 0xfa, 0x77, 0xbc, 0x71, 0xe3, 0x0f, 0x0f, 0x9e, 0x3c, 0xe5, 0xf9
132]);
133
134/*
135 * 确定密钥别名
136 */
137let keyAlias = 'AES256Alias_sample';
138
139/*
140 * 封装密钥属性集和密钥材料
141 */
142class propertyType {
143    tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM;
144    value: huks.HuksKeyAlg | huks.HuksKeySize | huks.HuksKeyPurpose = huks.HuksKeyAlg.HUKS_ALG_RSA;
145}
146
147let properties: propertyType[] = [
148    {
149        tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
150        value:huks.HuksKeyAlg.HUKS_ALG_AES
151    },
152    {
153        tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
154        value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256
155    },
156    {
157        tag: huks.HuksTag.HUKS_TAG_PURPOSE,
158        value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT
159    },
160]
161
162let options: huks.HuksOptions = {
163    properties: properties,
164    inData: plainTextSize32
165};
166
167/*
168 * 导入密钥
169 */
170try {
171    huks.importKeyItem(keyAlias, options, (error, data) => {
172         if (error) {
173            console.error(`callback: importKeyItem failed`);
174        } else {
175            console.info(`callback: importKeyItem success`);
176        }
177    });
178} catch (error) {
179    console.error(`callback: importKeyItem input arg invalid`);
180}
181```
182
183**调测验证**
184
185验证时查询密钥是否存在,如密钥存在即表示生成密钥成功。
186
187**代码示例:**
188
189```ts
190import huks from '@ohos.security.huks';
191
192let keyAlias = 'AES256Alias_sample';
193let isKeyExist = false;
194
195class keyPropertyType {
196    tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM;
197    value: huks.HuksKeyAlg = huks.HuksKeyAlg.HUKS_ALG_RSA;
198}
199
200let keyProperties: keyPropertyType[] = [
201    {
202        tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
203        value: huks.HuksKeyAlg.HUKS_ALG_AES
204    },
205]
206
207let huksOptions: huks.HuksOptions = {
208    properties: keyProperties, // 非空填充
209    inData: new Uint8Array(new Array()) // 非空填充
210}
211try {
212    huks.isKeyItemExist(keyAlias, huksOptions, (error, data) => {
213        if (error) {
214            console.error(`callback: isKeyItemExist failed`);
215        } else {
216            if (data !== null && data.valueOf() !== null) {
217                isKeyExist = data.valueOf();
218                console.info(`callback: isKeyItemExist success, isKeyExist = ${isKeyExist}`);
219            }
220        }
221    });
222} catch (error) {
223    console.error(`callback: isKeyItemExist input arg invalid`);
224}
225```
226
227### 加密导入
228
229相比明文导入,加密导入步骤更多,密钥材料更复杂,此章节将展示开发过程中关键的开发流程和密钥材料数据结构。下图是加密导入的基本开发流程。
230
231**图2** 加密导入开发流程
232
233![huks_import_wrapped_key](figures/huks_import_wrapped_key.png)
234
235**接口说明**
236
237根据开发流程,在导入加密密钥过程中,需要依次调用HUKS的生成密钥、导出公钥、导入加密密钥、删除密钥接口。
238
239关于接口的具体信息,可在[API参考文档](../reference/apis/js-apis-huks.md)中查看。
240
241**表1** 加密导入的接口介绍
242
243| 接口名                      | 描述                 |
244| -------------------------------------- | ----------------------------|
245|generateKeyItem(keyAlias: string, options: HuksOptions, callback: AsyncCallback\<void>) : void| 生成新密钥|
246|exportKeyItem(keyAlias: string, options: HuksOptions, callback: AsyncCallback\<HuksReturnResult>) : void| 导出密钥对的公钥|
247|importWrappedKeyItem(keyAlias: string, wrappingKeyAlias: string, options: HuksOptions, callback: AsyncCallback\<void>) : void|导入加密密钥|
248|deleteKeyItem(keyAlias: string, options: HuksOptions, callback: AsyncCallback\<void>) : void|删除密钥|
249
250需要注意的是,导出密钥接口返回的公钥明文材料是按照**X.509**格式封装,导入加密密钥接口中的密钥材料需满足**Length<sub>Data</sub>-Data** 的格式封装。具体,应用需要申请一个Uint8Array按照以下表格中的顺序依次封装。
251
252**表2** 加密密钥材料格式
253
254| 内容 | 业务公钥长度L<sub>pk2</sub> | 业务公钥pk2 | k2加密参数AAD2长度L<sub>AAD2</sub> | k2加密参数AAD2 |  k2加密参数Nonce2长度L<sub>Nonce2</sub> | k2加密参数Nonce2 |
255| :--: |:----:|:----: |:----: | :----:  | :----:|:----:|
256|长度| 4字节 |L<sub>pk2</sub>字节| 4字节 | L<sub>AAD2</sub>字节 | 4字节 | L<sub>Nonce2</sub>字节 |
257| 内容 | k2加密参数AEAD2长度L<sub>AEAD2</sub> | k2加密参数AEAD2 | k3密文长度L<sub>k3_enc</sub> | k3密文k3_enc |  k3加密参数AAD3长度L<sub>AAD3</sub> | k3加密参数AAD3 |
258|长度| 4字节 |L<sub>AEAD2</sub>字节| 4字节 | L<sub>k3_enc</sub>字节 | 4字节 | L<sub>AAD3</sub>字节 |
259| 内容| k3加密参数Nonce3长度L<sub>Nonce3</sub> | k3加密参数Nonce3 | k3加密参数AEAD3长度L<sub>AEAD3</sub> | k3加密参数AEAD3 |  **密钥明文材料长度** 的长度L<sub>k1'_size</sub> | 密钥明文材料长度k1'_size |
260|长度| 4字节 |L<sub>Nonce3</sub>字节| 4字节 | L<sub>AEAD3</sub>字节 | 4字节 | L<sub>k1'_size</sub>字节 |
261|内容|k1'密文长度L<sub>k1'_enc</sub>| k1'密文k1'_enc| | | | |
262|长度| 4字节 |L<sub>k1'_enc</sub>字节| | | | |
263
264**开发步骤**
265
266这里主要展示涉及调用HUKS的开发样例(使用ECDH密钥协商套件),部分在业务本地执行的步骤不在这里展示详细样例。
267
2681. 生成加密导入用途的密钥Caller_Key和Wrapping_Key
2692. 导出公钥材料
2703. 生成一个对称密钥Caller_Kek
2714. 使用Caller_Key和Wrapping_Key的公钥,协商出Agree_Key
2725. 使用Caller_Kek加密待导入密钥
2736. 使用Agree_Key加密Caller_Kek
2747. 封装加密导入密钥材料
2758. 导入封装的加密密钥材料
2769. 删除用于加密导入的密钥
277
278**代码示例:**
279
280```ts
281import huks from '@ohos.security.huks';
282import { BusinessError } from '@ohos.base';
283
284let IV = '0000000000000000';
285let AAD = "abababababababab";
286let NONCE = "hahahahahaha";
287let TAG_SIZE = 16;
288let FILED_LENGTH = 4;
289let importedAes192PlainKey = "The aes192 key to import";
290let callerAes256Kek = "The is kek to encrypt aes192 key";
291
292let callerKeyAlias = "test_caller_key_ecdh_aes192";
293let callerKekAliasAes256 = "test_caller_kek_ecdh_aes256";
294let callerAgreeKeyAliasAes256 = "test_caller_agree_key_ecdh_aes256";
295let importedKeyAliasAes192 = "test_import_key_ecdh_aes192";
296
297let huksPubKey: Uint8Array;
298let callerSelfPublicKey: Uint8Array;
299let outSharedKey: Uint8Array;
300let outPlainKeyEncData: Uint8Array;
301let outKekEncData: Uint8Array;
302let outKekEncTag: Uint8Array;
303let outAgreeKeyEncTag: Uint8Array;
304
305let mask = [0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000];
306function subUint8ArrayOf(arrayBuf: Uint8Array, start: number, end: number) {
307    let arr: number[] = [];
308    for (let i = start; i < end && i < arrayBuf.length; ++i) {
309        arr.push(arrayBuf[i]);
310    }
311    return new Uint8Array(arr);
312}
313
314function stringToUint8Array(str: string) {
315    let arr: number[] = [];
316    for (let i = 0, j = str.length; i < j; ++i) {
317        arr.push(str.charCodeAt(i));
318    }
319    return new Uint8Array(arr);
320}
321
322function assignLength(length: number, arrayBuf: Uint8Array, startIndex: number) {
323    let index = startIndex;
324    for (let i = 0; i < 4; i++) {
325        arrayBuf[index++] = (length & mask[i]) >> (i * 8);
326    }
327    return 4;
328}
329
330function assignData(data: Uint8Array, arrayBuf: Uint8Array, startIndex: number) {
331    let index = startIndex;
332    for (let i = 0; i < data.length; i++) {
333        arrayBuf[index++] = data[i];
334    }
335    return data.length;
336}
337
338
339let genWrappingKeyParams:huks.HuksOptions = {
340    properties: new Array<huks.HuksParam>(
341        {
342            tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
343            value: huks.HuksKeyAlg.HUKS_ALG_ECC
344        },
345        {
346            tag: huks.HuksTag.HUKS_TAG_PURPOSE,
347            value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_UNWRAP
348        },
349        {
350            tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
351            value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256
352        },
353        {
354            tag: huks.HuksTag.HUKS_TAG_PADDING,
355            value: huks.HuksKeyPadding.HUKS_PADDING_NONE
356        }
357    )
358}
359
360let genCallerEcdhParams:huks.HuksOptions = {
361    properties: new Array<huks.HuksParam>(
362        {
363            tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
364            value: huks.HuksKeyAlg.HUKS_ALG_ECC
365        },
366        {
367            tag: huks.HuksTag.HUKS_TAG_PURPOSE,
368            value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE
369        },
370        {
371            tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
372            value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256
373        }
374    )
375}
376
377let importParamsCallerKek: huks.HuksOptions = {
378    properties: new Array<huks.HuksParam>(
379        {
380            tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
381            value: huks.HuksKeyAlg.HUKS_ALG_AES
382        },
383        {
384            tag: huks.HuksTag.HUKS_TAG_PURPOSE,
385            value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT
386        },
387        {
388            tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
389            value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256
390        },
391        {
392            tag: huks.HuksTag.HUKS_TAG_PADDING,
393            value: huks.HuksKeyPadding.HUKS_PADDING_NONE
394        },
395        {
396            tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
397            value: huks.HuksCipherMode.HUKS_MODE_GCM
398        },
399        {
400            tag: huks.HuksTag.HUKS_TAG_DIGEST,
401            value: huks.HuksKeyDigest.HUKS_DIGEST_NONE
402        },
403        {
404            tag: huks.HuksTag.HUKS_TAG_IV,
405            value: stringToUint8Array(IV)
406        }
407    ),
408    inData: stringToUint8Array(callerAes256Kek)
409}
410
411let importParamsAgreeKey: huks.HuksOptions = {
412    properties: new Array<huks.HuksParam>(
413        {
414            tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
415            value: huks.HuksKeyAlg.HUKS_ALG_AES
416        },
417        {
418            tag: huks.HuksTag.HUKS_TAG_PURPOSE,
419            value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT
420        },
421        {
422            tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
423            value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256
424        },
425        {
426            tag: huks.HuksTag.HUKS_TAG_PADDING,
427            value: huks.HuksKeyPadding.HUKS_PADDING_NONE
428        },
429        {
430            tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
431            value: huks.HuksCipherMode.HUKS_MODE_GCM
432        },
433        {
434            tag: huks.HuksTag.HUKS_TAG_DIGEST,
435            value: huks.HuksKeyDigest.HUKS_DIGEST_NONE
436        },
437        {
438            tag: huks.HuksTag.HUKS_TAG_IV,
439            value: stringToUint8Array(IV)
440        }
441    ),
442}
443
444let callerAgreeParams: huks.HuksOptions = {
445    properties: new Array<huks.HuksParam>(
446        {
447            tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
448            value: huks.HuksKeyAlg.HUKS_ALG_ECDH
449        },
450        {
451            tag: huks.HuksTag.HUKS_TAG_PURPOSE,
452            value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE
453        },
454        {
455            tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
456            value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256
457        }
458    )
459}
460
461let encryptKeyCommonParams: huks.HuksOptions = {
462    properties: new Array<huks.HuksParam>(
463        {
464            tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
465            value: huks.HuksKeyAlg.HUKS_ALG_AES
466        },
467        {
468            tag: huks.HuksTag.HUKS_TAG_PURPOSE,
469            value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT
470        },
471        {
472            tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
473            value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256
474        },
475        {
476            tag: huks.HuksTag.HUKS_TAG_PADDING,
477            value: huks.HuksKeyPadding.HUKS_PADDING_NONE
478        },
479        {
480            tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
481            value: huks.HuksCipherMode.HUKS_MODE_GCM
482        },
483        {
484            tag: huks.HuksTag.HUKS_TAG_NONCE,
485            value: stringToUint8Array(NONCE)
486        },
487        {
488            tag: huks.HuksTag.HUKS_TAG_ASSOCIATED_DATA,
489            value: stringToUint8Array(AAD)
490        }
491    ),
492}
493
494let importWrappedAes192Params: huks.HuksOptions = {
495    properties: new Array<huks.HuksParam>(
496        {
497            tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
498            value: huks.HuksKeyAlg.HUKS_ALG_AES
499        },
500        {
501            tag: huks.HuksTag.HUKS_TAG_PURPOSE,
502            value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT |
503            huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT
504        },
505        {
506            tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
507            value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_192
508        },
509        {
510            tag: huks.HuksTag.HUKS_TAG_PADDING,
511            value: huks.HuksKeyPadding.HUKS_PADDING_NONE
512        },
513        {
514            tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
515            value: huks.HuksCipherMode.HUKS_MODE_CBC
516        },
517        {
518            tag: huks.HuksTag.HUKS_TAG_DIGEST,
519            value: huks.HuksKeyDigest.HUKS_DIGEST_NONE
520        },
521        {
522            tag: huks.HuksTag.HUKS_TAG_UNWRAP_ALGORITHM_SUITE,
523            value: huks.HuksUnwrapSuite.HUKS_UNWRAP_SUITE_ECDH_AES_256_GCM_NOPADDING
524        },
525        {
526            tag: huks.HuksTag.HUKS_TAG_IV,
527            value: stringToUint8Array(IV)
528        }
529    )
530}
531
532async function publicGenerateItemFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
533    console.info(`enter promise generateKeyItem`);
534    try {
535        await huks.generateKeyItem(keyAlias, huksOptions)
536        .then(data => {
537            console.info(`promise: generateKeyItem success, data = ${JSON.stringify(data)}`);
538        })
539        .catch((err: BusinessError) => {
540            console.error(`callback: generateKeyItem failed`);
541        })
542    } catch (err) {
543        console.error(`callback: generateKeyItem invalid`);
544    }
545}
546
547async function publicImportKeyItemFunc(keyAlias: string, HuksOptions: huks.HuksOptions) {
548    console.info(`enter promise importKeyItem`);
549    try {
550        await huks.importKeyItem(keyAlias, HuksOptions)
551        .then(data => {
552            console.info(`promise: importKeyItem success, data = ${JSON.stringify(data)}`);
553        }).catch((err: BusinessError) => {
554            console.error(`promise: importKeyItem failed`);
555        })
556    } catch (err) {
557        console.error(`promise: importKeyItem input arg invalid`);
558    }
559}
560
561async function publicDeleteKeyItemFunc(KeyAlias: string, HuksOptions: huks.HuksOptions) {
562    console.info(`enter promise deleteKeyItem`);
563    try {
564        await huks.deleteKeyItem(KeyAlias, HuksOptions)
565        .then(data => {
566            console.info(`promise: deleteKeyItem key success, data = ${JSON.stringify(data)}`);
567        })
568        .catch((err: BusinessError) => {
569            console.error(`promise: deleteKeyItem failed`);
570        })
571    } catch (err) {
572        console.error(`promise: deleteKeyItem input arg invalid`);
573    }
574}
575
576function importWrappedKeyItem(keyAlias: string, wrappingKeyAlias: string, huksOptions: huks.HuksOptions) {
577    return new Promise<void>((resolve, reject) => {
578        try {
579            huks.importWrappedKeyItem(keyAlias, wrappingKeyAlias, huksOptions, (error, data) => {
580                if (error) {
581                    reject(error);
582                } else {
583                    resolve(data);
584                }
585            });
586        } catch (error) {
587        }
588    });
589}
590
591async function publicImportWrappedKeyFunc(keyAlias: string, wrappingKeyAlias: string, huksOptions: huks.HuksOptions) {
592    console.info(`enter callback importWrappedKeyItem`);
593    for (let i = 0; i < huksOptions.inData!.length; i++) {
594        console.error(`${i}: ${huksOptions.inData![i]}`);
595    }
596    try {
597        await importWrappedKeyItem(keyAlias, wrappingKeyAlias, huksOptions)
598        .then((data) => {
599            console.info(`callback: importWrappedKeyItem success, data = ${JSON.stringify(data)}`);
600        })
601        .catch((error: BusinessError) => {
602            console.error(`callback: importWrappedKeyItem failed`);
603        });
604    } catch (error) {
605        console.error(`callback: importWrappedKeyItem input arg invalid`);
606    }
607}
608
609async function publicImportWrappedKeyPromise(keyAlias: string, wrappingKeyAlias: string, huksOptions: huks.HuksOptions) {
610    console.info(`enter callback importWrappedKeyItem`);
611    try {
612        await huks.importWrappedKeyItem(keyAlias, wrappingKeyAlias, huksOptions)
613        .then((data) => {
614            console.info(`callback: importWrappedKeyItem success, data = ${JSON.stringify(data)}`);
615        })
616        .catch((error: BusinessError) => {
617            console.error(`callback: importWrappedKeyItem failed`);
618        });
619    } catch (error) {
620        console.error(`callback: importWrappedKeyItem input arg invalid`);
621    }
622}
623
624async function publicInitFunc(srcKeyAlias: string, HuksOptions: huks.HuksOptions) {
625    let handle: number = 0;
626    console.info(`enter promise doInit`);
627    try {
628        await huks.initSession(srcKeyAlias, HuksOptions)
629        .then((data) => {
630            console.info(`promise: doInit success, data = ${JSON.stringify(data)}`);
631            handle = data.handle;
632        })
633        .catch((error: BusinessError) => {
634            console.error(`promise: doInit key failed`);
635        });
636    } catch (error) {
637        console.error(`promise: doInit input arg invalid`);
638    }
639    return handle;
640}
641
642async function publicUpdateSessionFunction(handle: number, HuksOptions: huks.HuksOptions) {
643    const maxUpdateSize = 64;
644    const inData = HuksOptions.inData!;
645    const lastInDataPosition = inData.length - 1;
646    let inDataSegSize = maxUpdateSize;
647    let inDataSegPosition = 0;
648    let isFinished = false;
649    let outData: number[] = [];
650
651    while (inDataSegPosition <= lastInDataPosition) {
652        if (inDataSegPosition + maxUpdateSize > lastInDataPosition) {
653            isFinished = true;
654            inDataSegSize = lastInDataPosition - inDataSegPosition + 1;
655            console.error(`enter promise doUpdate`);
656            break;
657        }
658        HuksOptions.inData = new Uint8Array(
659           Array.from(inData).slice(inDataSegPosition, inDataSegPosition + inDataSegSize)
660        );
661        console.error(`enter promise doUpdate`);
662        try {
663            await huks.updateSession(handle, HuksOptions)
664            .then((data) => {
665                console.error(`promise: doUpdate success, data = ${JSON.stringify(data)}`);
666                outData = outData.concat(Array.from(data.outData!));
667            })
668            .catch((error: BusinessError) => {
669                console.error(`promise: doUpdate failed`);
670            });
671        } catch (error) {
672            console.error(`promise: doUpdate input arg invalid`);
673        }
674        if ((!isFinished) && (inDataSegPosition + maxUpdateSize > lastInDataPosition)) {
675            console.log(`update size invalid isFinished = ${isFinished}`);
676            console.log(`inDataSegPosition = ${inDataSegPosition}`);
677            console.log(`lastInDataPosition = ${lastInDataPosition}`);
678            return;
679        }
680        inDataSegPosition += maxUpdateSize;
681    }
682    return outData;
683}
684
685async function publicFinishSession(handle: number, HuksOptions: huks.HuksOptions, inData: number[]) {
686    let outData: number[] = [];
687    console.info(`enter promise doFinish`);
688    try {
689        await huks.finishSession(handle, HuksOptions)
690        .then((data) => {
691            console.info(`promise: doFinish success, data = ${JSON.stringify(data)}`);
692            outData = inData.concat(Array.from(data.outData!));
693        })
694        .catch((error: BusinessError) => {
695            console.error(`promise: doFinish key failed`);
696        });
697    } catch (error) {
698        console.error(`promise: doFinish input arg invalid`);
699    }
700    return new Uint8Array(outData);
701}
702
703async function cipherFunction(keyAlias: string, HuksOptions: huks.HuksOptions) {
704    let handle = await publicInitFunc(keyAlias, HuksOptions);
705    let tmpData = await publicUpdateSessionFunction(handle, HuksOptions);
706    let outData = await publicFinishSession(handle, HuksOptions, tmpData!);
707    return outData;
708}
709
710async function agreeFunction(keyAlias: string, HuksOptions: huks.HuksOptions, huksPublicKey: Uint8Array) {
711    let handle = await publicInitFunc(keyAlias, HuksOptions);
712    let outSharedKey: Uint8Array = new Uint8Array;
713    HuksOptions.inData = huksPublicKey;
714    console.error(`enter promise doUpdate`);
715    try {
716        await huks.updateSession(handle, HuksOptions)
717        .then((data) => {
718            console.error(`promise: doUpdate success, data = ${JSON.stringify(data)}`);
719        })
720        .catch((error: BusinessError) => {
721            console.error(`promise: doUpdate failed`);
722        });
723    } catch (error) {
724        console.error(`promise: doUpdate input arg invalid`);
725    }
726    console.info(`enter promise doInit`);
727    try {
728        await huks.finishSession(handle, HuksOptions)
729        .then((data) => {
730            console.info(`promise: doInit success, data = ${JSON.stringify(data)}`);
731            outSharedKey = data.outData as Uint8Array;
732        })
733        .catch((error: BusinessError) => {
734            console.error(`promise: doInit key failed`);
735        });
736    } catch (error) {
737        console.error(`promise: doInit input arg invalid`);
738    }
739    return outSharedKey;
740}
741
742async function ImportKekAndAgreeSharedSecret(callerKekAlias: string, importKekParams: huks.HuksOptions, callerKeyAlias: string, huksPublicKey: Uint8Array, agreeParams: huks.HuksOptions) {
743    await publicImportKeyItemFunc(callerKekAlias, importKekParams);
744    outSharedKey = await agreeFunction(callerKeyAlias, agreeParams, huksPublicKey);
745
746    importParamsAgreeKey.inData = outSharedKey;
747    await publicImportKeyItemFunc(callerAgreeKeyAliasAes256, importParamsAgreeKey);
748}
749
750async function generateAndExportPublicKey(keyAlias: string, HuksOptions: huks.HuksOptions, caller: Boolean) {
751    await publicGenerateItemFunc(keyAlias, HuksOptions);
752    try {
753        await huks.exportKeyItem(keyAlias, HuksOptions)
754        .then((data) => {
755            console.info(`promise: exportKeyItem success, data = ${JSON.stringify(data)}`);
756            if (caller) {
757                callerSelfPublicKey = data.outData as Uint8Array;
758            } else {
759                huksPubKey = data.outData as Uint8Array;
760            }
761        })
762        .catch((error: BusinessError) => {
763            console.error(`promise: exportKeyItem failed`);
764        });
765    } catch (e) {
766        console.error(`promise: generate pubKey failed`);
767    }
768}
769
770async function EncryptImportedPlainKeyAndKek(keyAlias: string) {
771    encryptKeyCommonParams.inData = stringToUint8Array(keyAlias)
772    let plainKeyEncData = await cipherFunction(callerKekAliasAes256, encryptKeyCommonParams);
773    outKekEncTag = subUint8ArrayOf(plainKeyEncData, plainKeyEncData.length - TAG_SIZE, plainKeyEncData.length)
774    outPlainKeyEncData = subUint8ArrayOf(plainKeyEncData, 0, plainKeyEncData.length - TAG_SIZE)
775
776    encryptKeyCommonParams.inData = stringToUint8Array(callerAes256Kek)
777    let kekEncData = await cipherFunction(callerAgreeKeyAliasAes256, encryptKeyCommonParams)
778    outAgreeKeyEncTag = subUint8ArrayOf(kekEncData, kekEncData.length - TAG_SIZE, kekEncData.length)
779    outKekEncData = subUint8ArrayOf(kekEncData, 0, kekEncData.length - TAG_SIZE)
780}
781
782async function BuildWrappedDataAndImportWrappedKey(plainKey: string) {
783    let plainKeySizeBuff = new Uint8Array(4);
784    assignLength(plainKey.length, plainKeySizeBuff, 0);
785
786    let wrappedData = new Uint8Array(
787        FILED_LENGTH + huksPubKey.length +
788        FILED_LENGTH + AAD.length +
789        FILED_LENGTH + NONCE.length +
790        FILED_LENGTH + TAG_SIZE +
791        FILED_LENGTH + outKekEncData.length +
792        FILED_LENGTH + AAD.length +
793        FILED_LENGTH + NONCE.length +
794        FILED_LENGTH + TAG_SIZE +
795        FILED_LENGTH + plainKeySizeBuff.length +
796        FILED_LENGTH + outPlainKeyEncData.length
797    );
798    let index = 0;
799    let AADUint8Array = stringToUint8Array(AAD);
800    let NonceArray = stringToUint8Array(NONCE);
801
802    index += assignLength(callerSelfPublicKey.length, wrappedData, index);  // 4
803    index += assignData(callerSelfPublicKey, wrappedData, index); // 91
804    index += assignLength(AADUint8Array.length, wrappedData, index); // 4
805    index += assignData(AADUint8Array, wrappedData, index); // 16
806    index += assignLength(NonceArray.length, wrappedData, index); // 4
807    index += assignData(NonceArray, wrappedData, index); // 12
808    index += assignLength(outAgreeKeyEncTag.length, wrappedData, index); // 4
809    index += assignData(outAgreeKeyEncTag, wrappedData, index); // 16
810    index += assignLength(outKekEncData.length, wrappedData, index); // 4
811    index += assignData(outKekEncData, wrappedData, index); // 32
812    index += assignLength(AADUint8Array.length, wrappedData, index); // 4
813    index += assignData(AADUint8Array, wrappedData, index); // 16
814    index += assignLength(NonceArray.length, wrappedData, index); // 4
815    index += assignData(NonceArray, wrappedData, index); // 12
816    index += assignLength(outKekEncTag.length, wrappedData, index); // 4
817    index += assignData(outKekEncTag, wrappedData, index); // 16
818    index += assignLength(plainKeySizeBuff.length, wrappedData, index); // 4
819    index += assignData(plainKeySizeBuff, wrappedData, index); // 4
820    index += assignLength(outPlainKeyEncData.length, wrappedData, index); // 4
821    index += assignData(outPlainKeyEncData, wrappedData, index); // 24
822
823    return wrappedData;
824}
825
826async function ImportWrappedKey() {
827    const srcKeyAliesWrap = 'HUKS_Basic_Capability_Import_0200';
828    /*
829     * 生成、导出加密导入用途的、用于协商的密钥密钥Caller_Key和Wrapping_Key
830     */
831    await generateAndExportPublicKey(srcKeyAliesWrap, genWrappingKeyParams, false);
832    await generateAndExportPublicKey(callerKeyAlias, genCallerEcdhParams, true);
833
834    /**
835     * 生成一个对称密钥Caller_Kek
836     * 使用Caller_Key和Wrapping_Key的公钥,协商出Agree_Key
837     */
838    await ImportKekAndAgreeSharedSecret(callerKekAliasAes256, importParamsCallerKek, callerKeyAlias, huksPubKey, callerAgreeParams);
839
840    /**
841     * 使用Caller_Kek加密待导入密钥
842     * 使用Agree_Key加密Caller_Kek
843     */
844    await EncryptImportedPlainKeyAndKek(importedAes192PlainKey);
845
846    /**
847     * 封装加密导入的材料
848     */
849    let wrappedData = await BuildWrappedDataAndImportWrappedKey(importedAes192PlainKey);
850    importWrappedAes192Params.inData = wrappedData;
851
852    /**
853     * 导入封装的加密密钥材料
854     */
855    await publicImportWrappedKeyFunc(importedKeyAliasAes192, srcKeyAliesWrap, importWrappedAes192Params);
856
857    /**
858     * 删除用于加密导入的密钥
859     */
860    await publicDeleteKeyItemFunc(srcKeyAliesWrap, genWrappingKeyParams);
861    await publicDeleteKeyItemFunc(callerKeyAlias, genCallerEcdhParams);
862    await publicDeleteKeyItemFunc(importedKeyAliasAes192, importWrappedAes192Params);
863    await publicDeleteKeyItemFunc(callerKekAliasAes256, callerAgreeParams);
864}
865```
866
867**调测验证**
868
869验证时查询密钥是否存在,如密钥存在即表示生成密钥成功。
870
871**代码示例:**
872
873```ts
874import huks from '@ohos.security.huks';
875
876/*
877 * 确定密钥别名和封装密钥属性参数集
878 */
879let keyAlias = 'test_import_key_ecdh_aes192';
880let isKeyExist:Boolean;
881
882let keyProperties: Array<huks.HuksParam> = new Array();
883keyProperties[0] = {
884    tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
885    value: huks.HuksKeyAlg.HUKS_ALG_AES,
886}
887let huksOptions:huks.HuksOptions = {
888    properties: keyProperties, // 非空填充
889    inData: new Uint8Array(new Array()) // 非空填充
890}
891try {
892    huks.isKeyItemExist(keyAlias, huksOptions, (error, data)=> {
893        if (error) {
894            console.error(`callback: isKeyItemExist failed`);
895        } else {
896            if (data !== null && data.valueOf() !== null) {
897                isKeyExist = data.valueOf();
898                console.info(`callback: isKeyItemExist success, isKeyExist = ${isKeyExist}`);
899            }
900        }
901    });
902} catch (error) {
903    console.error(`callback: isKeyItemExist input arg invalid`);
904}
905```
906
907## 常见密钥操作
908
909**场景概述**
910
911为了实现对数据机密性、完整性等保护,在生成/导入密钥后,需要对数据进行密钥操作,比如加密解密、签名验签、密钥协商、密钥派生等,本章节提供了常用的密钥操作的示例。本章节提供的示例都没有设置二次身份访问控制,如设置了密钥访问控制请参考[密钥访问控制](#密钥访问控制)用法。
912
913**通用开发流程**
914
915HUKS基于密钥会话来操作数据,使用密钥时基于以下流程:
916
9171. **初始化密钥会话[huks.initSession()](../reference/apis/js-apis-huks.md#huksinitsession9):** 传入密钥别名和密钥操作参数,初始化一个密钥会话并获取会话句柄。其中密钥操作参数中必须包含对应密码算法所必须的参数,包括密码算法、密钥大小、密钥目的、工作模式、填充模式、散列模式、IV、Nonce、AAD等。如果密钥设置了访问控制属性,还需要其他参数具体[密钥访问控制](#密钥访问控制)。此步骤必选!
9182. **分段操作数据[huks.updateSession()](../reference/apis/js-apis-huks.md#huksupdatesession9):** 如数据过大(超过100K)或密码算法的要求需要对数据进行分段操作,反之可跳过此步。此步骤可选!
9193. **结束密钥会话[huks.finishSession()](../reference/apis/js-apis-huks.md#huksfinishsession9):** 操作最后一段数据并结束密钥会话,如过程中发生错误或不需要此次密钥操作数据,必须取消会话[huks.abortSession()](../reference/apis/js-apis-huks.md#huksabortsession9)。此步骤必选!
920
921### 加密解密
922
923```ts
924/*
925 * 以下以AES 128密钥的Callback操作使用为例
926 */
927import huks from '@ohos.security.huks';
928import { BusinessError } from '@ohos.base';
929
930let aesKeyAlias = 'test_aesKeyAlias';
931let handle:number;
932let plainText = '123456';
933let IV = '001122334455';
934let cipherData:Uint8Array;
935
936function StringToUint8Array(str: String) {
937    let arr:number[]=new Array();
938    for (let i = 0, j = str.length; i < j; ++i) {
939        arr.push(str.charCodeAt(i));
940    }
941    return new Uint8Array(arr);
942}
943
944function Uint8ArrayToString(fileData:Uint8Array) {
945    let dataString = '';
946    for (let i = 0; i < fileData.length; i++) {
947        dataString += String.fromCharCode(fileData[i]);
948    }
949    return dataString;
950}
951
952function GetAesGenerateProperties() {
953    let properties: Array<huks.HuksParam> = new Array();
954    let index = 0;
955    properties[index++] = {
956        tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
957        value: huks.HuksKeyAlg.HUKS_ALG_AES
958    };
959    properties[index++] = {
960        tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
961        value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_128
962    };
963    properties[index++] = {
964        tag: huks.HuksTag.HUKS_TAG_PURPOSE,
965        value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT |
966        huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT
967    }
968    return properties;
969}
970
971function GetAesEncryptProperties() {
972    let properties: Array<huks.HuksParam> = new Array();
973    let index = 0;
974    properties[index++] = {
975        tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
976        value: huks.HuksKeyAlg.HUKS_ALG_AES
977    };
978    properties[index++] = {
979        tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
980        value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_128
981    };
982    properties[index++] = {
983        tag: huks.HuksTag.HUKS_TAG_PURPOSE,
984        value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT
985    }
986    properties[index++] = {
987        tag: huks.HuksTag.HUKS_TAG_PADDING,
988        value: huks.HuksKeyPadding.HUKS_PADDING_PKCS7
989    }
990    properties[index++] = {
991        tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
992        value: huks.HuksCipherMode.HUKS_MODE_CBC
993    }
994    properties[index++] = {
995        tag: huks.HuksTag.HUKS_TAG_IV,
996        value: StringToUint8Array(IV)
997    }
998    return properties;
999}
1000
1001function GetAesDecryptProperties() {
1002    let properties: Array<huks.HuksParam> = new Array();
1003    let index = 0;
1004    properties[index++] = {
1005        tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
1006        value: huks.HuksKeyAlg.HUKS_ALG_AES
1007    };
1008    properties[index++] = {
1009        tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
1010        value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_128
1011    };
1012    properties[index++] = {
1013        tag: huks.HuksTag.HUKS_TAG_PURPOSE,
1014        value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT
1015    }
1016    properties[index++] = {
1017        tag: huks.HuksTag.HUKS_TAG_PADDING,
1018        value: huks.HuksKeyPadding.HUKS_PADDING_PKCS7
1019    }
1020    properties[index++] = {
1021        tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
1022        value: huks.HuksCipherMode.HUKS_MODE_CBC
1023    }
1024    properties[index++] = {
1025        tag: huks.HuksTag.HUKS_TAG_IV,
1026        value: StringToUint8Array(IV)
1027    }
1028    return properties;
1029}
1030
1031async function GenerateAesKey() {
1032    let genProperties = GetAesGenerateProperties();
1033    let options: huks.HuksOptions = {
1034        properties: genProperties
1035    }
1036    await huks.generateKeyItem(aesKeyAlias, options)
1037    .then((data) => {
1038        console.info(`callback: generate AES Key success, data = ${JSON.stringify(data)}`);
1039    }).catch((error: BusinessError)=>{
1040        console.error(`callback: generate AES Key failed`);
1041    })
1042}
1043
1044
1045async function EncryptData() {
1046    let encryptProperties = GetAesEncryptProperties();
1047    let options: huks.HuksOptions = {
1048        properties: encryptProperties,
1049        inData: StringToUint8Array(plainText)
1050    }
1051    await huks.initSession(aesKeyAlias, options)
1052    .then((data) => {
1053        handle = data.handle;
1054    }).catch((error: BusinessError)=>{
1055        console.error(`callback: init encryptdata failed`);
1056    })
1057    await huks.finishSession(handle, options)
1058    .then((data) => {
1059        console.info(`callback: encrypt data success, data is `+ Uint8ArrayToString(data.outData as Uint8Array));
1060        cipherData = data.outData as Uint8Array;
1061    }).catch((error: BusinessError)=>{
1062        console.error(`callback: encrypt data failed`);
1063    })
1064}
1065
1066async function DecryptData() {
1067    let decryptOptions = GetAesDecryptProperties()
1068    let options: huks.HuksOptions = {
1069        properties: decryptOptions,
1070        inData: cipherData
1071    }
1072    await huks.initSession(aesKeyAlias, options)
1073    .then((data) => {
1074        handle = data.handle;
1075    }).catch((error: BusinessError)=>{
1076        console.error(`callback: init decryptdata failed`);
1077    })
1078    await huks.finishSession(handle, options)
1079    .then((data) => {
1080        console.info(`callback: decrypt data success, data is ` + Uint8ArrayToString(data.outData as Uint8Array));
1081    }).catch((error: BusinessError)=>{
1082        console.error(`callback: decrypt data failed`);
1083    })
1084}
1085
1086async function DeleteKey() {
1087    let emptyOptions: huks.HuksOptions = {
1088        properties: []
1089    }
1090    await huks.deleteKeyItem(aesKeyAlias, emptyOptions)
1091    .then((data) => {
1092        console.info(`callback: delete data success`);
1093    }).catch((error: BusinessError)=>{
1094        console.error(`callback: delete data failed`);
1095    })
1096}
1097```
1098
1099### 密钥协商
1100
1101应用在协商密钥时建议传入[HuksKeyStorageType](../reference/apis/js-apis-huks.md#hukskeystoragetype)中定义的类型;从API10开始应用只能选择存储(HUKS_STORAGE_ONLY_USED_IN_HUKS),或者选择导出(HUKS_STORAGE_KEY_EXPORT_ALLOWED),若不传入,则默认同时支持存储和导出,存在安全问题,不推荐业务使用。
1102
1103```ts
1104/*
1105 * 以下以X25519 256 TEMP密钥的Callback操作使用为例
1106 */
1107import huks from '@ohos.security.huks';
1108import { BusinessError } from '@ohos.base';
1109
1110/*
1111 * 确定密钥别名和封装密钥属性参数集
1112 */
1113let srcKeyAliasFirst = "AgreeX25519KeyFirstAlias";
1114let srcKeyAliasSecond = "AgreeX25519KeySecondAlias";
1115let agreeX25519InData = 'AgreeX25519TestIndata';
1116let finishOutData : Uint8Array;
1117let handle: number;
1118let exportKey : Uint8Array;
1119let exportKeyFrist: Uint8Array;
1120let exportKeySecond : Uint8Array;
1121
1122/* 集成生成密钥参数集 */
1123let properties : Array<huks.HuksParam> = new Array();
1124properties[0] = {
1125    tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
1126    value: huks.HuksKeyAlg.HUKS_ALG_X25519,
1127}
1128properties[1] = {
1129    tag: huks.HuksTag.HUKS_TAG_PURPOSE,
1130    value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE,
1131}
1132properties[2] = {
1133    tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
1134    value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256,
1135}
1136properties[3] = {
1137    tag: huks.HuksTag.HUKS_TAG_DIGEST,
1138    value: huks.HuksKeyDigest.HUKS_DIGEST_NONE,
1139}
1140properties[4] = {
1141    tag: huks.HuksTag.HUKS_TAG_PADDING,
1142    value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
1143}
1144properties[5] = {
1145    tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
1146    value: huks.HuksCipherMode.HUKS_MODE_CBC,
1147}
1148properties[6] = {
1149    tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
1150    value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS,
1151}
1152let HuksOptions : huks.HuksOptions = {
1153    properties: properties,
1154    inData: new Uint8Array(new Array())
1155}
1156
1157/* 集成第一个协商参数集 */
1158let finishProperties : Array<huks.HuksParam> = new Array();
1159finishProperties[0] = {
1160    tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
1161    value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS,
1162}
1163finishProperties[1] = {
1164    tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS,
1165    value: true
1166}
1167finishProperties[2] = {
1168    tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
1169    value: huks.HuksKeyAlg.HUKS_ALG_AES,
1170}
1171finishProperties[3] = {
1172    tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
1173    value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256,
1174}
1175finishProperties[4] = {
1176    tag: huks.HuksTag.HUKS_TAG_PURPOSE,
1177    value:
1178    huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT |
1179    huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT,
1180}
1181finishProperties[5] = {
1182    tag: huks.HuksTag.HUKS_TAG_DIGEST,
1183    value: huks.HuksKeyDigest.HUKS_DIGEST_NONE,
1184}
1185finishProperties[6] = {
1186    tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS,
1187    value: StringToUint8Array(srcKeyAliasFirst+ 'final'),
1188}
1189finishProperties[7] = {
1190    tag: huks.HuksTag.HUKS_TAG_PADDING,
1191    value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
1192}
1193finishProperties[8] = {
1194    tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
1195    value: huks.HuksCipherMode.HUKS_MODE_ECB,
1196}
1197let finishOptionsFrist : huks.HuksOptions = {
1198    properties: finishProperties,
1199    inData: StringToUint8Array(agreeX25519InData)
1200}
1201/* 集成第二个协商参数集 */
1202let finishOptionsSecond : huks.HuksOptions = {
1203    properties: finishProperties,
1204    inData: StringToUint8Array(agreeX25519InData)
1205}
1206finishOptionsSecond.properties!.splice(6, 1, {
1207    tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS,
1208    value: StringToUint8Array(srcKeyAliasSecond + 'final'),
1209})
1210
1211function StringToUint8Array(str:string) {
1212    let arr: number[] = new Array();
1213    for (let i = 0, j = str.length; i < j; ++i) {
1214        arr.push(str.charCodeAt(i));
1215    }
1216return new Uint8Array(arr);
1217}
1218class throwObject {
1219    isThrow: boolean = false
1220}
1221function generateKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) {
1222    return new Promise<void>((resolve, reject) => {
1223        try {
1224            huks.generateKeyItem(keyAlias, huksOptions, (error, data) => {
1225                if (error) {
1226                    reject(error);
1227                } else {
1228                    resolve(data);
1229                }
1230            });
1231        } catch (error) {
1232            throwObject.isThrow = true;
1233            throw(error as Error);
1234        }
1235    });
1236}
1237
1238async function publicGenKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
1239    console.info(`enter callback generateKeyItem`);
1240    let throwObject :throwObject = {isThrow: false};
1241    try {
1242        await generateKeyItem(keyAlias, huksOptions, throwObject)
1243        .then((data) => {
1244            console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`);
1245        })
1246        .catch((error : BusinessError) => {
1247            if (throwObject.isThrow) {
1248                throw(error as Error);
1249            } else {
1250                console.error(`callback: generateKeyItem failed`);
1251            }
1252        });
1253    } catch (error) {
1254        console.error(`callback: generateKeyItem input arg invalid`);
1255    }
1256}
1257
1258function initSession(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) {
1259    return new Promise<huks.HuksSessionHandle>((resolve, reject) => {
1260        try {
1261            huks.initSession(keyAlias, huksOptions, (error, data) => {
1262                if (error) {
1263                    reject(error);
1264                } else {
1265                    resolve(data);
1266                }
1267            });
1268        } catch (error) {
1269            throwObject.isThrow = true;
1270            throw(error as Error);
1271        }
1272    });
1273}
1274
1275async function publicInitFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
1276    console.info(`enter callback doInit`);
1277    let throwObject:throwObject = {isThrow: false};
1278    try {
1279        await initSession(keyAlias, huksOptions, throwObject)
1280        .then ((data) => {
1281            console.info(`callback: doInit success, data = ${JSON.stringify(data)}`);
1282            handle = data.handle;
1283        })
1284        .catch((error : BusinessError) => {
1285            if (throwObject.isThrow) {
1286                throw(error as Error);
1287            } else {
1288                console.error(`callback: doInit failed`);
1289            }
1290        });
1291    } catch (error) {
1292        console.error(`callback: doInit input arg invalid`);
1293    }
1294}
1295
1296function updateSession(handle:number, huksOptions:huks.HuksOptions, throwObject:throwObject)  {
1297    return new Promise<huks.HuksReturnResult>((resolve, reject) => {
1298        try {
1299            huks.updateSession(handle, huksOptions, (error, data) => {
1300                if (error) {
1301                    reject(error);
1302                } else {
1303                    resolve(data);
1304                }
1305            });
1306        } catch (error) {
1307            throwObject.isThrow = true;
1308            throw(error as Error);
1309        }
1310    });
1311}
1312
1313async function publicUpdateFunc(handle:number, huksOptions:huks.HuksOptions) {
1314    console.info(`enter callback doUpdate`);
1315    let throwObject:throwObject = {isThrow: false};
1316    try {
1317        await updateSession(handle, huksOptions, throwObject)
1318        .then ((data) => {
1319            console.info(`callback: doUpdate success, data = ${JSON.stringify(data)}`);
1320        })
1321        .catch((error : BusinessError) => {
1322            if (throwObject.isThrow) {
1323                throw(error as Error);
1324            } else {
1325                console.error(`callback: doUpdate failed`);
1326            }
1327        });
1328    } catch (error) {
1329        console.error(`callback: doUpdate input arg invalid`);
1330    }
1331}
1332
1333function finishSession(handle:number, huksOptions:huks.HuksOptions, throwObject:throwObject) {
1334    return new Promise<huks.HuksReturnResult>((resolve, reject) => {
1335        try {
1336            huks.finishSession(handle, huksOptions, (error, data) =>{
1337                if (error) {
1338                    reject(error);
1339                } else {
1340                    resolve(data);
1341                }
1342            });
1343        } catch (error) {
1344            throwObject.isThrow = true;
1345            throw(error as Error);
1346        }
1347    });
1348}
1349
1350async function publicFinishFunc(handle:number, huksOptions:huks.HuksOptions) {
1351    console.info(`enter callback doFinish`);
1352    let throwObject:throwObject = {isThrow: false};
1353    try {
1354        await finishSession(handle, huksOptions, throwObject)
1355        .then ((data) => {
1356            finishOutData = data.outData as Uint8Array;
1357            console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`);
1358        })
1359        .catch((error : BusinessError) => {
1360            if (throwObject.isThrow) {
1361                throw(error as Error);
1362            } else {
1363                console.error(`callback: doFinish failed`);
1364            }
1365        });
1366    } catch (error) {
1367        console.error(`callback: doFinish input arg invalid`);
1368    }
1369}
1370
1371function exportKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) {
1372    return new Promise<huks.HuksReturnResult>((resolve, reject) => {
1373        try {
1374            huks.exportKeyItem(keyAlias, huksOptions, (error, data) => {
1375                if (error) {
1376                    reject(error);
1377                } else {
1378                    resolve(data);
1379                }
1380            });
1381        } catch (error) {
1382            throwObject.isThrow = true;
1383            throw(error as Error);
1384        }
1385    });
1386}
1387
1388async function publicExportKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
1389    console.info(`enter callback export`);
1390    let throwObject:throwObject = {isThrow: false};
1391    try {
1392        await exportKeyItem(keyAlias, huksOptions, throwObject)
1393        .then ((data) => {
1394            console.info(`callback: exportKeyItem success, data = ${JSON.stringify(data)}`);
1395            exportKey = data.outData as Uint8Array;
1396        })
1397        .catch((error : BusinessError) => {
1398            if (throwObject.isThrow) {
1399                throw(error as Error);
1400            } else {
1401                console.error(`callback: exportKeyItem failed`);
1402            }
1403        });
1404    } catch (error) {
1405        console.error(`callback: exportKeyItem input arg invalid`);
1406    }
1407}
1408
1409function deleteKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) {
1410    return new Promise<void>((resolve, reject) => {
1411        try {
1412            huks.deleteKeyItem(keyAlias, huksOptions, (error, data) => {
1413                if (error) {
1414                    reject(error);
1415                } else {
1416                    resolve(data);
1417                }
1418            });
1419        } catch (error) {
1420            throwObject.isThrow = true;
1421            throw(error as Error);
1422        }
1423    });
1424}
1425
1426async function publicDeleteKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
1427    console.info(`enter callback deleteKeyItem`);
1428    let throwObject : throwObject = {isThrow: false};
1429    try {
1430        await deleteKeyItem(keyAlias, huksOptions, throwObject)
1431        .then ((data) => {
1432           console.info(`callback: deleteKeyItem key success, data = ${JSON.stringify(data)}`);
1433        })
1434        .catch((error :BusinessError) => {
1435            if (throwObject.isThrow) {
1436                throw(error as Error);
1437            } else {
1438                console.error(`callback: deleteKeyItem failed`);
1439            }
1440        });
1441    } catch (error) {
1442        console.error(`callback: deletKeeyItem input arg invalid`);
1443    }
1444}
1445
1446async function testAgree() {
1447    /* 1.生成两个密钥并导出 */
1448    await publicGenKeyFunc(srcKeyAliasFirst, HuksOptions);
1449    await publicGenKeyFunc(srcKeyAliasSecond, HuksOptions);
1450
1451    await publicExportKeyFunc(srcKeyAliasFirst, HuksOptions);
1452    exportKeyFrist = exportKey;
1453    await publicExportKeyFunc(srcKeyAliasFirst, HuksOptions);
1454    exportKeySecond = exportKey;
1455
1456    /* 对第一个密钥进行协商 */
1457    await publicInitFunc(srcKeyAliasFirst, HuksOptions);
1458    HuksOptions.inData = exportKeySecond;
1459    await publicUpdateFunc(handle, HuksOptions);
1460    await publicFinishFunc(handle, finishOptionsFrist);
1461
1462    /* 对第二个密钥进行协商 */
1463    await publicInitFunc(srcKeyAliasSecond, HuksOptions);
1464    HuksOptions.inData = exportKeyFrist;
1465    await publicUpdateFunc(handle, HuksOptions);
1466    await publicFinishFunc(handle, finishOptionsSecond);
1467
1468    await publicDeleteKeyFunc(srcKeyAliasFirst, HuksOptions);
1469    await publicDeleteKeyFunc(srcKeyAliasSecond, HuksOptions);
1470}
1471```
1472
1473### 密钥派生
1474
1475应用在派生密钥时建议传入[HuksKeyStorageType](../reference/apis/js-apis-huks.md#hukskeystoragetype)中定义的类型;从API10开始应用只能选择存储(HUKS_STORAGE_ONLY_USED_IN_HUKS),或者选择导出(HUKS_STORAGE_KEY_EXPORT_ALLOWED),若不传入,则默认同时支持存储和导出,存在安全问题,不推荐业务使用。
1476
1477```ts
1478/*
1479 * 以下以HKDF256密钥的Promise操作使用为例
1480 */
1481import huks from '@ohos.security.huks';
1482import { BusinessError } from '@ohos.base';
1483
1484/*
1485 * 确定密钥别名和封装密钥属性参数集
1486 */
1487let srcKeyAlias = "hkdf_Key";
1488let deriveHkdfInData = "deriveHkdfTestIndata";
1489let handle:number;
1490let finishOutData:Uint8Array;
1491let HuksKeyDeriveKeySize = 32;
1492
1493/* 集成生成密钥参数集 */
1494let properties:Array<huks.HuksParam> = new Array();
1495properties[0] = {
1496    tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
1497    value: huks.HuksKeyAlg.HUKS_ALG_AES,
1498}
1499properties[1] = {
1500    tag: huks.HuksTag.HUKS_TAG_PURPOSE,
1501    value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DERIVE,
1502}
1503properties[2] = {
1504    tag: huks.HuksTag.HUKS_TAG_DIGEST,
1505    value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256,
1506}
1507properties[3] = {
1508    tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
1509    value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_128,
1510}
1511properties[4] = {
1512    tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
1513    value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS,
1514}
1515let huksOptions:huks.HuksOptions = {
1516    properties: properties,
1517    inData: new Uint8Array(new Array())
1518}
1519
1520/* 集成init时密钥参数集 */
1521let initProperties:Array<huks.HuksParam> = new Array();
1522initProperties[0] = {
1523    tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
1524    value: huks.HuksKeyAlg.HUKS_ALG_HKDF,
1525}
1526initProperties[1] = {
1527    tag: huks.HuksTag.HUKS_TAG_PURPOSE,
1528    value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DERIVE,
1529}
1530initProperties[2] = {
1531    tag: huks.HuksTag.HUKS_TAG_DIGEST,
1532    value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256,
1533}
1534initProperties[3] = {
1535    tag: huks.HuksTag.HUKS_TAG_DERIVE_KEY_SIZE,
1536    value: HuksKeyDeriveKeySize,
1537}
1538let initOptions:huks.HuksOptions = {
1539    properties: initProperties,
1540    inData: new Uint8Array(new Array())
1541}
1542
1543/* 集成finish时密钥参数集 */
1544let finishProperties:Array<huks.HuksParam> = new Array();
1545finishProperties[0] = {
1546    tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
1547    value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS,
1548}
1549finishProperties[1] = {
1550    tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS,
1551    value: true,
1552}
1553finishProperties[2] = {
1554    tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
1555    value: huks.HuksKeyAlg.HUKS_ALG_AES,
1556}
1557finishProperties[3] = {
1558    tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
1559    value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256,
1560}
1561finishProperties[4] = {
1562    tag: huks.HuksTag.HUKS_TAG_PURPOSE,
1563    value:
1564    huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT |
1565    huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT,
1566}
1567finishProperties[5] = {
1568    tag: huks.HuksTag.HUKS_TAG_DIGEST,
1569    value: huks.HuksKeyDigest.HUKS_DIGEST_NONE,
1570}
1571finishProperties[6] = {
1572    tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS,
1573    value: StringToUint8Array(srcKeyAlias),
1574}
1575finishProperties[7] = {
1576    tag: huks.HuksTag.HUKS_TAG_PADDING,
1577    value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
1578}
1579finishProperties[8] = {
1580    tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
1581    value: huks.HuksCipherMode.HUKS_MODE_ECB,
1582}
1583let finishOptions:huks.HuksOptions = {
1584    properties: finishProperties,
1585    inData: new Uint8Array(new Array())
1586}
1587
1588function StringToUint8Array(str:String) {
1589    let arr:number[]=new Array();
1590    for (let i = 0, j = str.length; i < j; ++i) {
1591        arr.push(str.charCodeAt(i));
1592    }
1593    return new Uint8Array(arr);
1594}
1595
1596class throwObject{
1597    isThrow=false;
1598}
1599
1600function generateKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) {
1601    return new Promise<void>((resolve, reject) => {
1602        try {
1603            huks.generateKeyItem(keyAlias, huksOptions, (error, data)=> {
1604                if (error) {
1605                    reject(error);
1606                } else {
1607                    resolve(data);
1608                }
1609            });
1610        } catch (error) {
1611            throwObject.isThrow = true;
1612            throw(error as Error);
1613        }
1614    });
1615}
1616
1617async function publicGenKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
1618    console.info(`enter callback generateKeyItem`);
1619    let throwObject:throwObject = {isThrow: false};
1620    try {
1621        await generateKeyItem(keyAlias, huksOptions, throwObject)
1622        .then((data) => {
1623            console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`);
1624        })
1625        .catch((error:BusinessError) => {
1626            if (throwObject.isThrow) {
1627                throw(error as Error);
1628            } else {
1629                console.error(`callback: generateKeyItem failed`);
1630            }
1631        });
1632    } catch (error) {
1633        console.error(`callback: generateKeyItem input arg invalid`);
1634    }
1635}
1636
1637function initSession(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) {
1638    return new Promise<huks.HuksSessionHandle>((resolve, reject) => {
1639        try {
1640            huks.initSession(keyAlias, huksOptions, (error, data)=> {
1641                if (error) {
1642                    reject(error);
1643                } else {
1644                    resolve(data);
1645                }
1646            });
1647        } catch (error) {
1648            throwObject.isThrow = true;
1649            throw(error as Error);
1650        }
1651    });
1652}
1653
1654async function publicInitFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
1655    console.info(`enter callback doInit`);
1656    let throwObject:throwObject = {isThrow: false};
1657    try {
1658        await initSession(keyAlias, huksOptions, throwObject)
1659        .then ((data) => {
1660            console.info(`callback: doInit success, data = ${JSON.stringify(data)}`);
1661            handle = data.handle;
1662        })
1663        .catch((error:BusinessError) => {
1664            if (throwObject.isThrow) {
1665                throw(error as Error);
1666            } else {
1667                console.error(`callback: doInit failed`);
1668            }
1669        });
1670    } catch (error) {
1671        console.error(`callback: doInit input arg invalid`);
1672    }
1673}
1674
1675function updateSession(handle:number, huksOptions:huks.HuksOptions, throwObject:throwObject) {
1676    return new Promise<huks.HuksOptions>((resolve, reject) => {
1677        try {
1678            huks.updateSession(handle, huksOptions, (error, data)=> {
1679                if (error) {
1680                    reject(error);
1681                } else {
1682                    resolve(data);
1683                }
1684            });
1685        } catch (error) {
1686            throwObject.isThrow = true;
1687            throw(error as Error);
1688        }
1689    });
1690}
1691
1692async function publicUpdateFunc(handle:number, huksOptions:huks.HuksOptions) {
1693    console.info(`enter callback doUpdate`);
1694    let throwObject:throwObject = {isThrow: false};
1695    try {
1696        await updateSession(handle, huksOptions, throwObject)
1697        .then ((data) => {
1698            console.info(`callback: doUpdate success, data = ${JSON.stringify(data)}`);
1699        })
1700        .catch((error:BusinessError) => {
1701            if (throwObject.isThrow) {
1702                throw(error as Error);
1703            } else {
1704                console.error(`callback: doUpdate failed`);
1705            }
1706        });
1707    } catch (error) {
1708        console.error(`callback: doUpdate input arg invalid`);
1709    }
1710}
1711
1712function finishSession(handle:number, huksOptions:huks.HuksOptions, throwObject:throwObject) {
1713    return new Promise<huks.HuksReturnResult>((resolve, reject) => {
1714        try {
1715            huks.finishSession(handle, huksOptions, (error, data)=> {
1716                if (error) {
1717                    reject(error);
1718                } else {
1719                    resolve(data);
1720                }
1721            });
1722        } catch (error) {
1723            throwObject.isThrow = true;
1724            throw(error as Error);
1725        }
1726    });
1727}
1728
1729async function publicFinishFunc(handle:number, huksOptions:huks.HuksOptions) {
1730    console.info(`enter callback doFinish`);
1731    let throwObject:throwObject = {isThrow: false};
1732    try {
1733        await finishSession(handle, huksOptions, throwObject)
1734        .then ((data) => {
1735            finishOutData = data.outData as Uint8Array;
1736            console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`);
1737        })
1738        .catch((error:BusinessError) => {
1739            if (throwObject.isThrow) {
1740                throw(error as Error);
1741            } else {
1742                console.error(`callback: doFinish failed`);
1743            }
1744        });
1745    } catch (error) {
1746        console.error(`callback: doFinish input arg invalid`);
1747    }
1748}
1749
1750function deleteKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) {
1751    return new Promise<void>((resolve, reject) => {
1752        try {
1753            huks.deleteKeyItem(keyAlias, huksOptions, (error, data)=> {
1754                if (error) {
1755                    reject(error);
1756                } else {
1757                    resolve(data);
1758                }
1759            });
1760        } catch (error) {
1761            throwObject.isThrow = true;
1762            throw(error as Error);
1763        }
1764    });
1765}
1766
1767async function publicDeleteKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
1768    console.info(`enter callback deleteKeyItem`);
1769    let throwObject:throwObject = {isThrow: false};
1770    try {
1771        await deleteKeyItem(keyAlias, huksOptions, throwObject)
1772        .then ((data) => {
1773            console.info(`callback: deleteKeyItem key success, data = ${JSON.stringify(data)}`);
1774        })
1775        .catch((error:BusinessError) => {
1776            if (throwObject.isThrow) {
1777                throw(error as Error);
1778            } else {
1779                console.error(`callback: deleteKeyItem failed`);
1780            }
1781        });
1782    } catch (error) {
1783        console.error(`callback: deletKeeyItem input arg invalid`);
1784    }
1785}
1786
1787async function testDerive() {
1788    /* 生成密钥 */
1789    await publicGenKeyFunc(srcKeyAlias, huksOptions);
1790
1791    /* 进行派生操作 */
1792    await publicInitFunc(srcKeyAlias, initOptions);
1793
1794    initOptions.inData = StringToUint8Array(deriveHkdfInData);
1795    await publicUpdateFunc(handle, initOptions);
1796    await publicFinishFunc(handle, finishOptions);
1797
1798    await publicDeleteKeyFunc(srcKeyAlias, huksOptions);
1799}
1800```
1801
1802## 密钥访问控制
1803
1804HUKS提供了全面完善的密钥访问控制能力,确保存储在HUKS中的密钥被合法正确的访问。
1805
1806首先,业务只能访问属于自己的密钥,即只能访问通过HUKS生成或导入的密钥。
1807其次,支持密钥的用户身份认证访问控制,对于高安敏感的业务密钥,需要在使用密钥的时候,再次要求用户即时的验证锁屏密码或生物特征,验证通过后,才能使用业务密钥。
1808除此之外,HUKS还支持严格限制密钥的使用用途,如支持只允许AES密钥进行加密解密,只允许RSA密钥进行签名验签。
1809
1810### 用户身份认证访问控制
1811
1812生成或导入密钥时,可以指定密钥必须经过用户身份认证后才能使用。您可以指定用于解锁设备锁屏的凭据(锁屏密码、指纹、人脸)的子集进行身份认证。在生成/导入密钥后,即使应用进程被攻击也不会导致未经用户授权的密钥访问,一般用于高敏感且高级别安全保护的场景,比如免密登录、免密支付、自动填充密码保护场景。
1813
1814除用户身份认证外,应用还须将密钥的授权访问类型(即失效条件)设置为以下两种类型之一:
1815
1816- **清除锁屏密码后密钥永久无效。** 设置此模式的前提是当前用户已经设置了锁屏密码,在生成/导入密钥后,一旦清除了锁屏密码,此类密钥将永久失效。注意,修改密码不会导致失效情况发生。此模式适合那些需要锁屏密码授权访问或用户强相关的数据保护的场景。
1817- **用户新录入生物特征后永久无效。** 此模式需要当前用户至少录入了一个生物特征(如指纹)才能生效,在生成/导入密钥后,一旦录入新的生物特征,这些密钥将永久失效。注意,仅删除生物特征不会导致失效情况发生。如果您不希望新录入的生物特征后,用户还可以授权访问原有数据(密钥保护的数据),那么可以使用此模式,如免密登录,免密支付等场景。
1818
1819此外,为了保证密钥使用时用户认证结果的有效性(不可重放),HUKS支持挑战值校验:在身份认证前,需要从HUKS获取挑战值(调用[huks.initSession()](../reference/apis/js-apis-huks.md#huksinitsession9)返回的[HuksSessionHandle](../reference/apis/js-apis-huks.md#hukssessionhandle9)中)传给用户身份认证方法(userIAM_userAuth.getAuthInstance),然后在密钥操作时校验认证令牌的挑战值。
1820
1821**开发流程**
1822
1823设置了二次用户身份认证的密钥,需要先初始化密钥会话并获取挑战值,然后将HUKS生成的挑战值传至用户身份认证方法进行用户身份认证,认证通过后获取一个认证令牌,将认证令牌传至HUKS进行密钥操作。
1824
1825![huks_key_user_auth_work_flow](./figures/huks_key_user_auth_work_flow.png)
1826
1827**接口说明**
1828
18291. 生成或导入密钥时,在密钥属性集中需指定三个参数:用户认证类型[HuksUserAuthType](../reference/apis/js-apis-huks.md#huksuserauthtype9)、授权访问类型[HuksAuthAccessType](../reference/apis/js-apis-huks.md#huksauthaccesstype9)、挑战值类型[HuksChallengeType](../reference/apis/js-apis-huks.md#hukschallengetype9)。
1830
1831   **表3** 用户认证类型:三种类型的子集
1832   | 名称            | 值  | 说明                      |
1833   | ------------------------------- |---|------------------------ |
1834   | HUKS_USER_AUTH_TYPE_FINGERPRINT |0x0001  | 用户认证类型为指纹,允许和人脸、锁屏密码同时设置  |
1835   | HUKS_USER_AUTH_TYPE_FACE     |0x0002   | 用户认证类型为人脸 ,允许和指纹、锁屏密码同时设置 |
1836   | HUKS_USER_AUTH_TYPE_PIN      |0x0004  | 用户认证类型为锁屏密码,允许和人脸、指纹同时设置 |
1837
1838   **表4** 安全访问类型:二选一
1839   | 名称                                    | 值   | 说明             |
1840   | --------------------------------------- | ---- | ------------------------------------------------ |
1841   | HUKS_AUTH_ACCESS_INVALID_CLEAR_PASSWORD | 1    | 清除锁屏密码后密钥无法访问。       |
1842   | HUKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL | 2    | 新录入生物特征后密钥无法访问,用户认证类型须包含生物认证类型。 |
1843
1844   **表5** 挑战值类型:三选一
1845   | 名称                            | 值   | 说明                        |
1846   | ------------------------------- | ---- | ------------------------------ |
1847   | HUKS_CHALLENGE_TYPE_NORMAL | 0    | 普通类型,每次密钥的使用需要独立的一次用户认证 |
1848   | HUKS_CHALLENGE_TYPE_CUSTOM        | 1    | 自定义类型,支持和多个密钥共享一次用户认证|
1849   | HUKS_CHALLENGE_TYPE_NONE         | 2    | 无挑战值类型,用户认证时不需要挑战值 |
1850
1851   > **注意**
1852   >
1853   > 当指定挑战值类型为**HUKS_CHALLENGE_TYPE_NONE** 时,不需要传递挑战值,但是存在新的限制:在用户身份认证后,一段时间内允许访问该密钥,超时后不能访问,需要重新认证才能访问。因此应用需要额外指定超时时间**HUKS_TAG_AUTH_TIMEOUT**属性(最大60秒)。
1854
18552. 使用密钥时,先初始化密钥会话,然后根据密钥生成/导入阶段指定的挑战值类型属性是否需要获取挑战值,或组装新的挑战值。
1856
1857   **表6** 使用密钥的接口介绍
1858   | 接口名                      | 描述                 |
1859   | -------------------------------------- | ----------------------------|
1860   |initSession(keyAlias: string, options: HuksOptions, callback: AsyncCallback\<HuksSessionHandle>) : void| 初始化密钥会话,获取挑战值|
1861   |updateSession(handle: number, options: HuksOptions, token: Uint8Array, callback: AsyncCallback\<HuksReturnResult>) : void| 分段操作数据,传递认证令牌|
1862   |finishSession(handle: number, options: HuksOptions, token: Uint8Array, callback: AsyncCallback\<HuksReturnResult>) : void| 结束密钥会话,传递认证令牌|
1863
1864**开发步骤**
1865
18661. 生成密钥并指定指纹访问控制和相关属性
1867
1868   ```ts
1869   import huks from '@ohos.security.huks';
1870   import { BusinessError } from '@ohos.base';
1871
1872   /*
1873    * 确定密钥别名和封装密钥属性参数集
1874    */
1875   let keyAlias = 'dh_key_fingerprint_access';
1876   let properties : Array<huks.HuksParam> = new Array();
1877   properties[0] = {
1878       tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
1879       value: huks.HuksKeyAlg.HUKS_ALG_SM4,
1880   }
1881   properties[1] = {
1882       tag: huks.HuksTag.HUKS_TAG_PURPOSE,
1883       value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT,
1884   }
1885   properties[2] = {
1886       tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
1887       value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128,
1888   }
1889   properties[3] = {
1890       tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
1891       value: huks.HuksCipherMode.HUKS_MODE_CBC,
1892   }
1893   properties[4] = {
1894       tag: huks.HuksTag.HUKS_TAG_PADDING,
1895       value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
1896   }
1897   // 指定密钥身份认证的类型:指纹
1898   properties[5] = {
1899       tag: huks.HuksTag.HUKS_TAG_USER_AUTH_TYPE,
1900       value: huks.HuksUserAuthType.HUKS_USER_AUTH_TYPE_FINGERPRINT
1901   }
1902   // 指定密钥安全授权的类型(失效类型):新录入生物特征(指纹)后无效
1903   properties[6] = {
1904       tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_ACCESS_TYPE,
1905       value: huks.HuksAuthAccessType.HUKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL
1906   }
1907   // 指定挑战值的类型:默认类型
1908   properties[7] = {
1909       tag: huks.HuksTag.HUKS_TAG_CHALLENGE_TYPE,
1910       value: huks.HuksChallengeType.HUKS_CHALLENGE_TYPE_NORMAL
1911   }
1912   let huksOptions : huks.HuksOptions = {
1913       properties: properties,
1914       inData: new Uint8Array(new Array())
1915   }
1916
1917   /*
1918    * 生成密钥
1919    */
1920   class throwObject {
1921       isThrow:boolean = false
1922   }
1923   function generateKeyItem(keyAlias : string, huksOptions:huks.HuksOptions, throwObject:throwObject) {
1924       return new Promise<void>((resolve, reject) => {
1925           try {
1926               huks.generateKeyItem(keyAlias, huksOptions, (error, data) => {
1927                   if (error) {
1928                       reject(error);
1929                   } else {
1930                       resolve(data);
1931                   }
1932               });
1933           } catch (error) {
1934               throwObject.isThrow = true;
1935               throw(error as Error);
1936           }
1937       });
1938   }
1939
1940   async function publicGenKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
1941       console.info(`enter callback generateKeyItem`);
1942       let throwObject : throwObject = {isThrow: false};
1943       try {
1944           await generateKeyItem(keyAlias, huksOptions, throwObject)
1945           .then((data) => {
1946               console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`);
1947           })
1948           .catch((error : BusinessError) => {
1949               if (throwObject.isThrow) {
1950                   throw(error as Error);
1951               } else {
1952                   console.error(`callback: generateKeyItem failed`);
1953               }
1954           });
1955       } catch (error) {
1956           console.error(`callback: generateKeyItem input arg invalid`);
1957       }
1958   }
1959
1960   async function TestGenKeyForFingerprintAccessControl() {
1961       await publicGenKeyFunc(keyAlias, huksOptions);
1962   }
1963   ```
1964
19652. 初始化密钥会话获取挑战值并发起指纹认证获取认证令牌
1966
1967   ```ts
1968   import huks from '@ohos.security.huks';
1969   import userIAM_userAuth from '@ohos.userIAM.userAuth';
1970   import { BusinessError } from '@ohos.base';
1971
1972   /*
1973    * 确定密钥别名和封装密钥属性参数集
1974    */
1975   let srcKeyAlias = 'sm4_key_fingerprint_access';
1976   let handle : number;
1977   let challenge : Uint8Array;
1978   let fingerAuthToken : Uint8Array;
1979   let authType = userIAM_userAuth.UserAuthType.FINGERPRINT;
1980   let authTrustLevel = userIAM_userAuth.AuthTrustLevel.ATL1;
1981
1982   /* 集成生成密钥参数集 & 加密参数集 */
1983   let properties : Array<huks.HuksParam> = new Array();
1984   properties[0] = {
1985       tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
1986       value: huks.HuksKeyAlg.HUKS_ALG_SM4,
1987   }
1988   properties[1] = {
1989       tag: huks.HuksTag.HUKS_TAG_PURPOSE,
1990       value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT,
1991   }
1992   properties[2] = {
1993       tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
1994       value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128,
1995   }
1996   properties[3] = {
1997       tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
1998       value: huks.HuksCipherMode.HUKS_MODE_CBC,
1999   }
2000   properties[4] = {
2001       tag: huks.HuksTag.HUKS_TAG_PADDING,
2002       value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
2003   }
2004   let huksOptions : huks.HuksOptions = {
2005       properties: properties,
2006       inData: new Uint8Array(new Array())
2007   }
2008
2009   class throwObject {
2010       isThrow:boolean=false
2011   }
2012
2013   function initSession(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) {
2014       return new Promise<huks.HuksSessionHandle>((resolve, reject) => {
2015           try {
2016               huks.initSession(keyAlias, huksOptions, (error, data) =>{
2017                   if (error) {
2018                       reject(error);
2019                   } else {
2020                       resolve(data);
2021                   }
2022               });
2023           } catch (error) {
2024               throwObject.isThrow = true;
2025               throw(error as Error);
2026           }
2027       });
2028   }
2029
2030   async function publicInitFunc(keyAlias:string, huksOptions:huks.HuksOptions) {
2031       console.info(`enter callback doInit`);
2032       let throwObject : throwObject = {isThrow: false};
2033       try {
2034           await initSession(keyAlias, huksOptions, throwObject)
2035           .then ((data) => {
2036               console.info(`callback: doInit success, data = ${JSON.stringify(data)}`);
2037               handle = data.handle;
2038               challenge = data.challenge as Uint8Array;
2039           })
2040           .catch((error : BusinessError) => {
2041               if (throwObject.isThrow) {
2042                   throw(error as Error);
2043               } else {
2044                   console.error(`callback: doInit failed`);
2045               }
2046           });
2047       } catch (error) {
2048           console.error(`callback: doInit input arg invalid`);
2049       }
2050   }
2051
2052   function userIAMAuthFinger(huksChallenge:Uint8Array) {
2053       // 获取认证对象
2054       let auth : userIAM_userAuth.AuthInstance;
2055       try {
2056           auth = userIAM_userAuth.getAuthInstance(huksChallenge, authType, authTrustLevel);
2057           console.log("get auth instance success");
2058       } catch (error) {
2059           console.log("get auth instance failed" + error);
2060           return;
2061       }
2062
2063       // 订阅认证结果
2064       try {
2065           auth.on("result", {
2066               callback: (result:userIAM_userAuth.AuthResultInfo) => {
2067               /* 认证成功获取认证令牌 */
2068               fingerAuthToken = result.token as Uint8Array;
2069           }
2070       });
2071           console.log("subscribe authentication event success");
2072       } catch (error) {
2073           console.log("subscribe authentication event failed " + error);
2074       }
2075
2076       // 开始认证
2077       try {
2078           auth.start();
2079           console.info("authV9 start auth success");
2080       } catch (error) {
2081           console.info("authV9 start auth failed, error = " + error);
2082       }
2083   }
2084
2085   async function testInitAndAuthFinger() {
2086       /* 初始化密钥会话获取挑战值 */
2087       await publicInitFunc(srcKeyAlias, huksOptions);
2088       /* 调用userIAM进行身份认证 */
2089       userIAMAuthFinger(challenge);
2090   }
2091   ```
2092
20933. 传入认证令牌进行数据操作
2094
2095   ```ts
2096   /*
2097   * 以下以SM4 128密钥的Callback操作使用为例
2098   */
2099   import huks from '@ohos.security.huks';
2100   import { BusinessError } from '@ohos.base';
2101
2102   /*
2103   * 确定密钥别名和封装密钥属性参数集
2104   */
2105   let srcKeyAlias = 'sm4_key_fingerprint_access';
2106   let IV = '1234567890123456';
2107   let cipherInData = 'Hks_SM4_Cipher_Test_101010101010101010110_string';
2108   let handle: number;
2109   let fingerAuthToken: Uint8Array;
2110   let finishOutData: Uint8Array;
2111
2112   class throwObject {
2113       isThrow: boolean = false;
2114   }
2115
2116   /* 集成生成密钥参数集 & 加密参数集 */
2117   class propertyEncryptType {
2118       tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM;
2119       value: huks.HuksKeyAlg | huks.HuksKeyPurpose | huks.HuksKeySize | huks.HuksKeyPadding | huks.HuksCipherMode
2120           | Uint8Array = huks.HuksKeyAlg.HUKS_ALG_SM4;
2121   }
2122
2123   let propertiesEncrypt: propertyEncryptType[] = [
2124       {
2125           tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
2126           value: huks.HuksKeyAlg.HUKS_ALG_SM4,
2127       },
2128       {
2129           tag: huks.HuksTag.HUKS_TAG_PURPOSE,
2130           value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT,
2131       },
2132       {
2133           tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
2134           value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128,
2135       },
2136       {
2137           tag: huks.HuksTag.HUKS_TAG_PADDING,
2138           value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
2139       },
2140       {
2141           tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
2142           value: huks.HuksCipherMode.HUKS_MODE_CBC,
2143       },
2144       {
2145           tag: huks.HuksTag.HUKS_TAG_IV,
2146           value: StringToUint8Array(IV),
2147       }
2148   ]
2149
2150   let encryptOptions: huks.HuksOptions = {
2151       properties: propertiesEncrypt,
2152       inData: new Uint8Array(new Array())
2153   }
2154
2155   function StringToUint8Array(str: string) {
2156       let arr: number[] = [];
2157       for (let i = 0, j = str.length; i < j; ++i) {
2158           arr.push(str.charCodeAt(i));
2159       }
2160       return new Uint8Array(arr);
2161   }
2162
2163   function updateSession(handle: number, huksOptions: huks.HuksOptions, token: Uint8Array, throwObject: throwObject) {
2164       return new Promise<huks.HuksReturnResult>((resolve, reject) => {
2165           try {
2166               huks.updateSession(handle, huksOptions, token, (error, data) => {
2167                   if (error) {
2168                       reject(error);
2169                   } else {
2170                       resolve(data);
2171                   }
2172               });
2173           } catch (error) {
2174               throwObject.isThrow = true;
2175               throw(error as Error);
2176           }
2177       });
2178   }
2179
2180   async function publicUpdateFunc(handle: number, token: Uint8Array, huksOptions: huks.HuksOptions) {
2181       console.info(`enter callback doUpdate`);
2182       let throwObject: throwObject = {isThrow: false};
2183       try {
2184           await updateSession(handle, huksOptions, token, throwObject)
2185           .then ((data) => {
2186               console.info(`callback: doUpdate success, data = ${JSON.stringify(data)}`);
2187           })
2188           .catch((error: BusinessError) => {
2189               if (throwObject.isThrow) {
2190                   throw(error as Error);
2191               } else {
2192                   console.error(`callback: doUpdate failed`);
2193               }
2194           });
2195       } catch (error) {
2196           console.error(`callback: doUpdate input arg invalid`);
2197       }
2198   }
2199
2200   function finishSession(handle: number, huksOptions: huks.HuksOptions, token: Uint8Array, throwObject: throwObject) {
2201       return new Promise<huks.HuksReturnResult>((resolve, reject) => {
2202           try {
2203               huks.finishSession(handle, huksOptions, token, (error, data) => {
2204                   if (error) {
2205                       reject(error);
2206                   } else {
2207                       resolve(data);
2208                   }
2209               });
2210           } catch (error) {
2211               throwObject.isThrow = true;
2212               throw(error as Error);
2213           }
2214       });
2215   }
2216
2217   async function publicFinishFunc(handle: number, token: Uint8Array, huksOptions: huks.HuksOptions) {
2218       console.info(`enter callback doFinish`);
2219       let throwObject: throwObject = {isThrow: false};
2220       try {
2221           await finishSession(handle, huksOptions, token, throwObject)
2222           .then ((data) => {
2223               finishOutData = data.outData as Uint8Array;
2224               console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`);
2225           })
2226           .catch((error: BusinessError) => {
2227               if (throwObject.isThrow) {
2228                   throw(error as Error);
2229               } else {
2230                   console.error(`callback: doFinish failed`);
2231               }
2232           });
2233       } catch (error) {
2234           console.error(`callback: doFinish input arg invalid`);
2235       }
2236   }
2237
2238   async function testSm4Cipher() {
2239       encryptOptions.inData = StringToUint8Array(cipherInData);
2240       /* 传入认证令牌 */
2241       await publicUpdateFunc(handle, fingerAuthToken, encryptOptions);
2242       encryptOptions.inData = new Uint8Array(new Array());
2243       /* 传入认证令牌 */
2244       await publicFinishFunc(handle, fingerAuthToken, encryptOptions);
2245       if (finishOutData === StringToUint8Array(cipherInData)) {
2246           console.info('test finish encrypt err ');
2247       } else {
2248           console.info('test finish encrypt success');
2249       }
2250   }
2251   ```
2252
2253### 细粒度用户身份认证访问控制
2254
2255该功能是基于已有[密钥访问控制](#密钥访问控制)能力的扩展,提供了基于生物特征和锁屏密码二次身份认证的细粒度访问控制能力,允许设置密钥在加密、解密、签名、验签、密钥协商、密钥派生的单个或多个场景时是否需要进行身份验证。比如,业务需要使用HUKS密钥加密保存帐号密码信息等数据,要求在加密的时候不进行指纹等身份认证,解密的时候需要进行指纹等身份认证,这是就需要依赖HUKS提供细粒度的二次身份认证访问控制机制。
2256
2257**开发流程**
2258
22591. 基于用户身份认证访问控制的流程,在密钥生成阶段,通过额外指定用于细粒度用户身份认证访问控制的HuksTag:[HUKS_TAG_KEY_AUTH_PURPOSE](../reference/apis/js-apis-huks.md#hukstag)值,来指定在某种算法用途的情况下需要使用用户身份认证访问控制能力。
22602. 基于用户身份认证访问控制的流程,在密钥使用阶段,业务无需再次指定HUKS_TAG_KEY_AUTH_PURPOSE值,同用户身份认证访问控制的开发流程。
2261
2262**接口说明**
2263
2264新增用于细粒度用户身份认证访问控制的HuksTag:[HUKS_TAG_KEY_AUTH_PURPOSE](../reference/apis/js-apis-huks.md#hukstag),该Tag值取值范围为枚举类[HuksKeyAlg](../reference/apis/js-apis-huks.md#hukskeyalg)。
2265
2266**表7** 细粒度用户身份认证访问控制Tag类型介绍
2267| 名称                      | 描述                 |
2268| -------------------------------------- | ----------------------------|
2269|HUKS_TAG_KEY_AUTH_PURPOSE| 表示密钥认证用途的tag,用于设置某种算法用途下需要用户身份认证访问控制|
2270
2271**注意**
2272
22731. 当业务未指定用户认证类型[HuksUserAuthType](../reference/apis/js-apis-huks.md#huksuserauthtype9)时表示默认都不需要用户身份认证访问控制能力,则此时设置HUKS_TAG_KEY_AUTH_PURPOSE是默认无效的; 当业务指定了[HuksUserAuthType](../reference/apis/js-apis-huks.md#huksuserauthtype9)时表示需要用户身份认证访问控制能力,此时若不设置HUKS_TAG_KEY_AUTH_PURPOSE值,则生成密钥阶段指定的算法用途在密钥使用时都默认需要进行用户身份认证访问控制。
22742. 当指定的算法是对称算法AES和SM4时,且同时指定用于加解密用途,则只允许设置CBC模式,其它模式不支持细粒度用户身份认证访问控制能力。
2275
2276**开发步骤**
2277
2278示例场景:密钥生成阶段,生成用于加解密的密钥并指定只有解密的时候需要用户身份认证访问控制;密钥使用阶段,加密时不需要用户身份认证访问控制,解密时需要用户身份认证访问控制
2279
22801. 生成密钥并指定指纹访问控制和相关属性,以及HUKS_TAG_KEY_AUTH_PURPOSE值
2281
2282   ```ts
2283   import huks from '@ohos.security.huks';
2284   import { BusinessError } from '@ohos.base';
2285
2286   /*
2287    * 确定密钥别名和封装密钥属性参数集
2288    */
2289   let keyAlias = 'dh_key_fingerprint_access';
2290
2291   class throwObject {
2292       isThrow: boolean = false;
2293   }
2294
2295   class propertyType {
2296       tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM;
2297       value: huks.HuksKeyAlg | huks.HuksKeyPurpose | huks.HuksKeySize | huks.HuksCipherMode | huks.HuksKeyPadding
2298           | huks.HuksUserAuthType | huks.HuksAuthAccessType | huks.HuksChallengeType = huks.HuksKeyAlg.HUKS_ALG_SM4
2299   }
2300   let properties: propertyType[] = [
2301       {
2302           tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
2303           value: huks.HuksKeyAlg.HUKS_ALG_SM4,
2304       },
2305       {
2306           tag: huks.HuksTag.HUKS_TAG_PURPOSE,
2307           value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT,
2308       },
2309       {
2310           tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
2311           value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128,
2312       },
2313       {
2314           tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
2315           value: huks.HuksCipherMode.HUKS_MODE_CBC,
2316       },
2317       {
2318           tag: huks.HuksTag.HUKS_TAG_PADDING,
2319           value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
2320       },
2321       {
2322           tag: huks.HuksTag.HUKS_TAG_USER_AUTH_TYPE,
2323           value: huks.HuksUserAuthType.HUKS_USER_AUTH_TYPE_FINGERPRINT
2324       },
2325       {
2326           tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_ACCESS_TYPE,
2327           value: huks.HuksAuthAccessType.HUKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL
2328       },
2329       {
2330           tag: huks.HuksTag.HUKS_TAG_CHALLENGE_TYPE,
2331           value: huks.HuksChallengeType.HUKS_CHALLENGE_TYPE_NORMAL
2332       },
2333       {
2334           tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_PURPOSE,
2335           value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT
2336       }
2337   ]
2338
2339   let huksOptions: huks.HuksOptions = {
2340       properties: properties,
2341       inData: new Uint8Array(new Array())
2342   }
2343
2344   /*
2345    * 生成密钥
2346    */
2347   async function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) {
2348       return new Promise<void>((resolve, reject) => {
2349           try {
2350               huks.generateKeyItem(keyAlias, huksOptions, (error, data) => {
2351                   if (error) {
2352                       reject(error);
2353                   } else {
2354                       resolve(data);
2355                   }
2356               });
2357           } catch (error) {
2358               throwObject.isThrow = true;
2359               throw(error as Error);
2360           }
2361       });
2362   }
2363
2364   async function publicGenKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
2365       console.info(`enter callback generateKeyItem`);
2366       let throwObject: throwObject = {isThrow: false};
2367       try {
2368           await generateKeyItem(keyAlias, huksOptions, throwObject)
2369           .then((data) => {
2370               console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`);
2371           })
2372           .catch((error: BusinessError) => {
2373               if (throwObject.isThrow) {
2374                   throw(error as Error);
2375               } else {
2376                   console.error(`callback: generateKeyItem failed`);
2377               }
2378           });
2379       } catch (error) {
2380           console.error(`callback: generateKeyItem input arg invalid`);
2381       }
2382   }
2383
2384   async function TestGenKeyForFingerprintAccessControl() {
2385       await publicGenKeyFunc(keyAlias, huksOptions);
2386   }
2387   ```
2388
23892. 使用密钥-加密场景-加密时不需要进行用户身份认证访问控制
2390
2391   ```ts
2392   import huks from '@ohos.security.huks';
2393   import { BusinessError } from '@ohos.base';
2394
2395   class HuksProperties {
2396       tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM;
2397       value: huks.HuksKeyAlg | huks.HuksKeySize | huks.HuksKeyPurpose | huks.HuksKeyPadding | huks.HuksCipherMode
2398           | Uint8Array = huks.HuksKeyAlg.HUKS_ALG_ECC;
2399   }
2400
2401   /*
2402    * 确定密钥别名和封装密钥属性参数集
2403    */
2404   let srcKeyAlias = 'sm4_key_fingerprint_access';
2405   let cipherInData = 'Hks_SM4_Cipher_Test_101010101010101010110_string'; // 明文数据
2406   let IV = '1234567890123456';
2407   let handle = 0;
2408   let cipherText: Uint8Array; // 加密后的密文数据
2409
2410   function StringToUint8Array(str: string) {
2411       let arr: number[] = [];
2412       for (let i = 0, j = str.length; i < j; ++i) {
2413           arr.push(str.charCodeAt(i));
2414       }
2415       return new Uint8Array(arr);
2416   }
2417
2418   /* 集成生成密钥参数集 & 加密参数集 */
2419   let propertiesEncrypt: HuksProperties[] = [
2420       {
2421           tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
2422           value: huks.HuksKeyAlg.HUKS_ALG_SM4,
2423       },
2424       {
2425           tag: huks.HuksTag.HUKS_TAG_PURPOSE,
2426           value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT,
2427       },
2428       {
2429           tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
2430           value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128,
2431       },
2432       {
2433           tag: huks.HuksTag.HUKS_TAG_PADDING,
2434           value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
2435       },
2436       {
2437           tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
2438           value: huks.HuksCipherMode.HUKS_MODE_CBC,
2439       },
2440       {
2441           tag: huks.HuksTag.HUKS_TAG_IV,
2442           value: StringToUint8Array(IV),
2443       }
2444   ];
2445   let encryptOptions: huks.HuksOptions = {
2446       properties: propertiesEncrypt,
2447       inData: new Uint8Array(new Array())
2448   }
2449   class throwObject1{
2450       isThrow: boolean = false;
2451   }
2452   function initSession(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject1) {
2453       return new Promise<huks.HuksSessionHandle>((resolve, reject) => {
2454           try {
2455               huks.initSession(keyAlias, huksOptions, (error, data) => {
2456                   if (error) {
2457                       reject(error);
2458                   } else {
2459                       resolve(data);
2460                   }
2461               });
2462           } catch (error) {
2463               throwObject.isThrow = true;
2464               throw (error as Error);
2465           }
2466       });
2467   }
2468
2469   async function publicInitFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
2470       console.info(`enter callback doInit`);
2471       let throwObject: throwObject1 = { isThrow: false };
2472       try {
2473           await initSession(keyAlias, huksOptions, throwObject)
2474           .then((data) => {
2475               console.info(`callback: doInit success, data = ${JSON.stringify(data)}`);
2476               handle = data.handle as number;
2477           })
2478           .catch((error: BusinessError) => {
2479               if (throwObject.isThrow) {
2480                   throw (error as Error);
2481               } else {
2482                   console.error(`callback: doInit failed`);
2483               }
2484           });
2485       } catch (error) {
2486           console.error(`callback: doInit input arg invalid`);
2487       }
2488   }
2489
2490   function finishSession(handle: number, huksOptions: huks.HuksOptions, throwObject: throwObject1) {
2491       return new Promise<huks.HuksReturnResult>((resolve, reject) => {
2492           try {
2493               huks.finishSession(handle, huksOptions, (error, data) => {
2494                   if (error) {
2495                       reject(error);
2496                   } else {
2497                       resolve(data);
2498                   }
2499               });
2500           } catch (error) {
2501               throwObject.isThrow = true;
2502               throw (error as Error);
2503           }
2504       });
2505   }
2506
2507   async function publicFinishFunc(handle: number, huksOptions: huks.HuksOptions) {
2508       console.info(`enter callback doFinish`);
2509       let throwObject: throwObject1 = { isThrow: false };
2510       try {
2511           await finishSession(handle, huksOptions, throwObject)
2512           .then((data) => {
2513               cipherText = data.outData as Uint8Array;
2514               console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`);
2515           })
2516           .catch((error: BusinessError) => {
2517               if (throwObject.isThrow) {
2518                   throw (error as Error);
2519               } else {
2520                   console.error(`callback: doFinish failed`);
2521               }
2522           });
2523       } catch (error) {
2524           console.error(`callback: doFinish input arg invalid`);
2525       }
2526   }
2527
2528   async function testSm4Cipher() {
2529       /* 初始化密钥会话获取挑战值 */
2530       await publicInitFunc(srcKeyAlias, encryptOptions);
2531
2532       /* 加密 */
2533       encryptOptions.inData = StringToUint8Array(cipherInData);
2534       await publicFinishFunc(handle, encryptOptions);
2535   }
2536   ```
2537
25383. 使用密钥-解密场景-解密时需要进行用户身份认证访问控制
2539
2540   ```ts
2541   import huks from '@ohos.security.huks';
2542   import userIAM_userAuth from '@ohos.userIAM.userAuth';
2543   import { BusinessError } from '@ohos.base';
2544
2545   /*
2546    * 确定密钥别名和封装密钥属性参数集
2547    */
2548   let srcKeyAlias = 'sm4_key_fingerprint_access';
2549   let cipherText = 'r56ywtTJUQC6JFJ2VV2kZw=='; // 加密时得到的密文数据, 业务需根据实际加密结果修改
2550   let IV = '1234567890123456';
2551   let handle: number;
2552   let finishOutData: Uint8Array; // 解密后的明文数据
2553   let fingerAuthToken: Uint8Array;
2554   let challenge: Uint8Array;
2555   let authType = userIAM_userAuth.UserAuthType.FINGERPRINT;
2556   let authTrustLevel = userIAM_userAuth.AuthTrustLevel.ATL1;
2557
2558   class throwObject {
2559       isThrow: boolean = false;
2560   }
2561
2562   function StringToUint8Array(str: string) {
2563       let arr: number[] = [];
2564       for (let i = 0, j = str.length; i < j; ++i) {
2565           arr.push(str.charCodeAt(i));
2566       }
2567       return new Uint8Array(arr);
2568   }
2569
2570   /* 集成生成密钥参数集 & 加密参数集 */
2571   class propertyDecryptType {
2572       tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM
2573       value: huks.HuksKeyAlg | huks.HuksKeyPurpose | huks.HuksKeySize | huks.HuksKeyPadding | huks.HuksCipherMode
2574           | Uint8Array = huks.HuksKeyAlg.HUKS_ALG_SM4
2575   }
2576
2577   let propertiesDecrypt: propertyDecryptType[] = [
2578       {
2579           tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
2580           value: huks.HuksKeyAlg.HUKS_ALG_SM4,
2581       },
2582       {
2583           tag: huks.HuksTag.HUKS_TAG_PURPOSE,
2584           value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT,
2585       },
2586       {
2587           tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
2588           value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128,
2589       },
2590       {
2591           tag: huks.HuksTag.HUKS_TAG_PADDING,
2592           value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
2593       },
2594       {
2595           tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
2596           value: huks.HuksCipherMode.HUKS_MODE_CBC,
2597       },
2598       {
2599           tag: huks.HuksTag.HUKS_TAG_IV,
2600           value: StringToUint8Array(IV),
2601       }
2602   ]
2603
2604   let decryptOptions: huks.HuksOptions = {
2605       properties: propertiesDecrypt,
2606       inData: new Uint8Array(new Array())
2607   }
2608
2609   function initSession(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) {
2610       return new Promise<huks.HuksSessionHandle>((resolve, reject) => {
2611           try {
2612               huks.initSession(keyAlias, huksOptions, (error, data) => {
2613                   if (error) {
2614                       reject(error);
2615                   } else {
2616                       resolve(data);
2617                   }
2618               });
2619           } catch (error) {
2620               throwObject.isThrow = true;
2621               throw(error as Error);
2622           }
2623       });
2624   }
2625
2626   async function publicInitFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
2627       console.info(`enter callback doInit`);
2628       let throwObject: throwObject = {isThrow: false};
2629       try {
2630           await initSession(keyAlias, huksOptions, throwObject)
2631           .then ((data) => {
2632               console.info(`callback: doInit success, data = ${JSON.stringify(data)}`);
2633               handle = data.handle;
2634               challenge = data.challenge as Uint8Array;
2635           })
2636           .catch((error: BusinessError) => {
2637               if (throwObject.isThrow) {
2638                   throw(error as Error);
2639               } else {
2640                   console.error(`callback: doInit failed`);
2641               }
2642           });
2643       } catch (error) {
2644           console.error(`callback: doInit input arg invalid`);
2645       }
2646   }
2647
2648   function userIAMAuthFinger(huksChallenge: Uint8Array) {
2649       // 获取认证对象
2650       let auth: userIAM_userAuth.AuthInstance ;
2651       try {
2652           auth = userIAM_userAuth.getAuthInstance(huksChallenge, authType, authTrustLevel);
2653           console.log("get auth instance success");
2654       } catch (error) {
2655           console.log("get auth instance failed" + error);
2656           return;
2657       }
2658
2659       // 订阅认证结果
2660       try {
2661           auth.on("result", {
2662               callback: (result) => {
2663                   /* 认证成功获取认证令牌 */
2664                   fingerAuthToken = (result as userIAM_userAuth.AuthResultInfo).token as Uint8Array;
2665               }
2666           });
2667           console.log("subscribe authentication event success");
2668       } catch (error) {
2669           console.log("subscribe authentication event failed " + error);
2670       }
2671
2672       // 开始认证
2673       try {
2674           auth.start();
2675           console.info("authV9 start auth success");
2676       } catch (error) {
2677           console.info("authV9 start auth failed, error = " + error);
2678       }
2679   }
2680
2681   function finishSession(handle: number, huksOptions: huks.HuksOptions, token: Uint8Array, throwObject: throwObject) {
2682       return new Promise<huks.HuksReturnResult>((resolve, reject) => {
2683           try {
2684               huks.finishSession(handle, huksOptions, token, (error, data) => {
2685                   if (error) {
2686                       reject(error);
2687                   } else {
2688                       resolve(data);
2689                   }
2690               });
2691           } catch (error) {
2692               throwObject.isThrow = true;
2693               throw(error as Error);
2694           }
2695       });
2696   }
2697
2698   async function publicFinishFunc(handle: number, token: Uint8Array, huksOptions: huks.HuksOptions) {
2699       console.info(`enter callback doFinish`);
2700       let throwObject: throwObject = {isThrow: false};
2701       try {
2702           await finishSession(handle, huksOptions, token, throwObject)
2703           .then ((data) => {
2704               finishOutData = data.outData as Uint8Array;
2705               console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`);
2706           })
2707           .catch((error: BusinessError) => {
2708               if (throwObject.isThrow) {
2709                   throw(error as Error);
2710               } else {
2711                   console.error(`callback: doFinish failed`);
2712               }
2713           });
2714       } catch (error) {
2715           console.error(`callback: doFinish input arg invalid`);
2716       }
2717   }
2718
2719   async function testSm4Cipher() {
2720       /* 初始化密钥会话获取挑战值 */
2721       await publicInitFunc(srcKeyAlias, decryptOptions);
2722
2723       /* 调用userIAM进行身份认证 */
2724       userIAMAuthFinger(challenge);
2725
2726       /* 认证成功后进行解密, 需要传入Auth获取到的authToken值 */
2727       decryptOptions.inData = StringToUint8Array(cipherText);
2728       await publicFinishFunc(handle, fingerAuthToken, decryptOptions);
2729   }
2730   ```
2731
2732## 密钥证明
2733
2734HUKS为密钥提供合法性证明能力,主要应用于非对称密钥的公钥的证明。基于PKI证书链技术,HUKS可以为存储在HUKS中的非对称密钥对的公钥签发证书,证明其公钥的合法性。业务可以通过OpenHarmony提供的根CA证书,逐级验证HUKS签发的密钥证明证书,来确保证书中的公钥以及对应的私钥,确实来自合法的硬件设备,且存储管理在HUKS中。
2735
2736**开发流程**
2737
27381. 指定密钥别名和需要证明的密钥属性的标签传入HUKS。
27392. 调用HUKS为应用生成一个依次由根CA证书、设备CA证书、设备证书、密钥证书组成的X.509证书链。
27403. 将证书链传输至受信任的服务器,并在服务器上解析和验证证书链的有效性和单个证书是否吊销。
2741
2742**接口说明**
2743
2744**表8** 密钥认证接口介绍
2745| 接口名                      | 描述                 |
2746| -------------------------------------- | ----------------------------|
2747|attestKeyItem(keyAlias: string, options: HuksOptions, callback: AsyncCallback\<HuksReturnResult>) : void| 密钥认证|
2748
2749**开发步骤**
2750
2751```ts
2752/*
2753 * 以下以attestKey Callback接口操作验证为例
2754 */
2755import huks from '@ohos.security.huks';
2756import { BusinessError } from '@ohos.base';
2757
2758/*
2759 * 确定密钥别名和封装密钥属性参数集
2760 */
2761let keyAliasString = "key attest";
2762let aliasString = keyAliasString;
2763let aliasUint8 = StringToUint8Array(keyAliasString);
2764let securityLevel = StringToUint8Array('sec_level');
2765let challenge = StringToUint8Array('challenge_data');
2766let versionInfo = StringToUint8Array('version_info');
2767let attestCertChain: Array<string>;
2768
2769class throwObject {
2770    isThrow: boolean = false;
2771}
2772
2773class genKeyPropertyType {
2774    tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM;
2775    value: huks.HuksKeyAlg | huks.HuksKeyStorageType | huks.HuksKeySize | huks.HuksKeyPurpose | huks.HuksKeyDigest
2776        | huks.HuksKeyPadding | huks.HuksKeyGenerateType | huks.HuksCipherMode = huks.HuksKeyAlg.HUKS_ALG_RSA
2777}
2778
2779let genKeyProperties: genKeyPropertyType[] = [
2780    {
2781        tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
2782        value: huks.HuksKeyAlg.HUKS_ALG_RSA
2783    },
2784    {
2785        tag: huks.HuksTag.HUKS_TAG_KEY_STORAGE_FLAG,
2786        value: huks.HuksKeyStorageType.HUKS_STORAGE_PERSISTENT
2787    },
2788    {
2789        tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
2790        value: huks.HuksKeySize.HUKS_RSA_KEY_SIZE_2048
2791    },
2792    {
2793        tag: huks.HuksTag.HUKS_TAG_PURPOSE,
2794        value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_VERIFY
2795    },
2796    {
2797        tag: huks.HuksTag.HUKS_TAG_DIGEST,
2798        value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256
2799    },
2800    {
2801        tag: huks.HuksTag.HUKS_TAG_PADDING,
2802        value: huks.HuksKeyPadding.HUKS_PADDING_PSS
2803    },
2804    {
2805        tag: huks.HuksTag.HUKS_TAG_KEY_GENERATE_TYPE,
2806        value: huks.HuksKeyGenerateType.HUKS_KEY_GENERATE_TYPE_DEFAULT
2807    },
2808    {
2809        tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
2810        value: huks.HuksCipherMode.HUKS_MODE_ECB
2811    }
2812]
2813
2814let genOptions: huks.HuksOptions = {
2815    properties: genKeyProperties
2816};
2817
2818class attestKeypropertyType {
2819    tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ATTESTATION_ID_SEC_LEVEL_INFO;
2820    value: Uint8Array = securityLevel;
2821}
2822
2823let attestKeyproperties: attestKeypropertyType[] = [
2824    {
2825        tag: huks.HuksTag.HUKS_TAG_ATTESTATION_ID_SEC_LEVEL_INFO,
2826        value: securityLevel
2827    },
2828    {
2829        tag: huks.HuksTag.HUKS_TAG_ATTESTATION_CHALLENGE,
2830        value: challenge
2831    },
2832    {
2833        tag: huks.HuksTag.HUKS_TAG_ATTESTATION_ID_VERSION_INFO,
2834        value: versionInfo
2835    },
2836    {
2837        tag: huks.HuksTag.HUKS_TAG_ATTESTATION_ID_ALIAS,
2838        value: aliasUint8
2839    }
2840]
2841
2842let huksOptions: huks.HuksOptions = {
2843    properties: attestKeyproperties
2844};
2845
2846function StringToUint8Array(str: string) {
2847    let arr: number[] = [];
2848    for (let i = 0, j = str.length; i < j; ++i) {
2849        arr.push(str.charCodeAt(i));
2850    }
2851    return new Uint8Array(arr);
2852}
2853
2854function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) {
2855    return new Promise<void>((resolve, reject) => {
2856        try {
2857            huks.generateKeyItem(keyAlias, huksOptions, (error, data) => {
2858                if (error) {
2859                    reject(error);
2860                } else {
2861                    resolve(data);
2862                }
2863            });
2864        } catch (error) {
2865            throwObject.isThrow = true;
2866            throw(error as Error);
2867        }
2868    });
2869}
2870
2871async function publicGenKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
2872    console.info(`enter callback generateKeyItem`);
2873    let throwObject: throwObject = {isThrow: false};
2874    try {
2875        await generateKeyItem(keyAlias, huksOptions, throwObject)
2876        .then((data) => {
2877            console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`);
2878        })
2879        .catch((error: BusinessError) => {
2880            if (throwObject.isThrow) {
2881                throw(error as Error);
2882            } else {
2883                console.error(`callback: generateKeyItem failed`);
2884            }
2885        });
2886    } catch (error) {
2887        console.error(`callback: generateKeyItem input arg invalid`);
2888    }
2889}
2890
2891function attestKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) {
2892    return new Promise<huks.HuksReturnResult>((resolve, reject) => {
2893        try {
2894            huks.attestKeyItem(keyAlias, huksOptions, (error, data) => {
2895                if (error) {
2896                    reject(error);
2897                } else {
2898                    resolve(data);
2899                }
2900            });
2901        } catch (error) {
2902            throwObject.isThrow = true;
2903            throw(error as Error);
2904        }
2905    });
2906}
2907
2908async function publicAttestKey(keyAlias: string, huksOptions: huks.HuksOptions) {
2909    console.info(`enter callback attestKeyItem`);
2910    let throwObject: throwObject = {isThrow: false};
2911    try {
2912        await attestKeyItem(keyAlias, huksOptions, throwObject)
2913        .then ((data) => {
2914            console.info(`callback: attestKeyItem success, data = ${JSON.stringify(data)}`);
2915            if (data !== null && data.certChains !== null) {
2916                attestCertChain = data.certChains as string[];
2917            }
2918        })
2919        .catch((error: BusinessError) => {
2920            if (throwObject.isThrow) {
2921                throw(error as Error);
2922            } else {
2923                console.error(`callback: attestKeyItem failed`);
2924            }
2925        });
2926    } catch (error) {
2927        console.error(`callback: attestKeyItem input arg invalid`);
2928    }
2929}
2930
2931async function AttestKeyTest() {
2932    await publicGenKeyFunc(aliasString, genOptions);
2933
2934    await publicAttestKey(aliasString, huksOptions);
2935    console.info('attest certChain data: ' + attestCertChain)
2936}
2937```
2938
2939**常见问题**
2940
29411. Cannot find name 'huks'.
2942
2943   不能找到huks,使用了接口函数但没导入security.huks.d.ts,添加import huks from '@ohos.security.huks';即可。
2944
29452. Property 'finishSession' does not exist on type 'typeof huks'. Did you mean 'finish'?
2946
2947   不能在huks库中找到finishSession,finishSession是API9版本的,请更新SDK版本或替换新版本的security.huks.d.ts文件。
2948
2949## 相关实例
2950
2951针对通用密钥库开发,有以下相关实例可供参考:
2952
2953- [`Huks`:通用密钥库系统(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-4.0-Release/code/BasicFeature/Security/Huks)