1# 密钥派生(ArkTS) 2 3<!--Kit: Universal Keystore Kit--> 4<!--Subsystem: Security--> 5<!--Owner: @wutiantian-gitee--> 6<!--Designer: @HighLowWorld--> 7<!--Tester: @wxy1234564846--> 8<!--Adviser: @zengyawen--> 9 10以HKDF256密钥为例,完成密钥派生。具体的场景介绍及支持的算法规格,请参考[密钥生成支持的算法](huks-key-generation-overview.md#支持的算法)。 11 12## 开发步骤 13 14**生成密钥** 15 161. 指定密钥别名,密钥别名命名规范参考[密钥生成介绍及算法规格](huks-key-generation-overview.md)。 17 182. 初始化密钥属性集,可指定参数HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG(可选),用于标识基于该密钥派生出的密钥是否由HUKS管理。 19 20 - 当TAG设置为HUKS_STORAGE_ONLY_USED_IN_HUKS时,表示基于该密钥派生出的密钥,由HUKS管理,可保证派生密钥全生命周期不出安全环境。 21 22 - 当TAG设置为HUKS_STORAGE_KEY_EXPORT_ALLOWED时,表示基于该密钥派生出的密钥,返回给调用方管理,由业务自行保证密钥安全。 23 24 - 若业务未设置TAG的具体值,表示基于该密钥派生出的密钥,即可由HUKS管理,也可返回给调用方管理,业务可在后续派生时再选择使用何种方式保护密钥。 25 263. 调用[generateKeyItem](../../reference/apis-universal-keystore-kit/js-apis-huks.md#huksgeneratekeyitem9)生成密钥,具体请参考[密钥生成](huks-key-generation-overview.md)。 27 28除此之外,开发者也可以参考[密钥导入](huks-key-import-overview.md),导入已有的密钥。 29 30**密钥派生** 31 321. 获取密钥别名,指定对应的属性参数HuksOptions。 33 34 可指定参数HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG(可选),用于标识派生得到的密钥是否由HUKS管理。 35 36 | 生成 | 派生 | 规格 | 37 | -------- | -------- | -------- | 38 | HUKS_STORAGE_ONLY_USED_IN_HUKS | HUKS_STORAGE_ONLY_USED_IN_HUKS | 密钥由HUKS管理 | 39 | HUKS_STORAGE_KEY_EXPORT_ALLOWED | HUKS_STORAGE_KEY_EXPORT_ALLOWED | 密钥返回给调用方管理 | 40 | 未指定TAG具体值 | HUKS_STORAGE_ONLY_USED_IN_HUKS | 密钥由HUKS管理 | 41 | 未指定TAG具体值 | HUKS_STORAGE_KEY_EXPORT_ALLOWED | 密钥返回给调用方管理 | 42 | 未指定TAG具体值 | 未指定TAG具体值 | 密钥返回给调用方管理 | 43 44 注:派生时指定的TAG值,不可与生成时指定的TAG值冲突。表格中仅列举有效的指定方式。 45 46 472. 调用[initSession](../../reference/apis-universal-keystore-kit/js-apis-huks.md#huksinitsession9)初始化密钥会话,并获取会话的句柄handle。 48 493. 调用[updateSession](../../reference/apis-universal-keystore-kit/js-apis-huks.md#huksupdatesession9)更新密钥会话。 50 514. 调用[finishSession](../../reference/apis-universal-keystore-kit/js-apis-huks.md#huksfinishsession9)结束密钥会话,完成派生。 52 53**删除密钥** 54 55当密钥废弃不用时,需要调用[deleteKeyItem](../../reference/apis-universal-keystore-kit/js-apis-huks.md#huksdeletekeyitem9)删除密钥,具体请参考[密钥删除](huks-delete-key-arkts.md)。 56 57## 开发案例 58 59### HKDF 60```ts 61/* 62 * 以下以HKDF密钥的Promise操作使用为例 63 */ 64import { huks } from '@kit.UniversalKeystoreKit'; 65import { BusinessError } from "@kit.BasicServicesKit"; 66 67function StringToUint8Array(str: string) { 68 let arr: number[] = new Array(); 69 for (let i = 0, j = str.length; i < j; ++i) { 70 arr.push(str.charCodeAt(i)); 71 } 72 return new Uint8Array(arr); 73} 74 75function Uint8ArrayToString(fileData: Uint8Array) { 76 let dataString = ''; 77 for (let i = 0; i < fileData.length; i++) { 78 dataString += String.fromCharCode(fileData[i]); 79 } 80 return dataString; 81} 82 83/* 84 * 确定密钥别名和封装密钥属性参数集 85 */ 86let srcKeyAlias = "hkdf_Key"; 87let deriveHkdfInData = "deriveHkdfTestIndata"; 88let handle: number; 89let HuksKeyDeriveKeySize = 32; 90/* 集成生成密钥参数集 */ 91let properties: Array<huks.HuksParam> = [{ 92 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 93 value: huks.HuksKeyAlg.HUKS_ALG_AES, 94 }, { 95 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 96 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DERIVE, 97 }, { 98 tag: huks.HuksTag.HUKS_TAG_DIGEST, 99 value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256, 100 }, { 101 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 102 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256, 103 }, { 104 tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, 105 value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS, 106 } 107]; 108 109let huksOptions: huks.HuksOptions = { 110 properties: properties, 111 inData: new Uint8Array(new Array()) 112} 113/* 集成init时密钥参数集 */ 114let initProperties: Array<huks.HuksParam> = [{ 115 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 116 value: huks.HuksKeyAlg.HUKS_ALG_HKDF, 117 }, { 118 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 119 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DERIVE, 120 }, { 121 tag: huks.HuksTag.HUKS_TAG_DIGEST, 122 value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256, 123 }, { 124 tag: huks.HuksTag.HUKS_TAG_DERIVE_KEY_SIZE, 125 value: HuksKeyDeriveKeySize, 126 } 127]; 128 129let initOptions: huks.HuksOptions = { 130 properties: initProperties, 131 inData: new Uint8Array(new Array()) 132} 133/* 集成finish时密钥参数集 */ 134let finishProperties: Array<huks.HuksParam> = [{ 135 tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, 136 value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS, 137 }, { 138 tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS, 139 value: true, 140 }, { 141 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 142 value: huks.HuksKeyAlg.HUKS_ALG_AES, 143 }, { 144 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 145 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256, 146 }, { 147 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 148 value: 149 huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | 150 huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT, 151 }, { 152 tag: huks.HuksTag.HUKS_TAG_DIGEST, 153 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE, 154 }, { 155 tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS, 156 value: StringToUint8Array(srcKeyAlias), 157 }, { 158 tag: huks.HuksTag.HUKS_TAG_PADDING, 159 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 160 }, { 161 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 162 value: huks.HuksCipherMode.HUKS_MODE_ECB, 163 } 164]; 165let finishOptions: huks.HuksOptions = { 166 properties: finishProperties, 167 inData: new Uint8Array(new Array()) 168} 169 170async function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions) { 171 console.info(`promise: enter generateKeyItem`); 172 try { 173 await huks.generateKeyItem(keyAlias, huksOptions) 174 .then(() => { 175 console.info(`promise: generateKeyItem success`); 176 }).catch((error: BusinessError) => { 177 console.error(`promise: generateKeyItem failed, errCode : ${error.code}, errMsg : ${error.message}`); 178 }) 179 } catch (error) { 180 console.error(`promise: generateKeyItem input arg invalid`); 181 } 182} 183 184async function initSession(keyAlias: string, huksOptions: huks.HuksOptions) { 185 console.info(`promise: enter initSession`); 186 try { 187 await huks.initSession(keyAlias, huksOptions) 188 .then((data) => { 189 handle = data.handle; 190 console.info(`promise: initSession success`); 191 }).catch((error: BusinessError) => { 192 console.error(`promise: initSession failed, errCode : ${error.code}, errMsg : ${error.message}`); 193 }) 194 } catch (error) { 195 console.error(`promise: initSession input arg invalid`); 196 } 197} 198 199async function updateSession(handle: number, huksOptions: huks.HuksOptions) { 200 console.info(`promise: enter updateSession`); 201 try { 202 await huks.updateSession(handle, huksOptions) 203 .then((data) => { 204 let outData = data.outData as Uint8Array; 205 console.info(`promise: updateSession success, data = ${Uint8ArrayToString(outData)}`); 206 }).catch((error: BusinessError) => { 207 console.error(`promise: updateSession failed, errCode : ${error.code}, errMsg : ${error.message}`); 208 }) 209 } catch (error) { 210 console.error(`promise: updateSession input arg invalid`); 211 } 212} 213 214async function finishSession(handle: number, huksOptions: huks.HuksOptions) { 215 console.info(`promise: enter finishSession`); 216 try { 217 await huks.finishSession(handle, huksOptions) 218 .then((data) => { 219 let outData = data.outData as Uint8Array; 220 console.info(`promise: finishSession success, data = ${Uint8ArrayToString(outData)}`); 221 }).catch((error: BusinessError) => { 222 console.error(`promise: finishSession failed, errCode : ${error.code}, errMsg : ${error.message}`); 223 }) 224 } catch (error) { 225 console.error(`promise: finishSession input arg invalid`); 226 } 227} 228 229async function deleteKeyItem(keyAlias: string, huksOptions: huks.HuksOptions) { 230 console.info(`promise: enter deleteKeyItem`); 231 try { 232 await huks.deleteKeyItem(keyAlias, huksOptions) 233 .then(() => { 234 console.info(`promise: deleteKeyItem success`); 235 }).catch((error: BusinessError) => { 236 console.error(`promise: deleteKeyItem failed, errCode : ${error.code}, errMsg : ${error.message}`); 237 }) 238 } catch (error) { 239 console.error(`promise: deleteKeyItem input arg invalid`); 240 } 241} 242 243async function testDerive() { 244 /* 生成密钥 */ 245 await generateKeyItem(srcKeyAlias, huksOptions); 246 /* 进行派生操作 */ 247 await initSession(srcKeyAlias, initOptions); 248 initOptions.inData = StringToUint8Array(deriveHkdfInData); 249 await updateSession(handle, initOptions); 250 await finishSession(handle, finishOptions); 251 await deleteKeyItem(srcKeyAlias, huksOptions); 252} 253``` 254### PBKDF2 255 256```ts 257/* 258 * 以下以PBKDF2密钥的Promise操作使用为例 259 */ 260import { huks } from '@kit.UniversalKeystoreKit'; 261import { BusinessError } from "@kit.BasicServicesKit"; 262 263function StringToUint8Array(str: string) { 264 let arr: number[] = new Array(); 265 for (let i = 0, j = str.length; i < j; ++i) { 266 arr.push(str.charCodeAt(i)); 267 } 268 return new Uint8Array(arr); 269} 270 271function Uint8ArrayToString(fileData: Uint8Array) { 272 let dataString = ''; 273 for (let i = 0; i < fileData.length; i++) { 274 dataString += String.fromCharCode(fileData[i]); 275 } 276 return dataString; 277} 278 279/* 280 * 确定密钥别名和封装密钥属性参数集 281 */ 282let srcKeyAlias = "pbkdf2_Key"; 283let salt = "mySalt"; 284let iterationCount = 10000; 285let derivedKeySize = 32; 286let handle: number; 287let finishOutData: Uint8Array; 288 289/* 集成生成密钥参数集 */ 290let properties: Array<huks.HuksParam> = [{ 291 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 292 value: huks.HuksKeyAlg.HUKS_ALG_AES, 293 }, { 294 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 295 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DERIVE, 296 }, { 297 tag: huks.HuksTag.HUKS_TAG_DIGEST, 298 value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256, 299 }, { 300 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 301 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256, 302 }, { 303 tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, 304 value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS, 305 } 306]; 307 308let huksOptions: huks.HuksOptions = { 309 properties: properties, 310 inData: new Uint8Array(new Array()) 311} 312 313/* 集成init时密钥参数集 */ 314let initProperties: Array<huks.HuksParam> = [{ 315 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 316 value: huks.HuksKeyAlg.HUKS_ALG_PBKDF2, 317 }, { 318 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 319 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DERIVE, 320 }, { 321 tag: huks.HuksTag.HUKS_TAG_DIGEST, 322 value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256, 323 }, { 324 tag: huks.HuksTag.HUKS_TAG_DERIVE_KEY_SIZE, 325 value: derivedKeySize, 326 }, { 327 tag: huks.HuksTag.HUKS_TAG_ITERATION, 328 value: iterationCount, 329 }, { 330 tag: huks.HuksTag.HUKS_TAG_SALT, 331 value: StringToUint8Array(salt), 332 } 333]; 334 335let initOptions: huks.HuksOptions = { 336 properties: initProperties, 337 inData: new Uint8Array(new Array()) 338} 339 340/* 集成finish时密钥参数集 */ 341let finishProperties: Array<huks.HuksParam> = [{ 342 tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, 343 value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS, 344 }, { 345 tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS, 346 value: true, 347 }, { 348 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 349 value: huks.HuksKeyAlg.HUKS_ALG_AES, 350 }, { 351 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 352 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256, 353 }, { 354 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 355 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT, 356 }, { 357 tag: huks.HuksTag.HUKS_TAG_DIGEST, 358 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE, 359 }, { 360 tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS, 361 value: StringToUint8Array(srcKeyAlias), 362 }, { 363 tag: huks.HuksTag.HUKS_TAG_PADDING, 364 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 365 }, { 366 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 367 value: huks.HuksCipherMode.HUKS_MODE_ECB, 368 } 369]; 370 371let finishOptions: huks.HuksOptions = { 372 properties: finishProperties, 373 inData: new Uint8Array(new Array()) 374} 375 376async function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions) { 377 console.info(`promise: enter generateKeyItem`); 378 try { 379 await huks.generateKeyItem(keyAlias, huksOptions) 380 .then(() => { 381 console.info(`promise: generateKeyItem success`); 382 }).catch((error: BusinessError) => { 383 console.error(`promise: generateKeyItem failed, errCode : ${error.code}, errMsg : ${error.message}`); 384 }) 385 } catch (error) { 386 console.error(`promise: generateKeyItem input arg invalid`); 387 } 388} 389 390async function initSession(keyAlias: string, huksOptions: huks.HuksOptions) { 391 console.info(`promise: enter initSession`); 392 try { 393 await huks.initSession(keyAlias, huksOptions) 394 .then((data) => { 395 handle = data.handle; 396 console.info(`promise: initSession success`); 397 }).catch((error: BusinessError) => { 398 console.error(`promise: initSession failed, errCode : ${error.code}, errMsg : ${error.message}`); 399 }) 400 } catch (error) { 401 console.error(`promise: initSession input arg invalid`); 402 } 403} 404 405async function updateSession(handle: number, huksOptions: huks.HuksOptions) { 406 console.info(`promise: enter updateSession`); 407 try { 408 await huks.updateSession(handle, huksOptions) 409 .then((data) => { 410 let outData = data.outData as Uint8Array; 411 console.info(`promise: updateSession success, data = ${Uint8ArrayToString(outData)}`); 412 }).catch((error: BusinessError) => { 413 console.error(`promise: updateSession failed, errCode : ${error.code}, errMsg : ${error.message}`); 414 }) 415 } catch (error) { 416 console.error(`promise: updateSession input arg invalid`); 417 } 418} 419 420async function finishSession(handle: number, huksOptions: huks.HuksOptions) { 421 console.info(`promise: enter finishSession`); 422 try { 423 await huks.finishSession(handle, huksOptions) 424 .then((data) => { 425 let outData = data.outData as Uint8Array; 426 console.info(`promise: finishSession success, data = ${Uint8ArrayToString(outData)}`); 427 }).catch((error: BusinessError) => { 428 console.error(`promise: finishSession failed, errCode : ${error.code}, errMsg : ${error.message}`); 429 }) 430 } catch (error) { 431 console.error(`promise: finishSession input arg invalid`); 432 } 433} 434 435async function deleteKeyItem(keyAlias: string, huksOptions: huks.HuksOptions) { 436 console.info(`promise: enter deleteKeyItem`); 437 try { 438 await huks.deleteKeyItem(keyAlias, huksOptions) 439 .then(() => { 440 console.info(`promise: deleteKeyItem success`); 441 }).catch((error: BusinessError) => { 442 console.error(`promise: deleteKeyItem failed, errCode : ${error.code}, errMsg : ${error.message}`); 443 }) 444 } catch (error) { 445 console.error(`promise: deleteKeyItem input arg invalid`); 446 } 447} 448async function testDerive() { 449 /* 生成密钥 */ 450 await generateKeyItem(srcKeyAlias, huksOptions); 451 /* 进行派生操作 */ 452 await initSession(srcKeyAlias, initOptions); 453 await updateSession(handle, initOptions); 454 await finishSession(handle, finishOptions); 455 await deleteKeyItem(srcKeyAlias, huksOptions); 456} 457```