• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# OpenHarmony通用密钥库开发指导
2
3## 概述
4
5### 功能简介
6
7HUKS(OpenHarmony Universal KeyStore)提供系统级的密钥管理能力,实现密钥全生命周期(生成、存储、使用、销毁)的管理和安全使用,满足生态应用和上层业务的诉求。其中,密钥的安全存储和安全使用环境是密钥安全最重要的约束,如对明文密钥的存储和使用不能出现在非安全环境中,需要保证在安全环境中使用(比如TEE,安全芯片等);本文档介绍了开发者在OpenHarmony HUKS架构的基础上适配安全存储和安全使用环境的步骤,以及如何去验证适配是否正确,以保证API接口的兼容。
8
9HUKS支持密钥全生命周期管理,包括以下特性:
10
111. 密钥生成/导入
12
132. 密钥存储
14
153. 密钥使用(加解密、签名验签、密钥派生、密钥协商、哈希、密钥访问控制等)
16
174. 密钥销毁
18
19### 基本概念
20
21- 服务层(HUKS Service)
22
23  承载密钥管理功能的一个独立的OpenHarmony Service附属于huks_service进程,HUKS Service并不直接处理密钥运算,依赖HUKS Core为上层提供服务。
24
25- 核心层(HUKS CORE)
26
27  提供密钥管理服务的核心功能模块,需要保证该模块处于安全环境中且密钥全生命周期明文不出HUKS Core模块。
28
29- 可信执行环境(Trusted Execution Environment)
30
31  通过划分软件和硬件资源的方法构建一个安全区域,使得安全区域内部的程序和数据得到保护。这种划分会分隔出两个执行环境——可信执行环境和普通执行环境。每个执行环境有独立的内部数据通路和计算所需存储空间,保证可信执行环境里的信息不会向外泄露。普通执行环境的应用不能访问可信执行环境的资源,可信执行环境中的应用在没有授权的情况下也无法相互访问。
32
33- 三段式(Init-Update-Finish)
34
35   Init:初始化密钥操作数据。
36
37   Update:分段操作数据并返回结果,或追加数据。
38
39   Finish:结束分段操作或追加数据,返回结果。
40
41### 实现原理
42
43以密钥的生成为例介绍HUKS Service与HUKS Core的通信过程,其他密钥操作类似:
44上层应用通过密钥管理SDK调用到HUKS Service,HUKS Service再调用HUKS Core,HUKS Core会调用密钥管理模块生成密钥。之后HUKS Core使用基于RootKey派生的加密密钥对生成的密钥加密再传给Service侧,Service侧再以文件形式存储加密后的密钥。
45
46![HUKS密钥生成流程图](figures/HUKS-GenerateKey1.png)
47
48### 约束与限制
49
50* HUKS的实现需要在可信执行环境中实现,保证密钥管理和操作的可信可靠。
51
52* HuksHdiAttestKey返回的证书链应该按照业务证书、设备证书、CA证书和根证书的顺序组装,在每项证书之前还需要加上证书的长度。证书链组装完成后添加整个证书链的长度组装成Blob格式。证书的具体格式如要自己实现应与服务器侧解析的格式相对应。
53
54![CertChain格式图](figures/HUKS-CertChain.png)
55
56* 接口返回的密钥必须按照密钥存储态组装成KeyBlob,哪些接口需要遵循该限制请见[接口说明](#接口说明)。
57
58   KeyBlob存储密钥的同时存储它的属性,结构见下图。构造KeyBlob的示例请参见[hks_keyblob.c/HksBuildKeyBlob](https://gitee.com/openharmony/security_huks/blob/master/services/huks_standard/huks_engine/main/core/src/hks_keyblob.c)59
60![KeyBlob格式图](figures/HUKS-KeyBlob.png)
61
62## 开发指导
63
64### 场景介绍
65
66HUKS Core作为向应用提供密钥库能力的基础,包括密钥管理及密钥的密码学操作等功能。如果想要使用自己的实现替换HUKS Core,需要实现以下接口。
67
68### 接口说明
69
70**表1** 接口功能介绍
71
72| 接口名                                                       | 功能介绍                                  | 约束与限制                     | 对应的js接口                                        |
73| ------------------------------------------------------------ | ---------------------------------------- | ----------------------------- | ------------------------------------------------------------ |
74| [HuksHdiModuleInit()](#hukshdimoduleinit)                   | HUKS Core的初始化。                            |  无                           | 无 |
75| [HuksHdiRefresh()](#hukshdirefresh)                          | 刷新根密钥。                              |  无                            | 无 |
76| [HuksHdiGenerateKey()](#hukshdigeneratekey)                  | 生成密钥。                                |  出参要遵循KeyBlob格式          |generateKey(keyAlias: string, options: HuksOptions)|
77| [HuksHdiImportKey()](#hukshdiimportkey)                     | 导入明文密钥。                            |  出参要遵循KeyBlob格式           | importKey(keyAlias: string, options: HuksOptions)|
78| [HuksHdiImportWrappedKey()](#hukshdiimportwrappedkey)        |导入加密密钥。                              |  出参要遵循KeyBlob格式          | importWrappedKey(keyAlias: string, wrappingKeyAlias: string, options: HuksOptions)|
79| [HuksHdiExportPublicKey()](#hukshdiexportpublickey)         | 导出公钥。                                 |无                             | exportKey(keyAlias: string, options: HuksOptions) |
80| [HuksHdiInit()](#hukshdiinit)                              | 三段式中的Init接口。                       |无                              | init(keyAlias: string, options: HuksOptions) |
81| [HuksHdiUpdate()](#hukshdiupdate)                           | 三段式中的Update接口。                     |签名验签时入参是原始数据          | update(handle: number, token?: Uint8Array, options: HuksOptions) |
82| [HuksHdiFinish()](#hukshdifinish)                           | 三段式中的Finish接口。                     |签名验签时入参是签名后数据        | finish(handle: number, options: HuksOptions) |
83| [HuksHdiAbort()](#hukshdiabort)                         | 终止三段式。                               |无                             | abort(handle: number, options: HuksOptions) |
84| [HuksHdiGetKeyProperties()](#hukshdigetkeyproperties)        | 获取密钥属性。                              |无                            | getKeyProperties(keyAlias: string, options: HuksOptions)|
85| [HuksHdiAttestKey()](#hukshdiattestkey)        | 获取密钥证书。                              |出参要遵循certChain格式                      | attestKey(keyAlias: string, options: HuksOptions)|
86
87- - -
88
89#### HuksHdiModuleInit
90
91**接口描述**
92
93HUKS Core的初始化,包括锁,加密算法库,authtoken key和根密钥。
94
95**接口原型**
96<pre><code>int32_t HuksHdiModuleInit();</code></pre>
97
98<details>
99  <summary><strong>返回值</strong></summary>
100
101  - HKS_SUCCESS:成功
102
103  - 其他:失败
104</details>
105
106- - -
107
108#### HuksHdiRefresh
109
110**接口描述**
111
112刷新根密钥。
113
114**接口原型**
115<pre><code>int32_t HuksHdiRefresh();</code></pre>
116
117<details>
118  <summary><strong>返回值</strong></summary>
119
120  - HKS_SUCCESS:成功
121
122  - 其他:失败
123</details>
124
125- - -
126
127#### HuksHdiGenerateKey
128
129**接口描述**
130
131根据paramSet生成密钥。
132
133**接口原型**
134<pre><code>int32_t HuksHdiGenerateKey(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, const struct HksBlob *keyIn, struct HksBlob *keyOut);</code></pre>
135
136<details>
137  <summary><strong>参数说明</strong></summary>
138  <pre>
139  <strong>const struct HksBlob *keyAlias</strong>
140  将要生成的密钥的别名,要求:
141  1. keyAlias != null
142  2. keyAlias -> data != null
143  3. keyAlias -> size != 0
144  <br></br>
145  <strong>const struct HksParamSet *paramSet</strong>
146  要生成密钥的参数
147  <br></br>
148  <strong>const struct HksBlob *keyIn</strong>
149  在agree key时使用
150  <br></br>
151  <strong>struct HksBlob *keyOut</strong>
152  出参,将paramset和生成的密钥存放在这里
153  </pre>
154</details>
155<br></br>
156
157<details>
158  <summary><strong>约束与限制</strong></summary>
159
160  1. 请在接口内检查上述参数是否符合要求,如是否是空指针、密钥算法是否支持等。
161
162  2. keyOut请参照KeyBlob的结构。
163
164</details>
165<br></br>
166
167<details>
168  <summary><strong>返回值</strong></summary>
169
170  - HKS_SUCCESS:成功
171
172  - 其他:失败
173</details>
174
175- - -
176
177#### HuksHdiImportKey
178
179**接口描述**
180
181导入明文密钥。
182
183**接口原型**
184<pre><code>int32_t HuksHdiImportKey(const struct HksBlob *keyAlias, const struct HksBlob *key, const struct HksParamSet *paramSet, struct HksBlob *keyOut);</code></pre>
185
186<details>
187  <summary><strong>参数说明</strong></summary>
188  <pre>
189  <strong>const struct HksBlob *msg</strong>
190  将要导入的密钥的别名,要求:
191  1. keyAlias != null
192  2. keyAlias -> data != null
193  3. keyAlias -> size != 0
194  <br></br>
195  <strong>const struct HksBlob *key</strong>
196  要导入的密钥,要求:
197  1. key != null
198  2. key -> data != null
199  3. key -> size != 0
200  <br></br>
201  <strong>const struct HksParamSet *paramSet</strong>
202  导入密钥的参数
203  <br></br>
204  <strong>struct HksBlob *keyOut</strong>
205  出参,将paramset和生成的密钥存放在这里
206  <br></br>
207  </pre>
208</details>
209<br></br>
210
211<details>
212  <summary><strong>约束与限制</strong></summary>
213
214  1. 请在接口内检查上述参数是否符合要求,如是否是空指针、密钥算法是否支持等。
215
216  2. keyOut请参照KeyBlob的结构。
217
218</details>
219<br></br>
220
221<details>
222  <summary><strong>返回值</strong></summary>
223
224  - HKS_SUCCESS:成功
225
226  - 其他:失败
227</details>
228
229- - -
230
231#### HuksHdiImportWrappedKey
232
233**接口描述**
234
235导入加密密钥。
236
237**接口原型**
238<pre><code>int32_t HuksHdiImportWrappedKey(const struct HksBlob *keyAlias, const struct HksBlob *wrappingUsedkey, const struct HksBlob *wrappedKeyData, const struct HksParamSet *paramSet, struct HksBlob *keyOut);</code></pre>
239
240<details>
241  <summary><strong>参数说明</strong></summary>
242  <pre>
243  <strong>const struct HksBlob *KeyAlias</strong>
244  将要导入的密钥的别名,要求:
245  1. keyAlias != null
246  2. keyAlias -> data != null
247  3. keyAlias -> size != 0
248  <br></br>
249  <strong>const struct HksBlob *key</strong>
250  要导入的密钥数据被加密时使用的密钥,要求:
251  1. wrappingUsedkey != null
252  2. wrappingUsedkey -> data != null
253  3. wrappingUsedkey -> size != 0
254  <br></br>
255  <strong>const struct HksBlob *wrappedKeyData</strong>
256  要导入的密钥的加密数据,要求:
257  1. wrappedKeyData != null
258  2. wrappedKeyData -> data != null
259  3. wrappedKeyData -> size != 0
260  <br></br>
261  <strong>const struct HksParamSet *paramSet</strong>
262  导入密钥的参数
263  <br></br>
264  <strong>struct HksBlob *keyOut</strong>
265  出参,将paramset和生成的密钥存放在这里
266  </pre>
267</details>
268<br></br>
269
270<details>
271  <summary><strong>约束与限制</strong></summary>
272
273  1. 请在接口内检查上述参数是否符合要求,如是否是空指针、密钥算法是否支持等。
274
275  2. keyOut请参照KeyBlob的结构。
276
277</details>
278<br></br>
279
280<details>
281  <summary><strong>返回值</strong></summary>
282
283  - HKS_SUCCESS:成功
284
285  - 其他:失败
286</details>
287
288- - -
289
290#### HuksHdiExportPublicKey
291
292**接口描述**
293
294导出公钥。
295
296**接口原型**
297<pre><code>int32_t HuksHdiExportPublicKey(const struct HksBlob *key, const struct HksParamSet *paramSet, struct HksBlob *keyOut);</code></pre>
298
299<details>
300  <summary><strong>参数说明</strong></summary>
301  <pre>
302  <strong>const struct HksBlob *key</strong>
303  与要导出的公钥对应的私钥,要求:
304  1. key != null
305  2. key -> data != null
306  3. key -> size != 0
307  <br></br>
308  <strong>const struct HksParamSet *paramSet</strong>
309  空参数
310  <br></br>
311  <strong>struct HksBlob *keyOut</strong>
312  出参,存放导出的公钥
313  </pre>
314</details>
315<br></br>
316
317<details>
318  <summary><strong>返回值</strong></summary>
319
320  - HKS_SUCCESS:成功
321
322  - 其他:失败
323</details>
324
325- - -
326
327#### HuksHdiInit
328
329**接口描述**
330
331三段式中的Init接口。
332
333**接口原型**
334<pre><code>int32_t HuksHdiInit(const struct HksBlob *key, const struct HksParamSet *paramSet, struct HksBlob *handle, struct HksBlob *token);</code></pre>
335
336<details>
337  <summary><strong>参数说明</strong></summary>
338  <pre>
339  <strong>const struct HksBlob *key</strong>
340  Init操作的密钥,要求:
341  1. key != null
342  2. key -> data != null
343  3. key -> size != 0
344  <br></br>
345  <strong>const struct HksParamSet *paramSet</strong>
346  Init操作的参数
347  <br></br>
348  <strong>struct HksBlob *handle</strong>
349  三段式的句柄
350  <br></br>
351  <strong>struct HksBlob *token</strong>
352  存放安全访问控制的challenge
353  </pre>
354</details>
355<br></br>
356
357<details>
358  <summary><strong>返回值</strong></summary>
359
360  - HKS_SUCCESS:成功
361
362  - 其他:失败
363</details>
364
365- - -
366
367#### HuksHdiUpdate
368
369**接口描述**
370
371三段式中的Update接口。
372
373**接口原型**
374<pre><code>int32_t HuksHdiUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet, const struct HksBlob *inData, struct HksBlob *outData);</code></pre>
375
376<details>
377  <summary><strong>参数说明</strong></summary>
378  <pre>
379  <strong>const struct HksBlob *handle</strong>
380  三段式的句柄
381  <br></br>
382  <strong> const struct HksParamSet *paramSet</strong>
383  Update操作的参数
384  <br></br>
385  <strong> const struct HksBlob *inData</strong>
386  Update操作的输入
387  <br></br>
388  <strong> struct HksBlob *outData</strong>
389  Update操作的结果
390  </pre>
391</details>
392<br></br>
393
394<details>
395  <summary><strong>约束与限制</strong></summary>
396
397  1. 在进行签名验签时inData要传入原文数据。
398
399</details>
400<br></br>
401
402<details>
403  <summary><strong>返回值</strong></summary>
404
405  - HKS_SUCCESS:成功
406
407  - 其他:失败
408</details>
409
410- - -
411
412#### HuksHdiFinish
413
414**接口描述**
415
416三段式中的Finish接口。
417
418**接口原型**
419<pre><code>int32_t HuksHdiFinish(const struct HksBlob *handle, const struct HksParamSet *paramSet, const struct HksBlob *inData, struct HksBlob *outData);</code></pre>
420
421<details>
422  <summary><strong>参数说明</strong></summary>
423  <pre>
424  <strong>const struct HksBlob *handle</strong>
425  三段式的句柄
426  <br></br>
427  <strong>const struct HksParamSet *paramSet</strong>
428  Finish操作的参数
429  <br></br>
430  <strong>const struct HksBlob *inData</strong>
431  Finish操作的输入
432  <br></br>
433  <strong>struct HksBlob *outData</strong>
434  Finish操作的结果
435  </pre>
436</details>
437<br></br>
438
439<details>
440  <summary><strong>约束与限制</strong></summary>
441
442  1. 在进行签名验签时inData要传入需要验证的签名数据,通过返回结果表示验签是否成功。
443
444</details>
445<br></br>
446
447<details>
448  <summary><strong>返回值</strong></summary>
449
450  - HKS_SUCCESS:成功
451
452  - 其他:失败
453</details>
454
455- - -
456
457#### HuksHdiAbort
458
459**接口描述**
460
461终止三段式。当Init,Update和Finish操作中的任一阶段发生错误时,都要调用abort来终止密钥的使用。
462
463**接口原型**
464<pre><code>int32_t HuksHdiAbort(const struct HksBlob *handle, const struct HksParamSet *paramSet);</code></pre>
465
466<details>
467  <summary><strong>参数说明</strong></summary>
468  <pre>
469  <strong>const struct HksBlob *handle</strong>
470  三段式的句柄
471  <br></br>
472  <strong>const struct HksParamSet *paramSet</strong>
473  Abort操作的参数
474  </pre>
475</details>
476<br></br>
477
478<details>
479  <summary><strong>返回值</strong></summary>
480
481  - HKS_SUCCESS:成功
482
483  - 其他:失败
484</details>
485
486- - -
487
488#### HuksHdiGetKeyProperties
489
490**接口描述**
491
492获取密钥属性。
493
494**接口原型**
495<pre><code>int32_t HuksHdiGetKeyProperties(const struct HksParamSet *paramSet, const struct HksBlob *key);</code></pre>
496
497<details>
498  <summary><strong>参数说明</strong></summary>
499  <pre>
500  <strong>const struct HksParamSet *paramSet</strong>
501  空对象
502  <br></br>
503  <strong>const struct HksBlob *key</strong>
504  要获取属性的密钥
505  </pre>
506</details>
507<br></br>
508
509<details>
510  <summary><strong>返回值</strong></summary>
511
512  - HKS_SUCCESS:成功
513
514  - 其他:失败
515</details>
516
517- - -
518
519#### HuksHdiAttestKey
520
521**接口描述**
522
523获取密钥证书。
524
525**接口原型**
526<pre><code>int32_t (*HuksHdiAttestKey)(const struct HksBlob *key, const struct HksParamSet *paramSet, struct HksBlob *certChain);</code></pre>
527
528<details>
529  <summary><strong>参数说明</strong></summary>
530  <pre>
531  <strong>const struct HksBlob *key</strong>
532  要获取证书的密钥
533  <br></br>
534  <strong>const struct HksParamSet *paramSet</strong>
535  获取证书操作的参数
536  <br></br>
537  <strong>struct HksBlob *certChain</strong>
538  出参,存放证书
539  </pre>
540</details>
541<br></br>
542
543<details>
544  <summary><strong>约束与限制</strong></summary>
545
546  1. certChain的格式需遵循[约束与限制第二点](#约束与限制)。
547
548</details>
549<br></br>
550
551<details>
552  <summary><strong>返回值</strong></summary>
553
554  - HKS_SUCCESS:成功
555
556  - 其他:失败
557</details>
558
559- - -
560
561### 开发步骤
562
563HDI接口到HUKS Core的适配在以下目录中:
564
565```undefined
566// base/security/user_auth/services/huks_standard/huks_engine/main
567├── BUILD.gn # 编译脚本
568├── core_dependency # 实现依赖
569└── core # HUKS Core层的软实现
570    ├── BUILD.gn # 编译脚本
571    ├── include
572    └── src
573        ├── hks_core_interfaces.c # HDI到HUKS Core的适配层
574        └── hks_core_service.c # 具体实现
575        └── ... #其他功能代码
576```
577
578关于HUKS Core接口的具体实现,开发者必须采用三段式。以下是三段式的开发步骤以及HUKS CORE的代码示例,开发者应参考以下代码实现所有的Hdi接口。
579
580其他HUKS Core接口的代码可以参考[hks_core_service.c](https://gitee.com/openharmony/security_huks/blob/master/services/huks_standard/huks_engine/main/core/src/hks_core_service.c)文件。
581
5821. 创建一个句柄,通过这个句柄在session中存储密钥操作相关的信息,使得外部可以通过这个句柄分多次进行同一密钥操作。
583
584   ```c
585
586   //三段式Init接口
587
588   int32_t HksCoreInit(const struct  HksBlob *key, const struct HksParamSet *paramSet, struct HksBlob *handle,
589    struct HksBlob *token)
590   {
591       HKS_LOG_D("HksCoreInit in Core start");
592       uint32_t pur = 0;
593       uint32_t alg = 0;
594       //检查参数
595       if (key == NULL || paramSet == NULL || handle == NULL || token == NULL) {
596           HKS_LOG_E("the pointer param entered is invalid");
597           return HKS_FAILURE;
598        }
599
600        if (handle->size < sizeof(uint64_t)) {
601            HKS_LOG_E("handle size is too small, size : %u", handle->size);
602            return HKS_ERROR_INSUFFICIENT_MEMORY;
603        }
604        //解密密钥文件
605        struct HuksKeyNode *keyNode = HksCreateKeyNode(key, paramSet);
606        if (keyNode == NULL || handle == NULL) {
607            HKS_LOG_E("the pointer param entered is invalid");
608            return HKS_ERROR_BAD_STATE;
609        }
610        //通过handle向session中存储信息,供Update/Finish使用。使得外部可以通过同个handle分多次进行同一密钥操作。
611        handle->size = sizeof(uint64_t);
612        (void)memcpy_s(handle->data, handle->size, &(keyNode->handle), handle->size);
613        //从参数中提取出算法
614        int32_t ret = GetPurposeAndAlgorithm(paramSet, &pur, &alg);
615        if (ret != HKS_SUCCESS) {
616            HksDeleteKeyNode(keyNode->handle);
617            return ret;
618        }
619        //检查密钥参数
620        ret = HksCoreSecureAccessInitParams(keyNode, paramSet, token);
621        if (ret != HKS_SUCCESS) {
622            HKS_LOG_E("init secure access params failed");
623            HksDeleteKeyNode(keyNode->handle);
624            return ret;
625        }
626        //通过密钥使用目的获取对应的算法库处理函数
627        uint32_t i;
628        uint32_t size = HKS_ARRAY_SIZE(g_hksCoreInitHandler);
629        for (i = 0; i < size; i++) {
630           if (g_hksCoreInitHandler[i].pur == pur) {
631               HKS_LOG_E("Core HksCoreInit [pur] = %d, pur = %d", g_hksCoreInitHandler[i].pur, pur);
632               ret = g_hksCoreInitHandler[i].handler(keyNode, paramSet, alg);
633               break;
634        }
635        }
636        //异常结果检查
637        if (ret != HKS_SUCCESS) {
638            HksDeleteKeyNode(keyNode->handle);
639            HKS_LOG_E("CoreInit failed, ret : %d", ret);
640            return ret;
641        }
642
643        if (i == size) {
644            HksDeleteKeyNode(keyNode->handle);
645            HKS_LOG_E("don't found purpose, pur : %u", pur);
646            return HKS_FAILURE;
647        }
648
649        HKS_LOG_D("HksCoreInit in Core end");
650        return ret;
651    }
652   ```
653
6542. 在执行密钥操作前通过句柄获得上下文信息,执行密钥操作时放入分片数据并取回密钥操作结果或者追加数据。
655
656    ```c
657    //三段式Update接口
658    int32_t HksCoreUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet, const struct HksBlob *inData,
659        struct HksBlob *outData)
660    {
661        HKS_LOG_D("HksCoreUpdate in Core start");
662        uint32_t pur = 0;
663        uint32_t alg = 0;
664        //检查参数
665        if (handle == NULL || paramSet == NULL || inData == NULL) {
666            HKS_LOG_E("the pointer param entered is invalid");
667            return HKS_FAILURE;
668        }
669
670        uint64_t sessionId;
671        struct HuksKeyNode *keyNode = NULL;
672        //根据handle获取本次三段式操作需要的上下文
673        int32_t ret = GetParamsForUpdateAndFinish(handle, &sessionId, &keyNode, &pur, &alg);
674        if (ret != HKS_SUCCESS) {
675            HKS_LOG_E("GetParamsForCoreUpdate failed");
676            return ret;
677        }
678        //校验密钥参数
679        ret = HksCoreSecureAccessVerifyParams(keyNode, paramSet);
680        if (ret != HKS_SUCCESS) {
681            HksDeleteKeyNode(sessionId);
682            HKS_LOG_E("HksCoreUpdate secure access verify failed");
683            return ret;
684        }
685        //调用对应的算法库密钥处理函数
686        uint32_t i;
687        uint32_t size = HKS_ARRAY_SIZE(g_hksCoreUpdateHandler);
688        for (i = 0; i < size; i++) {
689            if (g_hksCoreUpdateHandler[i].pur == pur) {
690                struct HksBlob appendInData = { 0, NULL };
691                ret = HksCoreAppendAuthInfoBeforeUpdate(keyNode, pur, paramSet, inData, &appendInData);
692                if (ret != HKS_SUCCESS) {
693                    HKS_LOG_E("before update: append auth info failed");
694                    break;
695                }
696                ret = g_hksCoreUpdateHandler[i].handler(keyNode, paramSet,
697                     appendInData.data == NULL ? inData : &appendInData, outData, alg);
698                if (appendInData.data != NULL) {
699                    HKS_FREE_BLOB(appendInData);
700                }
701                break;
702            }
703        }
704        //异常结果检查
705        if (ret != HKS_SUCCESS) {
706            HksDeleteKeyNode(keyNode->handle);
707            HKS_LOG_E("CoreUpdate failed, ret : %d", ret);
708            return ret;
709        }
710
711        if (i == size) {
712            HksDeleteKeyNode(sessionId);
713            HKS_LOG_E("don't found purpose, pur : %u", pur);
714            return HKS_FAILURE;
715        }
716        return ret;
717    }
718    ```
719
7203. 结束密钥操作并取回结果,销毁句柄。
721
722   ```c
723   //三段式Finish接口
724   int32_t HksCoreFinish(const struct HksBlob *handle, const struct HksParamSet *paramSet, const struct HksBlob *inData,
725    struct HksBlob *outData)
726   {
727       HKS_LOG_D("HksCoreFinish in Core start");
728       uint32_t pur = 0;
729       uint32_t alg = 0;
730       //检查参数
731       if (handle == NULL || paramSet == NULL || inData == NULL) {
732           HKS_LOG_E("the pointer param entered is invalid");
733           return HKS_FAILURE;
734       }
735
736       uint64_t sessionId;
737       struct HuksKeyNode *keyNode = NULL;
738       //根据handle获取本次三段式操作需要的上下文
739       int32_t ret = GetParamsForUpdateAndFinish(handle, &sessionId, &keyNode, &pur, &alg);
740       if (ret != HKS_SUCCESS) {
741           HKS_LOG_E("GetParamsForCoreUpdate failed");
742           return ret;
743       }
744       //校验密钥参数
745       ret = HksCoreSecureAccessVerifyParams(keyNode, paramSet);
746       if (ret != HKS_SUCCESS) {
747           HksDeleteKeyNode(sessionId);
748           HKS_LOG_E("HksCoreFinish secure access verify failed");
749           return ret;
750       }
751       //调用对应的算法库密钥处理函数
752       uint32_t i;
753       uint32_t size = HKS_ARRAY_SIZE(g_hksCoreFinishHandler);
754       for (i = 0; i < size; i++) {
755           if (g_hksCoreFinishHandler[i].pur == pur) {
756               uint32_t outDataBufferSize = (outData == NULL) ? 0 : outData->size;
757               struct HksBlob appendInData = { 0, NULL };
758               ret = HksCoreAppendAuthInfoBeforeFinish(keyNode, pur, paramSet, inData, &appendInData);
759               if (ret != HKS_SUCCESS) {
760                   HKS_LOG_E("before finish: append auth info failed");
761                   break;
762               }
763               ret = g_hksCoreFinishHandler[i].handler(keyNode, paramSet,
764                   appendInData.data == NULL ? inData : &appendInData, outData, alg);
765               if (appendInData.data != NULL) {
766                   HKS_FREE_BLOB(appendInData);
767               }
768               if (ret != HKS_SUCCESS) {
769                   break;
770               }
771               //添加密钥操作结束标签
772               ret = HksCoreAppendAuthInfoAfterFinish(keyNode, pur, paramSet, outDataBufferSize, outData);
773               break;
774           }
775       }
776       if (i == size) {
777           HKS_LOG_E("don't found purpose, pur : %d", pur);
778           ret = HKS_FAILURE;
779       }
780       //删除对应的session
781       HksDeleteKeyNode(sessionId);
782       HKS_LOG_D("HksCoreFinish in Core end");
783       return ret;
784   }
785   ```
786
787### 调测验证
788
789开发完成后,通过[HUKS JS接口](https://gitee.com/openharmony/security_huks/blob/master/interfaces/kits/js/@ohos.security.huks.d.ts)开发JS应用来验证能力是否完备。
790
791对于每个HDI接口,[接口说明](#接口说明)都提供了对应的JS接口。可以通过调用JS接口组合来验证对应的HDI接口的能力,也可以通过完整的密钥操作来验证接口的能力。
792
793JS测试代码示例如下,如果整个流程能够正常运行,代表HDI接口能力正常。更多的密钥操作类型请见[huks-guidelines.md](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/huks-guidelines.md)794
795**AES生成密钥和加密**
796
7971. 引入HUKS模块
798
799   ```js
800   import huks from '@ohos.security.huks'
801   ```
802
8032. 使用generateKey接口生成密钥。
804
805   ```js
806   var alias = 'testAlias';
807   var properties = new Array();
808   properties[0] = {
809     tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
810     value: huks.HuksKeyAlg.HUKS_ALG_ECC
811   };
812   properties[1] = {
813     tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
814     value: huks.HuksKeySize.HUKS_ECC_KEY_SIZE_224
815   };
816   properties[2] = {
817     tag: huks.HuksTag.HUKS_TAG_PURPOSE,
818     value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE
819   };
820   properties[3] = {
821     tag: huks.HuksTag.HUKS_TAG_DIGEST,
822     value: huks.HuksKeyDigest.HUKS_DIGEST_NONE
823   };
824   var options = {
825     properties: properties
826   }
827   var resultA = huks.generateKey(alias, options);
828   ```
829
8303. 使用Init接口进行init操作。
831
832   ```js
833   var alias = 'test001'
834   var properties = new Array();
835   properties[0] = {
836     tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
837     value: huks.HuksKeyAlg.HUKS_ALG_DH
838   };
839   properties[1] = {
840     tag: huks.HuksTag.HUKS_TAG_PURPOSE,
841     value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE
842   };
843   properties[2] = {
844     tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
845     value: huks.HuksKeySize.HUKS_DH_KEY_SIZE_4096
846   };
847   var options = {
848     properties: properties
849   };
850   huks.init(alias, options, function(err, data) {
851       if (err.code !== 0) {
852           console.log("test init err information: " + JSON.stringify(err));
853       } else {
854           console.log(`test init data: ${JSON.stringify(data)}`);
855       }
856   })
857   ```
858
8594. 使用Update接口进行update操作。
860
861   ```js
862   var properties = new Array();
863   properties[0] = {
864     tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
865     value: huks.HuksKeyAlg.HUKS_ALG_DH
866   };
867   properties[1] = {
868     tag: huks.HuksTag.HUKS_TAG_PURPOSE,
869     value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE
870   };
871   properties[2] = {
872     tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
873     value: huks.HuksKeySize.HUKS_DH_KEY_SIZE_4096
874   };
875   var options = {
876     properties: properties
877   };
878   var result = huks.update(handle, options)
879   ```
880
8815. 使用Finish接口进行finish操作。
882
883   ```js
884   var properties = new Array();
885   properties[0] = {
886     tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
887     value: huks.HuksKeyAlg.HUKS_ALG_DH
888   };
889   properties[1] = {
890     tag: huks.HuksTag.HUKS_TAG_PURPOSE,
891     value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE
892   };
893   properties[2] = {
894     tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
895     value: huks.HuksKeySize.HUKS_DH_KEY_SIZE_4096
896   };
897   var options = {
898     properties: properties
899   };
900   var result = huks.finish(handle, options)
901   ```