• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 密钥协商(C/C++)
2
3<!--Kit: Universal Keystore Kit-->
4<!--Subsystem: Security-->
5<!--Owner: @wutiantian-gitee-->
6<!--Designer: @HighLowWorld-->
7<!--Tester: @wxy1234564846-->
8<!--Adviser: @zengyawen-->
9
10以ECDH协商密钥类型为例,在密钥由HUKS管理的情况下,完成密钥协商。具体的场景介绍及支持的算法规格,请参考[密钥生成支持的算法](huks-key-generation-overview.md#支持的算法)。
11
12## 在CMake脚本中链接相关动态库
13```txt
14target_link_libraries(entry PUBLIC libhuks_ndk.z.so)
15```
16
17## 开发步骤
18
19**生成密钥**
20
21设备A、设备B各自生成一个非对称密钥,具体请参考[密钥生成](huks-key-generation-overview.md)或[密钥导入](huks-key-import-overview.md)。
22
23密钥生成时,可指定参数,OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG(可选),用于标识此步骤生成的密钥是否由HUKS管理。
24
25**导出密钥**
26
27设备A、B导出非对称密钥对的公钥材料,具体请参考[密钥导出](huks-export-key-arkts.md)。
28
29**密钥协商**
30
31设备A、B分别基于本端私钥和对端设备的公钥,协商出共享密钥。
32
33密钥协商时,可指定参数OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG(可选),用于标识协商得到的密钥是否由HUKS管理。
34
35- 当TAG设置为OH_HUKS_STORAGE_ONLY_USED_IN_HUKS时,表示基于该密钥协商出的密钥,由HUKS管理,可保证协商密钥全生命周期不出安全环境。
36
37- 当TAG设置为OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED时,表示基于该密钥协商出的密钥,返回给调用方管理,由业务自行保证密钥安全。
38
39- 若业务未设置TAG的具体值,表示基于该密钥协商出的密钥,既可由HUKS管理,也可返回给调用方管理,业务可在后续协商时再选择使用何种方式保护密钥。
40
41| 生成 | 协商 | 规格 |
42| -------- | -------- | -------- |
43| OH_HUKS_STORAGE_ONLY_USED_IN_HUKS | OH_HUKS_STORAGE_ONLY_USED_IN_HUKS | 密钥由HUKS管理 |
44| OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED | OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED | 密钥返回给调用方管理 |
45| 未指定TAG具体值 | OH_HUKS_STORAGE_ONLY_USED_IN_HUKS | 密钥由HUKS管理 |
46| 未指定TAG具体值 | OH_HUKS_STORAGE_KEY_EXPORT_ALLOWED | 密钥返回给调用方管理 |
47| 未指定TAG具体值 | 未指定TAG具体值 | 密钥返回给调用方管理 |
48
49注:协商时指定的TAG值,不可与生成时指定的TAG值冲突。表格中仅列举有效的指定方式。
50
51**删除密钥**
52
53当密钥废弃不用时,设备A、B均需要删除密钥,具体请参考[密钥删除](huks-delete-key-ndk.md)。
54
55```c++
56#include "huks/native_huks_api.h"
57#include "huks/native_huks_param.h"
58#include "napi/native_api.h"
59#include <string.h>
60/* 初始化参数 */
61OH_Huks_Result InitParamSet(
62    struct OH_Huks_ParamSet **paramSet,
63    const struct OH_Huks_Param *params,
64    uint32_t paramCount)
65{
66    OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
67    if (ret.errorCode != OH_HUKS_SUCCESS) {
68        return ret;
69    }
70    ret = OH_Huks_AddParams(*paramSet, params, paramCount);
71    if (ret.errorCode != OH_HUKS_SUCCESS) {
72        OH_Huks_FreeParamSet(paramSet);
73        return ret;
74    }
75    ret = OH_Huks_BuildParamSet(paramSet);
76    if (ret.errorCode != OH_HUKS_SUCCESS) {
77        OH_Huks_FreeParamSet(paramSet);
78        return ret;
79    }
80    return ret;
81}
82static const uint32_t IV_SIZE = 16;
83static uint8_t IV[IV_SIZE] = { 0 }; // this is a test value, for real use the iv should be different every time.
84static struct OH_Huks_Blob g_keyAliasFinal1001 = {
85    (uint32_t)strlen("HksECDHAgreeKeyAliasTest001_1_final"),
86    (uint8_t *)"HksECDHAgreeKeyAliasTest001_1_final"
87};
88/* 集成密钥参数集 */
89static struct OH_Huks_Param g_genAgreeParams[] = {
90    {
91        .tag = OH_HUKS_TAG_ALGORITHM,
92        .uint32Param = OH_HUKS_ALG_ECC
93    }, {
94        .tag = OH_HUKS_TAG_PURPOSE,
95        .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE
96    }, {
97        .tag = OH_HUKS_TAG_KEY_SIZE,
98        .uint32Param = OH_HUKS_ECC_KEY_SIZE_256
99    }, {
100        .tag = OH_HUKS_TAG_DIGEST,
101        .uint32Param = OH_HUKS_DIGEST_NONE
102    }
103};
104static struct OH_Huks_Param g_agreeParamsInit01[] = {
105    {
106        .tag = OH_HUKS_TAG_ALGORITHM,
107        .uint32Param = OH_HUKS_ALG_ECDH
108    }, {
109        .tag = OH_HUKS_TAG_PURPOSE,
110        .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE
111    }, {
112        .tag = OH_HUKS_TAG_KEY_SIZE,
113        .uint32Param = OH_HUKS_ECC_KEY_SIZE_256
114    }
115};
116static struct OH_Huks_Param g_agreeParamsFinish01[] = {
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_ALGORITHM,
122        .uint32Param = OH_HUKS_ALG_AES
123    }, {
124        .tag = OH_HUKS_TAG_KEY_SIZE,
125        .uint32Param = OH_HUKS_AES_KEY_SIZE_256
126    }, {
127        .tag = OH_HUKS_TAG_PURPOSE,
128        .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE
129    }, {
130        .tag = OH_HUKS_TAG_KEY_ALIAS,
131        .blob = g_keyAliasFinal1001
132    }, {
133        .tag = OH_HUKS_TAG_PADDING,
134        .uint32Param = OH_HUKS_PADDING_NONE
135    }, {
136        .tag = OH_HUKS_TAG_BLOCK_MODE,
137        .uint32Param = OH_HUKS_MODE_CBC
138    }
139};
140static struct OH_Huks_Blob g_keyAliasFinal2001 = {
141    (uint32_t)strlen("HksECDHAgreeKeyAliasTest001_2_final"),
142    (uint8_t *)"HksECDHAgreeKeyAliasTest001_2_final"
143};
144static struct OH_Huks_Param g_agreeParamsInit02[] = {
145    {
146        .tag = OH_HUKS_TAG_ALGORITHM,
147        .uint32Param = OH_HUKS_ALG_ECDH
148    }, {
149        .tag = OH_HUKS_TAG_PURPOSE,
150        .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE
151    }, {
152        .tag = OH_HUKS_TAG_KEY_SIZE,
153        .uint32Param = OH_HUKS_ECC_KEY_SIZE_256
154    }
155};
156static struct OH_Huks_Param g_agreeParamsFinish02[] = {
157    {
158        .tag = OH_HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
159        .uint32Param = OH_HUKS_STORAGE_ONLY_USED_IN_HUKS
160    }, {
161        .tag = OH_HUKS_TAG_ALGORITHM,
162        .uint32Param = OH_HUKS_ALG_AES
163    }, {
164        .tag = OH_HUKS_TAG_KEY_SIZE,
165        .uint32Param = OH_HUKS_AES_KEY_SIZE_256
166    }, {
167        .tag = OH_HUKS_TAG_PURPOSE,
168        .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE
169    }, {
170        .tag = OH_HUKS_TAG_KEY_ALIAS,
171        .blob = g_keyAliasFinal2001
172    }, {
173        .tag = OH_HUKS_TAG_PADDING,
174        .uint32Param = OH_HUKS_PADDING_NONE
175    }, {
176        .tag = OH_HUKS_TAG_BLOCK_MODE,
177        .uint32Param = OH_HUKS_MODE_CBC
178    }
179};
180static const uint32_t ECDH_COMMON_SIZE = 1024;
181static struct OH_Huks_Blob g_keyAlias01001 = {
182    (uint32_t)strlen("HksECDHAgreeKeyAliasTest001_1"),
183    (uint8_t *)"HksECDHAgreeKeyAliasTest001_1"
184};
185static struct OH_Huks_Blob g_keyAlias02001 = {
186    (uint32_t)strlen("HksECDHAgreeKeyAliasTest001_2"),
187    (uint8_t *)"HksECDHAgreeKeyAliasTest001_2"
188};
189OH_Huks_Result MallocAndCheckBlobData(
190    struct OH_Huks_Blob *blob,
191    const uint32_t blobSize)
192{
193    struct OH_Huks_Result ret;
194    ret.errorCode = OH_HUKS_SUCCESS;
195    blob->data = (uint8_t *)malloc(blobSize);
196    if (blob->data == NULL) {
197        ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR;
198    }
199    return ret;
200}
201/* 导出密钥 */
202OH_Huks_Result HksEcdhAgreeExport(const struct OH_Huks_Blob *keyAlias1, const struct OH_Huks_Blob *keyAlias2,
203    struct OH_Huks_Blob *publicKey1, struct OH_Huks_Blob *publicKey2, const struct OH_Huks_ParamSet *genParamSet)
204{
205    OH_Huks_Result ret = OH_Huks_ExportPublicKeyItem(keyAlias1, genParamSet, publicKey1);
206    if (ret.errorCode != OH_HUKS_SUCCESS) {
207        return ret;
208    }
209    ret = OH_Huks_ExportPublicKeyItem(keyAlias2, genParamSet, publicKey2);
210    if (ret.errorCode != OH_HUKS_SUCCESS) {
211        return ret;
212    }
213    return ret;
214}
215static const char *g_inData = "Hks_ECDH_Agree_Test_000000000000000000000000000000000000000000000000000000000000"
216                                    "00000000000000000000000000000000000000000000000000000000000000000000000000000000"
217                                    "0000000000000000000000000000000000000000000000000000000000000000000000000_string";
218/* 协商密钥操作 */
219OH_Huks_Result HksEcdhAgreeFinish(const struct OH_Huks_Blob *keyAlias, const struct OH_Huks_Blob *publicKey,
220    const struct OH_Huks_ParamSet *initParamSet, const struct OH_Huks_ParamSet *finishParamSet,
221    struct OH_Huks_Blob *outData)
222{
223    struct OH_Huks_Blob inData = {
224        (uint32_t)strlen(g_inData),
225        (uint8_t *)g_inData
226    };
227    uint8_t handleU[sizeof(uint64_t)] = {0};
228    struct OH_Huks_Blob handle = { sizeof(uint64_t), handleU };
229    OH_Huks_Result ret = OH_Huks_InitSession(keyAlias, initParamSet, &handle, nullptr);
230    if (ret.errorCode != OH_HUKS_SUCCESS) {
231        return ret;
232    }
233    uint8_t outDataU[ECDH_COMMON_SIZE] = {0};
234    struct OH_Huks_Blob outDataUpdate = { ECDH_COMMON_SIZE, outDataU };
235    ret = OH_Huks_UpdateSession(&handle, initParamSet, publicKey, &outDataUpdate);
236    if (ret.errorCode != OH_HUKS_SUCCESS) {
237        return ret;
238    }
239    ret = OH_Huks_FinishSession(&handle, finishParamSet, &inData, outData);
240    if (ret.errorCode != OH_HUKS_SUCCESS) {
241        return ret;
242    }
243    return ret;
244}
245/* 协商密钥整体流程 */
246static napi_value AgreeKey(napi_env env, napi_callback_info info)
247{
248    struct OH_Huks_ParamSet *genParamSet = nullptr;
249    struct OH_Huks_ParamSet *initParamSet01 = nullptr;
250    struct OH_Huks_ParamSet *finishParamSet01 = nullptr;
251    struct OH_Huks_ParamSet *initParamSet02 = nullptr;
252    struct OH_Huks_ParamSet *finishParamSet02 = nullptr;
253    struct OH_Huks_Blob publicKey01 = { .size = OH_HUKS_ECC_KEY_SIZE_256, .data = nullptr };
254    struct OH_Huks_Blob publicKey02 = { .size = OH_HUKS_ECC_KEY_SIZE_256, .data = nullptr };
255    struct OH_Huks_Blob outData01 = { .size = ECDH_COMMON_SIZE, .data = nullptr };
256    struct OH_Huks_Blob outData02 = { .size = ECDH_COMMON_SIZE, .data = nullptr };
257    OH_Huks_Result ohResult;
258    do {
259        /* 1.确定密钥别名集成密钥参数集 */
260        ohResult = InitParamSet(&genParamSet, g_genAgreeParams, sizeof(g_genAgreeParams) / sizeof(OH_Huks_Param));
261        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
262            break;
263        }
264        ohResult = InitParamSet(&initParamSet01, g_agreeParamsInit01,
265            sizeof(g_agreeParamsInit01) / sizeof(OH_Huks_Param));
266        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
267            break;
268        }
269        ohResult = InitParamSet(&finishParamSet01, g_agreeParamsFinish01,
270            sizeof(g_agreeParamsFinish01) / sizeof(OH_Huks_Param));
271        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
272            break;
273        }
274        ohResult = InitParamSet(&initParamSet02, g_agreeParamsInit02,
275            sizeof(g_agreeParamsInit02) / sizeof(OH_Huks_Param));
276        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
277            break;
278        }
279        ohResult = InitParamSet(&finishParamSet02, g_agreeParamsFinish02,
280            sizeof(g_agreeParamsFinish02) / sizeof(OH_Huks_Param));
281        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
282            break;
283        }
284        /* 2.设备A生成密钥 */
285        ohResult = OH_Huks_GenerateKeyItem(&g_keyAlias01001, genParamSet, nullptr);
286        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
287            break;
288        }
289        /* 3.设备B生成密钥 */
290        ohResult = OH_Huks_GenerateKeyItem(&g_keyAlias02001, genParamSet, nullptr);
291        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
292            break;
293        }
294        ohResult = MallocAndCheckBlobData(&publicKey01, publicKey01.size);
295        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
296            break;
297        }
298        ohResult = MallocAndCheckBlobData(&publicKey02, publicKey02.size);
299        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
300            break;
301        }
302        /* 4.设备A、B导出公钥 */
303        ohResult = HksEcdhAgreeExport(&g_keyAlias01001, &g_keyAlias02001, &publicKey01, &publicKey02, genParamSet);
304        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
305            break;
306        }
307        ohResult = MallocAndCheckBlobData(&outData01, outData01.size);
308        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
309            break;
310        }
311        ohResult = MallocAndCheckBlobData(&outData02, outData02.size);
312        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
313            break;
314        }
315        /* 5.设备A协商密钥 */
316        ohResult = HksEcdhAgreeFinish(&g_keyAlias01001, &publicKey02, initParamSet01, finishParamSet01, &outData01);
317        if (ohResult.errorCode != OH_HUKS_SUCCESS) {
318            break;
319        }
320        /* 5.设备B协商密钥 */
321        ohResult = HksEcdhAgreeFinish(&g_keyAlias02001, &publicKey01, initParamSet02, finishParamSet02, &outData02);
322    } while (0);
323    free(publicKey01.data);
324    free(publicKey02.data);
325    free(outData01.data);
326    free(outData02.data);
327    /* 6.设备A、B删除密钥 */
328    OH_Huks_DeleteKeyItem(&g_keyAlias01001, genParamSet);
329    OH_Huks_DeleteKeyItem(&g_keyAlias02001, genParamSet);
330    OH_Huks_DeleteKeyItem(&g_keyAliasFinal1001, NULL);
331    OH_Huks_DeleteKeyItem(&g_keyAliasFinal2001, NULL);
332    OH_Huks_FreeParamSet(&genParamSet);
333    OH_Huks_FreeParamSet(&initParamSet01);
334    OH_Huks_FreeParamSet(&finishParamSet01);
335    OH_Huks_FreeParamSet(&initParamSet02);
336    OH_Huks_FreeParamSet(&finishParamSet02);
337
338    napi_value ret;
339    napi_create_int32(env, ohResult.errorCode, &ret);
340    return ret;
341}
342```
343