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