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