1# 加密导入密钥(C/C++) 2 3 4以加密导入ECDH密钥对为例,涉及业务侧加密密钥的[密钥生成](huks-key-generation-overview.md)、[协商](huks-key-agreement-overview.md)等操作不在本示例中体现。 5 6 7具体的场景介绍及支持的算法规格,请参考[密钥导入的支持的算法](huks-key-import-overview.md#支持的算法)。 8 9 10## 开发步骤 11 121. 设备A(导入设备)将待导入密钥转换成[HUKS密钥材料格式](huks-concepts.md#密钥材料格式)To_Import_Key(仅针对非对称密钥,若待导入密钥是对称密钥则可省略此步骤)。 13 142. 设备B(被导入设备)生成一个加密导入用途的、用于协商的非对称密钥对Wrapping_Key(公钥Wrapping_Pk,私钥Wrapping_Sk),其密钥用途设置为unwrap,导出Wrapping_Key的公钥材料Wrapping_Pk并保存。 15 163. 设备A使用和设备B同样的算法,生成一个加密导入用途的、用于协商的非对称密钥对Caller_Key(公钥Caller_Pk,私钥Caller_Sk),导出Caller_Key的公钥材料Caller_Pk并保存。 17 184. 设备A生成一个对称密钥Caller_Kek,该密钥后续将用于加密To_Import_Key。 19 205. 设备A基于Caller_Key的私钥Caller_Sk和设备B Wrapping_Key的公钥Wrapping_Pk,协商出Shared_Key。 21 226. 设备A使用Caller_Kek加密To_Import_Key,生成To_Import_Key_Enc。 23 247. 设备A使用Shared_Key加密Caller_Kek,生成Caller_Kek_Enc。 25 268. 设备A封装Caller_Pk、Caller_Kek_Enc、To_Import_Key_Enc等加密导入的密钥材料并发送给设备B,加密导入密钥材料格式见[加密导入密钥材料格式](huks-key-import-overview.md#加密导入密钥材料格式)。 27 289. 设备B导入封装的加密密钥材料。 29 3010. 设备A、B删除用于加密导入的密钥。 31 32```c++ 33#include "napi/native_api.h" 34#include "huks/native_huks_api.h" 35#include "huks/native_huks_param.h" 36#include <algorithm> 37OH_Huks_Result InitParamSet(struct OH_Huks_ParamSet **paramSet, const struct OH_Huks_Param *params, 38 uint32_t paramCount) { 39 OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet); 40 if (ret.errorCode != OH_HUKS_SUCCESS) { 41 return ret; 42 } 43 ret = OH_Huks_AddParams(*paramSet, params, paramCount); 44 if (ret.errorCode != OH_HUKS_SUCCESS) { 45 OH_Huks_FreeParamSet(paramSet); 46 return ret; 47 } 48 ret = OH_Huks_BuildParamSet(paramSet); 49 if (ret.errorCode != OH_HUKS_SUCCESS) { 50 OH_Huks_FreeParamSet(paramSet); 51 return ret; 52 } 53 return ret; 54} 55struct HksImportWrappedKeyTestParams { 56 // server key, for real 57 struct OH_Huks_Blob *wrappingKeyAlias; 58 struct OH_Huks_ParamSet *genWrappingKeyParamSet; 59 uint32_t publicKeySize; 60 struct OH_Huks_Blob *callerKeyAlias; 61 struct OH_Huks_ParamSet *genCallerKeyParamSet; 62 struct OH_Huks_Blob *callerKekAlias; 63 struct OH_Huks_Blob *callerKek; 64 struct OH_Huks_ParamSet *importCallerKekParamSet; 65 struct OH_Huks_Blob *callerAgreeKeyAlias; 66 struct OH_Huks_ParamSet *agreeParamSet; 67 struct OH_Huks_ParamSet *importWrappedKeyParamSet; 68 struct OH_Huks_Blob *importedKeyAlias; 69 struct OH_Huks_Blob *importedPlainKey; 70 uint32_t keyMaterialLen; 71}; 72static const uint32_t IV_SIZE = 16; 73static uint8_t IV[IV_SIZE] = "bababababababab"; // 此处仅为测试数据,实际使用时该值每次应该不同 74static const uint32_t WRAPPED_KEY_IV_SIZE = 16; 75static uint8_t WRAPPED_KEY_IV[IV_SIZE] = "bababababababab"; // 此处仅为测试数据,实际使用时该值每次应该不同 76static const uint32_t AAD_SIZE = 16; 77static uint8_t AAD[AAD_SIZE] = "abababababababa"; // 此处仅为测试数据,实际使用时该值每次应该不同 78static const uint32_t NONCE_SIZE = 12; 79static uint8_t NONCE[NONCE_SIZE] = "hahahahahah"; // 此处仅为测试数据,实际使用时该值每次应该不同 80static const uint32_t AEAD_TAG_SIZE = 16; 81static const uint32_t X25519_256_SIZE = 256; 82static struct OH_Huks_Blob g_wrappingKeyAliasAes256 = {.size = (uint32_t)strlen("test_wrappingKey_x25519_aes256"), 83 .data = (uint8_t *)"test_wrappingKey_x25519_aes256"}; 84static struct OH_Huks_Blob g_callerKeyAliasAes256 = {.size = (uint32_t)strlen("test_caller_key_x25519_aes256"), 85 .data = (uint8_t *)"test_caller_key_x25519_aes256"}; 86static struct OH_Huks_Blob g_callerKekAliasAes256 = {.size = (uint32_t)strlen("test_caller_kek_x25519_aes256"), 87 .data = (uint8_t *)"test_caller_kek_x25519_aes256"}; 88static struct OH_Huks_Blob g_callerAes256Kek = {.size = (uint32_t)strlen("This is kek to encrypt plain key"), 89 .data = (uint8_t *)"This is kek to encrypt plain key"}; 90static struct OH_Huks_Blob g_callerAgreeKeyAliasAes256 = {.size = 91 (uint32_t)strlen("test_caller_agree_key_x25519_aes256"), 92 .data = (uint8_t *)"test_caller_agree_key_x25519_aes256"}; 93static struct OH_Huks_Blob g_importedKeyAliasAes256 = {.size = (uint32_t)strlen("test_import_key_x25519_aes256"), 94 .data = (uint8_t *)"test_import_key_x25519_aes256"}; 95static struct OH_Huks_Blob g_importedAes256PlainKey = {.size = (uint32_t)strlen("This is plain key to be imported"), 96 .data = (uint8_t *)"This is plain key to be imported"}; 97static struct OH_Huks_Param g_importWrappedAes256Params[] = { 98 {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES}, 99 {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT | OH_HUKS_KEY_PURPOSE_DECRYPT}, 100 {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256}, 101 {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE}, 102 {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM}, 103 {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE}, 104 {.tag = OH_HUKS_TAG_UNWRAP_ALGORITHM_SUITE, .uint32Param = OH_HUKS_UNWRAP_SUITE_X25519_AES_256_GCM_NOPADDING}, 105 {.tag = OH_HUKS_TAG_ASSOCIATED_DATA, 106 .blob = {.size = AAD_SIZE, .data = (uint8_t *)AAD}}, // 此处仅为测试数据,实际使用时该值应与调用者信息相关 107 {.tag = OH_HUKS_TAG_NONCE, 108 .blob = {.size = NONCE_SIZE, .data = (uint8_t *)NONCE}}}; // 此处仅为测试数据,实际使用时该值每次应该不同 109static const uint32_t g_x25519PubKeySize = 32; 110static struct OH_Huks_Param g_genWrappingKeyParams[] = { 111 {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_X25519}, 112 {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_UNWRAP}, 113 {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_CURVE25519_KEY_SIZE_256}}; 114static struct OH_Huks_Param g_genCallerX25519Params[] = { 115 {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_X25519}, 116 {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE}, 117 {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_CURVE25519_KEY_SIZE_256}}; 118static struct OH_Huks_Param g_importParamsCallerKek[] = { 119 {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES}, 120 {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT}, 121 {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256}, 122 {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE}, 123 {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM}, 124 {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE}, 125 {.tag = OH_HUKS_TAG_IV, 126 .blob = {.size = WRAPPED_KEY_IV_SIZE, 127 .data = (uint8_t *)WRAPPED_KEY_IV}}}; // 此处仅为测试数据,实际使用时该值每次应该不同 128static struct OH_Huks_Param g_callerAgreeParams[] = { 129 {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_X25519}, 130 {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_AGREE}, 131 {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_CURVE25519_KEY_SIZE_256}}; 132static struct OH_Huks_Param g_aesKekEncryptParams[] = { 133 {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES}, 134 {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT}, 135 {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256}, 136 {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE}, 137 {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM}, 138 {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE}, 139 {.tag = OH_HUKS_TAG_ASSOCIATED_DATA, 140 .blob = {.size = AAD_SIZE, .data = (uint8_t *)AAD}}, // 此处仅为测试数据,实际使用时该值应与调用者信息相关 141 {.tag = OH_HUKS_TAG_NONCE, 142 .blob = {.size = NONCE_SIZE, .data = (uint8_t *)NONCE}}}; // 此处仅为测试数据,实际使用时该值每次应该不同 143static struct OH_Huks_Param g_importAgreeKeyParams[] = { 144 {.tag = OH_HUKS_TAG_ALGORITHM, .uint32Param = OH_HUKS_ALG_AES}, 145 {.tag = OH_HUKS_TAG_PURPOSE, .uint32Param = OH_HUKS_KEY_PURPOSE_ENCRYPT}, 146 {.tag = OH_HUKS_TAG_KEY_SIZE, .uint32Param = OH_HUKS_AES_KEY_SIZE_256}, 147 {.tag = OH_HUKS_TAG_PADDING, .uint32Param = OH_HUKS_PADDING_NONE}, 148 {.tag = OH_HUKS_TAG_BLOCK_MODE, .uint32Param = OH_HUKS_MODE_GCM}, 149 {.tag = OH_HUKS_TAG_DIGEST, .uint32Param = OH_HUKS_DIGEST_NONE}, 150 {.tag = OH_HUKS_TAG_IV, 151 .blob = {.size = IV_SIZE, .data = (uint8_t *)IV}}}; // 此处仅为测试数据,实际使用时该值每次应该不同 152OH_Huks_Result HuksAgreeKey(const struct OH_Huks_ParamSet *paramSet, const struct OH_Huks_Blob *keyAlias, 153 const struct OH_Huks_Blob *peerPublicKey, struct OH_Huks_Blob *agreedKey) { 154 uint8_t temp[10] = {0}; 155 struct OH_Huks_Blob inData = {sizeof(temp), temp}; 156 uint8_t handleU[sizeof(uint64_t)] = {0}; 157 struct OH_Huks_Blob handle = {sizeof(uint64_t), handleU}; 158 OH_Huks_Result ret = OH_Huks_InitSession(keyAlias, paramSet, &handle, nullptr); 159 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 160 return ret; 161 } 162 uint8_t outDataU[1024] = {0}; 163 struct OH_Huks_Blob outDataUpdate = {1024, outDataU}; 164 ret = OH_Huks_UpdateSession(&handle, paramSet, peerPublicKey, &outDataUpdate); 165 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 166 return ret; 167 } 168 ret = OH_Huks_FinishSession(&handle, paramSet, &inData, agreedKey); 169 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 170 return ret; 171 } 172 return ret; 173} 174OH_Huks_Result MallocAndCheckBlobData(struct OH_Huks_Blob *blob, const uint32_t blobSize) { 175 struct OH_Huks_Result ret; 176 ret.errorCode = OH_HUKS_SUCCESS; 177 blob->data = (uint8_t *)malloc(blobSize); 178 if (blob->data == NULL) { 179 ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR; 180 } 181 return ret; 182} 183static const uint32_t TIMES = 4; 184static const uint32_t MAX_UPDATE_SIZE = 64; 185static const uint32_t MAX_OUTDATA_SIZE = MAX_UPDATE_SIZE * TIMES; 186#define HUKS_FREE_BLOB(blob) \ 187 do { \ 188 if ((blob).data != nullptr) { \ 189 free((blob).data); \ 190 (blob).data = nullptr; \ 191 } \ 192 (blob).size = 0; \ 193 } while (0) 194#define OH_HUKS_KEY_BYTES(keySize) (((keySize) + 7) / 8) 195static OH_Huks_Result HksEncryptLoopUpdate(const struct OH_Huks_Blob *handle, const struct OH_Huks_ParamSet *paramSet, 196 const struct OH_Huks_Blob *inData, struct OH_Huks_Blob *outData) { 197 struct OH_Huks_Result ret; 198 ret.errorCode = OH_HUKS_SUCCESS; 199 struct OH_Huks_Blob inDataSeg = *inData; 200 uint8_t *lastPtr = inData->data + inData->size - 1; 201 struct OH_Huks_Blob outDataSeg = {MAX_OUTDATA_SIZE, NULL}; 202 uint8_t *cur = outData->data; 203 outData->size = 0; 204 inDataSeg.size = MAX_UPDATE_SIZE; 205 bool isFinished = false; 206 while (inDataSeg.data <= lastPtr) { 207 if (inDataSeg.data + MAX_UPDATE_SIZE <= lastPtr) { 208 outDataSeg.size = MAX_OUTDATA_SIZE; 209 } else { 210 isFinished = true; 211 inDataSeg.size = lastPtr - inDataSeg.data + 1; 212 break; 213 } 214 if (MallocAndCheckBlobData(&outDataSeg, outDataSeg.size).errorCode != (int32_t)OH_HUKS_SUCCESS) { 215 ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR; 216 return ret; 217 } 218 ret = OH_Huks_UpdateSession(handle, paramSet, &inDataSeg, &outDataSeg); 219 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 220 free(outDataSeg.data); 221 return ret; 222 } 223 std::copy(outDataSeg.data, outDataSeg.data + outDataSeg.size, cur); 224 cur += outDataSeg.size; 225 outData->size += outDataSeg.size; 226 free(outDataSeg.data); 227 if ((isFinished == false) && (inDataSeg.data + MAX_UPDATE_SIZE > lastPtr)) { 228 ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR; 229 return ret; 230 } 231 inDataSeg.data += MAX_UPDATE_SIZE; 232 } 233 struct OH_Huks_Blob outDataFinish = {inDataSeg.size * TIMES, NULL}; 234 if (MallocAndCheckBlobData(&outDataFinish, outDataFinish.size).errorCode != (int32_t)OH_HUKS_SUCCESS) { 235 ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR; 236 return ret; 237 } 238 ret = OH_Huks_FinishSession(handle, paramSet, &inDataSeg, &outDataFinish); 239 if (ret.errorCode != OH_HUKS_SUCCESS) { 240 free(outDataFinish.data); 241 return ret; 242 } 243 std::copy(outDataFinish.data, outDataFinish.data + outDataFinish.size, cur); 244 outData->size += outDataFinish.size; 245 free(outDataFinish.data); 246 return ret; 247} 248OH_Huks_Result HuksEncrypt(const struct OH_Huks_Blob *key, const struct OH_Huks_ParamSet *paramSet, 249 const struct OH_Huks_Blob *plainText, struct OH_Huks_Blob *cipherText) { 250 uint8_t handle[sizeof(uint64_t)] = {0}; 251 struct OH_Huks_Blob handleBlob = {sizeof(uint64_t), handle}; 252 OH_Huks_Result ret = OH_Huks_InitSession(key, paramSet, &handleBlob, nullptr); 253 if (ret.errorCode != OH_HUKS_SUCCESS) { 254 return ret; 255 } 256 ret = HksEncryptLoopUpdate(&handleBlob, paramSet, plainText, cipherText); 257 return ret; 258} 259static OH_Huks_Result BuildWrappedKeyData(struct OH_Huks_Blob **blobArray, uint32_t size, 260 struct OH_Huks_Blob *outData) { 261 uint32_t totalLength = size * sizeof(uint32_t); 262 struct OH_Huks_Result ret; 263 ret.errorCode = OH_HUKS_SUCCESS; 264 /* 计算大小 */ 265 for (uint32_t i = 0; i < size; ++i) { 266 totalLength += blobArray[i]->size; 267 } 268 struct OH_Huks_Blob outBlob = {0, nullptr}; 269 outBlob.size = totalLength; 270 ret = MallocAndCheckBlobData(&outBlob, outBlob.size); 271 if (ret.errorCode != OH_HUKS_SUCCESS) { 272 return ret; 273 } 274 uint32_t offset = 0; 275 /* 拷贝数据 */ 276 for (uint32_t i = 0; i < size; ++i) { 277 if (totalLength - offset >= sizeof(blobArray[i]->size)) { 278 std::copy(reinterpret_cast<uint8_t *>(&blobArray[i]->size), 279 reinterpret_cast<uint8_t *>(&blobArray[i]->size) + sizeof(blobArray[i]->size), 280 outBlob.data + offset); 281 } else { 282 ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR; 283 return ret; 284 } 285 offset += sizeof(blobArray[i]->size); 286 if (totalLength - offset >= blobArray[i]->size) { 287 std::copy(blobArray[i]->data, blobArray[i]->data + blobArray[i]->size, outBlob.data + offset); 288 } else { 289 ret.errorCode = OH_HUKS_ERR_CODE_INTERNAL_ERROR; 290 return ret; 291 } 292 offset += blobArray[i]->size; 293 } 294 outData->size = outBlob.size; 295 outData->data = outBlob.data; 296 return ret; 297} 298static OH_Huks_Result CheckParamsValid(const struct HksImportWrappedKeyTestParams *params) { 299 struct OH_Huks_Result ret; 300 ret.errorCode = OH_HUKS_SUCCESS; 301 if (params == nullptr) { 302 ret.errorCode = OH_HUKS_ERR_CODE_ILLEGAL_ARGUMENT; 303 return ret; 304 } 305 if (params->wrappingKeyAlias == nullptr || params->genWrappingKeyParamSet == nullptr || 306 params->callerKeyAlias == nullptr || params->genCallerKeyParamSet == nullptr || 307 params->callerKekAlias == nullptr || params->callerKek == nullptr || 308 params->importCallerKekParamSet == nullptr || params->callerAgreeKeyAlias == nullptr || 309 params->agreeParamSet == nullptr || params->importWrappedKeyParamSet == nullptr || 310 params->importedKeyAlias == nullptr || params->importedPlainKey == nullptr) { 311 ret.errorCode = OH_HUKS_ERR_CODE_ILLEGAL_ARGUMENT; 312 return ret; 313 } 314 return ret; 315} 316static OH_Huks_Result GenerateAndExportHuksPublicKey(const struct HksImportWrappedKeyTestParams *params, 317 struct OH_Huks_Blob *huksPublicKey) { 318 OH_Huks_Result ret = OH_Huks_GenerateKeyItem(params->wrappingKeyAlias, params->genWrappingKeyParamSet, nullptr); 319 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 320 return ret; 321 } 322 huksPublicKey->size = params->publicKeySize; 323 ret = MallocAndCheckBlobData(huksPublicKey, huksPublicKey->size); 324 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 325 return ret; 326 } 327 ret = OH_Huks_ExportPublicKeyItem(params->wrappingKeyAlias, nullptr, huksPublicKey); 328 return ret; 329} 330static OH_Huks_Result GenerateAndExportCallerPublicKey(const struct HksImportWrappedKeyTestParams *params, 331 struct OH_Huks_Blob *callerSelfPublicKey) { 332 OH_Huks_Result ret = OH_Huks_GenerateKeyItem(params->callerKeyAlias, params->genCallerKeyParamSet, nullptr); 333 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 334 return ret; 335 } 336 callerSelfPublicKey->size = params->publicKeySize; 337 ret = MallocAndCheckBlobData(callerSelfPublicKey, callerSelfPublicKey->size); 338 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 339 return ret; 340 } 341 ret = OH_Huks_ExportPublicKeyItem(params->callerKeyAlias, params->genWrappingKeyParamSet, callerSelfPublicKey); 342 return ret; 343} 344static OH_Huks_Result ImportKekAndAgreeSharedSecret(const struct HksImportWrappedKeyTestParams *params, 345 const struct OH_Huks_Blob *huksPublicKey, 346 struct OH_Huks_Blob *outSharedKey) { 347 OH_Huks_Result ret = 348 OH_Huks_ImportKeyItem(params->callerKekAlias, params->importCallerKekParamSet, params->callerKek); 349 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 350 return ret; 351 } 352 ret = MallocAndCheckBlobData(outSharedKey, outSharedKey->size); 353 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 354 return ret; 355 } 356 ret = HuksAgreeKey(params->agreeParamSet, params->callerKeyAlias, huksPublicKey, outSharedKey); 357 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 358 return ret; 359 } 360 struct OH_Huks_ParamSet *importAgreeKeyParams = nullptr; 361 ret = InitParamSet(&importAgreeKeyParams, g_importAgreeKeyParams, 362 sizeof(g_importAgreeKeyParams) / sizeof(OH_Huks_Param)); 363 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 364 return ret; 365 } 366 ret = OH_Huks_ImportKeyItem(params->callerAgreeKeyAlias, importAgreeKeyParams, outSharedKey); 367 OH_Huks_FreeParamSet(&importAgreeKeyParams); 368 return ret; 369} 370static OH_Huks_Result EncryptImportedPlainKeyAndKek(const struct HksImportWrappedKeyTestParams *params, 371 struct OH_Huks_Blob *plainCipherText, 372 struct OH_Huks_Blob *kekCipherText) { 373 struct OH_Huks_ParamSet *encryptParamSet = nullptr; 374 OH_Huks_Result ret = 375 InitParamSet(&encryptParamSet, g_aesKekEncryptParams, sizeof(g_aesKekEncryptParams) / sizeof(OH_Huks_Param)); 376 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 377 return ret; 378 } 379 ret = HuksEncrypt(params->callerKekAlias, encryptParamSet, params->importedPlainKey, plainCipherText); 380 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 381 return ret; 382 } 383 ret = HuksEncrypt(params->callerAgreeKeyAlias, encryptParamSet, params->callerKek, kekCipherText); 384 OH_Huks_FreeParamSet(&encryptParamSet); 385 return ret; 386} 387static OH_Huks_Result ImportWrappedKey(const struct HksImportWrappedKeyTestParams *params, 388 struct OH_Huks_Blob *plainCipher, struct OH_Huks_Blob *kekCipherText, 389 struct OH_Huks_Blob *peerPublicKey, struct OH_Huks_Blob *wrappedKeyData) { 390 struct OH_Huks_Blob commonAad = {.size = AAD_SIZE, .data = reinterpret_cast<uint8_t *>(AAD)}; 391 struct OH_Huks_Blob commonNonce = {.size = NONCE_SIZE, .data = reinterpret_cast<uint8_t *>(NONCE)}; 392 struct OH_Huks_Blob keyMaterialLen = {.size = sizeof(uint32_t), .data = (uint8_t *)¶ms->keyMaterialLen}; 393 /* 从密文中拷贝AEAD的tag并缩小其大小 */ 394 const uint32_t tagSize = AEAD_TAG_SIZE; 395 uint8_t kekTagBuf[tagSize] = {0}; 396 struct OH_Huks_Blob kekTag = {.size = tagSize, .data = kekTagBuf}; 397 std::copy(plainCipher->data + (plainCipher->size - tagSize), 398 plainCipher->data + (plainCipher->size - tagSize) + tagSize, kekTag.data); 399 plainCipher->size -= tagSize; 400 /* 从密钥加密密钥的密文中拷贝AEAD的tag并缩小其大小 */ 401 uint8_t agreeKeyTagBuf[tagSize] = {0}; 402 struct OH_Huks_Blob agreeKeyTag = {.size = tagSize, .data = agreeKeyTagBuf}; 403 std::copy(kekCipherText->data + (kekCipherText->size - tagSize), 404 kekCipherText->data + (kekCipherText->size - tagSize) + tagSize, agreeKeyTagBuf); 405 kekCipherText->size -= tagSize; 406 struct OH_Huks_Blob *blobArray[] = {peerPublicKey, &commonAad, &commonNonce, &agreeKeyTag, kekCipherText, 407 &commonAad, &commonNonce, &kekTag, &keyMaterialLen, plainCipher}; 408 OH_Huks_Result ret = BuildWrappedKeyData(blobArray, OH_HUKS_IMPORT_WRAPPED_KEY_TOTAL_BLOBS, wrappedKeyData); 409 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 410 return ret; 411 } 412 struct OH_Huks_Param *purpose = nullptr; 413 ret = OH_Huks_GetParam(params->importWrappedKeyParamSet, OH_HUKS_TAG_PURPOSE, &purpose); 414 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 415 return ret; 416 } 417 ret = OH_Huks_ImportWrappedKeyItem(params->importedKeyAlias, params->wrappingKeyAlias, 418 params->importWrappedKeyParamSet, wrappedKeyData); 419 return ret; 420} 421OH_Huks_Result HksImportWrappedKeyTestCommonCase(const struct HksImportWrappedKeyTestParams *params) { 422 OH_Huks_Result ret = CheckParamsValid(params); 423 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 424 return ret; 425 } 426 struct OH_Huks_Blob huksPublicKey = {0, nullptr}; 427 struct OH_Huks_Blob callerSelfPublicKey = {0, nullptr}; 428 struct OH_Huks_Blob outSharedKey = {.size = OH_HUKS_KEY_BYTES(OH_HUKS_AES_KEY_SIZE_256), .data = nullptr}; 429 struct OH_Huks_Blob wrappedKeyData = {0, nullptr}; 430 uint8_t plainKeyCipherBuffer[OH_HUKS_MAX_KEY_SIZE] = {0}; 431 struct OH_Huks_Blob plainCipherText = {OH_HUKS_MAX_KEY_SIZE, plainKeyCipherBuffer}; 432 uint8_t kekCipherTextBuffer[OH_HUKS_MAX_KEY_SIZE] = {0}; 433 struct OH_Huks_Blob kekCipherText = {OH_HUKS_MAX_KEY_SIZE, kekCipherTextBuffer}; 434 /* 模拟加密导入密钥场景,设备A为远端设备(导入设备),设备B为本端设备(被导入设备) */ 435 do { 436 /** 437 * 1.设备A将待导入密钥转换成HUKS密钥材料格式To_Import_Key(仅针对非对称密钥,若待导入密钥是对称密钥则可省略此步骤), 438 * 本示例使用g_importedAes256PlainKey(对称密钥)作为模拟 439 */ 440 /* 2.设备B生成一个加密导入用途的、用于协商的非对称密钥对Wrapping_Key(公钥Wrapping_Pk,私钥Wrapping_Sk),其密钥用途设置为unwrap,导出Wrapping_Key公钥Wrapping_Pk存放在变量huksPublicKey中 441 */ 442 ret = GenerateAndExportHuksPublicKey(params, &huksPublicKey); 443 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 444 break; 445 } 446 /* 3.设备A使用和设备B同样的算法,生成一个加密导入用途的、用于协商的非对称密钥对Caller_Key(公钥Caller_Pk,私钥Caller_Sk),导出Caller_Key公钥Caller_Pk存放在变量callerSelfPublicKey中 447 */ 448 ret = GenerateAndExportCallerPublicKey(params, &callerSelfPublicKey); 449 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 450 break; 451 } 452 /** 453 * 4. 设备A生成一个对称密钥Caller_Kek,该密钥后续将用于加密To_Import_Key 454 * 5. 设备A基于Caller_Key的私钥Caller_Sk和设备B Wrapping_Key的公钥Wrapping_Pk,协商出Shared_Key 455 */ 456 ret = ImportKekAndAgreeSharedSecret(params, &huksPublicKey, &outSharedKey); 457 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 458 break; 459 } 460 /** 461 * 6. 设备A使用Caller_Kek加密To_Import_Key,生成To_Import_Key_Enc 462 * 7. 设备A使用Shared_Key加密Caller_Kek,生成Caller_Kek_Enc 463 */ 464 ret = EncryptImportedPlainKeyAndKek(params, &plainCipherText, &kekCipherText); 465 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 466 break; 467 } 468 /* 8. 设备A封装Caller_Pk、To_Import_Key_Enc、Caller_Kek_Enc等加密导入的材料并发送给设备B。 469 * 本示例作为变量存放在callerSelfPublicKey,plainCipherText,kekCipherText 470 * 9. 设备B导入封装的加密密钥材料 471 */ 472 ret = ImportWrappedKey(params, &plainCipherText, &kekCipherText, &callerSelfPublicKey, &wrappedKeyData); 473 } while (0); 474 /* 10. 设备A、B删除用于加密导入的密钥 */ 475 HUKS_FREE_BLOB(huksPublicKey); 476 HUKS_FREE_BLOB(callerSelfPublicKey); 477 HUKS_FREE_BLOB(outSharedKey); 478 HUKS_FREE_BLOB(wrappedKeyData); 479 return ret; 480} 481void HksClearKeysForWrappedKeyTest(const struct HksImportWrappedKeyTestParams *params) { 482 OH_Huks_Result ret = CheckParamsValid(params); 483 if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) { 484 return; 485 } 486 (void)OH_Huks_DeleteKeyItem(params->wrappingKeyAlias, nullptr); 487 (void)OH_Huks_DeleteKeyItem(params->callerKeyAlias, nullptr); 488 (void)OH_Huks_DeleteKeyItem(params->callerKekAlias, nullptr); 489 (void)OH_Huks_DeleteKeyItem(params->callerAgreeKeyAlias, nullptr); 490 (void)OH_Huks_DeleteKeyItem(params->importedKeyAlias, nullptr); 491} 492static OH_Huks_Result InitCommonTestParamsAndDoImport(struct HksImportWrappedKeyTestParams *importWrappedKeyTestParams, 493 const struct OH_Huks_Param *importedKeyParamSetArray, 494 uint32_t arraySize) { 495 struct OH_Huks_ParamSet *genX25519KeyParamSet = nullptr; 496 struct OH_Huks_ParamSet *genCallerKeyParamSet = nullptr; 497 struct OH_Huks_ParamSet *callerImportParamsKek = nullptr; 498 struct OH_Huks_ParamSet *agreeParamSet = nullptr; 499 struct OH_Huks_ParamSet *importPlainKeyParams = nullptr; 500 OH_Huks_Result ret; 501 do { 502 ret = InitParamSet(&genX25519KeyParamSet, g_genWrappingKeyParams, 503 sizeof(g_genWrappingKeyParams) / sizeof(OH_Huks_Param)); 504 if (ret.errorCode != OH_HUKS_SUCCESS) { 505 break; 506 } 507 importWrappedKeyTestParams->genWrappingKeyParamSet = genX25519KeyParamSet; 508 importWrappedKeyTestParams->publicKeySize = g_x25519PubKeySize; 509 ret = InitParamSet(&genCallerKeyParamSet, g_genCallerX25519Params, 510 sizeof(g_genCallerX25519Params) / sizeof(OH_Huks_Param)); 511 if (ret.errorCode != OH_HUKS_SUCCESS) { 512 break; 513 } 514 importWrappedKeyTestParams->genCallerKeyParamSet = genCallerKeyParamSet; 515 ret = InitParamSet(&callerImportParamsKek, g_importParamsCallerKek, 516 sizeof(g_importParamsCallerKek) / sizeof(OH_Huks_Param)); 517 if (ret.errorCode != OH_HUKS_SUCCESS) { 518 break; 519 } 520 importWrappedKeyTestParams->importCallerKekParamSet = callerImportParamsKek; 521 ret = InitParamSet(&agreeParamSet, g_callerAgreeParams, sizeof(g_callerAgreeParams) / sizeof(OH_Huks_Param)); 522 if (ret.errorCode != OH_HUKS_SUCCESS) { 523 break; 524 } 525 importWrappedKeyTestParams->agreeParamSet = agreeParamSet; 526 ret = InitParamSet(&importPlainKeyParams, importedKeyParamSetArray, arraySize); 527 if (ret.errorCode != OH_HUKS_SUCCESS) { 528 break; 529 } 530 importWrappedKeyTestParams->importWrappedKeyParamSet = importPlainKeyParams; 531 ret = HksImportWrappedKeyTestCommonCase(importWrappedKeyTestParams); 532 } while (0); 533 OH_Huks_FreeParamSet(&genX25519KeyParamSet); 534 OH_Huks_FreeParamSet(&genCallerKeyParamSet); 535 OH_Huks_FreeParamSet(&callerImportParamsKek); 536 OH_Huks_FreeParamSet(&agreeParamSet); 537 OH_Huks_FreeParamSet(&importPlainKeyParams); 538 return ret; 539} 540static napi_value ImportWrappedKey(napi_env env, napi_callback_info info) { 541 struct HksImportWrappedKeyTestParams importWrappedKeyTestParams001 = {0}; 542 importWrappedKeyTestParams001.wrappingKeyAlias = &g_wrappingKeyAliasAes256; 543 importWrappedKeyTestParams001.keyMaterialLen = g_importedAes256PlainKey.size; 544 importWrappedKeyTestParams001.callerKeyAlias = &g_callerKeyAliasAes256; 545 importWrappedKeyTestParams001.callerKekAlias = &g_callerKekAliasAes256; 546 importWrappedKeyTestParams001.callerKek = &g_callerAes256Kek; 547 importWrappedKeyTestParams001.callerAgreeKeyAlias = &g_callerAgreeKeyAliasAes256; 548 importWrappedKeyTestParams001.importedKeyAlias = &g_importedKeyAliasAes256; 549 importWrappedKeyTestParams001.importedPlainKey = &g_importedAes256PlainKey; 550 OH_Huks_Result ohResult = 551 InitCommonTestParamsAndDoImport(&importWrappedKeyTestParams001, g_importWrappedAes256Params, 552 sizeof(g_importWrappedAes256Params) / sizeof(struct OH_Huks_Param)); 553 HksClearKeysForWrappedKeyTest(&importWrappedKeyTestParams001); 554 napi_value ret; 555 napi_create_int32(env, ohResult.errorCode, &ret); 556 return ret; 557} 558``` 559 560 561## 调测验证 562 563调用[OH_Huks_IsKeyItemExist](../../reference/apis-universal-keystore-kit/_huks_key_api.md#oh_huks_iskeyitemexist)验证密钥是否存在,如密钥存在即表示密钥导入成功。 564 565```c++ 566#include "huks/native_huks_api.h" 567#include "huks/native_huks_param.h" 568#include <string.h> 569static napi_value IsKeyExist(napi_env env, napi_callback_info info) 570{ 571 /* 1.指定密钥别名 */ 572 struct OH_Huks_Blob keyAlias = { 573 (uint32_t)strlen("test_key"), 574 (uint8_t *)"test_key" 575 }; 576 577 /* 2.调用OH_Huks_IsKeyItemExist判断密钥是否存在 */ 578 struct OH_Huks_Result ohResult = OH_Huks_IsKeyItemExist(&keyAlias, NULL); 579 if (ohResult.errorCode != OH_HUKS_SUCCESS) { 580 // 失败 581 } else { 582 // 成功 583 } 584} 585``` 586