1# 密钥派生(C/C++)
2
3
4以HKDF256密钥为例,完成密钥派生。具体的场景介绍及支持的算法规格,请参考[密钥生成支持的算法](huks-key-generation-overview.md#支持的算法)。
5
6## 在CMake脚本中链接相关动态库
7```txt
8   target_link_libraries(entry PUBLIC libhuks_ndk.z.so)
9```
10
11## 开发步骤
12
13**生成密钥**
14
151. 指定密钥别名。
16
172. 初始化密钥属性集,可指定参数,OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG(可选),用于标识基于该密钥派生出的密钥是否由HUKS管理。
18
19    - 当TAG设置为OH_HUKS_STORAGE_ONLY_USED_IN_HUKS时,表示基于该密钥派生出的密钥,由HUKS管理,可保证派生密钥全生命周期不出安全环境。
20
21    - 当TAG设置为OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED时,表示基于该密钥派生出的密钥,返回给调用方管理,由业务自行保证密钥安全。
22
23    - 若业务未设置TAG的具体值,表示基于该密钥派生出的密钥,即可由HUKS管理,也可返回给调用方管理,业务可在后续派生时再选择使用何种方式保护密钥。
24
253. 调用[OH_Huks_GenerateKeyItem](../../reference/apis-universal-keystore-kit/_huks_key_api.md#oh_huks_generatekeyitem)生成密钥,具体请参考[密钥生成](huks-key-generation-overview.md)。
26
27除此之外,开发者也可以参考[密钥导入](huks-key-import-overview.md),导入已有的密钥。
28
29**密钥派生**
30
311. 获取密钥别名,指定对应的属性参数HuksOptions。
32
33   可指定参数OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG(可选),用于标识派生得到的密钥是否由HUKS管理。
34
35    | 生成 | 派生 | 规格 |
36    | -------- | -------- | -------- |
37    | OH_HUKS_STORAGE_ONLY_USED_IN_HUKS | OH_HUKS_STORAGE_ONLY_USED_IN_HUKS | 密钥由HUKS管理 |
38    | OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED | OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED | 密钥返回给调用方管理 |
39    | 未指定TAG具体值 | OH_HUKS_STORAGE_ONLY_USED_IN_HUKS | 密钥由HUKS管理 |
40    | 未指定TAG具体值 | OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED | 密钥返回给调用方管理 |
41    | 未指定TAG具体值 | 未指定TAG具体值 | 密钥返回给调用方管理 |
42
43    注:派生时指定的TAG值,不可与生成时指定的TAG值冲突。表格中仅列举有效的指定方式。
44
452. 调用[OH_Huks_InitSession](../../reference/apis-universal-keystore-kit/_huks_key_api.md#oh_huks_initsession)初始化密钥会话,并获取会话的句柄handle。
46
473. 调用[OH_Huks_UpdateSession](../../reference/apis-universal-keystore-kit/_huks_key_api.md#oh_huks_updatesession)更新密钥会话。
48
494. 调用[OH_Huks_FinishSession](../../reference/apis-universal-keystore-kit/_huks_key_api.md#oh_huks_finishsession)结束密钥会话,完成派生。
50
51**删除密钥**
52
53当密钥废弃不用时,需要调用OH_Huks_DeleteKeyItem删除密钥,具体请参考[密钥删除](huks-delete-key-ndk.md)。
54
55```c++
56#include "huks/native_huks_api.h"
57#include "huks/native_huks_param.h"
58#include <string.h>
59OH_Huks_Result InitParamSet(
60    struct OH_Huks_ParamSet **paramSet,
61    const struct OH_Huks_Param *params,
62    uint32_t paramCount)
63{
64    OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
65    if (ret.errorCode != OH_HUKS_SUCCESS) {
66        return ret;
67    }
68    ret = OH_Huks_AddParams(*paramSet, params, paramCount);
69    if (ret.errorCode != OH_HUKS_SUCCESS) {
70        OH_Huks_FreeParamSet(paramSet);
71        return ret;
72    }
73    ret = OH_Huks_BuildParamSet(paramSet);
74    if (ret.errorCode != OH_HUKS_SUCCESS) {
75        OH_Huks_FreeParamSet(paramSet);
76        return ret;
77    }
78    return ret;
79}
80static const uint32_t DERIVE_KEY_SIZE_32 = 32;
81static const uint32_t DERIVE_KEY_SIZE_256 = 256;
82static struct OH_Huks_Blob g_deriveKeyAlias = {
83    (uint32_t)strlen("test_derive"),
84    (uint8_t *)"test_derive"
85};
86static struct OH_Huks_Param g_genDeriveParams[] = {
87    {
88        .tag =  OH_HUKS_TAG_ALGORITHM,
89        .uint32Param = OH_HUKS_ALG_AES
90    }, {
91        .tag =  OH_HUKS_TAG_PURPOSE,
92        .uint32Param = OH_HUKS_KEY_PURPOSE_DERIVE
93    }, {
94        .tag =  OH_HUKS_TAG_DIGEST,
95        .uint32Param = OH_HUKS_DIGEST_SHA256
96    }, {
97        .tag =  OH_HUKS_TAG_KEY_SIZE,
98        .uint32Param = OH_HUKS_AES_KEY_SIZE_256
99    }
100};
101static struct OH_Huks_Param g_hkdfParams[] = {
102    {
103        .tag =  OH_HUKS_TAG_ALGORITHM,
104        .uint32Param = OH_HUKS_ALG_HKDF
105    }, {
106        .tag =  OH_HUKS_TAG_PURPOSE,
107        .uint32Param = OH_HUKS_KEY_PURPOSE_DERIVE
108    }, {
109        .tag =  OH_HUKS_TAG_DIGEST,
110        .uint32Param = OH_HUKS_DIGEST_SHA256
111    }, {
112        .tag =  OH_HUKS_TAG_DERIVE_KEY_SIZE,
113        .uint32Param = DERIVE_KEY_SIZE_32
114    }
115};
116static struct OH_Huks_Param g_hkdfFinishParams[] = {
117    {
118        .tag =  OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
119        .uint32Param = OH_HUKS_STORAGE_ONLY_USED_IN_HUKS
120    }, {
121        .tag =  OH_HUKS_TAG_KEY_ALIAS,
122        .blob = g_deriveKeyAlias
123    }, {
124        .tag =  OH_HUKS_TAG_ALGORITHM,
125        .uint32Param = OH_HUKS_ALG_AES
126    }, {
127        .tag =  OH_HUKS_TAG_KEY_SIZE,
128        .uint32Param = DERIVE_KEY_SIZE_256
129    }, {
130        .tag =  OH_HUKS_TAG_PURPOSE,
131        .uint32Param = OH_HUKS_KEY_PURPOSE_DERIVE
132    }, {
133        .tag =  OH_HUKS_TAG_DIGEST,
134        .uint32Param = OH_HUKS_DIGEST_SHA256
135    }
136};
137static const uint32_t COMMON_SIZE = 2048;
138static const char *g_deriveInData = "Hks_HKDF_Derive_Test_00000000000000000000000000000000000000000000000000000000000"
139                                    "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
140                                    "0000000000000000000000000000000000000000000000000000000000000000000000000_string";
141static napi_value DeriveKey(napi_env env, napi_callback_info info)
142{
143    struct OH_Huks_Blob genAlias = {
144        (uint32_t)strlen("test_signVerify"),
145        (uint8_t *)"test_signVerify"
146    };
147    struct OH_Huks_Blob inData = {
148        (uint32_t)strlen(g_deriveInData),
149        (uint8_t *)g_deriveInData
150    };
151    struct OH_Huks_ParamSet *genParamSet = nullptr;
152    struct OH_Huks_ParamSet *hkdfParamSet = nullptr;
153    struct OH_Huks_ParamSet *hkdfFinishParamSet = nullptr;
154    OH_Huks_Result ohResult;
155    do {
156        ohResult = InitParamSet(&genParamSet, g_genDeriveParams, sizeof(g_genDeriveParams) / sizeof(OH_Huks_Param));
157        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
158            break;
159        }
160
161        ohResult = InitParamSet(&hkdfParamSet, g_hkdfParams, sizeof(g_hkdfParams) / sizeof(OH_Huks_Param));
162        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
163           break;
164        }
165
166        // finish paramset
167        ohResult = InitParamSet(&hkdfFinishParamSet, g_hkdfFinishParams, sizeof(g_hkdfFinishParams) / sizeof(OH_Huks_Param));
168        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
169            break;
170        }
171
172        /* 1. Generate Key */
173        ohResult = OH_Huks_GenerateKeyItem(&genAlias, genParamSet, nullptr);
174        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
175            break;
176        }
177        /* 2. Derive */
178        // Init
179        uint8_t handleD[sizeof(uint64_t)] = {0};
180        struct OH_Huks_Blob handleDerive = { sizeof(uint64_t), handleD };
181        ohResult = OH_Huks_InitSession(&genAlias, hkdfParamSet, &handleDerive, nullptr);
182        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
183            break;
184        }
185        // Update
186        uint8_t tmpOut[COMMON_SIZE] = {0};
187        struct OH_Huks_Blob outData = { COMMON_SIZE, tmpOut };
188        ohResult = OH_Huks_UpdateSession(&handleDerive, hkdfParamSet, &inData, &outData);
189        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
190            break;
191        }
192        // Finish
193        uint8_t outDataD[COMMON_SIZE] = {0};
194        struct OH_Huks_Blob outDataDerive = { COMMON_SIZE, outDataD };
195        ohResult = OH_Huks_FinishSession(&handleDerive, hkdfFinishParamSet, &inData, &outDataDerive);
196    } while (0);
197    (void)OH_Huks_DeleteKeyItem(&genAlias, nullptr);
198    (void)OH_Huks_DeleteKeyItem(&g_deriveKeyAlias, nullptr);
199    OH_Huks_FreeParamSet(&genParamSet);
200    OH_Huks_FreeParamSet(&hkdfParamSet);
201    OH_Huks_FreeParamSet(&hkdfFinishParamSet);
202
203    napi_value ret;
204    napi_create_int32(env, ohResult.errorCode, &ret);
205    return ret;
206}
207```
208