1# 密钥协商(ArkTS)
2
3
4以协商密钥类型为X25519,并密钥仅在HUKS内使用为例,完成密钥协商。具体的场景介绍及支持的算法规格,请参考[密钥生成支持的算法](huks-key-generation-overview.md#支持的算法)。
5
6
7## 开发步骤
8
9**生成密钥**
10
11设备A、设备B各自生成一个非对称密钥,具体请参考[密钥生成](huks-key-generation-overview.md)或[密钥导入](huks-key-import-overview.md)。
12
13密钥生成时,可指定参数HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG(可选),用于标识基于该密钥协商出的密钥是否由HUKS管理。
14
15- 当TAG设置为HUKS_STORAGE_ONLY_USED_IN_HUKS时,表示基于该密钥协商出的密钥,由HUKS管理,可保证协商密钥全生命周期不出安全环境。
16
17- 当TAG设置为HUKS_STORAGE_KEY_EXPORT_ALLOWED时,表示基于该密钥协商出的密钥,返回给调用方管理,由业务自行保证密钥安全。
18
19- 若业务未设置TAG的具体值,表示基于该密钥协商出的密钥,可由HUKS管理,也可返回给调用方管理,业务可在后续协商时再选择使用何种方式保护密钥。
20
21**导出密钥**
22
23设备A、B导出非对称密钥对的公钥材料,具体请参考[密钥导出](huks-export-key-arkts.md)。
24
25**密钥协商**
26
27设备A、B分别基于本端私钥和对端设备的公钥,协商出共享密钥。
28
29密钥协商时,可指定参数HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG(可选),用于标识协商得到的密钥是否由HUKS管理。
30
31| 生成 | 协商 | 规格 |
32| -------- | -------- | -------- |
33| HUKS_STORAGE_ONLY_USED_IN_HUKS | HUKS_STORAGE_ONLY_USED_IN_HUKS | 密钥由HUKS管理 |
34| HUKS_STORAGE_KEY_EXPORT_ALLOWED | HUKS_STORAGE_KEY_EXPORT_ALLOWED | 密钥返回给调用方管理 |
35| 未指定TAG具体值 | HUKS_STORAGE_ONLY_USED_IN_HUKS | 密钥由HUKS管理 |
36| 未指定TAG具体值 | HUKS_STORAGE_KEY_EXPORT_ALLOWED | 密钥返回给调用方管理 |
37| 未指定TAG具体值 | 未指定TAG具体值 | 密钥返回给调用方管理 |
38
39注:协商时指定的TAG值,不可与生成时指定的TAG值冲突。表格中仅列举有效的指定方式。
40
41**删除密钥**
42
43当密钥废弃不用时,设备A、B均需要删除密钥,具体请参考[密钥删除](huks-delete-key-arkts.md)。
44
45
46下面分别以X25519 与 DH密钥为例,进行协商。
47- X25519非对称密钥协商用例
48  ```ts
49  /*
50  *以下以X25519密钥的Promise操作使用为例
51  */
52  import { huks } from '@kit.UniversalKeystoreKit';
53
54  /*
55  * 确定密钥别名和封装密钥属性参数集
56  */
57  let srcKeyAliasFirst = "AgreeX25519KeyFirstAlias";
58  let srcKeyAliasSecond = "AgreeX25519KeySecondAlias";
59  let agreeX25519InData = 'AgreeX25519TestIndata';
60  let finishOutData: Uint8Array;
61  let handle: number;
62  let exportKey: Uint8Array;
63  let exportKeyFirst: Uint8Array;
64  let exportKeySecond: Uint8Array;
65  /* 集成生成密钥参数集 */
66  let properties: Array<huks.HuksParam> = [{
67    tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
68    value: huks.HuksKeyAlg.HUKS_ALG_X25519,
69  }, {
70    tag: huks.HuksTag.HUKS_TAG_PURPOSE,
71    value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE,
72  }, {
73    tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
74    value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256,
75  }, {
76    tag: huks.HuksTag.HUKS_TAG_DIGEST,
77    value: huks.HuksKeyDigest.HUKS_DIGEST_NONE,
78  }, {
79    tag: huks.HuksTag.HUKS_TAG_PADDING,
80    value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
81  }, {
82    tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
83    value: huks.HuksCipherMode.HUKS_MODE_CBC,
84  }, {
85    tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
86    value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS,
87  }];
88  let HuksOptions: huks.HuksOptions = {
89    properties: properties,
90    inData: new Uint8Array(new Array())
91  }
92  /* 集成第一个协商参数集 */
93  const finishProperties: Array<huks.HuksParam> = [{
94    tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
95    value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS,
96  }, {
97    tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS,
98    value: true
99  }, {
100    tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
101    value: huks.HuksKeyAlg.HUKS_ALG_AES,
102  }, {
103    tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
104    value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256,
105  }, {
106    tag: huks.HuksTag.HUKS_TAG_PURPOSE,
107    value:
108    huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT |
109    huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT,
110  }, {
111    tag: huks.HuksTag.HUKS_TAG_DIGEST,
112    value: huks.HuksKeyDigest.HUKS_DIGEST_NONE,
113  }, {
114    tag: huks.HuksTag.HUKS_TAG_PADDING,
115    value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
116  }, {
117    tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
118    value: huks.HuksCipherMode.HUKS_MODE_ECB,
119  }];
120  let finishOptionsFirst: huks.HuksOptions = {
121    properties: [
122      ...finishProperties, {
123      tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS,
124      value: StringToUint8Array(srcKeyAliasFirst + 'final'),
125    }],
126    inData: StringToUint8Array(agreeX25519InData)
127  }
128  /* 集成第二个协商参数集 */
129  let finishOptionsSecond: huks.HuksOptions = {
130    properties: [
131      ...finishProperties, {
132      tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS,
133      value: StringToUint8Array(srcKeyAliasSecond + 'final'),
134    }],
135    inData: StringToUint8Array(agreeX25519InData)
136  }
137
138  function StringToUint8Array(str: string) {
139    let arr: number[] = new Array();
140    for (let i = 0, j = str.length; i < j; ++i) {
141      arr.push(str.charCodeAt(i));
142    }
143    return new Uint8Array(arr);
144  }
145
146  class throwObject {
147    isThrow: boolean = false
148  }
149
150  /* 生成密钥 */
151  function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) {
152    return new Promise<void>((resolve, reject) => {
153      try {
154        huks.generateKeyItem(keyAlias, huksOptions, (error, data) => {
155          if (error) {
156            reject(error);
157          } else {
158            resolve(data);
159          }
160        });
161      } catch (error) {
162        throwObject.isThrow = true;
163        throw (error as Error);
164      }
165    });
166  }
167
168  /* 调用generateKeyItem生成密钥 */
169  async function publicGenKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
170    console.info(`enter promise generateKeyItem`);
171    let throwObject: throwObject = { isThrow: false };
172    try {
173      await generateKeyItem(keyAlias, huksOptions, throwObject)
174        .then((data) => {
175          console.info(`promise: generateKeyItem success, data = ${JSON.stringify(data)}`);
176        })
177        .catch((error: Error) => {
178          if (throwObject.isThrow) {
179            throw (error as Error);
180          } else {
181            console.error(`promise: generateKeyItem failed, ${JSON.stringify(error)}`);
182          }
183        });
184    } catch (error) {
185      console.error(`promise: generateKeyItem input arg invalid, ${JSON.stringify(error)}`);
186    }
187  }
188
189  /*初始化密钥会话接口,并获取一个句柄(必选)和挑战值(可选)*/
190  function initSession(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) {
191    return new Promise<huks.HuksSessionHandle>((resolve, reject) => {
192      try {
193        huks.initSession(keyAlias, huksOptions, (error, data) => {
194          if (error) {
195            reject(error);
196          } else {
197            resolve(data);
198          }
199        });
200      } catch (error) {
201        throwObject.isThrow = true;
202        throw (error as Error);
203      }
204    });
205  }
206
207  /*调用initSession获取handle*/
208  async function publicInitFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
209    console.info(`enter promise doInit`);
210    let throwObject: throwObject = { isThrow: false };
211    try {
212      await initSession(keyAlias, huksOptions, throwObject)
213        .then((data) => {
214          console.info(`promise: doInit success, data = ${JSON.stringify(data)}`);
215          handle = data.handle;
216        })
217        .catch((error: Error) => {
218          if (throwObject.isThrow) {
219            throw (error as Error);
220          } else {
221            console.error(`promise: doInit failed, ${JSON.stringify(error)}`);
222          }
223        });
224    } catch (error) {
225      console.error(`promise: doInit input arg invalid, ${JSON.stringify(error)}`);
226    }
227  }
228
229  /* 分段添加密钥操作的数据并进行相应的密钥操作,输出处理数据 */
230  function updateSession(handle: number, huksOptions: huks.HuksOptions, throwObject: throwObject) {
231    return new Promise<huks.HuksReturnResult>((resolve, reject) => {
232      try {
233        huks.updateSession(handle, huksOptions, (error, data) => {
234          if (error) {
235            reject(error);
236          } else {
237            resolve(data);
238          }
239        });
240      } catch (error) {
241        throwObject.isThrow = true;
242        throw (error as Error);
243      }
244    });
245  }
246
247  /* 调用updateSession进行协商操作 */
248  async function publicUpdateFunc(handle: number, huksOptions: huks.HuksOptions) {
249    console.info(`enter promise doUpdate`);
250    let throwObject: throwObject = { isThrow: false };
251    try {
252      await updateSession(handle, huksOptions, throwObject)
253        .then((data) => {
254          console.info(`promise: doUpdate success, data = ${JSON.stringify(data)}`);
255        })
256        .catch((error: Error) => {
257          if (throwObject.isThrow) {
258            throw (error as Error);
259          } else {
260            console.error(`promise: doUpdate failed, ${JSON.stringify(error)}`);
261          }
262        });
263    } catch (error) {
264      console.error(`promise: doUpdate input arg invalid, ${JSON.stringify(error)}`);
265    }
266  }
267
268  /* 结束密钥会话并进行相应的密钥操作,输出处理数据 */
269  function finishSession(handle: number, huksOptions: huks.HuksOptions, throwObject: throwObject) {
270    return new Promise<huks.HuksReturnResult>((resolve, reject) => {
271      try {
272        huks.finishSession(handle, huksOptions, (error, data) => {
273          if (error) {
274            reject(error);
275          } else {
276            resolve(data);
277          }
278        });
279      } catch (error) {
280        throwObject.isThrow = true;
281        throw (error as Error);
282      }
283    });
284  }
285
286  /* 调用finishSession结束操作 */
287  async function publicFinishFunc(handle: number, huksOptions: huks.HuksOptions) {
288    console.info(`enter promise doFinish`);
289    let throwObject: throwObject = { isThrow: false };
290    try {
291      await finishSession(handle, huksOptions, throwObject)
292        .then((data) => {
293          finishOutData = data.outData as Uint8Array;
294          console.info(`promise: doFinish success, data = ${JSON.stringify(data)}`);
295        })
296        .catch((error: Error) => {
297          if (throwObject.isThrow) {
298            throw (error as Error);
299          } else {
300            console.error(`promise: doFinish failed, ${JSON.stringify(error)}`);
301          }
302        });
303    } catch (error) {
304      console.error(`promise: doFinish input arg invalid, ${JSON.stringify(error)}`);
305    }
306  }
307
308  /* 导出密钥 */
309  function exportKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) {
310    return new Promise<huks.HuksReturnResult>((resolve, reject) => {
311      try {
312        huks.exportKeyItem(keyAlias, huksOptions, (error, data) => {
313          if (error) {
314            reject(error);
315          } else {
316            resolve(data);
317          }
318        });
319      } catch (error) {
320        throwObject.isThrow = true;
321        throw (error as Error);
322      }
323    });
324  }
325
326  /* 调用exportKeyItem导出公钥操作 */
327  async function publicExportKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
328    console.info(`enter promise export`);
329    let throwObject: throwObject = { isThrow: false };
330    try {
331      await exportKeyItem(keyAlias, huksOptions, throwObject)
332        .then((data) => {
333          console.info(`promise: exportKeyItem success, data = ${JSON.stringify(data)}`);
334          exportKey = data.outData as Uint8Array;
335        })
336        .catch((error: Error) => {
337          if (throwObject.isThrow) {
338            throw (error as Error);
339          } else {
340            console.error(`promise: exportKeyItem failed, ${JSON.stringify(error)}`);
341          }
342        });
343    } catch (error) {
344      console.error(`promise: exportKeyItem input arg invalid, ${JSON.stringify(error)}`);
345    }
346  }
347
348  /* 删除密钥操作 */
349  function deleteKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) {
350    return new Promise<void>((resolve, reject) => {
351      try {
352        huks.deleteKeyItem(keyAlias, huksOptions, (error, data) => {
353          if (error) {
354            reject(error);
355          } else {
356            resolve(data);
357          }
358        });
359      } catch (error) {
360        throwObject.isThrow = true;
361        throw (error as Error);
362      }
363    });
364  }
365
366  /* 调用deleteKeyItem删除密钥操作 */
367  async function publicDeleteKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
368    console.info(`enter promise deleteKeyItem`);
369    let throwObject: throwObject = { isThrow: false };
370    try {
371      await deleteKeyItem(keyAlias, huksOptions, throwObject)
372        .then((data) => {
373          console.info(`promise: deleteKeyItem key success, data = ${JSON.stringify(data)}`);
374        })
375        .catch((error: Error) => {
376          if (throwObject.isThrow) {
377            throw (error as Error);
378          } else {
379            console.error(`promise: deleteKeyItem failed, ${JSON.stringify(error)}`);
380          }
381        });
382    } catch (error) {
383      console.error(`promise: deleteKeyItem input arg invalid, ${JSON.stringify(error)}`);
384    }
385  }
386
387  async function testAgree() {
388    /* 1.确定密钥别名并集成并集成要参数集 A设备:srcKeyAliasFirst  B设备:srcKeyAliasSecond*/
389    /* 2.设备A生成密钥 */
390    await publicGenKeyFunc(srcKeyAliasFirst, HuksOptions);
391    /* 3.设备B生成密钥 */
392    await publicGenKeyFunc(srcKeyAliasSecond, HuksOptions);
393    /* 4.设备A、B导出非对称密钥的公钥 */
394    await publicExportKeyFunc(srcKeyAliasFirst, HuksOptions);
395    exportKeyFirst = exportKey;
396    await publicExportKeyFunc(srcKeyAliasSecond, HuksOptions);
397    exportKeySecond = exportKey;
398    /* 5.对第一个密钥进行协商(三段式)*/
399    await publicInitFunc(srcKeyAliasFirst, HuksOptions);
400    HuksOptions.inData = exportKeySecond;
401    await publicUpdateFunc(handle, HuksOptions);
402    await publicFinishFunc(handle, finishOptionsFirst);
403    /* 5.对第二个密钥进行协商(三段式) */
404    await publicInitFunc(srcKeyAliasSecond, HuksOptions);
405    HuksOptions.inData = exportKeyFirst;
406    await publicUpdateFunc(handle, HuksOptions);
407    await publicFinishFunc(handle, finishOptionsSecond);
408    /* 6.设备A、B删除密钥 */
409    await publicDeleteKeyFunc(srcKeyAliasFirst, HuksOptions);
410    await publicDeleteKeyFunc(srcKeyAliasSecond, HuksOptions);
411  }
412  ```
413
414- DH密钥协商用例
415
416  ```ts
417  /*
418  *以下以 DH密钥的Promise操作使用为例
419  */
420  import { huks } from '@kit.UniversalKeystoreKit'
421
422  function StringToUint8Array(str: string) {
423    let arr: number[] = []
424    for (let i = 0, j = str.length; i < j; ++i) {
425      arr.push(str.charCodeAt(i))
426    }
427    return new Uint8Array(arr)
428  }
429
430  function Uint8ArrayToBigInt(arr: Uint8Array): bigint {
431    let i = 0
432    const byteMax: bigint = BigInt('0x100')
433    let result: bigint = BigInt('0')
434    while (i < arr.length) {
435      result = result * byteMax
436      result = result + BigInt(arr[i])
437      i += 1
438    }
439    return result
440  }
441
442  const dhAgree: Array<huks.HuksParam> = [{
443    tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
444    value: huks.HuksKeyAlg.HUKS_ALG_DH,
445  }, {
446    tag: huks.HuksTag.HUKS_TAG_PURPOSE,
447    value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE,
448  }]
449  const dh2048Agree: Array<huks.HuksParam> = [
450    ...dhAgree, {
451    tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
452    value: huks.HuksKeySize.HUKS_DH_KEY_SIZE_2048,
453  }]
454  const dhGenOptions: huks.HuksOptions = {
455    properties: dh2048Agree,
456    inData: new Uint8Array([])
457  }
458  const emptyOptions: huks.HuksOptions = {
459    properties: [],
460    inData: new Uint8Array([])
461  }
462
463  async function HuksDhAgreeExportKey(keyAlias: string,
464    peerPubKey: huks.HuksReturnResult): Promise<huks.HuksReturnResult> {
465    const initHandle = await huks.initSession(keyAlias, dhGenOptions)
466    const dhAgreeUpdateBobPubKey: huks.HuksOptions = {
467      properties: [
468        ...dh2048Agree, {
469        tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
470        value: huks.HuksKeyStorageType.HUKS_STORAGE_KEY_EXPORT_ALLOWED,
471      }],
472      inData: peerPubKey.outData
473    }
474    await huks.updateSession(initHandle.handle, dhAgreeUpdateBobPubKey)
475    return await huks.finishSession(initHandle.handle, emptyOptions)
476  }
477
478  async function HuksDhAgreeExportTest(
479    aliasA: string, aliasB: string,
480    pubKeyA: huks.HuksReturnResult, pubKeyB: huks.HuksReturnResult) {
481
482    const agreedKeyFromAlice = await HuksDhAgreeExportKey(aliasA, pubKeyB)
483    console.info(`ok! agreedKeyFromAlice export is 0x${Uint8ArrayToBigInt(agreedKeyFromAlice.outData).toString(16)}`)
484
485    const agreedKeyFromBob = await HuksDhAgreeExportKey(aliasB, pubKeyA)
486    console.info(`ok! agreedKeyFromBob export is 0x${Uint8ArrayToBigInt(agreedKeyFromBob.outData).toString(16)}`)
487  }
488
489  async function HuksDhAgreeInHuks(keyAlias: string, peerPubKey: huks.HuksReturnResult,
490    aliasAgreedKey: string): Promise<huks.HuksReturnResult> {
491    const onlyUsedInHuks: Array<huks.HuksParam> = [{
492      tag: huks.HuksTag.HUKS_TAG_KEY_STORAGE_FLAG,
493      value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS,
494    }, {
495      tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG,
496      value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS,
497    }]
498    const dhAgreeInit: huks.HuksOptions = {
499      properties: [
500        ...dhAgree,
501        { tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256, },
502        ...onlyUsedInHuks],
503      inData: new Uint8Array([])
504    }
505    const dhAgreeFinishParams: Array<huks.HuksParam> = [
506      ...onlyUsedInHuks,
507      { tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS, value: true },
508      { tag: huks.HuksTag.HUKS_TAG_ALGORITHM, value: huks.HuksKeyAlg.HUKS_ALG_AES },
509      { tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 },
510      {
511        tag: huks.HuksTag.HUKS_TAG_PURPOSE,
512        value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT
513      }]
514
515    const handle = await huks.initSession(keyAlias, dhAgreeInit)
516    const dhAgreeUpdatePubKey: huks.HuksOptions = {
517      properties: [...dhAgree, ...onlyUsedInHuks],
518      inData: peerPubKey.outData
519    }
520    await huks.updateSession(handle.handle, dhAgreeUpdatePubKey)
521    const dhAgreeAliceFinnish: huks.HuksOptions = {
522      properties: [...dhAgreeFinishParams, {
523        tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS, value: StringToUint8Array(aliasAgreedKey)
524      }], inData: new Uint8Array([])
525    }
526    return await huks.finishSession(handle.handle, dhAgreeAliceFinnish)
527  }
528
529  async function HuksDhAgreeInHuksTest(
530    aliasA: string, aliasB: string,
531    pubKeyA: huks.HuksReturnResult, pubKeyB: huks.HuksReturnResult,
532    aliasAgreedKeyFromA: string, aliasAgreedKeyFromB: string) {
533
534    const finishAliceResult = await HuksDhAgreeInHuks(aliasA, pubKeyB, aliasAgreedKeyFromA)
535    console.info(`ok! finishAliceResult in huks is 0x${Uint8ArrayToBigInt(finishAliceResult.outData).toString(16)}`)
536    const aliceAgreedExist = await huks.isKeyItemExist(aliasAgreedKeyFromA, emptyOptions)
537    console.info(`ok! aliceAgreedExist in huks is ${aliceAgreedExist}`)
538
539    const finishBobResult = await HuksDhAgreeInHuks(aliasB, pubKeyA, aliasAgreedKeyFromB)
540    console.info(`ok! finishBobResult in huks is 0x${Uint8ArrayToBigInt(finishBobResult.outData).toString(16)}`)
541    const bobAgreedExist = await huks.isKeyItemExist(aliasAgreedKeyFromB, emptyOptions)
542    console.info(`ok! bobAgreedExist in huks is ${bobAgreedExist}`)
543
544    await huks.deleteKeyItem(aliasAgreedKeyFromA, emptyOptions)
545    await huks.deleteKeyItem(aliasAgreedKeyFromB, emptyOptions)
546  }
547
548  export default async function HuksDhAgreeTest() {
549    const aliasAlice = 'alice'
550    const aliasBob = 'bob'
551
552    /* 调用generateKeyItem生成别名为alice与bob的两个密钥 */
553    await huks.generateKeyItem(aliasAlice, dhGenOptions)
554    await huks.generateKeyItem(aliasBob, dhGenOptions)
555
556    /* 导出非对称密钥alice与bob的的公钥 */
557    const pubKeyAlice = await huks.exportKeyItem(aliasAlice, emptyOptions)
558    const pubKeyBob = await huks.exportKeyItem(aliasBob, emptyOptions)
559
560    /* 开始协商,协商生成的密钥返回给业务管理 */
561    await HuksDhAgreeExportTest(aliasAlice, aliasBob, pubKeyAlice, pubKeyBob)
562
563    /* 开始协商,协商生成的密钥由HUKS管理 */
564    await HuksDhAgreeInHuksTest(aliasAlice, aliasBob, pubKeyAlice, pubKeyBob, 'agreedKeyFromAlice', 'agreedKeyFromBob')
565
566    await huks.deleteKeyItem(aliasAlice, emptyOptions)
567    await huks.deleteKeyItem(aliasBob, emptyOptions)
568  }
569  ```
570