1# Importing a Key in Ciphertext (ArkTS) 2 3 4This topic walks you through on how to import an ECDH key pair. However, the example does not cover the operations such as [key generation](huks-key-generation-overview.md) and [key agreement](huks-key-agreement-overview.md) of the service side. 5 6 7For details about the scenarios and supported algorithm specifications, see [Supported Algorithms](huks-key-import-overview.md#supported-algorithms). 8 9 10## How to Develop 11 121. Convert the key to be imported from device A (device from which the key is imported) to [HUKS key material format](huks-concepts.md#key material format) **To_Import_Key**. (This step applies only to asymmetric key pairs. If the key to be imported is a symmetric key, skip over this step.) 13 142. Generate an asymmetric key pair **Wrapping_Key** (public key **Wrapping_Pk** and private key **Wrapping_Sk**) with the purpose of **HUKS_KEY_PURPOSE_UNWRAP** for device B (device to which the key is imported), and export the public key **Wrapping_Pk** of **Wrapping_Key** and save it. The asymmetric key pair **Wrapping_Key** is used for key agreement in the encrypted import process. 15 163. Use the same algorithm to generate an asymmetric key pair **Caller_Key** (public key **Caller_Pk** and private key **Caller_Sk**) with the purpose of **HUKS_KEY_PURPOSE_UNWRAP** for device A, and export the public key **Caller_Pk** of **Caller_Key** and save it. The asymmetric key pair **Caller_Key** is used for key agreement in the encrypted import process. 17 184. Generate a symmetric key **Caller_Kek** for device A. This key is used to encrypt **To_Import_Key**. 19 205. Perform key agreement with the private key **Caller_Sk** in **Caller_Key** of device A and the public key **Wrapping_Pk** in **Wrapping_Key** of device B to yield a **Shared_Key**. 21 226. Use **Caller_Kek** to encrypt **To_Import_Key** of device A and generate **To_Import_Key_Enc**. 23 247. Use **Shared_Key** to encrypt **Caller_Kek** of device A and generate **Caller_Kek_Enc**. 25 268. Encapsulate the key material **Caller_Pk**, **Caller_Kek_Enc**, and **To_Import_Key_Enc** of device A, and sends it to device B. For details about the format of the key material to be imported, see [Key Material Format for Encrypted Import](huks-key-import-overview.md#key-material-format-for-encrypted-import). 27 289. Import the encrypted key material to device B. 29 3010. Delete the intermediate keys (keys used for encrypting the key to import) from devices A and B. 31 32```ts 33import { expect } from '@ohos/hypium'; 34import huks from '@ohos.security.huks'; 35import { BusinessError } from '@ohos.base'; 36let IV = '0000000000000000'; 37let AAD = "abababababababab"; 38let NONCE = "hahahahahaha"; 39let TAG_SIZE = 16; 40let FILED_LENGTH = 4; 41let importedAes192PlainKey = "The aes192 key to import"; 42let callerAes256Kek = "The is kek to encrypt aes192 key"; 43let callerKeyAlias = "test_caller_key_ecdh_aes192"; 44let callerKekAliasAes256 = "test_caller_kek_ecdh_aes256"; 45let callerAgreeKeyAliasAes256 = "test_caller_agree_key_ecdh_aes256"; 46let importedKeyAliasAes192 = "test_import_key_ecdh_aes192"; 47let huksPubKey: Uint8Array; 48let callerSelfPublicKey: Uint8Array; 49let outSharedKey: Uint8Array; 50let outPlainKeyEncData: Uint8Array; 51let outKekEncData: Uint8Array; 52let outKekEncTag: Uint8Array; 53let outAgreeKeyEncTag: Uint8Array; 54let mask = [0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000]; 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} 62function stringToUint8Array(str: string) { 63 let arr: number[] = []; 64 for (let i = 0, j = str.length; i < j; ++i) { 65 arr.push(str.charCodeAt(i)); 66 } 67 return new Uint8Array(arr); 68} 69function assignLength(length: number, arrayBuf: Uint8Array, startIndex: number) { 70 let index = startIndex; 71 for (let i = 0; i < 4; i++) { 72 arrayBuf[index++] = (length & mask[i]) >> (i * 8); 73 } 74 return 4; 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} 83let genWrappingKeyParams: huks.HuksOptions = { 84 properties: new Array<huks.HuksParam>( 85 { 86 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 87 value: huks.HuksKeyAlg.HUKS_ALG_ECC 88 }, 89 { 90 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 91 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_UNWRAP 92 }, 93 { 94 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 95 value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256 96 }, 97 { 98 tag: huks.HuksTag.HUKS_TAG_PADDING, 99 value: huks.HuksKeyPadding.HUKS_PADDING_NONE 100 } 101 ) 102} 103let genCallerEcdhParams:huks.HuksOptions = { 104 properties: new Array<huks.HuksParam>( 105 { 106 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 107 value: huks.HuksKeyAlg.HUKS_ALG_ECC 108 }, 109 { 110 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 111 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE 112 }, 113 { 114 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 115 value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256 116 } 117 ) 118} 119let importParamsCallerKek: huks.HuksOptions = { 120 properties: new Array<huks.HuksParam>( 121 { 122 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 123 value: huks.HuksKeyAlg.HUKS_ALG_AES 124 }, 125 { 126 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 127 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT 128 }, 129 { 130 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 131 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 132 }, 133 { 134 tag: huks.HuksTag.HUKS_TAG_PADDING, 135 value: huks.HuksKeyPadding.HUKS_PADDING_NONE 136 }, 137 { 138 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 139 value: huks.HuksCipherMode.HUKS_MODE_GCM 140 }, 141 { 142 tag: huks.HuksTag.HUKS_TAG_DIGEST, 143 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE 144 }, 145 { 146 tag: huks.HuksTag.HUKS_TAG_IV, 147 value: stringToUint8Array(IV) 148 } 149 ), 150 inData: stringToUint8Array(callerAes256Kek) 151} 152let importParamsAgreeKey: huks.HuksOptions = { 153 properties: new Array<huks.HuksParam>( 154 { 155 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 156 value: huks.HuksKeyAlg.HUKS_ALG_AES 157 }, 158 { 159 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 160 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT 161 }, 162 { 163 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 164 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 165 }, 166 { 167 tag: huks.HuksTag.HUKS_TAG_PADDING, 168 value: huks.HuksKeyPadding.HUKS_PADDING_NONE 169 }, 170 { 171 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 172 value: huks.HuksCipherMode.HUKS_MODE_GCM 173 }, 174 { 175 tag: huks.HuksTag.HUKS_TAG_DIGEST, 176 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE 177 }, 178 { 179 tag: huks.HuksTag.HUKS_TAG_IV, 180 value: stringToUint8Array(IV) 181 } 182 ), 183} 184let callerAgreeParams: huks.HuksOptions = { 185 properties: new Array<huks.HuksParam>( 186 { 187 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 188 value: huks.HuksKeyAlg.HUKS_ALG_ECDH 189 }, 190 { 191 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 192 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE 193 }, 194 { 195 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 196 value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256 197 } 198 ) 199} 200let encryptKeyCommonParams: huks.HuksOptions = { 201 properties: new Array<huks.HuksParam>( 202 { 203 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 204 value: huks.HuksKeyAlg.HUKS_ALG_AES 205 }, 206 { 207 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 208 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT 209 }, 210 { 211 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 212 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 213 }, 214 { 215 tag: huks.HuksTag.HUKS_TAG_PADDING, 216 value: huks.HuksKeyPadding.HUKS_PADDING_NONE 217 }, 218 { 219 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 220 value: huks.HuksCipherMode.HUKS_MODE_GCM 221 }, 222 { 223 tag: huks.HuksTag.HUKS_TAG_NONCE, 224 value: stringToUint8Array(NONCE) 225 }, 226 { 227 tag: huks.HuksTag.HUKS_TAG_ASSOCIATED_DATA, 228 value: stringToUint8Array(AAD) 229 } 230 ), 231} 232let importWrappedAes192Params: huks.HuksOptions = { 233 properties: new Array<huks.HuksParam>( 234 { 235 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 236 value: huks.HuksKeyAlg.HUKS_ALG_AES 237 }, 238 { 239 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 240 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | 241 huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT 242 }, 243 { 244 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 245 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_192 246 }, 247 { 248 tag: huks.HuksTag.HUKS_TAG_PADDING, 249 value: huks.HuksKeyPadding.HUKS_PADDING_NONE 250 }, 251 { 252 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 253 value: huks.HuksCipherMode.HUKS_MODE_CBC 254 }, 255 { 256 tag: huks.HuksTag.HUKS_TAG_DIGEST, 257 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE 258 }, 259 { 260 tag: huks.HuksTag.HUKS_TAG_UNWRAP_ALGORITHM_SUITE, 261 value: huks.HuksUnwrapSuite.HUKS_UNWRAP_SUITE_ECDH_AES_256_GCM_NOPADDING 262 }, 263 { 264 tag: huks.HuksTag.HUKS_TAG_IV, 265 value: stringToUint8Array(IV) 266 } 267 ) 268} 269async function publicGenerateItemFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 270 console.info(`enter promise generateKeyItem`); 271 try { 272 await huks.generateKeyItem(keyAlias, huksOptions) 273 .then(data => { 274 console.info(`promise: generateKeyItem success, data = ${JSON.stringify(data)}`); 275 }) 276 .catch((err: BusinessError) => { 277 console.error(`promise: generateKeyItem failed` + err); 278 expect(null).assertFail(); 279 }) 280 } catch (err) { 281 console.error(`promise: generateKeyItem invalid` + err); 282 expect(null).assertFail(); 283 } 284} 285async function publicImportKeyItemFunc(keyAlias: string, HuksOptions: huks.HuksOptions) { 286 console.info(`enter promise importKeyItem`); 287 try { 288 await huks.importKeyItem(keyAlias, HuksOptions) 289 .then(data => { 290 console.info(`promise: importKeyItem success, data = ${JSON.stringify(data)}`); 291 }).catch((err: BusinessError) => { 292 console.error(`promise: importKeyItem failed` + err); 293 expect(null).assertFail(); 294 }) 295 } catch (err) { 296 console.error(`promise: importKeyItem input arg invalid` + err); 297 expect(null).assertFail(); 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: BusinessError) => { 308 console.error(`promise: deleteKeyItem failed` + err); 309 expect(null).assertFail(); 310 }) 311 } catch (err) { 312 console.error(`promise: deleteKeyItem input arg invalid` + err); 313 expect(null).assertFail(); 314 } 315} 316function importWrappedKeyItem(keyAlias: string, wrappingKeyAlias: string, huksOptions: huks.HuksOptions) { 317 return new Promise<void>((resolve, reject) => { 318 try { 319 huks.importWrappedKeyItem(keyAlias, wrappingKeyAlias, huksOptions, (error, data) => { 320 if (error) { 321 reject(error); 322 } else { 323 resolve(data); 324 } 325 }); 326 } catch (error) { 327 expect(null).assertFail(); 328 } 329 }); 330} 331async function publicImportWrappedKeyFunc(keyAlias: string, wrappingKeyAlias: string, huksOptions: huks.HuksOptions) { 332 console.info(`enter promise importWrappedKeyItem`); 333 for (let i = 0; i < huksOptions.inData!.length; i++) { 334 console.error(`${i}: ${huksOptions.inData![i]}`); 335 } 336 try { 337 await importWrappedKeyItem(keyAlias, wrappingKeyAlias, huksOptions) 338 .then((data) => { 339 console.info(`promise: importWrappedKeyItem success, data = ${JSON.stringify(data)}`); 340 }) 341 .catch((error: BusinessError) => { 342 console.error(`promise: importWrappedKeyItem failed` + error); 343 expect(null).assertFail(); 344 }); 345 } catch (error) { 346 console.error(`promise: importWrappedKeyItem input arg invalid` + error); 347 expect(null).assertFail(); 348 } 349} 350async function publicImportWrappedKeyPromise(keyAlias: string, wrappingKeyAlias: string, huksOptions: huks.HuksOptions) { 351 console.info(`enter promise importWrappedKeyItem`); 352 try { 353 await huks.importWrappedKeyItem(keyAlias, wrappingKeyAlias, huksOptions) 354 .then((data) => { 355 console.info(`promise: importWrappedKeyItem success, data = ${JSON.stringify(data)}`); 356 }) 357 .catch((error: BusinessError) => { 358 console.error(`promise: importWrappedKeyItem failed` + error); 359 expect(null).assertFail(); 360 }); 361 } catch (error) { 362 console.error(`promise: importWrappedKeyItem input arg invalid` + error); 363 expect(null).assertFail(); 364 } 365} 366async function publicInitFunc(srcKeyAlias: string, HuksOptions: huks.HuksOptions) { 367 let handle: number = 0; 368 console.info(`enter promise doInit`); 369 try { 370 await huks.initSession(srcKeyAlias, HuksOptions) 371 .then((data) => { 372 console.info(`promise: doInit success, data = ${JSON.stringify(data)}`); 373 handle = data.handle; 374 }) 375 .catch((error: BusinessError) => { 376 console.error(`promise: doInit key failed` + error); 377 expect(null).assertFail(); 378 }); 379 } catch (error) { 380 console.error(`promise: doInit input arg invalid` + error); 381 expect(null).assertFail(); 382 } 383 return handle; 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.error(`promise: doUpdate success, data = ${JSON.stringify(data)}`); 409 outData = outData.concat(Array.from(data.outData!)); 410 }) 411 .catch((error: BusinessError) => { 412 console.error(`promise: doUpdate failed` + error); 413 expect(null).assertFail(); 414 }); 415 } catch (error) { 416 console.error(`promise: doUpdate input arg invalid` + error); 417 expect(null).assertFail(); 418 } 419 if ((!isFinished) && (inDataSegPosition + maxUpdateSize > lastInDataPosition)) { 420 console.log(`update size invalid isFinished = ${isFinished}`); 421 console.log(`inDataSegPosition = ${inDataSegPosition}`); 422 console.log(`lastInDataPosition = ${lastInDataPosition}`); 423 expect(null).assertFail(); 424 return; 425 } 426 inDataSegPosition += maxUpdateSize; 427 } 428 return outData; 429} 430async function publicFinishSession(handle: number, HuksOptions: huks.HuksOptions, inData: number[]) { 431 let outData: number[] = []; 432 console.info(`enter promise doFinish`); 433 try { 434 await huks.finishSession(handle, HuksOptions) 435 .then((data) => { 436 console.info(`promise: doFinish success, data = ${JSON.stringify(data)}`); 437 outData = inData.concat(Array.from(data.outData!)); 438 }) 439 .catch((error: BusinessError) => { 440 console.error(`promise: doFinish key failed` + error); 441 expect(null).assertFail(); 442 }); 443 } catch (error) { 444 console.error(`promise: doFinish input arg invalid` + error); 445 expect(null).assertFail(); 446 } 447 return new Uint8Array(outData); 448} 449async function cipherFunction(keyAlias: string, HuksOptions: huks.HuksOptions) { 450 let handle = await publicInitFunc(keyAlias, HuksOptions); 451 let tmpData = await publicUpdateSessionFunction(handle, HuksOptions); 452 let outData = await publicFinishSession(handle, HuksOptions, tmpData!); 453 return outData; 454} 455async function agreeFunction(keyAlias: string, HuksOptions: huks.HuksOptions, huksPublicKey: Uint8Array) { 456 let handle = await publicInitFunc(keyAlias, HuksOptions); 457 let outSharedKey: Uint8Array = new Uint8Array; 458 HuksOptions.inData = huksPublicKey; 459 console.info(`enter promise doUpdate`); 460 try { 461 await huks.updateSession(handle, HuksOptions) 462 .then((data) => { 463 console.error(`promise: doUpdate success, data = ${JSON.stringify(data)}`); 464 }) 465 .catch((error: BusinessError) => { 466 console.error(`promise: doUpdate failed` + error); 467 expect(null).assertFail(); 468 }); 469 } catch (error) { 470 console.error(`promise: doUpdate input arg invalid` + error); 471 expect(null).assertFail(); 472 } 473 console.info(`enter promise doInit`); 474 try { 475 await huks.finishSession(handle, HuksOptions) 476 .then((data) => { 477 console.info(`promise: doInit success, data = ${JSON.stringify(data)}`); 478 outSharedKey = data.outData as Uint8Array; 479 }) 480 .catch((error: BusinessError) => { 481 console.error(`promise: doInit key failed` + error); 482 expect(null).assertFail(); 483 }); 484 } catch (error) { 485 console.error(`promise: doInit input arg invalid` + error); 486 expect(null).assertFail(); 487 } 488 return outSharedKey; 489} 490async function ImportKekAndAgreeSharedSecret(callerKekAlias: string, importKekParams: huks.HuksOptions, callerKeyAlias: string, huksPublicKey: Uint8Array, agreeParams: huks.HuksOptions) { 491 await publicImportKeyItemFunc(callerKekAlias, importKekParams); 492 outSharedKey = await agreeFunction(callerKeyAlias, agreeParams, huksPublicKey); 493 importParamsAgreeKey.inData = outSharedKey; 494 await publicImportKeyItemFunc(callerAgreeKeyAliasAes256, importParamsAgreeKey); 495} 496async function generateAndExportPublicKey(keyAlias: string, HuksOptions: huks.HuksOptions, caller: Boolean) { 497 await publicGenerateItemFunc(keyAlias, HuksOptions); 498 try { 499 await huks.exportKeyItem(keyAlias, HuksOptions) 500 .then((data) => { 501 console.info(`promise: exportKeyItem success, data = ${JSON.stringify(data)}`); 502 if (caller) { 503 callerSelfPublicKey = data.outData as Uint8Array; 504 } else { 505 huksPubKey = data.outData as Uint8Array; 506 } 507 }) 508 .catch((error: BusinessError) => { 509 console.error(`promise: exportKeyItem failed` + error); 510 expect(null).assertFail(); 511 }); 512 } catch (error) { 513 console.error(`promise: generate pubKey failed` + error); 514 expect(null).assertFail(); 515 } 516} 517async function EncryptImportedPlainKeyAndKek(keyAlias: string) { 518 encryptKeyCommonParams.inData = stringToUint8Array(keyAlias) 519 let plainKeyEncData = await cipherFunction(callerKekAliasAes256, encryptKeyCommonParams); 520 outKekEncTag = subUint8ArrayOf(plainKeyEncData, plainKeyEncData.length - TAG_SIZE, plainKeyEncData.length) 521 outPlainKeyEncData = subUint8ArrayOf(plainKeyEncData, 0, plainKeyEncData.length - TAG_SIZE) 522 encryptKeyCommonParams.inData = stringToUint8Array(callerAes256Kek) 523 let kekEncData = await cipherFunction(callerAgreeKeyAliasAes256, encryptKeyCommonParams) 524 outAgreeKeyEncTag = subUint8ArrayOf(kekEncData, kekEncData.length - TAG_SIZE, kekEncData.length) 525 outKekEncData = subUint8ArrayOf(kekEncData, 0, kekEncData.length - TAG_SIZE) 526} 527async function BuildWrappedDataAndImportWrappedKey(plainKey: string) { 528 let plainKeySizeBuff = new Uint8Array(4); 529 assignLength(plainKey.length, plainKeySizeBuff, 0); 530 let wrappedData = new Uint8Array( 531 FILED_LENGTH + huksPubKey.length + 532 FILED_LENGTH + AAD.length + 533 FILED_LENGTH + NONCE.length + 534 FILED_LENGTH + TAG_SIZE + 535 FILED_LENGTH + outKekEncData.length + 536 FILED_LENGTH + AAD.length + 537 FILED_LENGTH + NONCE.length + 538 FILED_LENGTH + TAG_SIZE + 539 FILED_LENGTH + plainKeySizeBuff.length + 540 FILED_LENGTH + outPlainKeyEncData.length 541 ); 542 let index = 0; 543 let AADUint8Array = stringToUint8Array(AAD); 544 let NonceArray = stringToUint8Array(NONCE); 545 index += assignLength(callerSelfPublicKey.length, wrappedData, index); // 4 546 index += assignData(callerSelfPublicKey, wrappedData, index); // 91 547 index += assignLength(AADUint8Array.length, wrappedData, index); // 4 548 index += assignData(AADUint8Array, wrappedData, index); // 16 549 index += assignLength(NonceArray.length, wrappedData, index); // 4 550 index += assignData(NonceArray, wrappedData, index); // 12 551 index += assignLength(outAgreeKeyEncTag.length, wrappedData, index); // 4 552 index += assignData(outAgreeKeyEncTag, wrappedData, index); // 16 553 index += assignLength(outKekEncData.length, wrappedData, index); // 4 554 index += assignData(outKekEncData, wrappedData, index); // 32 555 index += assignLength(AADUint8Array.length, wrappedData, index); // 4 556 index += assignData(AADUint8Array, wrappedData, index); // 16 557 index += assignLength(NonceArray.length, wrappedData, index); // 4 558 index += assignData(NonceArray, wrappedData, index); // 12 559 index += assignLength(outKekEncTag.length, wrappedData, index); // 4 560 index += assignData(outKekEncTag, wrappedData, index); // 16 561 index += assignLength(plainKeySizeBuff.length, wrappedData, index); // 4 562 index += assignData(plainKeySizeBuff, wrappedData, index); // 4 563 index += assignLength(outPlainKeyEncData.length, wrappedData, index); // 4 564 index += assignData(outPlainKeyEncData, wrappedData, index); // 24 565 return wrappedData; 566} 567/* Simulate the encrypted key import scenario. Import a key from device A (remote device) to device B (local device). */ 568async function ImportWrappedKey() { 569 /** 570 * 1. If the key to be imported from device A is an asymmetric key pair, convert it into the HUKS key material format **To_Import_Key**. Skip over this step if the key is a symmetric key. 571 * This example uses a 256-bit AES key (symmetric key) as an example. 572 */ 573 574 /* 2. Generate an asymmetric key pair Wrapping_Key (public key Wrapping_Pk and private key Wrapping_Sk) with the purpose of HUKS_KEY_PURPOSE_UNWRAP for device B, export the public key Wrapping_Pk of Wrapping_Key, and save it to huksPubKey. */ 575 const srcKeyAliesWrap = 'HUKS_Basic_Capability_Import_0200'; 576 await generateAndExportPublicKey(srcKeyAliesWrap, genWrappingKeyParams, false); 577 578 /* 3. Use the same algorithm to generate an asymmetric key pair Caller_Key (public key Caller_Pk and private key Caller_Sk) with the purpose of HUKS_KEY_PURPOSE_UNWRAP for device A, export the public key Caller_Pk of Caller_Key, save it to callerSelfPublicKey. */ 579 await generateAndExportPublicKey(callerKeyAlias, genCallerEcdhParams, true); 580 581 /** 582 4. Generate a symmetric key Caller_Kek for device A. This key is used to encrypt To_Import_Key. 583 * 5. Perform key agreement with the private key Caller_Sk in Caller_Key of device A and the public key Wrapping_Pk in Wrapping_Key of device B to yield a Shared_Key. 584 */ 585 await ImportKekAndAgreeSharedSecret(callerKekAliasAes256, importParamsCallerKek, callerKeyAlias, huksPubKey, callerAgreeParams); 586 587 /** 588 * 6. Use Caller_Kek to encrypt To_Import_Key of device A and generate To_Import_Key_Enc. 589 * 7. Use Shared_Key to encrypt Caller_Kek of device A and generate Caller_Kek_Enc. 590 */ 591 await EncryptImportedPlainKeyAndKek(importedAes192PlainKey); 592 593 /* 8. Encapsulate the key material Caller_Pk, To_Import_Key_Enc, and Caller_Kek_Enc of device A, and sends it to device B. In this example, Caller_Pk is placed in callerSelfPublicKey, To_Import_Key_Enc in PlainKeyEncData, and Caller_Kek_Enc in KekEncData. */ 594 let wrappedData = await BuildWrappedDataAndImportWrappedKey(importedAes192PlainKey); 595 importWrappedAes192Params.inData = wrappedData; 596 597 /* 9. Import the encapsulated key material to device B. */ 598 await publicImportWrappedKeyFunc(importedKeyAliasAes192, srcKeyAliesWrap, importWrappedAes192Params); 599 600 /* 10. Delete the intermediate keys (keys used for encrypting the key to import) from devices A and B. */ 601 await publicDeleteKeyItemFunc(srcKeyAliesWrap, genWrappingKeyParams); 602 await publicDeleteKeyItemFunc(callerKeyAlias, genCallerEcdhParams); 603 await publicDeleteKeyItemFunc(importedKeyAliasAes192, importWrappedAes192Params); 604 await publicDeleteKeyItemFunc(callerKekAliasAes256, callerAgreeParams); 605} 606``` 607 608 609## Verification 610 611Use [huks.isKeyItemExist](../../reference/apis-universal-keystore-kit/js-apis-huks.md#huksiskeyitemexist9) to check whether the key exists. If the key exists, the key is successfully imported. 612 613```ts 614import huks from '@ohos.security.huks'; 615/* 616 * Set the key alias and encapsulate the key property set. 617 */ 618let keyAlias = 'test_import_key_ecdh_aes192'; 619let isKeyExist:Boolean; 620let keyProperties: Array<huks.HuksParam> = new Array(); 621keyProperties[0] = { 622 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 623 value: huks.HuksKeyAlg.HUKS_ALG_AES, 624} 625let huksOptions:huks.HuksOptions = { 626 properties: keyProperties, // It cannot be empty. 627 inData: new Uint8Array(new Array()) // It cannot be empty. 628} 629try { 630 huks.isKeyItemExist(keyAlias, huksOptions, (error, data)=> { 631 if (error) { 632 console.error(`callback: isKeyItemExist failed` + 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` + error); 642} 643``` 644