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