1# 加密导入密钥(ArkTS) 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```ts 33import { huks } from '@kit.UniversalKeystoreKit'; 34 35let IV = '0000000000000000'; 36let AAD = "abababababababab"; 37let NONCE = "hahahahahaha"; 38let TAG_SIZE = 16; 39let FILED_LENGTH = 4; 40let importedAes192PlainKey = "The aes192 key to import"; 41let callerAes256Kek = "The is kek to encrypt aes192 key"; 42let callerKeyAlias = "test_caller_key_ecdh_aes192"; 43let callerKekAliasAes256 = "test_caller_kek_ecdh_aes256"; 44let callerAgreeKeyAliasAes256 = "test_caller_agree_key_ecdh_aes256"; 45let importedKeyAliasAes192 = "test_import_key_ecdh_aes192"; 46let huksPubKey: Uint8Array; 47let callerSelfPublicKey: Uint8Array; 48let outSharedKey: Uint8Array; 49let outPlainKeyEncData: Uint8Array; 50let outKekEncData: Uint8Array; 51let outKekEncTag: Uint8Array; 52let outAgreeKeyEncTag: Uint8Array; 53let mask = [0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000]; 54 55function subUint8ArrayOf(arrayBuf: Uint8Array, start: number, end: number) { 56 let arr: number[] = []; 57 for (let i = start; i < end && i < arrayBuf.length; ++i) { 58 arr.push(arrayBuf[i]); 59 } 60 return new Uint8Array(arr); 61} 62 63function stringToUint8Array(str: string) { 64 let arr: number[] = []; 65 for (let i = 0, j = str.length; i < j; ++i) { 66 arr.push(str.charCodeAt(i)); 67 } 68 return new Uint8Array(arr); 69} 70 71function assignLength(length: number, arrayBuf: Uint8Array, startIndex: number) { 72 let index = startIndex; 73 for (let i = 0; i < 4; i++) { 74 arrayBuf[index++] = (length & mask[i]) >> (i * 8); 75 } 76 return 4; 77} 78 79function assignData(data: Uint8Array, arrayBuf: Uint8Array, startIndex: number) { 80 let index = startIndex; 81 for (let i = 0; i < data.length; i++) { 82 arrayBuf[index++] = data[i]; 83 } 84 return data.length; 85} 86 87let genWrappingKeyParams: huks.HuksOptions = { 88 properties: new Array<huks.HuksParam>( 89 { 90 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 91 value: huks.HuksKeyAlg.HUKS_ALG_ECC 92 }, 93 { 94 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 95 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_UNWRAP 96 }, 97 { 98 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 99 value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256 100 }, 101 { 102 tag: huks.HuksTag.HUKS_TAG_PADDING, 103 value: huks.HuksKeyPadding.HUKS_PADDING_NONE 104 } 105 ) 106} 107let genCallerEcdhParams: huks.HuksOptions = { 108 properties: new Array<huks.HuksParam>( 109 { 110 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 111 value: huks.HuksKeyAlg.HUKS_ALG_ECC 112 }, 113 { 114 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 115 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE 116 }, 117 { 118 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 119 value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256 120 } 121 ) 122} 123let importParamsCallerKek: huks.HuksOptions = { 124 properties: new Array<huks.HuksParam>( 125 { 126 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 127 value: huks.HuksKeyAlg.HUKS_ALG_AES 128 }, 129 { 130 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 131 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT 132 }, 133 { 134 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 135 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 136 }, 137 { 138 tag: huks.HuksTag.HUKS_TAG_PADDING, 139 value: huks.HuksKeyPadding.HUKS_PADDING_NONE 140 }, 141 { 142 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 143 value: huks.HuksCipherMode.HUKS_MODE_GCM 144 }, 145 { 146 tag: huks.HuksTag.HUKS_TAG_DIGEST, 147 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE 148 }, 149 { 150 tag: huks.HuksTag.HUKS_TAG_IV, 151 value: stringToUint8Array(IV) 152 } 153 ), 154 inData: stringToUint8Array(callerAes256Kek) 155} 156let importParamsAgreeKey: huks.HuksOptions = { 157 properties: new Array<huks.HuksParam>( 158 { 159 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 160 value: huks.HuksKeyAlg.HUKS_ALG_AES 161 }, 162 { 163 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 164 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT 165 }, 166 { 167 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 168 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 169 }, 170 { 171 tag: huks.HuksTag.HUKS_TAG_PADDING, 172 value: huks.HuksKeyPadding.HUKS_PADDING_NONE 173 }, 174 { 175 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 176 value: huks.HuksCipherMode.HUKS_MODE_GCM 177 }, 178 { 179 tag: huks.HuksTag.HUKS_TAG_DIGEST, 180 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE 181 }, 182 { 183 tag: huks.HuksTag.HUKS_TAG_IV, 184 value: stringToUint8Array(IV) 185 } 186 ), 187} 188let callerAgreeParams: huks.HuksOptions = { 189 properties: new Array<huks.HuksParam>( 190 { 191 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 192 value: huks.HuksKeyAlg.HUKS_ALG_ECDH 193 }, 194 { 195 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 196 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE 197 }, 198 { 199 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 200 value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256 201 } 202 ) 203} 204let encryptKeyCommonParams: huks.HuksOptions = { 205 properties: new Array<huks.HuksParam>( 206 { 207 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 208 value: huks.HuksKeyAlg.HUKS_ALG_AES 209 }, 210 { 211 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 212 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT 213 }, 214 { 215 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 216 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 217 }, 218 { 219 tag: huks.HuksTag.HUKS_TAG_PADDING, 220 value: huks.HuksKeyPadding.HUKS_PADDING_NONE 221 }, 222 { 223 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 224 value: huks.HuksCipherMode.HUKS_MODE_GCM 225 }, 226 { 227 tag: huks.HuksTag.HUKS_TAG_NONCE, 228 value: stringToUint8Array(NONCE) 229 }, 230 { 231 tag: huks.HuksTag.HUKS_TAG_ASSOCIATED_DATA, 232 value: stringToUint8Array(AAD) 233 } 234 ), 235} 236let importWrappedAes192Params: huks.HuksOptions = { 237 properties: new Array<huks.HuksParam>( 238 { 239 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 240 value: huks.HuksKeyAlg.HUKS_ALG_AES 241 }, 242 { 243 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 244 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | 245 huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT 246 }, 247 { 248 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 249 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_192 250 }, 251 { 252 tag: huks.HuksTag.HUKS_TAG_PADDING, 253 value: huks.HuksKeyPadding.HUKS_PADDING_NONE 254 }, 255 { 256 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 257 value: huks.HuksCipherMode.HUKS_MODE_CBC 258 }, 259 { 260 tag: huks.HuksTag.HUKS_TAG_DIGEST, 261 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE 262 }, 263 { 264 tag: huks.HuksTag.HUKS_TAG_UNWRAP_ALGORITHM_SUITE, 265 value: huks.HuksUnwrapSuite.HUKS_UNWRAP_SUITE_ECDH_AES_256_GCM_NOPADDING 266 }, 267 { 268 tag: huks.HuksTag.HUKS_TAG_IV, 269 value: stringToUint8Array(IV) 270 } 271 ) 272} 273 274async function publicGenerateItemFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 275 console.info(`enter promise generateKeyItem`); 276 try { 277 await huks.generateKeyItem(keyAlias, huksOptions) 278 .then(data => { 279 console.info(`promise: generateKeyItem success, data = ${JSON.stringify(data)}`); 280 }) 281 .catch((err: Error) => { 282 console.error(`promise: generateKeyItem failed, ${JSON.stringify(err)}`); 283 }) 284 } catch (err) { 285 console.error(`promise: generateKeyItem invalid, ${JSON.stringify(err)}`); 286 } 287} 288 289async function publicImportKeyItemFunc(keyAlias: string, HuksOptions: huks.HuksOptions) { 290 console.info(`enter promise importKeyItem`); 291 try { 292 await huks.importKeyItem(keyAlias, HuksOptions) 293 .then(data => { 294 console.info(`promise: importKeyItem success, data = ${JSON.stringify(data)}`); 295 }).catch((err: Error) => { 296 console.error(`promise: importKeyItem failed, ${JSON.stringify(err)}`); 297 }) 298 } catch (err) { 299 console.error(`promise: importKeyItem input arg invalid, ${JSON.stringify(err)}`); 300 } 301} 302 303async function publicDeleteKeyItemFunc(KeyAlias: string, HuksOptions: huks.HuksOptions) { 304 console.info(`enter promise deleteKeyItem`); 305 try { 306 await huks.deleteKeyItem(KeyAlias, HuksOptions) 307 .then(data => { 308 console.info(`promise: deleteKeyItem key success, data = ${JSON.stringify(data)}`); 309 }) 310 .catch((err: Error) => { 311 console.error(`promise: deleteKeyItem failed, ${JSON.stringify(err)}`); 312 }) 313 } catch (err) { 314 console.error(`promise: deleteKeyItem input arg invalid, ${JSON.stringify(err)}`); 315 } 316} 317 318function importWrappedKeyItem(keyAlias: string, wrappingKeyAlias: string, huksOptions: huks.HuksOptions) { 319 return new Promise<void>((resolve, reject) => { 320 try { 321 huks.importWrappedKeyItem(keyAlias, wrappingKeyAlias, huksOptions, (error, data) => { 322 if (error) { 323 reject(error); 324 } else { 325 resolve(data); 326 } 327 }); 328 } catch (error) { 329 } 330 }); 331} 332 333async function publicImportWrappedKeyFunc(keyAlias: string, wrappingKeyAlias: string, huksOptions: huks.HuksOptions) { 334 console.info(`enter promise importWrappedKeyItem`); 335 for (let i = 0; i < huksOptions.inData!.length; i++) { 336 console.error(`${i}: ${huksOptions.inData![i]}`); 337 } 338 try { 339 await importWrappedKeyItem(keyAlias, wrappingKeyAlias, huksOptions) 340 .then((data) => { 341 console.info(`promise: importWrappedKeyItem success, data = ${JSON.stringify(data)}`); 342 }) 343 .catch((error: Error) => { 344 console.error(`promise: importWrappedKeyItem failed, ${JSON.stringify(error)}`); 345 }); 346 } catch (error) { 347 console.error(`promise: importWrappedKeyItem input arg invalid, ${JSON.stringify(error)}`); 348 } 349} 350 351async function publicImportWrappedKeyPromise(keyAlias: string, wrappingKeyAlias: string, 352 huksOptions: huks.HuksOptions) { 353 console.info(`enter promise importWrappedKeyItem`); 354 try { 355 await huks.importWrappedKeyItem(keyAlias, wrappingKeyAlias, huksOptions) 356 .then((data) => { 357 console.info(`promise: importWrappedKeyItem success, data = ${JSON.stringify(data)}`); 358 }) 359 .catch((error: Error) => { 360 console.error(`promise: importWrappedKeyItem failed, ${JSON.stringify(error)}`); 361 }); 362 } catch (error) { 363 console.error(`promise: importWrappedKeyItem input arg invalid, ${JSON.stringify(error)}`); 364 } 365} 366 367async function publicInitFunc(srcKeyAlias: string, HuksOptions: huks.HuksOptions) { 368 let handle: number = 0; 369 console.info(`enter promise doInit`); 370 try { 371 await huks.initSession(srcKeyAlias, HuksOptions) 372 .then((data) => { 373 console.info(`promise: doInit success, data = ${JSON.stringify(data)}`); 374 handle = data.handle; 375 }) 376 .catch((error: Error) => { 377 console.error(`promise: doInit key failed, ${JSON.stringify(error)}`); 378 }); 379 } catch (error) { 380 console.error(`promise: doInit input arg invalid, ${JSON.stringify(error)}`); 381 } 382 return handle; 383} 384 385async function publicUpdateSessionFunction(handle: number, HuksOptions: huks.HuksOptions) { 386 const maxUpdateSize = 64; 387 const inData = HuksOptions.inData!; 388 const lastInDataPosition = inData.length - 1; 389 let inDataSegSize = maxUpdateSize; 390 let inDataSegPosition = 0; 391 let isFinished = false; 392 let outData: number[] = []; 393 394 while (inDataSegPosition <= lastInDataPosition) { 395 if (inDataSegPosition + maxUpdateSize > lastInDataPosition) { 396 isFinished = true; 397 inDataSegSize = lastInDataPosition - inDataSegPosition + 1; 398 console.info(`enter promise doUpdate`); 399 break; 400 } 401 HuksOptions.inData = new Uint8Array( 402 Array.from(inData).slice(inDataSegPosition, inDataSegPosition + inDataSegSize) 403 ); 404 console.info(`enter promise doUpdate`); 405 try { 406 await huks.updateSession(handle, HuksOptions) 407 .then((data) => { 408 console.info(`promise: doUpdate success, data = ${JSON.stringify(data)}`); 409 outData = outData.concat(Array.from(data.outData!)); 410 }) 411 .catch((error: Error) => { 412 console.error(`promise: doUpdate failed, ${JSON.stringify(error)}`); 413 }); 414 } catch (error) { 415 console.error(`promise: doUpdate input arg invalid, ${JSON.stringify(error)}`); 416 } 417 if ((!isFinished) && (inDataSegPosition + maxUpdateSize > lastInDataPosition)) { 418 console.error(`update size invalid isFinished = ${isFinished}`); 419 console.error(`inDataSegPosition = ${inDataSegPosition}`); 420 console.error(`lastInDataPosition = ${lastInDataPosition}`); 421 return; 422 } 423 inDataSegPosition += maxUpdateSize; 424 } 425 return outData; 426} 427 428async function publicFinishSession(handle: number, HuksOptions: huks.HuksOptions, inData: number[]) { 429 let outData: number[] = []; 430 console.info(`enter promise doFinish`); 431 try { 432 await huks.finishSession(handle, HuksOptions) 433 .then((data) => { 434 console.info(`promise: doFinish success, data = ${JSON.stringify(data)}`); 435 outData = inData.concat(Array.from(data.outData!)); 436 }) 437 .catch((error: Error) => { 438 console.error(`promise: doFinish key failed, ${JSON.stringify(error)}`); 439 }); 440 } catch (error) { 441 console.error(`promise: doFinish input arg invalid, ${JSON.stringify(error)}`); 442 } 443 return new Uint8Array(outData); 444} 445 446async function cipherFunction(keyAlias: string, HuksOptions: huks.HuksOptions) { 447 let handle = await publicInitFunc(keyAlias, HuksOptions); 448 let tmpData = await publicUpdateSessionFunction(handle, HuksOptions); 449 let outData = await publicFinishSession(handle, HuksOptions, tmpData!); 450 return outData; 451} 452 453async function agreeFunction(keyAlias: string, HuksOptions: huks.HuksOptions, huksPublicKey: Uint8Array) { 454 let handle = await publicInitFunc(keyAlias, HuksOptions); 455 let outSharedKey: Uint8Array = new Uint8Array; 456 HuksOptions.inData = huksPublicKey; 457 console.info(`enter promise doUpdate`); 458 try { 459 await huks.updateSession(handle, HuksOptions) 460 .then((data) => { 461 console.error(`promise: doUpdate success, data = ${JSON.stringify(data)}`); 462 }) 463 .catch((error: Error) => { 464 console.error(`promise: doUpdate failed, ${JSON.stringify(error)}`); 465 }); 466 } catch (error) { 467 console.error(`promise: doUpdate input arg invalid, ${JSON.stringify(error)}`); 468 } 469 console.info(`enter promise doInit`); 470 try { 471 await huks.finishSession(handle, HuksOptions) 472 .then((data) => { 473 console.info(`promise: doInit success, data = ${JSON.stringify(data)}`); 474 outSharedKey = data.outData as Uint8Array; 475 }) 476 .catch((error: Error) => { 477 console.error(`promise: doInit key failed, ${JSON.stringify(error)}`); 478 }); 479 } catch (error) { 480 console.error(`promise: doInit input arg invalid, ${JSON.stringify(error)}`); 481 } 482 return outSharedKey; 483} 484 485async function ImportKekAndAgreeSharedSecret(callerKekAlias: string, importKekParams: huks.HuksOptions, 486 callerKeyAlias: string, huksPublicKey: Uint8Array, agreeParams: huks.HuksOptions) { 487 await publicImportKeyItemFunc(callerKekAlias, importKekParams); 488 outSharedKey = await agreeFunction(callerKeyAlias, agreeParams, huksPublicKey); 489 importParamsAgreeKey.inData = outSharedKey; 490 await publicImportKeyItemFunc(callerAgreeKeyAliasAes256, importParamsAgreeKey); 491} 492 493async function generateAndExportPublicKey(keyAlias: string, HuksOptions: huks.HuksOptions, caller: Boolean) { 494 await publicGenerateItemFunc(keyAlias, HuksOptions); 495 try { 496 await huks.exportKeyItem(keyAlias, HuksOptions) 497 .then((data) => { 498 console.info(`promise: exportKeyItem success, data = ${JSON.stringify(data)}`); 499 if (caller) { 500 callerSelfPublicKey = data.outData as Uint8Array; 501 } else { 502 huksPubKey = data.outData as Uint8Array; 503 } 504 }) 505 .catch((error: Error) => { 506 console.error(`promise: exportKeyItem failed, ${JSON.stringify(error)}`); 507 }); 508 } catch (error) { 509 console.error(`promise: generate pubKey failed, ${JSON.stringify(error)}`); 510 } 511} 512 513async function EncryptImportedPlainKeyAndKek(keyAlias: string) { 514 encryptKeyCommonParams.inData = stringToUint8Array(keyAlias) 515 let plainKeyEncData = await cipherFunction(callerKekAliasAes256, encryptKeyCommonParams); 516 outKekEncTag = subUint8ArrayOf(plainKeyEncData, plainKeyEncData.length - TAG_SIZE, plainKeyEncData.length) 517 outPlainKeyEncData = subUint8ArrayOf(plainKeyEncData, 0, plainKeyEncData.length - TAG_SIZE) 518 encryptKeyCommonParams.inData = stringToUint8Array(callerAes256Kek) 519 let kekEncData = await cipherFunction(callerAgreeKeyAliasAes256, encryptKeyCommonParams) 520 outAgreeKeyEncTag = subUint8ArrayOf(kekEncData, kekEncData.length - TAG_SIZE, kekEncData.length) 521 outKekEncData = subUint8ArrayOf(kekEncData, 0, kekEncData.length - TAG_SIZE) 522} 523 524async function BuildWrappedDataAndImportWrappedKey(plainKey: string) { 525 let plainKeySizeBuff = new Uint8Array(4); 526 assignLength(plainKey.length, plainKeySizeBuff, 0); 527 let wrappedData = new Uint8Array( 528 FILED_LENGTH + huksPubKey.length + 529 FILED_LENGTH + AAD.length + 530 FILED_LENGTH + NONCE.length + 531 FILED_LENGTH + TAG_SIZE + 532 FILED_LENGTH + outKekEncData.length + 533 FILED_LENGTH + AAD.length + 534 FILED_LENGTH + NONCE.length + 535 FILED_LENGTH + TAG_SIZE + 536 FILED_LENGTH + plainKeySizeBuff.length + 537 FILED_LENGTH + outPlainKeyEncData.length 538 ); 539 let index = 0; 540 let AADUint8Array = stringToUint8Array(AAD); 541 let NonceArray = stringToUint8Array(NONCE); 542 index += assignLength(callerSelfPublicKey.length, wrappedData, index); // 4 543 index += assignData(callerSelfPublicKey, wrappedData, index); // 91 544 index += assignLength(AADUint8Array.length, wrappedData, index); // 4 545 index += assignData(AADUint8Array, wrappedData, index); // 16 546 index += assignLength(NonceArray.length, wrappedData, index); // 4 547 index += assignData(NonceArray, wrappedData, index); // 12 548 index += assignLength(outAgreeKeyEncTag.length, wrappedData, index); // 4 549 index += assignData(outAgreeKeyEncTag, wrappedData, index); // 16 550 index += assignLength(outKekEncData.length, wrappedData, index); // 4 551 index += assignData(outKekEncData, wrappedData, index); // 32 552 index += assignLength(AADUint8Array.length, wrappedData, index); // 4 553 index += assignData(AADUint8Array, wrappedData, index); // 16 554 index += assignLength(NonceArray.length, wrappedData, index); // 4 555 index += assignData(NonceArray, wrappedData, index); // 12 556 index += assignLength(outKekEncTag.length, wrappedData, index); // 4 557 index += assignData(outKekEncTag, wrappedData, index); // 16 558 index += assignLength(plainKeySizeBuff.length, wrappedData, index); // 4 559 index += assignData(plainKeySizeBuff, wrappedData, index); // 4 560 index += assignLength(outPlainKeyEncData.length, wrappedData, index); // 4 561 index += assignData(outPlainKeyEncData, wrappedData, index); // 24 562 return wrappedData; 563} 564 565/* 模拟加密导入密钥场景,设备A为远端设备(导入设备),设备B为本端设备(被导入设备) */ 566async function ImportWrappedKey() { 567 /** 568 * 1.设备A将待导入密钥转换成HUKS密钥材料格式To_Import_Key(仅针对非对称密钥,若待导入密钥是对称密钥则可省略此步骤), 569 * 本示例使用importedAes256PlainKey(对称密钥)作为模拟 570 */ 571 572 /* 2.设备B生成一个加密导入用途的、用于协商的非对称密钥对Wrapping_Key(公钥Wrapping_Pk,私钥Wrapping_Sk),其密钥用途设置为unwrap,导出Wrapping_Key公钥Wrapping_Pk存放在变量huksPubKey中 */ 573 const srcKeyAliasWrap = 'HUKS_Basic_Capability_Import_0200'; 574 await generateAndExportPublicKey(srcKeyAliasWrap, genWrappingKeyParams, false); 575 576 /* 3.设备A使用和设备B同样的算法,生成一个加密导入用途的、用于协商的非对称密钥对Caller_Key(公钥Caller_Pk,私钥Caller_Sk),导出Caller_Key公钥Caller_Pk存放在变量callerSelfPublicKey中 */ 577 await generateAndExportPublicKey(callerKeyAlias, genCallerEcdhParams, true); 578 579 /** 580 * 4.设备A生成一个对称密钥Caller_Kek,该密钥后续将用于加密To_Import_Key 581 * 5.设备A基于Caller_Key的私钥Caller_Sk和Wrapping_Key的公钥Wrapping_Pk,协商出Shared_Key 582 */ 583 await ImportKekAndAgreeSharedSecret(callerKekAliasAes256, importParamsCallerKek, callerKeyAlias, huksPubKey, 584 callerAgreeParams); 585 586 /** 587 * 6.设备A使用Caller_Kek加密To_Import_Key,生成To_Import_Key_Enc 588 * 7.设备A使用Shared_Key加密Caller_Kek,生成Caller_Kek_Enc 589 */ 590 await EncryptImportedPlainKeyAndKek(importedAes192PlainKey); 591 592 /* 8.设备A封装Caller_Pk、To_Import_Key_Enc、Caller_Kek_Enc等加密导入的材料并发送给设备B。本示例作为变量存放在callerSelfPublicKey,PlainKeyEncData,KekEncData */ 593 let wrappedData = await BuildWrappedDataAndImportWrappedKey(importedAes192PlainKey); 594 importWrappedAes192Params.inData = wrappedData; 595 596 /* 9.设备B导入封装的加密密钥材料 */ 597 await publicImportWrappedKeyFunc(importedKeyAliasAes192, srcKeyAliasWrap, importWrappedAes192Params); 598 599 /* 10.设备A、B删除用于加密导入的密钥 */ 600 await publicDeleteKeyItemFunc(srcKeyAliasWrap, genWrappingKeyParams); 601 await publicDeleteKeyItemFunc(callerKeyAlias, genCallerEcdhParams); 602 await publicDeleteKeyItemFunc(importedKeyAliasAes192, importWrappedAes192Params); 603 await publicDeleteKeyItemFunc(callerKekAliasAes256, callerAgreeParams); 604} 605 606``` 607 608 609## 调测验证 610 611调用[huks.isKeyItemExist](../../reference/apis-universal-keystore-kit/js-apis-huks.md#huksiskeyitemexist9)验证密钥是否存在,如密钥存在即表示密钥导入成功。 612 613```ts 614import { huks } from '@kit.UniversalKeystoreKit'; 615 616/* 617 * 确定密钥别名和封装密钥属性参数集 618 */ 619let keyAlias = 'test_import_key_ecdh_aes192'; 620let isKeyExist: Boolean; 621let keyProperties: Array<huks.HuksParam> = [{ 622 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 623 value: huks.HuksKeyAlg.HUKS_ALG_AES, 624}]; 625let huksOptions: huks.HuksOptions = { 626 properties: keyProperties, // 非空填充 627 inData: new Uint8Array(new Array()) // 非空填充 628} 629try { 630 huks.isKeyItemExist(keyAlias, huksOptions, (error, data) => { 631 if (error) { 632 console.error(`callback: isKeyItemExist failed, ${JSON.stringify(error)}`); 633 } else { 634 if (data !== null && data.valueOf() !== null) { 635 isKeyExist = data.valueOf(); 636 console.info(`callback: isKeyItemExist success, isKeyExist = ${isKeyExist}`); 637 } 638 } 639 }); 640} catch (error) { 641 console.error(`callback: isKeyItemExist input arg invalid, ${JSON.stringify(error)}`); 642} 643``` 644