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