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