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