• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Key Agreement (ArkTS)
2
3
4This topic walks you through on how to agree on a 256-bit X25519 key that is used only in HUKS. For details about the scenarios and supported algorithms, see [Supported Algorithms](huks-key-generation-overview.md#supported-algorithms).
5
6
7## How to Develop
8
9**Key Generation**
10
11Generate an asymmetric key for device A and device B each. For details, see [Key Generation](huks-key-generation-overview.md) or [Key Import](huks-key-import-overview.md).
12
13When generating a key, you can set **HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG** (optional) to specify how the shared secret generated from this key through key agreement is managed.
14
15- If this tag is set to **HUKS_STORAGE_ONLY_USED_IN_HUKS**, the shared secret is managed by HUKS. That is, the shared secret is always in a secure environment throughout its lifecycle.
16
17- If this tag is set to **HUKS_STORAGE_KEY_EXPORT_ALLOWED**, the shared secret generated will be returned to the caller for management. That is, the service side ensures the key security.
18
19- If this tag is not set, the shared secret generated can be either managed by HUKS or returned to the caller for management. The key protection mode can be set in the subsequent key agreement on the service side.
20
21**Key Export**
22
23Export the public key of the asymmetric key pair of device A and device B. For details, see [Key Export](huks-export-key-arkts.md).
24
25**Key Agreement**
26
27Perform key agreement using the public key of the peer device and private key of the local device (that is, public key of device B and private key of device A for device A, and public key of device A and private key of device B for device B) to produce a shared secret.
28
29During key agreement, you can set **HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG** (optional) to specify how the shared secret generated is managed.
30
31| Key Generation| Key Agreement| Specifications|
32| -------- | -------- | -------- |
33| HUKS_STORAGE_ONLY_USED_IN_HUKS | HUKS_STORAGE_ONLY_USED_IN_HUKS | The key is managed by HUKS.|
34| HUKS_STORAGE_KEY_EXPORT_ALLOWED | HUKS_STORAGE_KEY_EXPORT_ALLOWED | The key is returned to the caller for management.|
35| The tag is not set.| HUKS_STORAGE_ONLY_USED_IN_HUKS | The key is managed by HUKS.|
36| The tag is not set.| HUKS_STORAGE_KEY_EXPORT_ALLOWED | The key is returned to the caller for management.|
37| The tag is not set.| The tag is not set.| The key is returned to the caller for management.|
38
39>**NOTE**<br>The tag value set in key agreement should not conflict with the tag value set in key generation. The above table lists only valid settings.
40
41**Key Deletion**
42
43Delete the keys from device A and device B when the keys are not required. For details, see [Deleting a Key](huks-delete-key-arkts.md).
44
45
46Example: Perform X25519 key agreement.
47```ts
48/*
49* Agree on a 256-bit X25519 key using promise-based APIs.
50*/
51import { huks } from '@kit.UniversalKeystoreKit';
52
53/*
54* Set the key alias and encapsulate the key property set.
55*/
56let srcKeyAliasFirst = "AgreeX25519KeyFirstAlias";
57let srcKeyAliasSecond = "AgreeX25519KeySecondAlias";
58let agreeX25519InData = 'AgreeX25519TestIndata';
59let finishOutData: Uint8Array;
60let handle: number;
61let exportKey: Uint8Array;
62let exportKeyFirst: Uint8Array;
63let exportKeySecond: Uint8Array;
64/* Set the parameter set used for generating the key. */
65let properties: Array<huks.HuksParam> = [{
66  tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
67  value: huks.HuksKeyAlg.HUKS_ALG_X25519,
68}, {
69  tag: huks.HuksTag.HUKS_TAG_PURPOSE,
70  value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE,
71}, {
72  tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
73  value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256,
74}, {
75  tag: huks.HuksTag.HUKS_TAG_DIGEST,
76  value: huks.HuksKeyDigest.HUKS_DIGEST_NONE,
77}, {
78  tag: huks.HuksTag.HUKS_TAG_PADDING,
79  value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
80}, {
81  tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
82  value: huks.HuksCipherMode.HUKS_MODE_CBC,
83}, {
84  tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
85  value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS,
86}];
87let HuksOptions: huks.HuksOptions = {
88  properties: properties,
89  inData: new Uint8Array(new Array())
90}
91/* Set the parameter set for the first key agreement. */
92const finishProperties: Array<huks.HuksParam> = [{
93  tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
94  value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS,
95}, {
96  tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS,
97  value: true
98}, {
99  tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
100  value: huks.HuksKeyAlg.HUKS_ALG_AES,
101}, {
102  tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
103  value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256,
104}, {
105  tag: huks.HuksTag.HUKS_TAG_PURPOSE,
106  value:
107  huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT |
108  huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT,
109}, {
110  tag: huks.HuksTag.HUKS_TAG_DIGEST,
111  value: huks.HuksKeyDigest.HUKS_DIGEST_NONE,
112}, {
113  tag: huks.HuksTag.HUKS_TAG_PADDING,
114  value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
115}, {
116  tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
117  value: huks.HuksCipherMode.HUKS_MODE_ECB,
118}];
119let finishOptionsFirst: huks.HuksOptions = {
120  properties: [
121    ...finishProperties, {
122    tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS,
123    value: StringToUint8Array(srcKeyAliasFirst + 'final'),
124  }],
125  inData: StringToUint8Array(agreeX25519InData)
126}
127/* Set the parameter set for the second key agreement. */
128let finishOptionsSecond: huks.HuksOptions = {
129  properties: [
130    ...finishProperties, {
131    tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS,
132    value: StringToUint8Array(srcKeyAliasSecond + 'final'),
133  }],
134  inData: StringToUint8Array(agreeX25519InData)
135}
136
137function StringToUint8Array(str: string) {
138  let arr: number[] = new Array();
139  for (let i = 0, j = str.length; i < j; ++i) {
140    arr.push(str.charCodeAt(i));
141  }
142  return new Uint8Array(arr);
143}
144
145class throwObject {
146  isThrow: boolean = false
147}
148
149/* Generate a key. */
150function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) {
151  return new Promise<void>((resolve, reject) => {
152    try {
153      huks.generateKeyItem(keyAlias, huksOptions, (error, data) => {
154        if (error) {
155          reject(error);
156        } else {
157          resolve(data);
158        }
159      });
160    } catch (error) {
161      throwObject.isThrow = true;
162      throw (error as Error);
163    }
164  });
165}
166
167/* Call generateKeyItem to generate a key. */
168async function publicGenKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
169  console.info(`enter promise generateKeyItem`);
170  let throwObject: throwObject = { isThrow: false };
171  try {
172    await generateKeyItem(keyAlias, huksOptions, throwObject)
173      .then((data) => {
174        console.info(`promise: generateKeyItem success, data = ${JSON.stringify(data)}`);
175      })
176      .catch((error: Error) => {
177        if (throwObject.isThrow) {
178          throw (error as Error);
179        } else {
180          console.error(`promise: generateKeyItem failed, ${JSON.stringify(error)}`);
181        }
182      });
183  } catch (error) {
184    console.error(`promise: generateKeyItem input arg invalid, ${JSON.stringify(error)}`);
185  }
186}
187
188/* Initializes a key session, which returns a session handle (mandatory) and a challenge (optional). */
189function initSession(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) {
190  return new Promise<huks.HuksSessionHandle>((resolve, reject) => {
191    try {
192      huks.initSession(keyAlias, huksOptions, (error, data) => {
193        if (error) {
194          reject(error);
195        } else {
196          resolve(data);
197        }
198      });
199    } catch (error) {
200      throwObject.isThrow = true;
201      throw (error as Error);
202    }
203  });
204}
205
206/* Call initSession. A session handle is returned. */
207async function publicInitFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
208  console.info(`enter promise doInit`);
209  let throwObject: throwObject = { isThrow: false };
210  try {
211    await initSession(keyAlias, huksOptions, throwObject)
212      .then((data) => {
213        console.info(`promise: doInit success, data = ${JSON.stringify(data)}`);
214        handle = data.handle;
215      })
216      .catch((error: Error) => {
217        if (throwObject.isThrow) {
218          throw (error as Error);
219        } else {
220          console.error(`promise: doInit failed, ${JSON.stringify(error)}`);
221        }
222      });
223  } catch (error) {
224    console.error(`promise: doInit input arg invalid, ${JSON.stringify(error)}`);
225  }
226}
227
228/* Call updateSession multiple times to process data by segment and output the processed data. */
229function updateSession(handle: number, huksOptions: huks.HuksOptions, throwObject: throwObject) {
230  return new Promise<huks.HuksReturnResult>((resolve, reject) => {
231    try {
232      huks.updateSession(handle, huksOptions, (error, data) => {
233        if (error) {
234          reject(error);
235        } else {
236          resolve(data);
237        }
238      });
239    } catch (error) {
240      throwObject.isThrow = true;
241      throw (error as Error);
242    }
243  });
244}
245
246/* Call updateSession to perform key agreement. */
247async function publicUpdateFunc(handle: number, huksOptions: huks.HuksOptions) {
248  console.info(`enter promise doUpdate`);
249  let throwObject: throwObject = { isThrow: false };
250  try {
251    await updateSession(handle, huksOptions, throwObject)
252      .then((data) => {
253        console.info(`promise: doUpdate success, data = ${JSON.stringify(data)}`);
254      })
255      .catch((error: Error) => {
256        if (throwObject.isThrow) {
257          throw (error as Error);
258        } else {
259          console.error(`promise: doUpdate failed, ${JSON.stringify(error)}`);
260        }
261      });
262  } catch (error) {
263    console.error(`promise: doUpdate input arg invalid, ${JSON.stringify(error)}`);
264  }
265}
266
267/* Finish the key session to output the shared secret key. */
268function finishSession(handle: number, huksOptions: huks.HuksOptions, throwObject: throwObject) {
269  return new Promise<huks.HuksReturnResult>((resolve, reject) => {
270    try {
271      huks.finishSession(handle, huksOptions, (error, data) => {
272        if (error) {
273          reject(error);
274        } else {
275          resolve(data);
276        }
277      });
278    } catch (error) {
279      throwObject.isThrow = true;
280      throw (error as Error);
281    }
282  });
283}
284
285/* Call finishSession to finish the operation. */
286async function publicFinishFunc(handle: number, huksOptions: huks.HuksOptions) {
287  console.info(`enter promise doFinish`);
288  let throwObject: throwObject = { isThrow: false };
289  try {
290    await finishSession(handle, huksOptions, throwObject)
291      .then((data) => {
292        finishOutData = data.outData as Uint8Array;
293        console.info(`promise: doFinish success, data = ${JSON.stringify(data)}`);
294      })
295      .catch((error: Error) => {
296        if (throwObject.isThrow) {
297          throw (error as Error);
298        } else {
299          console.error(`promise: doFinish failed, ${JSON.stringify(error)}`);
300        }
301      });
302  } catch (error) {
303    console.error(`promise: doFinish input arg invalid, ${JSON.stringify(error)}`);
304  }
305}
306
307/* Export a key. */
308function exportKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) {
309  return new Promise<huks.HuksReturnResult>((resolve, reject) => {
310    try {
311      huks.exportKeyItem(keyAlias, huksOptions, (error, data) => {
312        if (error) {
313          reject(error);
314        } else {
315          resolve(data);
316        }
317      });
318    } catch (error) {
319      throwObject.isThrow = true;
320      throw (error as Error);
321    }
322  });
323}
324
325/* Call exportKeyItem to export the public key. */
326async function publicExportKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
327  console.info(`enter promise export`);
328  let throwObject: throwObject = { isThrow: false };
329  try {
330    await exportKeyItem(keyAlias, huksOptions, throwObject)
331      .then((data) => {
332        console.info(`promise: exportKeyItem success, data = ${JSON.stringify(data)}`);
333        exportKey = data.outData as Uint8Array;
334      })
335      .catch((error: Error) => {
336        if (throwObject.isThrow) {
337          throw (error as Error);
338        } else {
339          console.error(`promise: exportKeyItem failed, ${JSON.stringify(error)}`);
340        }
341      });
342  } catch (error) {
343    console.error(`promise: exportKeyItem input arg invalid, ${JSON.stringify(error)}`);
344  }
345}
346
347/* Delete the keys. */
348function deleteKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) {
349  return new Promise<void>((resolve, reject) => {
350    try {
351      huks.deleteKeyItem(keyAlias, huksOptions, (error, data) => {
352        if (error) {
353          reject(error);
354        } else {
355          resolve(data);
356        }
357      });
358    } catch (error) {
359      throwObject.isThrow = true;
360      throw (error as Error);
361    }
362  });
363}
364
365/* Call deleteKeyItem to delete a key. */
366async function publicDeleteKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
367  console.info(`enter promise deleteKeyItem`);
368  let throwObject: throwObject = { isThrow: false };
369  try {
370    await deleteKeyItem(keyAlias, huksOptions, throwObject)
371      .then((data) => {
372        console.info(`promise: deleteKeyItem key success, data = ${JSON.stringify(data)}`);
373      })
374      .catch((error: Error) => {
375        if (throwObject.isThrow) {
376          throw (error as Error);
377        } else {
378          console.error(`promise: deleteKeyItem failed, ${JSON.stringify(error)}`);
379        }
380      });
381  } catch (error) {
382    console.error(`promise: deleteKeyItem input arg invalid, ${JSON.stringify(error)}`);
383  }
384}
385
386async function testAgree() {
387  /* 1. Set the key alias srcKeyAliasFirst for device A and srcKeyAliasSecond for device B, and parameters for generating the key pairs. */
388  /* 2. Generate an asymmetric key pair for device A. */
389  await publicGenKeyFunc(srcKeyAliasFirst, HuksOptions);
390  /* 3. Generate an asymmetric key pair for device B. */
391  await publicGenKeyFunc(srcKeyAliasSecond, HuksOptions);
392  /* 4. Export the public keys of the key pairs of device A and device B. */
393  await publicExportKeyFunc(srcKeyAliasFirst, HuksOptions);
394  exportKeyFirst = exportKey;
395  await publicExportKeyFunc(srcKeyAliasSecond, HuksOptions);
396  exportKeySecond = exportKey;
397  /* 5. Perform key agreement (Init-Update-Finish) for device A. */
398  await publicInitFunc(srcKeyAliasFirst, HuksOptions);
399  HuksOptions.inData = exportKeySecond;
400  await publicUpdateFunc(handle, HuksOptions);
401  await publicFinishFunc(handle, finishOptionsFirst);
402  /* 5. Perform key agreement (Init-Update-Finish) for device B. */
403  await publicInitFunc(srcKeyAliasSecond, HuksOptions);
404  HuksOptions.inData = exportKeyFirst;
405  await publicUpdateFunc(handle, HuksOptions);
406  await publicFinishFunc(handle, finishOptionsSecond);
407  /* 6. Delete keys from device A and device B. */
408  await publicDeleteKeyFunc(srcKeyAliasFirst, HuksOptions);
409  await publicDeleteKeyFunc(srcKeyAliasSecond, HuksOptions);
410}
411```
412
413Example: Perform DH key agreement.
414
415```ts
416/*
417 * Agree on a DH key using promise-based APIs.
418 */
419import { huks } from '@kit.UniversalKeystoreKit'
420
421function StringToUint8Array(str: string) {
422  let arr: number[] = []
423  for (let i = 0, j = str.length; i < j; ++i) {
424    arr.push(str.charCodeAt(i))
425  }
426  return new Uint8Array(arr)
427}
428
429function Uint8ArrayToBigInt(arr: Uint8Array): bigint {
430  let i = 0
431  const byteMax: bigint = BigInt('0x100')
432  let result: bigint = BigInt('0')
433  while (i < arr.length) {
434    result = result * byteMax
435    result = result + BigInt(arr[i])
436    i += 1
437  }
438  return result
439}
440
441const dhAgree: Array<huks.HuksParam> = [{
442  tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
443  value: huks.HuksKeyAlg.HUKS_ALG_DH,
444}, {
445  tag: huks.HuksTag.HUKS_TAG_PURPOSE,
446  value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE,
447}]
448const dh2048Agree: Array<huks.HuksParam> = [
449  ...dhAgree, {
450  tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
451  value: huks.HuksKeySize.HUKS_DH_KEY_SIZE_2048,
452}]
453const dhGenOptions: huks.HuksOptions = {
454  properties: dh2048Agree,
455  inData: new Uint8Array([])
456}
457const emptyOptions: huks.HuksOptions = {
458  properties: [],
459  inData: new Uint8Array([])
460}
461
462async function HuksDhAgreeExportKey(keyAlias: string,
463  peerPubKey: huks.HuksReturnResult): Promise<huks.HuksReturnResult> {
464  const initHandle = await huks.initSession(keyAlias, dhGenOptions)
465  const dhAgreeUpdateBobPubKey: huks.HuksOptions = {
466    properties: [
467      ...dh2048Agree, {
468      tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
469      value: huks.HuksKeyStorageType.HUKS_STORAGE_KEY_EXPORT_ALLOWED,
470    }],
471    inData: peerPubKey.outData
472  }
473  await huks.updateSession(initHandle.handle, dhAgreeUpdateBobPubKey)
474  return await huks.finishSession(initHandle.handle, emptyOptions)
475}
476
477async function HuksDhAgreeExportTest(
478  aliasA: string, aliasB: string,
479  pubKeyA: huks.HuksReturnResult, pubKeyB: huks.HuksReturnResult) {
480
481  const agreedKeyFromAlice = await HuksDhAgreeExportKey(aliasA, pubKeyB)
482  console.info(`ok! agreedKeyFromAlice export is 0x${Uint8ArrayToBigInt(agreedKeyFromAlice.outData).toString(16)}`)
483
484  const agreedKeyFromBob = await HuksDhAgreeExportKey(aliasB, pubKeyA)
485  console.info(`ok! agreedKeyFromBob export is 0x${Uint8ArrayToBigInt(agreedKeyFromBob.outData).toString(16)}`)
486}
487
488async function HuksDhAgreeInHuks(keyAlias: string, peerPubKey: huks.HuksReturnResult,
489  aliasAgreedKey: string): Promise<huks.HuksReturnResult> {
490  const onlyUsedInHuks: Array<huks.HuksParam> = [{
491    tag: huks.HuksTag.HUKS_TAG_KEY_STORAGE_FLAG,
492    value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS,
493  }, {
494    tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
495    value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS,
496  }]
497  const dhAgreeInit: huks.HuksOptions = {
498    properties: [
499      ...dhAgree,
500      { tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256, },
501      ...onlyUsedInHuks],
502    inData: new Uint8Array([])
503  }
504  const dhAgreeFinishParams: Array<huks.HuksParam> = [
505    ...onlyUsedInHuks,
506    { tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS, value: true },
507    { tag: huks.HuksTag.HUKS_TAG_ALGORITHM, value: huks.HuksKeyAlg.HUKS_ALG_AES },
508    { tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 },
509    {
510      tag: huks.HuksTag.HUKS_TAG_PURPOSE,
511      value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT
512    }]
513
514  const handle = await huks.initSession(keyAlias, dhAgreeInit)
515  const dhAgreeUpdatePubKey: huks.HuksOptions = {
516    properties: [...dhAgree, ...onlyUsedInHuks],
517    inData: peerPubKey.outData
518  }
519  await huks.updateSession(handle.handle, dhAgreeUpdatePubKey)
520  const dhAgreeAliceFinnish: huks.HuksOptions = {
521    properties: [...dhAgreeFinishParams, {
522      tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS, value: StringToUint8Array(aliasAgreedKey)
523    }], inData: new Uint8Array([])
524  }
525  return await huks.finishSession(handle.handle, dhAgreeAliceFinnish)
526}
527
528async function HuksDhAgreeInHuksTest(
529  aliasA: string, aliasB: string,
530  pubKeyA: huks.HuksReturnResult, pubKeyB: huks.HuksReturnResult,
531  aliasAgreedKeyFromA: string, aliasAgreedKeyFromB: string) {
532
533  const finishAliceResult = await HuksDhAgreeInHuks(aliasA, pubKeyB, aliasAgreedKeyFromA)
534  console.info(`ok! finishAliceResult in huks is 0x${Uint8ArrayToBigInt(finishAliceResult.outData).toString(16)}`)
535  const aliceAgreedExist = await huks.isKeyItemExist(aliasAgreedKeyFromA, emptyOptions)
536  console.info(`ok! aliceAgreedExist in huks is ${aliceAgreedExist}`)
537
538  const finishBobResult = await HuksDhAgreeInHuks(aliasB, pubKeyA, aliasAgreedKeyFromB)
539  console.info(`ok! finishBobResult in huks is 0x${Uint8ArrayToBigInt(finishBobResult.outData).toString(16)}`)
540  const bobAgreedExist = await huks.isKeyItemExist(aliasAgreedKeyFromB, emptyOptions)
541  console.info(`ok! bobAgreedExist in huks is ${bobAgreedExist}`)
542
543  await huks.deleteKeyItem(aliasAgreedKeyFromA, emptyOptions)
544  await huks.deleteKeyItem(aliasAgreedKeyFromB, emptyOptions)
545}
546
547export default async function HuksDhAgreeTest() {
548  const aliasAlice = 'alice'
549  const aliasBob = 'bob'
550
551  /* Call generateKeyItem to generate a key with alias of alice and a key with alias of bob. */
552  await huks.generateKeyItem(aliasAlice, dhGenOptions)
553  await huks.generateKeyItem(aliasBob, dhGenOptions)
554
555  /* Export the public keys of asymmetric key pairs alice and bob. */
556  const pubKeyAlice = await huks.exportKeyItem(aliasAlice, emptyOptions)
557  const pubKeyBob = await huks.exportKeyItem(aliasBob, emptyOptions)
558
559  /* Perform key agreement and return the shared secret generated to the caller for management. */
560  await HuksDhAgreeExportTest(aliasAlice, aliasBob, pubKeyAlice, pubKeyBob)
561
562  /* Perform key agreement and let HUKS manage the shared secret generated. */
563  await HuksDhAgreeInHuksTest(aliasAlice, aliasBob, pubKeyAlice, pubKeyBob, 'agreedKeyFromAlice', 'agreedKeyFromBob')
564
565  await huks.deleteKeyItem(aliasAlice, emptyOptions)
566  await huks.deleteKeyItem(aliasBob, emptyOptions)
567}
568```
569