1# 密钥协商(ArkTS) 2 3 4以协商密钥类型为X25519 256,并密钥仅在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密钥生成时,可指定参数TAG(可选),HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG: 14 15- HUKS_STORAGE_ONLY_USED_IN_HUKS:表示由该密钥协商出的密钥存储于HUKS中,由HUKS进行托管。 16 17- HUKS_STORAGE_KEY_EXPORT_ALLOWED(默认):表示由该密钥协商出的密钥直接导出给业务方,HUKS不对其进行托管服务。 18 19**导出密钥** 20 21设备A、B导出非对称密钥对的公钥材料,具体请参考[密钥导出](huks-export-key-arkts.md)。 22 23**密钥协商** 24 25设备A、B分别基于本端私钥和对端设备的公钥,协商出共享密钥。 26 27**删除密钥** 28 29当密钥废弃不用时,设备A、B均需要删除密钥,具体请参考[密钥删除](huks-delete-key-arkts.md)。 30 31```ts 32/* 33 *以下以X25519 256密钥的Promise操作使用为例 34 */ 35 import huks from '@ohos.security.huks'; 36 import { BusinessError } from '@ohos.base'; 37 /* 38 * 确定密钥别名和封装密钥属性参数集 39 */ 40 let srcKeyAliasFirst = "AgreeX25519KeyFirstAlias"; 41 let srcKeyAliasSecond = "AgreeX25519KeySecondAlias"; 42 let agreeX25519InData = 'AgreeX25519TestIndata'; 43 let finishOutData: Uint8Array; 44 let handle: number; 45 let exportKey: Uint8Array; 46 let exportKeyFrist: Uint8Array; 47 let exportKeySecond: Uint8Array; 48 /* 集成生成密钥参数集 */ 49 let properties: Array<huks.HuksParam> = new Array(); 50 properties[0] = { 51 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 52 value: huks.HuksKeyAlg.HUKS_ALG_X25519, 53 } 54 properties[1] = { 55 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 56 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE, 57 } 58 properties[2] = { 59 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 60 value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256, 61 } 62 properties[3] = { 63 tag: huks.HuksTag.HUKS_TAG_DIGEST, 64 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE, 65 } 66 properties[4] = { 67 tag: huks.HuksTag.HUKS_TAG_PADDING, 68 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 69 } 70 properties[5] = { 71 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 72 value: huks.HuksCipherMode.HUKS_MODE_CBC, 73 } 74 properties[6] = { 75 tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, 76 value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS, 77 } 78 let HuksOptions: huks.HuksOptions = { 79 properties: properties, 80 inData: new Uint8Array(new Array()) 81 } 82 /* 集成第一个协商参数集 */ 83 let finishProperties: Array<huks.HuksParam> = new Array(); 84 finishProperties[0] = { 85 tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, 86 value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS, 87 } 88 finishProperties[1] = { 89 tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS, 90 value: true 91 } 92 finishProperties[2] = { 93 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 94 value: huks.HuksKeyAlg.HUKS_ALG_AES, 95 } 96 finishProperties[3] = { 97 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 98 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256, 99 } 100 finishProperties[4] = { 101 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 102 value: 103 huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | 104 huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT, 105 } 106 finishProperties[5] = { 107 tag: huks.HuksTag.HUKS_TAG_DIGEST, 108 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE, 109 } 110 finishProperties[6] = { 111 tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS, 112 value: StringToUint8Array(srcKeyAliasFirst+ 'final'), 113 } 114 finishProperties[7] = { 115 tag: huks.HuksTag.HUKS_TAG_PADDING, 116 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 117 } 118 finishProperties[8] = { 119 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 120 value: huks.HuksCipherMode.HUKS_MODE_ECB, 121 } 122 let finishOptionsFrist: huks.HuksOptions = { 123 properties: finishProperties, 124 inData: StringToUint8Array(agreeX25519InData) 125 } 126 /* 集成第二个协商参数集 */ 127 let finishPropertiesSecond = [...finishProperties] 128 finishPropertiesSecond[6] = { 129 tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS, 130 value: StringToUint8Array(srcKeyAliasSecond + 'final'), 131 } 132 let finishOptionsSecond: huks.HuksOptions = { 133 properties: finishPropertiesSecond, 134 inData: StringToUint8Array(agreeX25519InData) 135 } 136 function StringToUint8Array(str:string) { 137 let arr: number[] = new Array(); 138 for (let i = 0, j = str.length; i < j; ++i) { 139 arr.push(str.charCodeAt(i)); 140 } 141 return new Uint8Array(arr); 142 } 143 class throwObject { 144 isThrow: boolean = false 145 } 146 /* 生成密钥 */ 147 function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) { 148 return new Promise<void>((resolve, reject) => { 149 try { 150 huks.generateKeyItem(keyAlias, huksOptions, (error, data) => { 151 if (error) { 152 reject(error); 153 } else { 154 resolve(data); 155 } 156 }); 157 } catch (error) { 158 throwObject.isThrow = true; 159 throw(error as Error); 160 } 161 }); 162 } 163 /* 调用generateKeyItem生成密钥 */ 164 async function publicGenKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 165 console.info(`enter promise generateKeyItem`); 166 let throwObject:throwObject = {isThrow: false}; 167 try { 168 await generateKeyItem(keyAlias, huksOptions, throwObject) 169 .then((data) => { 170 console.info(`promise: generateKeyItem success, data = ${JSON.stringify(data)}`); 171 }) 172 .catch((error: BusinessError) => { 173 if (throwObject.isThrow) { 174 throw(error as Error); 175 } else { 176 console.error(`promise: generateKeyItem failed` + error); 177 } 178 }); 179 } catch (error) { 180 console.error(`promise: generateKeyItem input arg invalid` + error); 181 } 182 } 183 /*初始化密钥会话接口,并获取一个句柄(必选)和挑战值(可选)*/ 184 function initSession(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) { 185 return new Promise<huks.HuksSessionHandle>((resolve, reject) => { 186 try { 187 huks.initSession(keyAlias, huksOptions, (error, data) => { 188 if (error) { 189 reject(error); 190 } else { 191 resolve(data); 192 } 193 }); 194 } catch (error) { 195 throwObject.isThrow = true; 196 throw(error as Error); 197 } 198 }); 199 } 200 /*调用initSession获取handle*/ 201 async function publicInitFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 202 console.info(`enter promise doInit`); 203 let throwObject: throwObject = {isThrow: false}; 204 try { 205 await initSession(keyAlias, huksOptions, throwObject) 206 .then ((data) => { 207 console.info(`promise: doInit success, data = ${JSON.stringify(data)}`); 208 handle = data.handle; 209 }) 210 .catch((error: BusinessError) => { 211 if (throwObject.isThrow) { 212 throw(error as Error); 213 } else { 214 console.error(`promise: doInit failed` + error); 215 } 216 }); 217 } catch (error) { 218 console.error(`promise: doInit input arg invalid` + error); 219 } 220 } 221 /* 分段添加密钥操作的数据并进行相应的密钥操作,输出处理数据 */ 222 function updateSession(handle: number, huksOptions: huks.HuksOptions, throwObject: throwObject) { 223 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 224 try { 225 huks.updateSession(handle, huksOptions, (error, data) => { 226 if (error) { 227 reject(error); 228 } else { 229 resolve(data); 230 } 231 }); 232 } catch (error) { 233 throwObject.isThrow = true; 234 throw(error as Error); 235 } 236 }); 237 } 238 /* 调用updateSession进行协商操作 */ 239 async function publicUpdateFunc(handle: number, huksOptions: huks.HuksOptions) { 240 console.info(`enter promise doUpdate`); 241 let throwObject: throwObject = {isThrow: false}; 242 try { 243 await updateSession(handle, huksOptions, throwObject) 244 .then ((data) => { 245 console.info(`promise: doUpdate success, data = ${JSON.stringify(data)}`); 246 }) 247 .catch((error: BusinessError) => { 248 if (throwObject.isThrow) { 249 throw(error as Error); 250 } else { 251 console.error(`promise: doUpdate failed` + error); 252 } 253 }); 254 } catch (error) { 255 console.error(`promise: doUpdate input arg invalid` + error); 256 } 257 } 258 /* 结束密钥会话并进行相应的密钥操作,输出处理数据 */ 259 function finishSession(handle: number, huksOptions: huks.HuksOptions, throwObject: throwObject) { 260 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 261 try { 262 huks.finishSession(handle, huksOptions, (error, data) =>{ 263 if (error) { 264 reject(error); 265 } else { 266 resolve(data); 267 } 268 }); 269 } catch (error) { 270 throwObject.isThrow = true; 271 throw(error as Error); 272 } 273 }); 274 } 275 /* 调用finishSession结束操作 */ 276 async function publicFinishFunc(handle: number, huksOptions: huks.HuksOptions) { 277 console.info(`enter promise doFinish`); 278 let throwObject: throwObject = {isThrow: false}; 279 try { 280 await finishSession(handle, huksOptions, throwObject) 281 .then ((data) => { 282 finishOutData = data.outData as Uint8Array; 283 console.info(`promise: doFinish success, data = ${JSON.stringify(data)}`); 284 }) 285 .catch((error: BusinessError) => { 286 if (throwObject.isThrow) { 287 throw(error as Error); 288 } else { 289 console.error(`promise: doFinish failed` + error); 290 } 291 }); 292 } catch (error) { 293 console.error(`promise: doFinish input arg invalid` + error); 294 } 295 } 296 /* 导出密钥 */ 297 function exportKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) { 298 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 299 try { 300 huks.exportKeyItem(keyAlias, huksOptions, (error, data) => { 301 if (error) { 302 reject(error); 303 } else { 304 resolve(data); 305 } 306 }); 307 } catch (error) { 308 throwObject.isThrow = true; 309 throw(error as Error); 310 } 311 }); 312 } 313 /* 调用exportKeyItem导出公钥操作 */ 314 async function publicExportKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 315 console.info(`enter promise export`); 316 let throwObject: throwObject = {isThrow: false}; 317 try { 318 await exportKeyItem(keyAlias, huksOptions, throwObject) 319 .then ((data) => { 320 console.info(`promise: exportKeyItem success, data = ${JSON.stringify(data)}`); 321 exportKey = data.outData as Uint8Array; 322 }) 323 .catch((error: BusinessError) => { 324 if (throwObject.isThrow) { 325 throw(error as Error); 326 } else { 327 console.error(`promise: exportKeyItem failed` + error); 328 } 329 }); 330 } catch (error) { 331 console.error(`promise: exportKeyItem input arg invalid` + error); 332 } 333 } 334 /* 删除密钥操作 */ 335 function deleteKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) { 336 return new Promise<void>((resolve, reject) => { 337 try { 338 huks.deleteKeyItem(keyAlias, huksOptions, (error, data) => { 339 if (error) { 340 reject(error); 341 } else { 342 resolve(data); 343 } 344 }); 345 } catch (error) { 346 throwObject.isThrow = true; 347 throw(error as Error); 348 } 349 }); 350 } 351 /* 调用deleteKeyItem删除密钥操作 */ 352 async function publicDeleteKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 353 console.info(`enter promise deleteKeyItem`); 354 let throwObject: throwObject = {isThrow: false}; 355 try { 356 await deleteKeyItem(keyAlias, huksOptions, throwObject) 357 .then ((data) => { 358 console.info(`promise: deleteKeyItem key success, data = ${JSON.stringify(data)}`); 359 }) 360 .catch((error :BusinessError) => { 361 if (throwObject.isThrow) { 362 throw(error as Error); 363 } else { 364 console.error(`promise: deleteKeyItem failed` + error); 365 } 366 }); 367 } catch (error) { 368 console.error(`promise: deletKeeyItem input arg invalid` + error); 369 } 370 } 371 async function testAgree() { 372 /* 1.确定密钥别名并集成并集成要参数集 A设备:srcKeyAliasFirst B设备:srcKeyAliasSecond*/ 373 /* 2.设备A生成密钥 */ 374 await publicGenKeyFunc(srcKeyAliasFirst, HuksOptions); 375 /* 3.设备B生成密钥 */ 376 await publicGenKeyFunc(srcKeyAliasSecond, HuksOptions); 377 /* 4.设备A、B导出非对称密钥的公钥 */ 378 await publicExportKeyFunc(srcKeyAliasFirst, HuksOptions); 379 exportKeyFrist = exportKey; 380 await publicExportKeyFunc(srcKeyAliasFirst, HuksOptions); 381 exportKeySecond = exportKey; 382 /* 5.对第一个密钥进行协商(三段式)*/ 383 await publicInitFunc(srcKeyAliasFirst, HuksOptions); 384 HuksOptions.inData = exportKeySecond; 385 await publicUpdateFunc(handle, HuksOptions); 386 await publicFinishFunc(handle, finishOptionsFrist); 387 /* 5.对第二个密钥进行协商(三段式) */ 388 await publicInitFunc(srcKeyAliasSecond, HuksOptions); 389 HuksOptions.inData = exportKeyFrist; 390 await publicUpdateFunc(handle, HuksOptions); 391 await publicFinishFunc(handle, finishOptionsSecond); 392 /* 6.设备A、B删除密钥 */ 393 await publicDeleteKeyFunc(srcKeyAliasFirst, HuksOptions); 394 await publicDeleteKeyFunc(srcKeyAliasSecond, HuksOptions); 395 } 396``` 397