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