• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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```