1# Key Agreement (ArkTS) 2 3 4This topic walks you through on how to agree on an 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 46The following uses X25519 and DH key agreement as examples. 47Example: Perform X25519 key agreement. 48 ```ts 49 /* 50 * Agree on an X25519 key using promise-based APIs. 51 */ 52 import { huks } from '@kit.UniversalKeystoreKit'; 53 54 /* 55 * Set the key alias and encapsulate the key property set. 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 /* Set the parameter set used for generating the key. */ 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 /* Set the parameter set for the first key agreement. */ 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 /* Set the parameter set for the second key agreement. */ 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 /* Generate a key. */ 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 /* Call generateKeyItem to generate a key. */ 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 /* Initializes a key session, which returns a session handle (mandatory) and a challenge (optional). */ 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 /* Call initSession. A session handle is returned. */ 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 /* Call updateSession multiple times to process data by segment and output the processed data. */ 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 /* Call updateSession to perform key agreement. */ 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 /* Finish the key session to output the shared secret key. */ 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 /* Call finishSession to finish the operation. */ 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 /* Export a key. */ 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 /* Call exportKeyItem to export the public key. */ 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 /* Delete the keys. */ 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 /* Call deleteKeyItem to delete a key. */ 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. Set the key alias srcKeyAliasFirst for device A and srcKeyAliasSecond for device B, and parameters for generating the key pairs. */ 389 /* 2. Generate an asymmetric key pair for device A. */ 390 await publicGenKeyFunc(srcKeyAliasFirst, HuksOptions); 391 /* 3. Generate an asymmetric key pair for device B. */ 392 await publicGenKeyFunc(srcKeyAliasSecond, HuksOptions); 393 /* 4. Export the public keys of the key pairs of device A and device B. */ 394 await publicExportKeyFunc(srcKeyAliasFirst, HuksOptions); 395 exportKeyFirst = exportKey; 396 await publicExportKeyFunc(srcKeyAliasSecond, HuksOptions); 397 exportKeySecond = exportKey; 398 /* 5. Perform key agreement (Init-Update-Finish) for device A. */ 399 await publicInitFunc(srcKeyAliasFirst, HuksOptions); 400 HuksOptions.inData = exportKeySecond; 401 await publicUpdateFunc(handle, HuksOptions); 402 await publicFinishFunc(handle, finishOptionsFirst); 403 /* 5. Perform key agreement (Init-Update-Finish) for device B. */ 404 await publicInitFunc(srcKeyAliasSecond, HuksOptions); 405 HuksOptions.inData = exportKeyFirst; 406 await publicUpdateFunc(handle, HuksOptions); 407 await publicFinishFunc(handle, finishOptionsSecond); 408 /* 6. Delete keys from device A and device B. */ 409 await publicDeleteKeyFunc(srcKeyAliasFirst, HuksOptions); 410 await publicDeleteKeyFunc(srcKeyAliasSecond, HuksOptions); 411 } 412 ``` 413 414Example: Perform DH key agreement. 415 416 ```ts 417 /* 418 * Agree on a DH key using promise-based APIs. 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 /* Call generateKeyItem to generate a key with alias of alice and a key with alias of bob. */ 553 await huks.generateKeyItem(aliasAlice, dhGenOptions) 554 await huks.generateKeyItem(aliasBob, dhGenOptions) 555 556 /* Export the public keys of asymmetric key pairs alice and bob. */ 557 const pubKeyAlice = await huks.exportKeyItem(aliasAlice, emptyOptions) 558 const pubKeyBob = await huks.exportKeyItem(aliasBob, emptyOptions) 559 560 /* Perform key agreement and return the shared secret generated to the caller for management. */ 561 await HuksDhAgreeExportTest(aliasAlice, aliasBob, pubKeyAlice, pubKeyBob) 562 563 /* Perform key agreement and let HUKS manage the shared secret generated. */ 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