1 2# 通用密钥库开发指导(ArkTS) 3 4> **说明** 5> 6> 本开发指导需使用API version 9及以上版本SDK。 7 8## 生成新密钥 9 10HUKS提供为业务安全随机生成密钥的能力。通过HUKS生成的密钥,密钥的全生命周期明文不会出安全环境,能保证任何人都无法接触获取到密钥的明文。即使生成密钥的业务自身,后续也只能通过HUKS提供的接口请求执行密钥操作,获取操作结果,但无法接触到密钥自身。 11 12**开发步骤** 13 14生成密钥时使用[huks.generateKeyItem(keyAlias,options,callback)](../reference/apis/js-apis-huks.md#huksgeneratekeyitem9)方法,传入keyAlias作为密钥别名,传入options包含该密钥的属性集,传入callback用于回调异步结果。关于接口的具体信息,可在[API参考文档](../reference/apis/js-apis-huks.md)中查看。 15 161. 确定密钥别名; 172. 初始化密钥属性集:通过[HuksParam](../reference/apis/js-apis-huks.md#huksparam)封装密钥属性,搭配Array组成密钥属性集,并赋值给[HuksOptions](../reference/apis/js-apis-huks.md#huksoptions)(properties字段),其中必须包含[HuksKeyAlg](../reference/apis/js-apis-huks.md#hukskeyalg),[HuksKeySize](../reference/apis/js-apis-huks.md#hukskeysize),[HuksKeyPurpose](../reference/apis/js-apis-huks.md#hukskeypurpose)属性; 183. 将密钥别名与密钥参数集作为参数传入,生成密钥。 19 20> **说明** 21> 22> 存储的 keyAlias 密钥别名最大为64字节 23 24**代码示例:** 25 26```ts 27/* 28 * 以下以生成DH密钥的Callback操作使用为例 29 */ 30import huks from '@ohos.security.huks'; 31import { BusinessError } from '@ohos.base'; 32 33class HuksProperties { 34 tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM; 35 value: huks.HuksKeyAlg | huks.HuksKeySize | huks.HuksKeyPurpose | huks.HuksKeyDigest = huks.HuksKeyAlg.HUKS_ALG_ECC; 36} 37 38/* 39 * 确定密钥别名和封装密钥属性参数集 40 */ 41let keyAlias = 'dh_key'; 42let properties1: HuksProperties[] = [ 43 { 44 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 45 value: huks.HuksKeyAlg.HUKS_ALG_DH 46 }, 47 { 48 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 49 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE 50 }, 51 { 52 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 53 value: huks.HuksKeySize.HUKS_DH_KEY_SIZE_2048 54 }, 55 { 56 tag: huks.HuksTag.HUKS_TAG_DIGEST, 57 value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256 58 } 59]; 60 61let huksOptions: huks.HuksOptions = { 62 properties: properties1, 63 inData: new Uint8Array(new Array()) 64} 65 66/* 67 * 生成密钥 68 */ 69function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions){ 70 return new Promise<void>((resolve, reject) => { 71 try { 72 huks.generateKeyItem(keyAlias, huksOptions, (error, data) => { 73 if (error) { 74 reject(error); 75 } else { 76 resolve(data); 77 } 78 }); 79 } catch (error) { 80 throw (error as Error); 81 } 82 }); 83} 84 85async function publicGenKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 86 console.info(`enter callback generateKeyItem`); 87 try { 88 await generateKeyItem(keyAlias, huksOptions) 89 .then((data) => { 90 console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`); 91 }) 92 .catch((error: BusinessError) => { 93 console.error(`callback: generateKeyItem failed`); 94 }); 95 } catch (error) { 96 console.error(`callback: generateKeyItem input arg invalid`); 97 } 98} 99 100async function TestGenKey() { 101 await publicGenKeyFunc(keyAlias, huksOptions); 102} 103``` 104 105## 导入外部密钥 106 107如果密钥是在HUKS外部生成(比如应用间协商生成、服务器端生成),应用可以将密钥导入到HUKS托管。HUKS支持直接将密钥明文导入到HUKS,但是明文导入会导致密钥暴露在REE内存中,一般适用于轻量级设备或低安业务。对于高安敏感业务,HUKS还提供了安全导入密钥的能力,允许业务自己生成密钥,并通过与处于安全环境中的HUKS建立端到端的加密传输通道,将密钥安全加密导入到HUKS中,确保导入传入过程中密钥不被泄露。 108 109与生成密钥一样,密钥一旦导入到HUKS中,密钥的生命周期明文不出安全环境,同样能保证任何人都无法接触获取到密钥的明文。 110 111### 明文导入 112 113导入明文密钥时使用[huks.importKeyItem(keyAlias,options,callback)](../reference/apis/js-apis-huks.md#huksimportkeyitem9)方法,传入keyAlias作为密钥别名,传入options,其中必须包含密钥材料和密钥属性集,传入callback用于回调异步结果。关于接口的具体信息,可在[API参考文档](../reference/apis/js-apis-huks.md)中查看。 114 1151. 确定密钥别名; 1162. 封装密钥材料和密钥属性集:密钥材料须符合[HUKS密钥材料格式](./huks-appendix.md#密钥材料格式)并以Uint8Array形式赋值给[HuksOptions](../reference/apis/js-apis-huks.md#huksoptions)的inData字段;另外,通过[HuksParam](../reference/apis/js-apis-huks.md#huksparam)封装密钥属性,搭配Array组成密钥属性集赋值给properties字段,属性集中必须包含[HuksKeyAlg](../reference/apis/js-apis-huks.md#hukskeyalg),[HuksKeySize](../reference/apis/js-apis-huks.md#hukskeysize),[HuksKeyPurpose](../reference/apis/js-apis-huks.md#hukskeypurpose)属性; 1173. 导入密钥。 118 119**代码示例:** 120 121```ts 122import huks from '@ohos.security.huks' 123 124/* 125 * 以导入AES256密钥为例 126 */ 127 128/* 密钥 */ 129let plainTextSize32 = new Uint8Array([ 130 0xfb, 0x8b, 0x9f, 0x12, 0xa0, 0x83, 0x19, 0xbe, 0x6a, 0x6f, 0x63, 0x2a, 0x7c, 0x86, 0xba, 0xca, 131 0x64, 0x0b, 0x88, 0x96, 0xe2, 0xfa, 0x77, 0xbc, 0x71, 0xe3, 0x0f, 0x0f, 0x9e, 0x3c, 0xe5, 0xf9 132]); 133 134/* 135 * 确定密钥别名 136 */ 137let keyAlias = 'AES256Alias_sample'; 138 139/* 140 * 封装密钥属性集和密钥材料 141 */ 142class propertyType { 143 tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM; 144 value: huks.HuksKeyAlg | huks.HuksKeySize | huks.HuksKeyPurpose = huks.HuksKeyAlg.HUKS_ALG_RSA; 145} 146 147let properties: propertyType[] = [ 148 { 149 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 150 value:huks.HuksKeyAlg.HUKS_ALG_AES 151 }, 152 { 153 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 154 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 155 }, 156 { 157 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 158 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT 159 }, 160] 161 162let options: huks.HuksOptions = { 163 properties: properties, 164 inData: plainTextSize32 165}; 166 167/* 168 * 导入密钥 169 */ 170try { 171 huks.importKeyItem(keyAlias, options, (error, data) => { 172 if (error) { 173 console.error(`callback: importKeyItem failed`); 174 } else { 175 console.info(`callback: importKeyItem success`); 176 } 177 }); 178} catch (error) { 179 console.error(`callback: importKeyItem input arg invalid`); 180} 181``` 182 183**调测验证** 184 185验证时查询密钥是否存在,如密钥存在即表示生成密钥成功。 186 187**代码示例:** 188 189```ts 190import huks from '@ohos.security.huks'; 191 192let keyAlias = 'AES256Alias_sample'; 193let isKeyExist = false; 194 195class keyPropertyType { 196 tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM; 197 value: huks.HuksKeyAlg = huks.HuksKeyAlg.HUKS_ALG_RSA; 198} 199 200let keyProperties: keyPropertyType[] = [ 201 { 202 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 203 value: huks.HuksKeyAlg.HUKS_ALG_AES 204 }, 205] 206 207let huksOptions: huks.HuksOptions = { 208 properties: keyProperties, // 非空填充 209 inData: new Uint8Array(new Array()) // 非空填充 210} 211try { 212 huks.isKeyItemExist(keyAlias, huksOptions, (error, data) => { 213 if (error) { 214 console.error(`callback: isKeyItemExist failed`); 215 } else { 216 if (data !== null && data.valueOf() !== null) { 217 isKeyExist = data.valueOf(); 218 console.info(`callback: isKeyItemExist success, isKeyExist = ${isKeyExist}`); 219 } 220 } 221 }); 222} catch (error) { 223 console.error(`callback: isKeyItemExist input arg invalid`); 224} 225``` 226 227### 加密导入 228 229相比明文导入,加密导入步骤更多,密钥材料更复杂,此章节将展示开发过程中关键的开发流程和密钥材料数据结构。下图是加密导入的基本开发流程。 230 231**图2** 加密导入开发流程 232 233 234 235**接口说明** 236 237根据开发流程,在导入加密密钥过程中,需要依次调用HUKS的生成密钥、导出公钥、导入加密密钥、删除密钥接口。 238 239关于接口的具体信息,可在[API参考文档](../reference/apis/js-apis-huks.md)中查看。 240 241**表1** 加密导入的接口介绍 242 243| 接口名 | 描述 | 244| -------------------------------------- | ----------------------------| 245|generateKeyItem(keyAlias: string, options: HuksOptions, callback: AsyncCallback\<void>) : void| 生成新密钥| 246|exportKeyItem(keyAlias: string, options: HuksOptions, callback: AsyncCallback\<HuksReturnResult>) : void| 导出密钥对的公钥| 247|importWrappedKeyItem(keyAlias: string, wrappingKeyAlias: string, options: HuksOptions, callback: AsyncCallback\<void>) : void|导入加密密钥| 248|deleteKeyItem(keyAlias: string, options: HuksOptions, callback: AsyncCallback\<void>) : void|删除密钥| 249 250需要注意的是,导出密钥接口返回的公钥明文材料是按照**X.509**格式封装,导入加密密钥接口中的密钥材料需满足**Length<sub>Data</sub>-Data** 的格式封装。具体,应用需要申请一个Uint8Array按照以下表格中的顺序依次封装。 251 252**表2** 加密密钥材料格式 253 254| 内容 | 业务公钥长度L<sub>pk2</sub> | 业务公钥pk2 | k2加密参数AAD2长度L<sub>AAD2</sub> | k2加密参数AAD2 | k2加密参数Nonce2长度L<sub>Nonce2</sub> | k2加密参数Nonce2 | 255| :--: |:----:|:----: |:----: | :----: | :----:|:----:| 256|长度| 4字节 |L<sub>pk2</sub>字节| 4字节 | L<sub>AAD2</sub>字节 | 4字节 | L<sub>Nonce2</sub>字节 | 257| 内容 | k2加密参数AEAD2长度L<sub>AEAD2</sub> | k2加密参数AEAD2 | k3密文长度L<sub>k3_enc</sub> | k3密文k3_enc | k3加密参数AAD3长度L<sub>AAD3</sub> | k3加密参数AAD3 | 258|长度| 4字节 |L<sub>AEAD2</sub>字节| 4字节 | L<sub>k3_enc</sub>字节 | 4字节 | L<sub>AAD3</sub>字节 | 259| 内容| k3加密参数Nonce3长度L<sub>Nonce3</sub> | k3加密参数Nonce3 | k3加密参数AEAD3长度L<sub>AEAD3</sub> | k3加密参数AEAD3 | **密钥明文材料长度** 的长度L<sub>k1'_size</sub> | 密钥明文材料长度k1'_size | 260|长度| 4字节 |L<sub>Nonce3</sub>字节| 4字节 | L<sub>AEAD3</sub>字节 | 4字节 | L<sub>k1'_size</sub>字节 | 261|内容|k1'密文长度L<sub>k1'_enc</sub>| k1'密文k1'_enc| | | | | 262|长度| 4字节 |L<sub>k1'_enc</sub>字节| | | | | 263 264**开发步骤** 265 266这里主要展示涉及调用HUKS的开发样例(使用ECDH密钥协商套件),部分在业务本地执行的步骤不在这里展示详细样例。 267 2681. 生成加密导入用途的密钥Caller_Key和Wrapping_Key 2692. 导出公钥材料 2703. 生成一个对称密钥Caller_Kek 2714. 使用Caller_Key和Wrapping_Key的公钥,协商出Agree_Key 2725. 使用Caller_Kek加密待导入密钥 2736. 使用Agree_Key加密Caller_Kek 2747. 封装加密导入密钥材料 2758. 导入封装的加密密钥材料 2769. 删除用于加密导入的密钥 277 278**代码示例:** 279 280```ts 281import huks from '@ohos.security.huks'; 282import { BusinessError } from '@ohos.base'; 283 284let IV = '0000000000000000'; 285let AAD = "abababababababab"; 286let NONCE = "hahahahahaha"; 287let TAG_SIZE = 16; 288let FILED_LENGTH = 4; 289let importedAes192PlainKey = "The aes192 key to import"; 290let callerAes256Kek = "The is kek to encrypt aes192 key"; 291 292let callerKeyAlias = "test_caller_key_ecdh_aes192"; 293let callerKekAliasAes256 = "test_caller_kek_ecdh_aes256"; 294let callerAgreeKeyAliasAes256 = "test_caller_agree_key_ecdh_aes256"; 295let importedKeyAliasAes192 = "test_import_key_ecdh_aes192"; 296 297let huksPubKey: Uint8Array; 298let callerSelfPublicKey: Uint8Array; 299let outSharedKey: Uint8Array; 300let outPlainKeyEncData: Uint8Array; 301let outKekEncData: Uint8Array; 302let outKekEncTag: Uint8Array; 303let outAgreeKeyEncTag: Uint8Array; 304 305let mask = [0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000]; 306function subUint8ArrayOf(arrayBuf: Uint8Array, start: number, end: number) { 307 let arr: number[] = []; 308 for (let i = start; i < end && i < arrayBuf.length; ++i) { 309 arr.push(arrayBuf[i]); 310 } 311 return new Uint8Array(arr); 312} 313 314function stringToUint8Array(str: string) { 315 let arr: number[] = []; 316 for (let i = 0, j = str.length; i < j; ++i) { 317 arr.push(str.charCodeAt(i)); 318 } 319 return new Uint8Array(arr); 320} 321 322function assignLength(length: number, arrayBuf: Uint8Array, startIndex: number) { 323 let index = startIndex; 324 for (let i = 0; i < 4; i++) { 325 arrayBuf[index++] = (length & mask[i]) >> (i * 8); 326 } 327 return 4; 328} 329 330function assignData(data: Uint8Array, arrayBuf: Uint8Array, startIndex: number) { 331 let index = startIndex; 332 for (let i = 0; i < data.length; i++) { 333 arrayBuf[index++] = data[i]; 334 } 335 return data.length; 336} 337 338 339let genWrappingKeyParams:huks.HuksOptions = { 340 properties: new Array<huks.HuksParam>( 341 { 342 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 343 value: huks.HuksKeyAlg.HUKS_ALG_ECC 344 }, 345 { 346 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 347 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_UNWRAP 348 }, 349 { 350 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 351 value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256 352 }, 353 { 354 tag: huks.HuksTag.HUKS_TAG_PADDING, 355 value: huks.HuksKeyPadding.HUKS_PADDING_NONE 356 } 357 ) 358} 359 360let genCallerEcdhParams:huks.HuksOptions = { 361 properties: new Array<huks.HuksParam>( 362 { 363 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 364 value: huks.HuksKeyAlg.HUKS_ALG_ECC 365 }, 366 { 367 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 368 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE 369 }, 370 { 371 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 372 value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256 373 } 374 ) 375} 376 377let importParamsCallerKek: huks.HuksOptions = { 378 properties: new Array<huks.HuksParam>( 379 { 380 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 381 value: huks.HuksKeyAlg.HUKS_ALG_AES 382 }, 383 { 384 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 385 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT 386 }, 387 { 388 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 389 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 390 }, 391 { 392 tag: huks.HuksTag.HUKS_TAG_PADDING, 393 value: huks.HuksKeyPadding.HUKS_PADDING_NONE 394 }, 395 { 396 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 397 value: huks.HuksCipherMode.HUKS_MODE_GCM 398 }, 399 { 400 tag: huks.HuksTag.HUKS_TAG_DIGEST, 401 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE 402 }, 403 { 404 tag: huks.HuksTag.HUKS_TAG_IV, 405 value: stringToUint8Array(IV) 406 } 407 ), 408 inData: stringToUint8Array(callerAes256Kek) 409} 410 411let importParamsAgreeKey: huks.HuksOptions = { 412 properties: new Array<huks.HuksParam>( 413 { 414 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 415 value: huks.HuksKeyAlg.HUKS_ALG_AES 416 }, 417 { 418 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 419 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT 420 }, 421 { 422 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 423 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 424 }, 425 { 426 tag: huks.HuksTag.HUKS_TAG_PADDING, 427 value: huks.HuksKeyPadding.HUKS_PADDING_NONE 428 }, 429 { 430 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 431 value: huks.HuksCipherMode.HUKS_MODE_GCM 432 }, 433 { 434 tag: huks.HuksTag.HUKS_TAG_DIGEST, 435 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE 436 }, 437 { 438 tag: huks.HuksTag.HUKS_TAG_IV, 439 value: stringToUint8Array(IV) 440 } 441 ), 442} 443 444let callerAgreeParams: huks.HuksOptions = { 445 properties: new Array<huks.HuksParam>( 446 { 447 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 448 value: huks.HuksKeyAlg.HUKS_ALG_ECDH 449 }, 450 { 451 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 452 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE 453 }, 454 { 455 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 456 value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256 457 } 458 ) 459} 460 461let encryptKeyCommonParams: huks.HuksOptions = { 462 properties: new Array<huks.HuksParam>( 463 { 464 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 465 value: huks.HuksKeyAlg.HUKS_ALG_AES 466 }, 467 { 468 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 469 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT 470 }, 471 { 472 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 473 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256 474 }, 475 { 476 tag: huks.HuksTag.HUKS_TAG_PADDING, 477 value: huks.HuksKeyPadding.HUKS_PADDING_NONE 478 }, 479 { 480 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 481 value: huks.HuksCipherMode.HUKS_MODE_GCM 482 }, 483 { 484 tag: huks.HuksTag.HUKS_TAG_NONCE, 485 value: stringToUint8Array(NONCE) 486 }, 487 { 488 tag: huks.HuksTag.HUKS_TAG_ASSOCIATED_DATA, 489 value: stringToUint8Array(AAD) 490 } 491 ), 492} 493 494let importWrappedAes192Params: huks.HuksOptions = { 495 properties: new Array<huks.HuksParam>( 496 { 497 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 498 value: huks.HuksKeyAlg.HUKS_ALG_AES 499 }, 500 { 501 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 502 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | 503 huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT 504 }, 505 { 506 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 507 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_192 508 }, 509 { 510 tag: huks.HuksTag.HUKS_TAG_PADDING, 511 value: huks.HuksKeyPadding.HUKS_PADDING_NONE 512 }, 513 { 514 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 515 value: huks.HuksCipherMode.HUKS_MODE_CBC 516 }, 517 { 518 tag: huks.HuksTag.HUKS_TAG_DIGEST, 519 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE 520 }, 521 { 522 tag: huks.HuksTag.HUKS_TAG_UNWRAP_ALGORITHM_SUITE, 523 value: huks.HuksUnwrapSuite.HUKS_UNWRAP_SUITE_ECDH_AES_256_GCM_NOPADDING 524 }, 525 { 526 tag: huks.HuksTag.HUKS_TAG_IV, 527 value: stringToUint8Array(IV) 528 } 529 ) 530} 531 532async function publicGenerateItemFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 533 console.info(`enter promise generateKeyItem`); 534 try { 535 await huks.generateKeyItem(keyAlias, huksOptions) 536 .then(data => { 537 console.info(`promise: generateKeyItem success, data = ${JSON.stringify(data)}`); 538 }) 539 .catch((err: BusinessError) => { 540 console.error(`callback: generateKeyItem failed`); 541 }) 542 } catch (err) { 543 console.error(`callback: generateKeyItem invalid`); 544 } 545} 546 547async function publicImportKeyItemFunc(keyAlias: string, HuksOptions: huks.HuksOptions) { 548 console.info(`enter promise importKeyItem`); 549 try { 550 await huks.importKeyItem(keyAlias, HuksOptions) 551 .then(data => { 552 console.info(`promise: importKeyItem success, data = ${JSON.stringify(data)}`); 553 }).catch((err: BusinessError) => { 554 console.error(`promise: importKeyItem failed`); 555 }) 556 } catch (err) { 557 console.error(`promise: importKeyItem input arg invalid`); 558 } 559} 560 561async function publicDeleteKeyItemFunc(KeyAlias: string, HuksOptions: huks.HuksOptions) { 562 console.info(`enter promise deleteKeyItem`); 563 try { 564 await huks.deleteKeyItem(KeyAlias, HuksOptions) 565 .then(data => { 566 console.info(`promise: deleteKeyItem key success, data = ${JSON.stringify(data)}`); 567 }) 568 .catch((err: BusinessError) => { 569 console.error(`promise: deleteKeyItem failed`); 570 }) 571 } catch (err) { 572 console.error(`promise: deleteKeyItem input arg invalid`); 573 } 574} 575 576function importWrappedKeyItem(keyAlias: string, wrappingKeyAlias: string, huksOptions: huks.HuksOptions) { 577 return new Promise<void>((resolve, reject) => { 578 try { 579 huks.importWrappedKeyItem(keyAlias, wrappingKeyAlias, huksOptions, (error, data) => { 580 if (error) { 581 reject(error); 582 } else { 583 resolve(data); 584 } 585 }); 586 } catch (error) { 587 } 588 }); 589} 590 591async function publicImportWrappedKeyFunc(keyAlias: string, wrappingKeyAlias: string, huksOptions: huks.HuksOptions) { 592 console.info(`enter callback importWrappedKeyItem`); 593 for (let i = 0; i < huksOptions.inData!.length; i++) { 594 console.error(`${i}: ${huksOptions.inData![i]}`); 595 } 596 try { 597 await importWrappedKeyItem(keyAlias, wrappingKeyAlias, huksOptions) 598 .then((data) => { 599 console.info(`callback: importWrappedKeyItem success, data = ${JSON.stringify(data)}`); 600 }) 601 .catch((error: BusinessError) => { 602 console.error(`callback: importWrappedKeyItem failed`); 603 }); 604 } catch (error) { 605 console.error(`callback: importWrappedKeyItem input arg invalid`); 606 } 607} 608 609async function publicImportWrappedKeyPromise(keyAlias: string, wrappingKeyAlias: string, huksOptions: huks.HuksOptions) { 610 console.info(`enter callback importWrappedKeyItem`); 611 try { 612 await huks.importWrappedKeyItem(keyAlias, wrappingKeyAlias, huksOptions) 613 .then((data) => { 614 console.info(`callback: importWrappedKeyItem success, data = ${JSON.stringify(data)}`); 615 }) 616 .catch((error: BusinessError) => { 617 console.error(`callback: importWrappedKeyItem failed`); 618 }); 619 } catch (error) { 620 console.error(`callback: importWrappedKeyItem input arg invalid`); 621 } 622} 623 624async function publicInitFunc(srcKeyAlias: string, HuksOptions: huks.HuksOptions) { 625 let handle: number = 0; 626 console.info(`enter promise doInit`); 627 try { 628 await huks.initSession(srcKeyAlias, HuksOptions) 629 .then((data) => { 630 console.info(`promise: doInit success, data = ${JSON.stringify(data)}`); 631 handle = data.handle; 632 }) 633 .catch((error: BusinessError) => { 634 console.error(`promise: doInit key failed`); 635 }); 636 } catch (error) { 637 console.error(`promise: doInit input arg invalid`); 638 } 639 return handle; 640} 641 642async function publicUpdateSessionFunction(handle: number, HuksOptions: huks.HuksOptions) { 643 const maxUpdateSize = 64; 644 const inData = HuksOptions.inData!; 645 const lastInDataPosition = inData.length - 1; 646 let inDataSegSize = maxUpdateSize; 647 let inDataSegPosition = 0; 648 let isFinished = false; 649 let outData: number[] = []; 650 651 while (inDataSegPosition <= lastInDataPosition) { 652 if (inDataSegPosition + maxUpdateSize > lastInDataPosition) { 653 isFinished = true; 654 inDataSegSize = lastInDataPosition - inDataSegPosition + 1; 655 console.error(`enter promise doUpdate`); 656 break; 657 } 658 HuksOptions.inData = new Uint8Array( 659 Array.from(inData).slice(inDataSegPosition, inDataSegPosition + inDataSegSize) 660 ); 661 console.error(`enter promise doUpdate`); 662 try { 663 await huks.updateSession(handle, HuksOptions) 664 .then((data) => { 665 console.error(`promise: doUpdate success, data = ${JSON.stringify(data)}`); 666 outData = outData.concat(Array.from(data.outData!)); 667 }) 668 .catch((error: BusinessError) => { 669 console.error(`promise: doUpdate failed`); 670 }); 671 } catch (error) { 672 console.error(`promise: doUpdate input arg invalid`); 673 } 674 if ((!isFinished) && (inDataSegPosition + maxUpdateSize > lastInDataPosition)) { 675 console.log(`update size invalid isFinished = ${isFinished}`); 676 console.log(`inDataSegPosition = ${inDataSegPosition}`); 677 console.log(`lastInDataPosition = ${lastInDataPosition}`); 678 return; 679 } 680 inDataSegPosition += maxUpdateSize; 681 } 682 return outData; 683} 684 685async function publicFinishSession(handle: number, HuksOptions: huks.HuksOptions, inData: number[]) { 686 let outData: number[] = []; 687 console.info(`enter promise doFinish`); 688 try { 689 await huks.finishSession(handle, HuksOptions) 690 .then((data) => { 691 console.info(`promise: doFinish success, data = ${JSON.stringify(data)}`); 692 outData = inData.concat(Array.from(data.outData!)); 693 }) 694 .catch((error: BusinessError) => { 695 console.error(`promise: doFinish key failed`); 696 }); 697 } catch (error) { 698 console.error(`promise: doFinish input arg invalid`); 699 } 700 return new Uint8Array(outData); 701} 702 703async function cipherFunction(keyAlias: string, HuksOptions: huks.HuksOptions) { 704 let handle = await publicInitFunc(keyAlias, HuksOptions); 705 let tmpData = await publicUpdateSessionFunction(handle, HuksOptions); 706 let outData = await publicFinishSession(handle, HuksOptions, tmpData!); 707 return outData; 708} 709 710async function agreeFunction(keyAlias: string, HuksOptions: huks.HuksOptions, huksPublicKey: Uint8Array) { 711 let handle = await publicInitFunc(keyAlias, HuksOptions); 712 let outSharedKey: Uint8Array = new Uint8Array; 713 HuksOptions.inData = huksPublicKey; 714 console.error(`enter promise doUpdate`); 715 try { 716 await huks.updateSession(handle, HuksOptions) 717 .then((data) => { 718 console.error(`promise: doUpdate success, data = ${JSON.stringify(data)}`); 719 }) 720 .catch((error: BusinessError) => { 721 console.error(`promise: doUpdate failed`); 722 }); 723 } catch (error) { 724 console.error(`promise: doUpdate input arg invalid`); 725 } 726 console.info(`enter promise doInit`); 727 try { 728 await huks.finishSession(handle, HuksOptions) 729 .then((data) => { 730 console.info(`promise: doInit success, data = ${JSON.stringify(data)}`); 731 outSharedKey = data.outData as Uint8Array; 732 }) 733 .catch((error: BusinessError) => { 734 console.error(`promise: doInit key failed`); 735 }); 736 } catch (error) { 737 console.error(`promise: doInit input arg invalid`); 738 } 739 return outSharedKey; 740} 741 742async function ImportKekAndAgreeSharedSecret(callerKekAlias: string, importKekParams: huks.HuksOptions, callerKeyAlias: string, huksPublicKey: Uint8Array, agreeParams: huks.HuksOptions) { 743 await publicImportKeyItemFunc(callerKekAlias, importKekParams); 744 outSharedKey = await agreeFunction(callerKeyAlias, agreeParams, huksPublicKey); 745 746 importParamsAgreeKey.inData = outSharedKey; 747 await publicImportKeyItemFunc(callerAgreeKeyAliasAes256, importParamsAgreeKey); 748} 749 750async function generateAndExportPublicKey(keyAlias: string, HuksOptions: huks.HuksOptions, caller: Boolean) { 751 await publicGenerateItemFunc(keyAlias, HuksOptions); 752 try { 753 await huks.exportKeyItem(keyAlias, HuksOptions) 754 .then((data) => { 755 console.info(`promise: exportKeyItem success, data = ${JSON.stringify(data)}`); 756 if (caller) { 757 callerSelfPublicKey = data.outData as Uint8Array; 758 } else { 759 huksPubKey = data.outData as Uint8Array; 760 } 761 }) 762 .catch((error: BusinessError) => { 763 console.error(`promise: exportKeyItem failed`); 764 }); 765 } catch (e) { 766 console.error(`promise: generate pubKey failed`); 767 } 768} 769 770async function EncryptImportedPlainKeyAndKek(keyAlias: string) { 771 encryptKeyCommonParams.inData = stringToUint8Array(keyAlias) 772 let plainKeyEncData = await cipherFunction(callerKekAliasAes256, encryptKeyCommonParams); 773 outKekEncTag = subUint8ArrayOf(plainKeyEncData, plainKeyEncData.length - TAG_SIZE, plainKeyEncData.length) 774 outPlainKeyEncData = subUint8ArrayOf(plainKeyEncData, 0, plainKeyEncData.length - TAG_SIZE) 775 776 encryptKeyCommonParams.inData = stringToUint8Array(callerAes256Kek) 777 let kekEncData = await cipherFunction(callerAgreeKeyAliasAes256, encryptKeyCommonParams) 778 outAgreeKeyEncTag = subUint8ArrayOf(kekEncData, kekEncData.length - TAG_SIZE, kekEncData.length) 779 outKekEncData = subUint8ArrayOf(kekEncData, 0, kekEncData.length - TAG_SIZE) 780} 781 782async function BuildWrappedDataAndImportWrappedKey(plainKey: string) { 783 let plainKeySizeBuff = new Uint8Array(4); 784 assignLength(plainKey.length, plainKeySizeBuff, 0); 785 786 let wrappedData = new Uint8Array( 787 FILED_LENGTH + huksPubKey.length + 788 FILED_LENGTH + AAD.length + 789 FILED_LENGTH + NONCE.length + 790 FILED_LENGTH + TAG_SIZE + 791 FILED_LENGTH + outKekEncData.length + 792 FILED_LENGTH + AAD.length + 793 FILED_LENGTH + NONCE.length + 794 FILED_LENGTH + TAG_SIZE + 795 FILED_LENGTH + plainKeySizeBuff.length + 796 FILED_LENGTH + outPlainKeyEncData.length 797 ); 798 let index = 0; 799 let AADUint8Array = stringToUint8Array(AAD); 800 let NonceArray = stringToUint8Array(NONCE); 801 802 index += assignLength(callerSelfPublicKey.length, wrappedData, index); // 4 803 index += assignData(callerSelfPublicKey, wrappedData, index); // 91 804 index += assignLength(AADUint8Array.length, wrappedData, index); // 4 805 index += assignData(AADUint8Array, wrappedData, index); // 16 806 index += assignLength(NonceArray.length, wrappedData, index); // 4 807 index += assignData(NonceArray, wrappedData, index); // 12 808 index += assignLength(outAgreeKeyEncTag.length, wrappedData, index); // 4 809 index += assignData(outAgreeKeyEncTag, wrappedData, index); // 16 810 index += assignLength(outKekEncData.length, wrappedData, index); // 4 811 index += assignData(outKekEncData, wrappedData, index); // 32 812 index += assignLength(AADUint8Array.length, wrappedData, index); // 4 813 index += assignData(AADUint8Array, wrappedData, index); // 16 814 index += assignLength(NonceArray.length, wrappedData, index); // 4 815 index += assignData(NonceArray, wrappedData, index); // 12 816 index += assignLength(outKekEncTag.length, wrappedData, index); // 4 817 index += assignData(outKekEncTag, wrappedData, index); // 16 818 index += assignLength(plainKeySizeBuff.length, wrappedData, index); // 4 819 index += assignData(plainKeySizeBuff, wrappedData, index); // 4 820 index += assignLength(outPlainKeyEncData.length, wrappedData, index); // 4 821 index += assignData(outPlainKeyEncData, wrappedData, index); // 24 822 823 return wrappedData; 824} 825 826async function ImportWrappedKey() { 827 const srcKeyAliesWrap = 'HUKS_Basic_Capability_Import_0200'; 828 /* 829 * 生成、导出加密导入用途的、用于协商的密钥密钥Caller_Key和Wrapping_Key 830 */ 831 await generateAndExportPublicKey(srcKeyAliesWrap, genWrappingKeyParams, false); 832 await generateAndExportPublicKey(callerKeyAlias, genCallerEcdhParams, true); 833 834 /** 835 * 生成一个对称密钥Caller_Kek 836 * 使用Caller_Key和Wrapping_Key的公钥,协商出Agree_Key 837 */ 838 await ImportKekAndAgreeSharedSecret(callerKekAliasAes256, importParamsCallerKek, callerKeyAlias, huksPubKey, callerAgreeParams); 839 840 /** 841 * 使用Caller_Kek加密待导入密钥 842 * 使用Agree_Key加密Caller_Kek 843 */ 844 await EncryptImportedPlainKeyAndKek(importedAes192PlainKey); 845 846 /** 847 * 封装加密导入的材料 848 */ 849 let wrappedData = await BuildWrappedDataAndImportWrappedKey(importedAes192PlainKey); 850 importWrappedAes192Params.inData = wrappedData; 851 852 /** 853 * 导入封装的加密密钥材料 854 */ 855 await publicImportWrappedKeyFunc(importedKeyAliasAes192, srcKeyAliesWrap, importWrappedAes192Params); 856 857 /** 858 * 删除用于加密导入的密钥 859 */ 860 await publicDeleteKeyItemFunc(srcKeyAliesWrap, genWrappingKeyParams); 861 await publicDeleteKeyItemFunc(callerKeyAlias, genCallerEcdhParams); 862 await publicDeleteKeyItemFunc(importedKeyAliasAes192, importWrappedAes192Params); 863 await publicDeleteKeyItemFunc(callerKekAliasAes256, callerAgreeParams); 864} 865``` 866 867**调测验证** 868 869验证时查询密钥是否存在,如密钥存在即表示生成密钥成功。 870 871**代码示例:** 872 873```ts 874import huks from '@ohos.security.huks'; 875 876/* 877 * 确定密钥别名和封装密钥属性参数集 878 */ 879let keyAlias = 'test_import_key_ecdh_aes192'; 880let isKeyExist:Boolean; 881 882let keyProperties: Array<huks.HuksParam> = new Array(); 883keyProperties[0] = { 884 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 885 value: huks.HuksKeyAlg.HUKS_ALG_AES, 886} 887let huksOptions:huks.HuksOptions = { 888 properties: keyProperties, // 非空填充 889 inData: new Uint8Array(new Array()) // 非空填充 890} 891try { 892 huks.isKeyItemExist(keyAlias, huksOptions, (error, data)=> { 893 if (error) { 894 console.error(`callback: isKeyItemExist failed`); 895 } else { 896 if (data !== null && data.valueOf() !== null) { 897 isKeyExist = data.valueOf(); 898 console.info(`callback: isKeyItemExist success, isKeyExist = ${isKeyExist}`); 899 } 900 } 901 }); 902} catch (error) { 903 console.error(`callback: isKeyItemExist input arg invalid`); 904} 905``` 906 907## 常见密钥操作 908 909**场景概述** 910 911为了实现对数据机密性、完整性等保护,在生成/导入密钥后,需要对数据进行密钥操作,比如加密解密、签名验签、密钥协商、密钥派生等,本章节提供了常用的密钥操作的示例。本章节提供的示例都没有设置二次身份访问控制,如设置了密钥访问控制请参考[密钥访问控制](#密钥访问控制)用法。 912 913**通用开发流程** 914 915HUKS基于密钥会话来操作数据,使用密钥时基于以下流程: 916 9171. **初始化密钥会话[huks.initSession()](../reference/apis/js-apis-huks.md#huksinitsession9):** 传入密钥别名和密钥操作参数,初始化一个密钥会话并获取会话句柄。其中密钥操作参数中必须包含对应密码算法所必须的参数,包括密码算法、密钥大小、密钥目的、工作模式、填充模式、散列模式、IV、Nonce、AAD等。如果密钥设置了访问控制属性,还需要其他参数具体[密钥访问控制](#密钥访问控制)。此步骤必选! 9182. **分段操作数据[huks.updateSession()](../reference/apis/js-apis-huks.md#huksupdatesession9):** 如数据过大(超过100K)或密码算法的要求需要对数据进行分段操作,反之可跳过此步。此步骤可选! 9193. **结束密钥会话[huks.finishSession()](../reference/apis/js-apis-huks.md#huksfinishsession9):** 操作最后一段数据并结束密钥会话,如过程中发生错误或不需要此次密钥操作数据,必须取消会话[huks.abortSession()](../reference/apis/js-apis-huks.md#huksabortsession9)。此步骤必选! 920 921### 加密解密 922 923```ts 924/* 925 * 以下以AES 128密钥的Callback操作使用为例 926 */ 927import huks from '@ohos.security.huks'; 928import { BusinessError } from '@ohos.base'; 929 930let aesKeyAlias = 'test_aesKeyAlias'; 931let handle:number; 932let plainText = '123456'; 933let IV = '001122334455'; 934let cipherData:Uint8Array; 935 936function StringToUint8Array(str: String) { 937 let arr:number[]=new Array(); 938 for (let i = 0, j = str.length; i < j; ++i) { 939 arr.push(str.charCodeAt(i)); 940 } 941 return new Uint8Array(arr); 942} 943 944function Uint8ArrayToString(fileData:Uint8Array) { 945 let dataString = ''; 946 for (let i = 0; i < fileData.length; i++) { 947 dataString += String.fromCharCode(fileData[i]); 948 } 949 return dataString; 950} 951 952function GetAesGenerateProperties() { 953 let properties: Array<huks.HuksParam> = new Array(); 954 let index = 0; 955 properties[index++] = { 956 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 957 value: huks.HuksKeyAlg.HUKS_ALG_AES 958 }; 959 properties[index++] = { 960 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 961 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_128 962 }; 963 properties[index++] = { 964 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 965 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | 966 huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT 967 } 968 return properties; 969} 970 971function GetAesEncryptProperties() { 972 let properties: Array<huks.HuksParam> = new Array(); 973 let index = 0; 974 properties[index++] = { 975 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 976 value: huks.HuksKeyAlg.HUKS_ALG_AES 977 }; 978 properties[index++] = { 979 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 980 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_128 981 }; 982 properties[index++] = { 983 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 984 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT 985 } 986 properties[index++] = { 987 tag: huks.HuksTag.HUKS_TAG_PADDING, 988 value: huks.HuksKeyPadding.HUKS_PADDING_PKCS7 989 } 990 properties[index++] = { 991 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 992 value: huks.HuksCipherMode.HUKS_MODE_CBC 993 } 994 properties[index++] = { 995 tag: huks.HuksTag.HUKS_TAG_IV, 996 value: StringToUint8Array(IV) 997 } 998 return properties; 999} 1000 1001function GetAesDecryptProperties() { 1002 let properties: Array<huks.HuksParam> = new Array(); 1003 let index = 0; 1004 properties[index++] = { 1005 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 1006 value: huks.HuksKeyAlg.HUKS_ALG_AES 1007 }; 1008 properties[index++] = { 1009 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 1010 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_128 1011 }; 1012 properties[index++] = { 1013 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 1014 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT 1015 } 1016 properties[index++] = { 1017 tag: huks.HuksTag.HUKS_TAG_PADDING, 1018 value: huks.HuksKeyPadding.HUKS_PADDING_PKCS7 1019 } 1020 properties[index++] = { 1021 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 1022 value: huks.HuksCipherMode.HUKS_MODE_CBC 1023 } 1024 properties[index++] = { 1025 tag: huks.HuksTag.HUKS_TAG_IV, 1026 value: StringToUint8Array(IV) 1027 } 1028 return properties; 1029} 1030 1031async function GenerateAesKey() { 1032 let genProperties = GetAesGenerateProperties(); 1033 let options: huks.HuksOptions = { 1034 properties: genProperties 1035 } 1036 await huks.generateKeyItem(aesKeyAlias, options) 1037 .then((data) => { 1038 console.info(`callback: generate AES Key success, data = ${JSON.stringify(data)}`); 1039 }).catch((error: BusinessError)=>{ 1040 console.error(`callback: generate AES Key failed`); 1041 }) 1042} 1043 1044 1045async function EncryptData() { 1046 let encryptProperties = GetAesEncryptProperties(); 1047 let options: huks.HuksOptions = { 1048 properties: encryptProperties, 1049 inData: StringToUint8Array(plainText) 1050 } 1051 await huks.initSession(aesKeyAlias, options) 1052 .then((data) => { 1053 handle = data.handle; 1054 }).catch((error: BusinessError)=>{ 1055 console.error(`callback: init encryptdata failed`); 1056 }) 1057 await huks.finishSession(handle, options) 1058 .then((data) => { 1059 console.info(`callback: encrypt data success, data is `+ Uint8ArrayToString(data.outData as Uint8Array)); 1060 cipherData = data.outData as Uint8Array; 1061 }).catch((error: BusinessError)=>{ 1062 console.error(`callback: encrypt data failed`); 1063 }) 1064} 1065 1066async function DecryptData() { 1067 let decryptOptions = GetAesDecryptProperties() 1068 let options: huks.HuksOptions = { 1069 properties: decryptOptions, 1070 inData: cipherData 1071 } 1072 await huks.initSession(aesKeyAlias, options) 1073 .then((data) => { 1074 handle = data.handle; 1075 }).catch((error: BusinessError)=>{ 1076 console.error(`callback: init decryptdata failed`); 1077 }) 1078 await huks.finishSession(handle, options) 1079 .then((data) => { 1080 console.info(`callback: decrypt data success, data is ` + Uint8ArrayToString(data.outData as Uint8Array)); 1081 }).catch((error: BusinessError)=>{ 1082 console.error(`callback: decrypt data failed`); 1083 }) 1084} 1085 1086async function DeleteKey() { 1087 let emptyOptions: huks.HuksOptions = { 1088 properties: [] 1089 } 1090 await huks.deleteKeyItem(aesKeyAlias, emptyOptions) 1091 .then((data) => { 1092 console.info(`callback: delete data success`); 1093 }).catch((error: BusinessError)=>{ 1094 console.error(`callback: delete data failed`); 1095 }) 1096} 1097``` 1098 1099### 密钥协商 1100 1101应用在协商密钥时建议传入[HuksKeyStorageType](../reference/apis/js-apis-huks.md#hukskeystoragetype)中定义的类型;从API10开始应用只能选择存储(HUKS_STORAGE_ONLY_USED_IN_HUKS),或者选择导出(HUKS_STORAGE_KEY_EXPORT_ALLOWED),若不传入,则默认同时支持存储和导出,存在安全问题,不推荐业务使用。 1102 1103```ts 1104/* 1105 * 以下以X25519 256 TEMP密钥的Callback操作使用为例 1106 */ 1107import huks from '@ohos.security.huks'; 1108import { BusinessError } from '@ohos.base'; 1109 1110/* 1111 * 确定密钥别名和封装密钥属性参数集 1112 */ 1113let srcKeyAliasFirst = "AgreeX25519KeyFirstAlias"; 1114let srcKeyAliasSecond = "AgreeX25519KeySecondAlias"; 1115let agreeX25519InData = 'AgreeX25519TestIndata'; 1116let finishOutData : Uint8Array; 1117let handle: number; 1118let exportKey : Uint8Array; 1119let exportKeyFrist: Uint8Array; 1120let exportKeySecond : Uint8Array; 1121 1122/* 集成生成密钥参数集 */ 1123let properties : Array<huks.HuksParam> = new Array(); 1124properties[0] = { 1125 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 1126 value: huks.HuksKeyAlg.HUKS_ALG_X25519, 1127} 1128properties[1] = { 1129 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 1130 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE, 1131} 1132properties[2] = { 1133 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 1134 value: huks.HuksKeySize.HUKS_CURVE25519_KEY_SIZE_256, 1135} 1136properties[3] = { 1137 tag: huks.HuksTag.HUKS_TAG_DIGEST, 1138 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE, 1139} 1140properties[4] = { 1141 tag: huks.HuksTag.HUKS_TAG_PADDING, 1142 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 1143} 1144properties[5] = { 1145 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 1146 value: huks.HuksCipherMode.HUKS_MODE_CBC, 1147} 1148properties[6] = { 1149 tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, 1150 value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS, 1151} 1152let HuksOptions : huks.HuksOptions = { 1153 properties: properties, 1154 inData: new Uint8Array(new Array()) 1155} 1156 1157/* 集成第一个协商参数集 */ 1158let finishProperties : Array<huks.HuksParam> = new Array(); 1159finishProperties[0] = { 1160 tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, 1161 value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS, 1162} 1163finishProperties[1] = { 1164 tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS, 1165 value: true 1166} 1167finishProperties[2] = { 1168 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 1169 value: huks.HuksKeyAlg.HUKS_ALG_AES, 1170} 1171finishProperties[3] = { 1172 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 1173 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256, 1174} 1175finishProperties[4] = { 1176 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 1177 value: 1178 huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | 1179 huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT, 1180} 1181finishProperties[5] = { 1182 tag: huks.HuksTag.HUKS_TAG_DIGEST, 1183 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE, 1184} 1185finishProperties[6] = { 1186 tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS, 1187 value: StringToUint8Array(srcKeyAliasFirst+ 'final'), 1188} 1189finishProperties[7] = { 1190 tag: huks.HuksTag.HUKS_TAG_PADDING, 1191 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 1192} 1193finishProperties[8] = { 1194 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 1195 value: huks.HuksCipherMode.HUKS_MODE_ECB, 1196} 1197let finishOptionsFrist : huks.HuksOptions = { 1198 properties: finishProperties, 1199 inData: StringToUint8Array(agreeX25519InData) 1200} 1201/* 集成第二个协商参数集 */ 1202let finishOptionsSecond : huks.HuksOptions = { 1203 properties: finishProperties, 1204 inData: StringToUint8Array(agreeX25519InData) 1205} 1206finishOptionsSecond.properties!.splice(6, 1, { 1207 tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS, 1208 value: StringToUint8Array(srcKeyAliasSecond + 'final'), 1209}) 1210 1211function StringToUint8Array(str:string) { 1212 let arr: number[] = new Array(); 1213 for (let i = 0, j = str.length; i < j; ++i) { 1214 arr.push(str.charCodeAt(i)); 1215 } 1216return new Uint8Array(arr); 1217} 1218class throwObject { 1219 isThrow: boolean = false 1220} 1221function generateKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1222 return new Promise<void>((resolve, reject) => { 1223 try { 1224 huks.generateKeyItem(keyAlias, huksOptions, (error, data) => { 1225 if (error) { 1226 reject(error); 1227 } else { 1228 resolve(data); 1229 } 1230 }); 1231 } catch (error) { 1232 throwObject.isThrow = true; 1233 throw(error as Error); 1234 } 1235 }); 1236} 1237 1238async function publicGenKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) { 1239 console.info(`enter callback generateKeyItem`); 1240 let throwObject :throwObject = {isThrow: false}; 1241 try { 1242 await generateKeyItem(keyAlias, huksOptions, throwObject) 1243 .then((data) => { 1244 console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`); 1245 }) 1246 .catch((error : BusinessError) => { 1247 if (throwObject.isThrow) { 1248 throw(error as Error); 1249 } else { 1250 console.error(`callback: generateKeyItem failed`); 1251 } 1252 }); 1253 } catch (error) { 1254 console.error(`callback: generateKeyItem input arg invalid`); 1255 } 1256} 1257 1258function initSession(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1259 return new Promise<huks.HuksSessionHandle>((resolve, reject) => { 1260 try { 1261 huks.initSession(keyAlias, huksOptions, (error, data) => { 1262 if (error) { 1263 reject(error); 1264 } else { 1265 resolve(data); 1266 } 1267 }); 1268 } catch (error) { 1269 throwObject.isThrow = true; 1270 throw(error as Error); 1271 } 1272 }); 1273} 1274 1275async function publicInitFunc(keyAlias:string, huksOptions:huks.HuksOptions) { 1276 console.info(`enter callback doInit`); 1277 let throwObject:throwObject = {isThrow: false}; 1278 try { 1279 await initSession(keyAlias, huksOptions, throwObject) 1280 .then ((data) => { 1281 console.info(`callback: doInit success, data = ${JSON.stringify(data)}`); 1282 handle = data.handle; 1283 }) 1284 .catch((error : BusinessError) => { 1285 if (throwObject.isThrow) { 1286 throw(error as Error); 1287 } else { 1288 console.error(`callback: doInit failed`); 1289 } 1290 }); 1291 } catch (error) { 1292 console.error(`callback: doInit input arg invalid`); 1293 } 1294} 1295 1296function updateSession(handle:number, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1297 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 1298 try { 1299 huks.updateSession(handle, huksOptions, (error, data) => { 1300 if (error) { 1301 reject(error); 1302 } else { 1303 resolve(data); 1304 } 1305 }); 1306 } catch (error) { 1307 throwObject.isThrow = true; 1308 throw(error as Error); 1309 } 1310 }); 1311} 1312 1313async function publicUpdateFunc(handle:number, huksOptions:huks.HuksOptions) { 1314 console.info(`enter callback doUpdate`); 1315 let throwObject:throwObject = {isThrow: false}; 1316 try { 1317 await updateSession(handle, huksOptions, throwObject) 1318 .then ((data) => { 1319 console.info(`callback: doUpdate success, data = ${JSON.stringify(data)}`); 1320 }) 1321 .catch((error : BusinessError) => { 1322 if (throwObject.isThrow) { 1323 throw(error as Error); 1324 } else { 1325 console.error(`callback: doUpdate failed`); 1326 } 1327 }); 1328 } catch (error) { 1329 console.error(`callback: doUpdate input arg invalid`); 1330 } 1331} 1332 1333function finishSession(handle:number, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1334 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 1335 try { 1336 huks.finishSession(handle, huksOptions, (error, data) =>{ 1337 if (error) { 1338 reject(error); 1339 } else { 1340 resolve(data); 1341 } 1342 }); 1343 } catch (error) { 1344 throwObject.isThrow = true; 1345 throw(error as Error); 1346 } 1347 }); 1348} 1349 1350async function publicFinishFunc(handle:number, huksOptions:huks.HuksOptions) { 1351 console.info(`enter callback doFinish`); 1352 let throwObject:throwObject = {isThrow: false}; 1353 try { 1354 await finishSession(handle, huksOptions, throwObject) 1355 .then ((data) => { 1356 finishOutData = data.outData as Uint8Array; 1357 console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`); 1358 }) 1359 .catch((error : BusinessError) => { 1360 if (throwObject.isThrow) { 1361 throw(error as Error); 1362 } else { 1363 console.error(`callback: doFinish failed`); 1364 } 1365 }); 1366 } catch (error) { 1367 console.error(`callback: doFinish input arg invalid`); 1368 } 1369} 1370 1371function exportKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1372 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 1373 try { 1374 huks.exportKeyItem(keyAlias, huksOptions, (error, data) => { 1375 if (error) { 1376 reject(error); 1377 } else { 1378 resolve(data); 1379 } 1380 }); 1381 } catch (error) { 1382 throwObject.isThrow = true; 1383 throw(error as Error); 1384 } 1385 }); 1386} 1387 1388async function publicExportKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) { 1389 console.info(`enter callback export`); 1390 let throwObject:throwObject = {isThrow: false}; 1391 try { 1392 await exportKeyItem(keyAlias, huksOptions, throwObject) 1393 .then ((data) => { 1394 console.info(`callback: exportKeyItem success, data = ${JSON.stringify(data)}`); 1395 exportKey = data.outData as Uint8Array; 1396 }) 1397 .catch((error : BusinessError) => { 1398 if (throwObject.isThrow) { 1399 throw(error as Error); 1400 } else { 1401 console.error(`callback: exportKeyItem failed`); 1402 } 1403 }); 1404 } catch (error) { 1405 console.error(`callback: exportKeyItem input arg invalid`); 1406 } 1407} 1408 1409function deleteKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1410 return new Promise<void>((resolve, reject) => { 1411 try { 1412 huks.deleteKeyItem(keyAlias, huksOptions, (error, data) => { 1413 if (error) { 1414 reject(error); 1415 } else { 1416 resolve(data); 1417 } 1418 }); 1419 } catch (error) { 1420 throwObject.isThrow = true; 1421 throw(error as Error); 1422 } 1423 }); 1424} 1425 1426async function publicDeleteKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) { 1427 console.info(`enter callback deleteKeyItem`); 1428 let throwObject : throwObject = {isThrow: false}; 1429 try { 1430 await deleteKeyItem(keyAlias, huksOptions, throwObject) 1431 .then ((data) => { 1432 console.info(`callback: deleteKeyItem key success, data = ${JSON.stringify(data)}`); 1433 }) 1434 .catch((error :BusinessError) => { 1435 if (throwObject.isThrow) { 1436 throw(error as Error); 1437 } else { 1438 console.error(`callback: deleteKeyItem failed`); 1439 } 1440 }); 1441 } catch (error) { 1442 console.error(`callback: deletKeeyItem input arg invalid`); 1443 } 1444} 1445 1446async function testAgree() { 1447 /* 1.生成两个密钥并导出 */ 1448 await publicGenKeyFunc(srcKeyAliasFirst, HuksOptions); 1449 await publicGenKeyFunc(srcKeyAliasSecond, HuksOptions); 1450 1451 await publicExportKeyFunc(srcKeyAliasFirst, HuksOptions); 1452 exportKeyFrist = exportKey; 1453 await publicExportKeyFunc(srcKeyAliasFirst, HuksOptions); 1454 exportKeySecond = exportKey; 1455 1456 /* 对第一个密钥进行协商 */ 1457 await publicInitFunc(srcKeyAliasFirst, HuksOptions); 1458 HuksOptions.inData = exportKeySecond; 1459 await publicUpdateFunc(handle, HuksOptions); 1460 await publicFinishFunc(handle, finishOptionsFrist); 1461 1462 /* 对第二个密钥进行协商 */ 1463 await publicInitFunc(srcKeyAliasSecond, HuksOptions); 1464 HuksOptions.inData = exportKeyFrist; 1465 await publicUpdateFunc(handle, HuksOptions); 1466 await publicFinishFunc(handle, finishOptionsSecond); 1467 1468 await publicDeleteKeyFunc(srcKeyAliasFirst, HuksOptions); 1469 await publicDeleteKeyFunc(srcKeyAliasSecond, HuksOptions); 1470} 1471``` 1472 1473### 密钥派生 1474 1475应用在派生密钥时建议传入[HuksKeyStorageType](../reference/apis/js-apis-huks.md#hukskeystoragetype)中定义的类型;从API10开始应用只能选择存储(HUKS_STORAGE_ONLY_USED_IN_HUKS),或者选择导出(HUKS_STORAGE_KEY_EXPORT_ALLOWED),若不传入,则默认同时支持存储和导出,存在安全问题,不推荐业务使用。 1476 1477```ts 1478/* 1479 * 以下以HKDF256密钥的Promise操作使用为例 1480 */ 1481import huks from '@ohos.security.huks'; 1482import { BusinessError } from '@ohos.base'; 1483 1484/* 1485 * 确定密钥别名和封装密钥属性参数集 1486 */ 1487let srcKeyAlias = "hkdf_Key"; 1488let deriveHkdfInData = "deriveHkdfTestIndata"; 1489let handle:number; 1490let finishOutData:Uint8Array; 1491let HuksKeyDeriveKeySize = 32; 1492 1493/* 集成生成密钥参数集 */ 1494let properties:Array<huks.HuksParam> = new Array(); 1495properties[0] = { 1496 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 1497 value: huks.HuksKeyAlg.HUKS_ALG_AES, 1498} 1499properties[1] = { 1500 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 1501 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DERIVE, 1502} 1503properties[2] = { 1504 tag: huks.HuksTag.HUKS_TAG_DIGEST, 1505 value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256, 1506} 1507properties[3] = { 1508 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 1509 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_128, 1510} 1511properties[4] = { 1512 tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, 1513 value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS, 1514} 1515let huksOptions:huks.HuksOptions = { 1516 properties: properties, 1517 inData: new Uint8Array(new Array()) 1518} 1519 1520/* 集成init时密钥参数集 */ 1521let initProperties:Array<huks.HuksParam> = new Array(); 1522initProperties[0] = { 1523 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 1524 value: huks.HuksKeyAlg.HUKS_ALG_HKDF, 1525} 1526initProperties[1] = { 1527 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 1528 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DERIVE, 1529} 1530initProperties[2] = { 1531 tag: huks.HuksTag.HUKS_TAG_DIGEST, 1532 value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256, 1533} 1534initProperties[3] = { 1535 tag: huks.HuksTag.HUKS_TAG_DERIVE_KEY_SIZE, 1536 value: HuksKeyDeriveKeySize, 1537} 1538let initOptions:huks.HuksOptions = { 1539 properties: initProperties, 1540 inData: new Uint8Array(new Array()) 1541} 1542 1543/* 集成finish时密钥参数集 */ 1544let finishProperties:Array<huks.HuksParam> = new Array(); 1545finishProperties[0] = { 1546 tag: huks.HuksTag.HUKS_TAG_DERIVED_AGREED_KEY_STORAGE_FLAG, 1547 value: huks.HuksKeyStorageType.HUKS_STORAGE_ONLY_USED_IN_HUKS, 1548} 1549finishProperties[1] = { 1550 tag: huks.HuksTag.HUKS_TAG_IS_KEY_ALIAS, 1551 value: true, 1552} 1553finishProperties[2] = { 1554 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 1555 value: huks.HuksKeyAlg.HUKS_ALG_AES, 1556} 1557finishProperties[3] = { 1558 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 1559 value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256, 1560} 1561finishProperties[4] = { 1562 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 1563 value: 1564 huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | 1565 huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT, 1566} 1567finishProperties[5] = { 1568 tag: huks.HuksTag.HUKS_TAG_DIGEST, 1569 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE, 1570} 1571finishProperties[6] = { 1572 tag: huks.HuksTag.HUKS_TAG_KEY_ALIAS, 1573 value: StringToUint8Array(srcKeyAlias), 1574} 1575finishProperties[7] = { 1576 tag: huks.HuksTag.HUKS_TAG_PADDING, 1577 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 1578} 1579finishProperties[8] = { 1580 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 1581 value: huks.HuksCipherMode.HUKS_MODE_ECB, 1582} 1583let finishOptions:huks.HuksOptions = { 1584 properties: finishProperties, 1585 inData: new Uint8Array(new Array()) 1586} 1587 1588function StringToUint8Array(str:String) { 1589 let arr:number[]=new Array(); 1590 for (let i = 0, j = str.length; i < j; ++i) { 1591 arr.push(str.charCodeAt(i)); 1592 } 1593 return new Uint8Array(arr); 1594} 1595 1596class throwObject{ 1597 isThrow=false; 1598} 1599 1600function generateKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1601 return new Promise<void>((resolve, reject) => { 1602 try { 1603 huks.generateKeyItem(keyAlias, huksOptions, (error, data)=> { 1604 if (error) { 1605 reject(error); 1606 } else { 1607 resolve(data); 1608 } 1609 }); 1610 } catch (error) { 1611 throwObject.isThrow = true; 1612 throw(error as Error); 1613 } 1614 }); 1615} 1616 1617async function publicGenKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) { 1618 console.info(`enter callback generateKeyItem`); 1619 let throwObject:throwObject = {isThrow: false}; 1620 try { 1621 await generateKeyItem(keyAlias, huksOptions, throwObject) 1622 .then((data) => { 1623 console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`); 1624 }) 1625 .catch((error:BusinessError) => { 1626 if (throwObject.isThrow) { 1627 throw(error as Error); 1628 } else { 1629 console.error(`callback: generateKeyItem failed`); 1630 } 1631 }); 1632 } catch (error) { 1633 console.error(`callback: generateKeyItem input arg invalid`); 1634 } 1635} 1636 1637function initSession(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1638 return new Promise<huks.HuksSessionHandle>((resolve, reject) => { 1639 try { 1640 huks.initSession(keyAlias, huksOptions, (error, data)=> { 1641 if (error) { 1642 reject(error); 1643 } else { 1644 resolve(data); 1645 } 1646 }); 1647 } catch (error) { 1648 throwObject.isThrow = true; 1649 throw(error as Error); 1650 } 1651 }); 1652} 1653 1654async function publicInitFunc(keyAlias:string, huksOptions:huks.HuksOptions) { 1655 console.info(`enter callback doInit`); 1656 let throwObject:throwObject = {isThrow: false}; 1657 try { 1658 await initSession(keyAlias, huksOptions, throwObject) 1659 .then ((data) => { 1660 console.info(`callback: doInit success, data = ${JSON.stringify(data)}`); 1661 handle = data.handle; 1662 }) 1663 .catch((error:BusinessError) => { 1664 if (throwObject.isThrow) { 1665 throw(error as Error); 1666 } else { 1667 console.error(`callback: doInit failed`); 1668 } 1669 }); 1670 } catch (error) { 1671 console.error(`callback: doInit input arg invalid`); 1672 } 1673} 1674 1675function updateSession(handle:number, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1676 return new Promise<huks.HuksOptions>((resolve, reject) => { 1677 try { 1678 huks.updateSession(handle, huksOptions, (error, data)=> { 1679 if (error) { 1680 reject(error); 1681 } else { 1682 resolve(data); 1683 } 1684 }); 1685 } catch (error) { 1686 throwObject.isThrow = true; 1687 throw(error as Error); 1688 } 1689 }); 1690} 1691 1692async function publicUpdateFunc(handle:number, huksOptions:huks.HuksOptions) { 1693 console.info(`enter callback doUpdate`); 1694 let throwObject:throwObject = {isThrow: false}; 1695 try { 1696 await updateSession(handle, huksOptions, throwObject) 1697 .then ((data) => { 1698 console.info(`callback: doUpdate success, data = ${JSON.stringify(data)}`); 1699 }) 1700 .catch((error:BusinessError) => { 1701 if (throwObject.isThrow) { 1702 throw(error as Error); 1703 } else { 1704 console.error(`callback: doUpdate failed`); 1705 } 1706 }); 1707 } catch (error) { 1708 console.error(`callback: doUpdate input arg invalid`); 1709 } 1710} 1711 1712function finishSession(handle:number, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1713 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 1714 try { 1715 huks.finishSession(handle, huksOptions, (error, data)=> { 1716 if (error) { 1717 reject(error); 1718 } else { 1719 resolve(data); 1720 } 1721 }); 1722 } catch (error) { 1723 throwObject.isThrow = true; 1724 throw(error as Error); 1725 } 1726 }); 1727} 1728 1729async function publicFinishFunc(handle:number, huksOptions:huks.HuksOptions) { 1730 console.info(`enter callback doFinish`); 1731 let throwObject:throwObject = {isThrow: false}; 1732 try { 1733 await finishSession(handle, huksOptions, throwObject) 1734 .then ((data) => { 1735 finishOutData = data.outData as Uint8Array; 1736 console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`); 1737 }) 1738 .catch((error:BusinessError) => { 1739 if (throwObject.isThrow) { 1740 throw(error as Error); 1741 } else { 1742 console.error(`callback: doFinish failed`); 1743 } 1744 }); 1745 } catch (error) { 1746 console.error(`callback: doFinish input arg invalid`); 1747 } 1748} 1749 1750function deleteKeyItem(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1751 return new Promise<void>((resolve, reject) => { 1752 try { 1753 huks.deleteKeyItem(keyAlias, huksOptions, (error, data)=> { 1754 if (error) { 1755 reject(error); 1756 } else { 1757 resolve(data); 1758 } 1759 }); 1760 } catch (error) { 1761 throwObject.isThrow = true; 1762 throw(error as Error); 1763 } 1764 }); 1765} 1766 1767async function publicDeleteKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) { 1768 console.info(`enter callback deleteKeyItem`); 1769 let throwObject:throwObject = {isThrow: false}; 1770 try { 1771 await deleteKeyItem(keyAlias, huksOptions, throwObject) 1772 .then ((data) => { 1773 console.info(`callback: deleteKeyItem key success, data = ${JSON.stringify(data)}`); 1774 }) 1775 .catch((error:BusinessError) => { 1776 if (throwObject.isThrow) { 1777 throw(error as Error); 1778 } else { 1779 console.error(`callback: deleteKeyItem failed`); 1780 } 1781 }); 1782 } catch (error) { 1783 console.error(`callback: deletKeeyItem input arg invalid`); 1784 } 1785} 1786 1787async function testDerive() { 1788 /* 生成密钥 */ 1789 await publicGenKeyFunc(srcKeyAlias, huksOptions); 1790 1791 /* 进行派生操作 */ 1792 await publicInitFunc(srcKeyAlias, initOptions); 1793 1794 initOptions.inData = StringToUint8Array(deriveHkdfInData); 1795 await publicUpdateFunc(handle, initOptions); 1796 await publicFinishFunc(handle, finishOptions); 1797 1798 await publicDeleteKeyFunc(srcKeyAlias, huksOptions); 1799} 1800``` 1801 1802## 密钥访问控制 1803 1804HUKS提供了全面完善的密钥访问控制能力,确保存储在HUKS中的密钥被合法正确的访问。 1805 1806首先,业务只能访问属于自己的密钥,即只能访问通过HUKS生成或导入的密钥。 1807其次,支持密钥的用户身份认证访问控制,对于高安敏感的业务密钥,需要在使用密钥的时候,再次要求用户即时的验证锁屏密码或生物特征,验证通过后,才能使用业务密钥。 1808除此之外,HUKS还支持严格限制密钥的使用用途,如支持只允许AES密钥进行加密解密,只允许RSA密钥进行签名验签。 1809 1810### 用户身份认证访问控制 1811 1812生成或导入密钥时,可以指定密钥必须经过用户身份认证后才能使用。您可以指定用于解锁设备锁屏的凭据(锁屏密码、指纹、人脸)的子集进行身份认证。在生成/导入密钥后,即使应用进程被攻击也不会导致未经用户授权的密钥访问,一般用于高敏感且高级别安全保护的场景,比如免密登录、免密支付、自动填充密码保护场景。 1813 1814除用户身份认证外,应用还须将密钥的授权访问类型(即失效条件)设置为以下两种类型之一: 1815 1816- **清除锁屏密码后密钥永久无效。** 设置此模式的前提是当前用户已经设置了锁屏密码,在生成/导入密钥后,一旦清除了锁屏密码,此类密钥将永久失效。注意,修改密码不会导致失效情况发生。此模式适合那些需要锁屏密码授权访问或用户强相关的数据保护的场景。 1817- **用户新录入生物特征后永久无效。** 此模式需要当前用户至少录入了一个生物特征(如指纹)才能生效,在生成/导入密钥后,一旦录入新的生物特征,这些密钥将永久失效。注意,仅删除生物特征不会导致失效情况发生。如果您不希望新录入的生物特征后,用户还可以授权访问原有数据(密钥保护的数据),那么可以使用此模式,如免密登录,免密支付等场景。 1818 1819此外,为了保证密钥使用时用户认证结果的有效性(不可重放),HUKS支持挑战值校验:在身份认证前,需要从HUKS获取挑战值(调用[huks.initSession()](../reference/apis/js-apis-huks.md#huksinitsession9)返回的[HuksSessionHandle](../reference/apis/js-apis-huks.md#hukssessionhandle9)中)传给用户身份认证方法(userIAM_userAuth.getAuthInstance),然后在密钥操作时校验认证令牌的挑战值。 1820 1821**开发流程** 1822 1823设置了二次用户身份认证的密钥,需要先初始化密钥会话并获取挑战值,然后将HUKS生成的挑战值传至用户身份认证方法进行用户身份认证,认证通过后获取一个认证令牌,将认证令牌传至HUKS进行密钥操作。 1824 1825 1826 1827**接口说明** 1828 18291. 生成或导入密钥时,在密钥属性集中需指定三个参数:用户认证类型[HuksUserAuthType](../reference/apis/js-apis-huks.md#huksuserauthtype9)、授权访问类型[HuksAuthAccessType](../reference/apis/js-apis-huks.md#huksauthaccesstype9)、挑战值类型[HuksChallengeType](../reference/apis/js-apis-huks.md#hukschallengetype9)。 1830 1831 **表3** 用户认证类型:三种类型的子集 1832 | 名称 | 值 | 说明 | 1833 | ------------------------------- |---|------------------------ | 1834 | HUKS_USER_AUTH_TYPE_FINGERPRINT |0x0001 | 用户认证类型为指纹,允许和人脸、锁屏密码同时设置 | 1835 | HUKS_USER_AUTH_TYPE_FACE |0x0002 | 用户认证类型为人脸 ,允许和指纹、锁屏密码同时设置 | 1836 | HUKS_USER_AUTH_TYPE_PIN |0x0004 | 用户认证类型为锁屏密码,允许和人脸、指纹同时设置 | 1837 1838 **表4** 安全访问类型:二选一 1839 | 名称 | 值 | 说明 | 1840 | --------------------------------------- | ---- | ------------------------------------------------ | 1841 | HUKS_AUTH_ACCESS_INVALID_CLEAR_PASSWORD | 1 | 清除锁屏密码后密钥无法访问。 | 1842 | HUKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL | 2 | 新录入生物特征后密钥无法访问,用户认证类型须包含生物认证类型。 | 1843 1844 **表5** 挑战值类型:三选一 1845 | 名称 | 值 | 说明 | 1846 | ------------------------------- | ---- | ------------------------------ | 1847 | HUKS_CHALLENGE_TYPE_NORMAL | 0 | 普通类型,每次密钥的使用需要独立的一次用户认证 | 1848 | HUKS_CHALLENGE_TYPE_CUSTOM | 1 | 自定义类型,支持和多个密钥共享一次用户认证| 1849 | HUKS_CHALLENGE_TYPE_NONE | 2 | 无挑战值类型,用户认证时不需要挑战值 | 1850 1851 > **注意** 1852 > 1853 > 当指定挑战值类型为**HUKS_CHALLENGE_TYPE_NONE** 时,不需要传递挑战值,但是存在新的限制:在用户身份认证后,一段时间内允许访问该密钥,超时后不能访问,需要重新认证才能访问。因此应用需要额外指定超时时间**HUKS_TAG_AUTH_TIMEOUT**属性(最大60秒)。 1854 18552. 使用密钥时,先初始化密钥会话,然后根据密钥生成/导入阶段指定的挑战值类型属性是否需要获取挑战值,或组装新的挑战值。 1856 1857 **表6** 使用密钥的接口介绍 1858 | 接口名 | 描述 | 1859 | -------------------------------------- | ----------------------------| 1860 |initSession(keyAlias: string, options: HuksOptions, callback: AsyncCallback\<HuksSessionHandle>) : void| 初始化密钥会话,获取挑战值| 1861 |updateSession(handle: number, options: HuksOptions, token: Uint8Array, callback: AsyncCallback\<HuksReturnResult>) : void| 分段操作数据,传递认证令牌| 1862 |finishSession(handle: number, options: HuksOptions, token: Uint8Array, callback: AsyncCallback\<HuksReturnResult>) : void| 结束密钥会话,传递认证令牌| 1863 1864**开发步骤** 1865 18661. 生成密钥并指定指纹访问控制和相关属性 1867 1868 ```ts 1869 import huks from '@ohos.security.huks'; 1870 import { BusinessError } from '@ohos.base'; 1871 1872 /* 1873 * 确定密钥别名和封装密钥属性参数集 1874 */ 1875 let keyAlias = 'dh_key_fingerprint_access'; 1876 let properties : Array<huks.HuksParam> = new Array(); 1877 properties[0] = { 1878 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 1879 value: huks.HuksKeyAlg.HUKS_ALG_SM4, 1880 } 1881 properties[1] = { 1882 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 1883 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT, 1884 } 1885 properties[2] = { 1886 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 1887 value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, 1888 } 1889 properties[3] = { 1890 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 1891 value: huks.HuksCipherMode.HUKS_MODE_CBC, 1892 } 1893 properties[4] = { 1894 tag: huks.HuksTag.HUKS_TAG_PADDING, 1895 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 1896 } 1897 // 指定密钥身份认证的类型:指纹 1898 properties[5] = { 1899 tag: huks.HuksTag.HUKS_TAG_USER_AUTH_TYPE, 1900 value: huks.HuksUserAuthType.HUKS_USER_AUTH_TYPE_FINGERPRINT 1901 } 1902 // 指定密钥安全授权的类型(失效类型):新录入生物特征(指纹)后无效 1903 properties[6] = { 1904 tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_ACCESS_TYPE, 1905 value: huks.HuksAuthAccessType.HUKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL 1906 } 1907 // 指定挑战值的类型:默认类型 1908 properties[7] = { 1909 tag: huks.HuksTag.HUKS_TAG_CHALLENGE_TYPE, 1910 value: huks.HuksChallengeType.HUKS_CHALLENGE_TYPE_NORMAL 1911 } 1912 let huksOptions : huks.HuksOptions = { 1913 properties: properties, 1914 inData: new Uint8Array(new Array()) 1915 } 1916 1917 /* 1918 * 生成密钥 1919 */ 1920 class throwObject { 1921 isThrow:boolean = false 1922 } 1923 function generateKeyItem(keyAlias : string, huksOptions:huks.HuksOptions, throwObject:throwObject) { 1924 return new Promise<void>((resolve, reject) => { 1925 try { 1926 huks.generateKeyItem(keyAlias, huksOptions, (error, data) => { 1927 if (error) { 1928 reject(error); 1929 } else { 1930 resolve(data); 1931 } 1932 }); 1933 } catch (error) { 1934 throwObject.isThrow = true; 1935 throw(error as Error); 1936 } 1937 }); 1938 } 1939 1940 async function publicGenKeyFunc(keyAlias:string, huksOptions:huks.HuksOptions) { 1941 console.info(`enter callback generateKeyItem`); 1942 let throwObject : throwObject = {isThrow: false}; 1943 try { 1944 await generateKeyItem(keyAlias, huksOptions, throwObject) 1945 .then((data) => { 1946 console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`); 1947 }) 1948 .catch((error : BusinessError) => { 1949 if (throwObject.isThrow) { 1950 throw(error as Error); 1951 } else { 1952 console.error(`callback: generateKeyItem failed`); 1953 } 1954 }); 1955 } catch (error) { 1956 console.error(`callback: generateKeyItem input arg invalid`); 1957 } 1958 } 1959 1960 async function TestGenKeyForFingerprintAccessControl() { 1961 await publicGenKeyFunc(keyAlias, huksOptions); 1962 } 1963 ``` 1964 19652. 初始化密钥会话获取挑战值并发起指纹认证获取认证令牌 1966 1967 ```ts 1968 import huks from '@ohos.security.huks'; 1969 import userIAM_userAuth from '@ohos.userIAM.userAuth'; 1970 import { BusinessError } from '@ohos.base'; 1971 1972 /* 1973 * 确定密钥别名和封装密钥属性参数集 1974 */ 1975 let srcKeyAlias = 'sm4_key_fingerprint_access'; 1976 let handle : number; 1977 let challenge : Uint8Array; 1978 let fingerAuthToken : Uint8Array; 1979 let authType = userIAM_userAuth.UserAuthType.FINGERPRINT; 1980 let authTrustLevel = userIAM_userAuth.AuthTrustLevel.ATL1; 1981 1982 /* 集成生成密钥参数集 & 加密参数集 */ 1983 let properties : Array<huks.HuksParam> = new Array(); 1984 properties[0] = { 1985 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 1986 value: huks.HuksKeyAlg.HUKS_ALG_SM4, 1987 } 1988 properties[1] = { 1989 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 1990 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT, 1991 } 1992 properties[2] = { 1993 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 1994 value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, 1995 } 1996 properties[3] = { 1997 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 1998 value: huks.HuksCipherMode.HUKS_MODE_CBC, 1999 } 2000 properties[4] = { 2001 tag: huks.HuksTag.HUKS_TAG_PADDING, 2002 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 2003 } 2004 let huksOptions : huks.HuksOptions = { 2005 properties: properties, 2006 inData: new Uint8Array(new Array()) 2007 } 2008 2009 class throwObject { 2010 isThrow:boolean=false 2011 } 2012 2013 function initSession(keyAlias:string, huksOptions:huks.HuksOptions, throwObject:throwObject) { 2014 return new Promise<huks.HuksSessionHandle>((resolve, reject) => { 2015 try { 2016 huks.initSession(keyAlias, huksOptions, (error, data) =>{ 2017 if (error) { 2018 reject(error); 2019 } else { 2020 resolve(data); 2021 } 2022 }); 2023 } catch (error) { 2024 throwObject.isThrow = true; 2025 throw(error as Error); 2026 } 2027 }); 2028 } 2029 2030 async function publicInitFunc(keyAlias:string, huksOptions:huks.HuksOptions) { 2031 console.info(`enter callback doInit`); 2032 let throwObject : throwObject = {isThrow: false}; 2033 try { 2034 await initSession(keyAlias, huksOptions, throwObject) 2035 .then ((data) => { 2036 console.info(`callback: doInit success, data = ${JSON.stringify(data)}`); 2037 handle = data.handle; 2038 challenge = data.challenge as Uint8Array; 2039 }) 2040 .catch((error : BusinessError) => { 2041 if (throwObject.isThrow) { 2042 throw(error as Error); 2043 } else { 2044 console.error(`callback: doInit failed`); 2045 } 2046 }); 2047 } catch (error) { 2048 console.error(`callback: doInit input arg invalid`); 2049 } 2050 } 2051 2052 function userIAMAuthFinger(huksChallenge:Uint8Array) { 2053 // 获取认证对象 2054 let auth : userIAM_userAuth.AuthInstance; 2055 try { 2056 auth = userIAM_userAuth.getAuthInstance(huksChallenge, authType, authTrustLevel); 2057 console.log("get auth instance success"); 2058 } catch (error) { 2059 console.log("get auth instance failed" + error); 2060 return; 2061 } 2062 2063 // 订阅认证结果 2064 try { 2065 auth.on("result", { 2066 callback: (result:userIAM_userAuth.AuthResultInfo) => { 2067 /* 认证成功获取认证令牌 */ 2068 fingerAuthToken = result.token as Uint8Array; 2069 } 2070 }); 2071 console.log("subscribe authentication event success"); 2072 } catch (error) { 2073 console.log("subscribe authentication event failed " + error); 2074 } 2075 2076 // 开始认证 2077 try { 2078 auth.start(); 2079 console.info("authV9 start auth success"); 2080 } catch (error) { 2081 console.info("authV9 start auth failed, error = " + error); 2082 } 2083 } 2084 2085 async function testInitAndAuthFinger() { 2086 /* 初始化密钥会话获取挑战值 */ 2087 await publicInitFunc(srcKeyAlias, huksOptions); 2088 /* 调用userIAM进行身份认证 */ 2089 userIAMAuthFinger(challenge); 2090 } 2091 ``` 2092 20933. 传入认证令牌进行数据操作 2094 2095 ```ts 2096 /* 2097 * 以下以SM4 128密钥的Callback操作使用为例 2098 */ 2099 import huks from '@ohos.security.huks'; 2100 import { BusinessError } from '@ohos.base'; 2101 2102 /* 2103 * 确定密钥别名和封装密钥属性参数集 2104 */ 2105 let srcKeyAlias = 'sm4_key_fingerprint_access'; 2106 let IV = '1234567890123456'; 2107 let cipherInData = 'Hks_SM4_Cipher_Test_101010101010101010110_string'; 2108 let handle: number; 2109 let fingerAuthToken: Uint8Array; 2110 let finishOutData: Uint8Array; 2111 2112 class throwObject { 2113 isThrow: boolean = false; 2114 } 2115 2116 /* 集成生成密钥参数集 & 加密参数集 */ 2117 class propertyEncryptType { 2118 tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM; 2119 value: huks.HuksKeyAlg | huks.HuksKeyPurpose | huks.HuksKeySize | huks.HuksKeyPadding | huks.HuksCipherMode 2120 | Uint8Array = huks.HuksKeyAlg.HUKS_ALG_SM4; 2121 } 2122 2123 let propertiesEncrypt: propertyEncryptType[] = [ 2124 { 2125 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 2126 value: huks.HuksKeyAlg.HUKS_ALG_SM4, 2127 }, 2128 { 2129 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 2130 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT, 2131 }, 2132 { 2133 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 2134 value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, 2135 }, 2136 { 2137 tag: huks.HuksTag.HUKS_TAG_PADDING, 2138 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 2139 }, 2140 { 2141 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 2142 value: huks.HuksCipherMode.HUKS_MODE_CBC, 2143 }, 2144 { 2145 tag: huks.HuksTag.HUKS_TAG_IV, 2146 value: StringToUint8Array(IV), 2147 } 2148 ] 2149 2150 let encryptOptions: huks.HuksOptions = { 2151 properties: propertiesEncrypt, 2152 inData: new Uint8Array(new Array()) 2153 } 2154 2155 function StringToUint8Array(str: string) { 2156 let arr: number[] = []; 2157 for (let i = 0, j = str.length; i < j; ++i) { 2158 arr.push(str.charCodeAt(i)); 2159 } 2160 return new Uint8Array(arr); 2161 } 2162 2163 function updateSession(handle: number, huksOptions: huks.HuksOptions, token: Uint8Array, throwObject: throwObject) { 2164 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 2165 try { 2166 huks.updateSession(handle, huksOptions, token, (error, data) => { 2167 if (error) { 2168 reject(error); 2169 } else { 2170 resolve(data); 2171 } 2172 }); 2173 } catch (error) { 2174 throwObject.isThrow = true; 2175 throw(error as Error); 2176 } 2177 }); 2178 } 2179 2180 async function publicUpdateFunc(handle: number, token: Uint8Array, huksOptions: huks.HuksOptions) { 2181 console.info(`enter callback doUpdate`); 2182 let throwObject: throwObject = {isThrow: false}; 2183 try { 2184 await updateSession(handle, huksOptions, token, throwObject) 2185 .then ((data) => { 2186 console.info(`callback: doUpdate success, data = ${JSON.stringify(data)}`); 2187 }) 2188 .catch((error: BusinessError) => { 2189 if (throwObject.isThrow) { 2190 throw(error as Error); 2191 } else { 2192 console.error(`callback: doUpdate failed`); 2193 } 2194 }); 2195 } catch (error) { 2196 console.error(`callback: doUpdate input arg invalid`); 2197 } 2198 } 2199 2200 function finishSession(handle: number, huksOptions: huks.HuksOptions, token: Uint8Array, throwObject: throwObject) { 2201 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 2202 try { 2203 huks.finishSession(handle, huksOptions, token, (error, data) => { 2204 if (error) { 2205 reject(error); 2206 } else { 2207 resolve(data); 2208 } 2209 }); 2210 } catch (error) { 2211 throwObject.isThrow = true; 2212 throw(error as Error); 2213 } 2214 }); 2215 } 2216 2217 async function publicFinishFunc(handle: number, token: Uint8Array, huksOptions: huks.HuksOptions) { 2218 console.info(`enter callback doFinish`); 2219 let throwObject: throwObject = {isThrow: false}; 2220 try { 2221 await finishSession(handle, huksOptions, token, throwObject) 2222 .then ((data) => { 2223 finishOutData = data.outData as Uint8Array; 2224 console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`); 2225 }) 2226 .catch((error: BusinessError) => { 2227 if (throwObject.isThrow) { 2228 throw(error as Error); 2229 } else { 2230 console.error(`callback: doFinish failed`); 2231 } 2232 }); 2233 } catch (error) { 2234 console.error(`callback: doFinish input arg invalid`); 2235 } 2236 } 2237 2238 async function testSm4Cipher() { 2239 encryptOptions.inData = StringToUint8Array(cipherInData); 2240 /* 传入认证令牌 */ 2241 await publicUpdateFunc(handle, fingerAuthToken, encryptOptions); 2242 encryptOptions.inData = new Uint8Array(new Array()); 2243 /* 传入认证令牌 */ 2244 await publicFinishFunc(handle, fingerAuthToken, encryptOptions); 2245 if (finishOutData === StringToUint8Array(cipherInData)) { 2246 console.info('test finish encrypt err '); 2247 } else { 2248 console.info('test finish encrypt success'); 2249 } 2250 } 2251 ``` 2252 2253### 细粒度用户身份认证访问控制 2254 2255该功能是基于已有[密钥访问控制](#密钥访问控制)能力的扩展,提供了基于生物特征和锁屏密码二次身份认证的细粒度访问控制能力,允许设置密钥在加密、解密、签名、验签、密钥协商、密钥派生的单个或多个场景时是否需要进行身份验证。比如,业务需要使用HUKS密钥加密保存帐号密码信息等数据,要求在加密的时候不进行指纹等身份认证,解密的时候需要进行指纹等身份认证,这是就需要依赖HUKS提供细粒度的二次身份认证访问控制机制。 2256 2257**开发流程** 2258 22591. 基于用户身份认证访问控制的流程,在密钥生成阶段,通过额外指定用于细粒度用户身份认证访问控制的HuksTag:[HUKS_TAG_KEY_AUTH_PURPOSE](../reference/apis/js-apis-huks.md#hukstag)值,来指定在某种算法用途的情况下需要使用用户身份认证访问控制能力。 22602. 基于用户身份认证访问控制的流程,在密钥使用阶段,业务无需再次指定HUKS_TAG_KEY_AUTH_PURPOSE值,同用户身份认证访问控制的开发流程。 2261 2262**接口说明** 2263 2264新增用于细粒度用户身份认证访问控制的HuksTag:[HUKS_TAG_KEY_AUTH_PURPOSE](../reference/apis/js-apis-huks.md#hukstag),该Tag值取值范围为枚举类[HuksKeyAlg](../reference/apis/js-apis-huks.md#hukskeyalg)。 2265 2266**表7** 细粒度用户身份认证访问控制Tag类型介绍 2267| 名称 | 描述 | 2268| -------------------------------------- | ----------------------------| 2269|HUKS_TAG_KEY_AUTH_PURPOSE| 表示密钥认证用途的tag,用于设置某种算法用途下需要用户身份认证访问控制| 2270 2271**注意** 2272 22731. 当业务未指定用户认证类型[HuksUserAuthType](../reference/apis/js-apis-huks.md#huksuserauthtype9)时表示默认都不需要用户身份认证访问控制能力,则此时设置HUKS_TAG_KEY_AUTH_PURPOSE是默认无效的; 当业务指定了[HuksUserAuthType](../reference/apis/js-apis-huks.md#huksuserauthtype9)时表示需要用户身份认证访问控制能力,此时若不设置HUKS_TAG_KEY_AUTH_PURPOSE值,则生成密钥阶段指定的算法用途在密钥使用时都默认需要进行用户身份认证访问控制。 22742. 当指定的算法是对称算法AES和SM4时,且同时指定用于加解密用途,则只允许设置CBC模式,其它模式不支持细粒度用户身份认证访问控制能力。 2275 2276**开发步骤** 2277 2278示例场景:密钥生成阶段,生成用于加解密的密钥并指定只有解密的时候需要用户身份认证访问控制;密钥使用阶段,加密时不需要用户身份认证访问控制,解密时需要用户身份认证访问控制 2279 22801. 生成密钥并指定指纹访问控制和相关属性,以及HUKS_TAG_KEY_AUTH_PURPOSE值 2281 2282 ```ts 2283 import huks from '@ohos.security.huks'; 2284 import { BusinessError } from '@ohos.base'; 2285 2286 /* 2287 * 确定密钥别名和封装密钥属性参数集 2288 */ 2289 let keyAlias = 'dh_key_fingerprint_access'; 2290 2291 class throwObject { 2292 isThrow: boolean = false; 2293 } 2294 2295 class propertyType { 2296 tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM; 2297 value: huks.HuksKeyAlg | huks.HuksKeyPurpose | huks.HuksKeySize | huks.HuksCipherMode | huks.HuksKeyPadding 2298 | huks.HuksUserAuthType | huks.HuksAuthAccessType | huks.HuksChallengeType = huks.HuksKeyAlg.HUKS_ALG_SM4 2299 } 2300 let properties: propertyType[] = [ 2301 { 2302 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 2303 value: huks.HuksKeyAlg.HUKS_ALG_SM4, 2304 }, 2305 { 2306 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 2307 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT, 2308 }, 2309 { 2310 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 2311 value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, 2312 }, 2313 { 2314 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 2315 value: huks.HuksCipherMode.HUKS_MODE_CBC, 2316 }, 2317 { 2318 tag: huks.HuksTag.HUKS_TAG_PADDING, 2319 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 2320 }, 2321 { 2322 tag: huks.HuksTag.HUKS_TAG_USER_AUTH_TYPE, 2323 value: huks.HuksUserAuthType.HUKS_USER_AUTH_TYPE_FINGERPRINT 2324 }, 2325 { 2326 tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_ACCESS_TYPE, 2327 value: huks.HuksAuthAccessType.HUKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL 2328 }, 2329 { 2330 tag: huks.HuksTag.HUKS_TAG_CHALLENGE_TYPE, 2331 value: huks.HuksChallengeType.HUKS_CHALLENGE_TYPE_NORMAL 2332 }, 2333 { 2334 tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_PURPOSE, 2335 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT 2336 } 2337 ] 2338 2339 let huksOptions: huks.HuksOptions = { 2340 properties: properties, 2341 inData: new Uint8Array(new Array()) 2342 } 2343 2344 /* 2345 * 生成密钥 2346 */ 2347 async function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) { 2348 return new Promise<void>((resolve, reject) => { 2349 try { 2350 huks.generateKeyItem(keyAlias, huksOptions, (error, data) => { 2351 if (error) { 2352 reject(error); 2353 } else { 2354 resolve(data); 2355 } 2356 }); 2357 } catch (error) { 2358 throwObject.isThrow = true; 2359 throw(error as Error); 2360 } 2361 }); 2362 } 2363 2364 async function publicGenKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 2365 console.info(`enter callback generateKeyItem`); 2366 let throwObject: throwObject = {isThrow: false}; 2367 try { 2368 await generateKeyItem(keyAlias, huksOptions, throwObject) 2369 .then((data) => { 2370 console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`); 2371 }) 2372 .catch((error: BusinessError) => { 2373 if (throwObject.isThrow) { 2374 throw(error as Error); 2375 } else { 2376 console.error(`callback: generateKeyItem failed`); 2377 } 2378 }); 2379 } catch (error) { 2380 console.error(`callback: generateKeyItem input arg invalid`); 2381 } 2382 } 2383 2384 async function TestGenKeyForFingerprintAccessControl() { 2385 await publicGenKeyFunc(keyAlias, huksOptions); 2386 } 2387 ``` 2388 23892. 使用密钥-加密场景-加密时不需要进行用户身份认证访问控制 2390 2391 ```ts 2392 import huks from '@ohos.security.huks'; 2393 import { BusinessError } from '@ohos.base'; 2394 2395 class HuksProperties { 2396 tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM; 2397 value: huks.HuksKeyAlg | huks.HuksKeySize | huks.HuksKeyPurpose | huks.HuksKeyPadding | huks.HuksCipherMode 2398 | Uint8Array = huks.HuksKeyAlg.HUKS_ALG_ECC; 2399 } 2400 2401 /* 2402 * 确定密钥别名和封装密钥属性参数集 2403 */ 2404 let srcKeyAlias = 'sm4_key_fingerprint_access'; 2405 let cipherInData = 'Hks_SM4_Cipher_Test_101010101010101010110_string'; // 明文数据 2406 let IV = '1234567890123456'; 2407 let handle = 0; 2408 let cipherText: Uint8Array; // 加密后的密文数据 2409 2410 function StringToUint8Array(str: string) { 2411 let arr: number[] = []; 2412 for (let i = 0, j = str.length; i < j; ++i) { 2413 arr.push(str.charCodeAt(i)); 2414 } 2415 return new Uint8Array(arr); 2416 } 2417 2418 /* 集成生成密钥参数集 & 加密参数集 */ 2419 let propertiesEncrypt: HuksProperties[] = [ 2420 { 2421 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 2422 value: huks.HuksKeyAlg.HUKS_ALG_SM4, 2423 }, 2424 { 2425 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 2426 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT, 2427 }, 2428 { 2429 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 2430 value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, 2431 }, 2432 { 2433 tag: huks.HuksTag.HUKS_TAG_PADDING, 2434 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 2435 }, 2436 { 2437 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 2438 value: huks.HuksCipherMode.HUKS_MODE_CBC, 2439 }, 2440 { 2441 tag: huks.HuksTag.HUKS_TAG_IV, 2442 value: StringToUint8Array(IV), 2443 } 2444 ]; 2445 let encryptOptions: huks.HuksOptions = { 2446 properties: propertiesEncrypt, 2447 inData: new Uint8Array(new Array()) 2448 } 2449 class throwObject1{ 2450 isThrow: boolean = false; 2451 } 2452 function initSession(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject1) { 2453 return new Promise<huks.HuksSessionHandle>((resolve, reject) => { 2454 try { 2455 huks.initSession(keyAlias, huksOptions, (error, data) => { 2456 if (error) { 2457 reject(error); 2458 } else { 2459 resolve(data); 2460 } 2461 }); 2462 } catch (error) { 2463 throwObject.isThrow = true; 2464 throw (error as Error); 2465 } 2466 }); 2467 } 2468 2469 async function publicInitFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 2470 console.info(`enter callback doInit`); 2471 let throwObject: throwObject1 = { isThrow: false }; 2472 try { 2473 await initSession(keyAlias, huksOptions, throwObject) 2474 .then((data) => { 2475 console.info(`callback: doInit success, data = ${JSON.stringify(data)}`); 2476 handle = data.handle as number; 2477 }) 2478 .catch((error: BusinessError) => { 2479 if (throwObject.isThrow) { 2480 throw (error as Error); 2481 } else { 2482 console.error(`callback: doInit failed`); 2483 } 2484 }); 2485 } catch (error) { 2486 console.error(`callback: doInit input arg invalid`); 2487 } 2488 } 2489 2490 function finishSession(handle: number, huksOptions: huks.HuksOptions, throwObject: throwObject1) { 2491 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 2492 try { 2493 huks.finishSession(handle, huksOptions, (error, data) => { 2494 if (error) { 2495 reject(error); 2496 } else { 2497 resolve(data); 2498 } 2499 }); 2500 } catch (error) { 2501 throwObject.isThrow = true; 2502 throw (error as Error); 2503 } 2504 }); 2505 } 2506 2507 async function publicFinishFunc(handle: number, huksOptions: huks.HuksOptions) { 2508 console.info(`enter callback doFinish`); 2509 let throwObject: throwObject1 = { isThrow: false }; 2510 try { 2511 await finishSession(handle, huksOptions, throwObject) 2512 .then((data) => { 2513 cipherText = data.outData as Uint8Array; 2514 console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`); 2515 }) 2516 .catch((error: BusinessError) => { 2517 if (throwObject.isThrow) { 2518 throw (error as Error); 2519 } else { 2520 console.error(`callback: doFinish failed`); 2521 } 2522 }); 2523 } catch (error) { 2524 console.error(`callback: doFinish input arg invalid`); 2525 } 2526 } 2527 2528 async function testSm4Cipher() { 2529 /* 初始化密钥会话获取挑战值 */ 2530 await publicInitFunc(srcKeyAlias, encryptOptions); 2531 2532 /* 加密 */ 2533 encryptOptions.inData = StringToUint8Array(cipherInData); 2534 await publicFinishFunc(handle, encryptOptions); 2535 } 2536 ``` 2537 25383. 使用密钥-解密场景-解密时需要进行用户身份认证访问控制 2539 2540 ```ts 2541 import huks from '@ohos.security.huks'; 2542 import userIAM_userAuth from '@ohos.userIAM.userAuth'; 2543 import { BusinessError } from '@ohos.base'; 2544 2545 /* 2546 * 确定密钥别名和封装密钥属性参数集 2547 */ 2548 let srcKeyAlias = 'sm4_key_fingerprint_access'; 2549 let cipherText = 'r56ywtTJUQC6JFJ2VV2kZw=='; // 加密时得到的密文数据, 业务需根据实际加密结果修改 2550 let IV = '1234567890123456'; 2551 let handle: number; 2552 let finishOutData: Uint8Array; // 解密后的明文数据 2553 let fingerAuthToken: Uint8Array; 2554 let challenge: Uint8Array; 2555 let authType = userIAM_userAuth.UserAuthType.FINGERPRINT; 2556 let authTrustLevel = userIAM_userAuth.AuthTrustLevel.ATL1; 2557 2558 class throwObject { 2559 isThrow: boolean = false; 2560 } 2561 2562 function StringToUint8Array(str: string) { 2563 let arr: number[] = []; 2564 for (let i = 0, j = str.length; i < j; ++i) { 2565 arr.push(str.charCodeAt(i)); 2566 } 2567 return new Uint8Array(arr); 2568 } 2569 2570 /* 集成生成密钥参数集 & 加密参数集 */ 2571 class propertyDecryptType { 2572 tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM 2573 value: huks.HuksKeyAlg | huks.HuksKeyPurpose | huks.HuksKeySize | huks.HuksKeyPadding | huks.HuksCipherMode 2574 | Uint8Array = huks.HuksKeyAlg.HUKS_ALG_SM4 2575 } 2576 2577 let propertiesDecrypt: propertyDecryptType[] = [ 2578 { 2579 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 2580 value: huks.HuksKeyAlg.HUKS_ALG_SM4, 2581 }, 2582 { 2583 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 2584 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT, 2585 }, 2586 { 2587 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 2588 value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, 2589 }, 2590 { 2591 tag: huks.HuksTag.HUKS_TAG_PADDING, 2592 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 2593 }, 2594 { 2595 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 2596 value: huks.HuksCipherMode.HUKS_MODE_CBC, 2597 }, 2598 { 2599 tag: huks.HuksTag.HUKS_TAG_IV, 2600 value: StringToUint8Array(IV), 2601 } 2602 ] 2603 2604 let decryptOptions: huks.HuksOptions = { 2605 properties: propertiesDecrypt, 2606 inData: new Uint8Array(new Array()) 2607 } 2608 2609 function initSession(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) { 2610 return new Promise<huks.HuksSessionHandle>((resolve, reject) => { 2611 try { 2612 huks.initSession(keyAlias, huksOptions, (error, data) => { 2613 if (error) { 2614 reject(error); 2615 } else { 2616 resolve(data); 2617 } 2618 }); 2619 } catch (error) { 2620 throwObject.isThrow = true; 2621 throw(error as Error); 2622 } 2623 }); 2624 } 2625 2626 async function publicInitFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 2627 console.info(`enter callback doInit`); 2628 let throwObject: throwObject = {isThrow: false}; 2629 try { 2630 await initSession(keyAlias, huksOptions, throwObject) 2631 .then ((data) => { 2632 console.info(`callback: doInit success, data = ${JSON.stringify(data)}`); 2633 handle = data.handle; 2634 challenge = data.challenge as Uint8Array; 2635 }) 2636 .catch((error: BusinessError) => { 2637 if (throwObject.isThrow) { 2638 throw(error as Error); 2639 } else { 2640 console.error(`callback: doInit failed`); 2641 } 2642 }); 2643 } catch (error) { 2644 console.error(`callback: doInit input arg invalid`); 2645 } 2646 } 2647 2648 function userIAMAuthFinger(huksChallenge: Uint8Array) { 2649 // 获取认证对象 2650 let auth: userIAM_userAuth.AuthInstance ; 2651 try { 2652 auth = userIAM_userAuth.getAuthInstance(huksChallenge, authType, authTrustLevel); 2653 console.log("get auth instance success"); 2654 } catch (error) { 2655 console.log("get auth instance failed" + error); 2656 return; 2657 } 2658 2659 // 订阅认证结果 2660 try { 2661 auth.on("result", { 2662 callback: (result) => { 2663 /* 认证成功获取认证令牌 */ 2664 fingerAuthToken = (result as userIAM_userAuth.AuthResultInfo).token as Uint8Array; 2665 } 2666 }); 2667 console.log("subscribe authentication event success"); 2668 } catch (error) { 2669 console.log("subscribe authentication event failed " + error); 2670 } 2671 2672 // 开始认证 2673 try { 2674 auth.start(); 2675 console.info("authV9 start auth success"); 2676 } catch (error) { 2677 console.info("authV9 start auth failed, error = " + error); 2678 } 2679 } 2680 2681 function finishSession(handle: number, huksOptions: huks.HuksOptions, token: Uint8Array, throwObject: throwObject) { 2682 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 2683 try { 2684 huks.finishSession(handle, huksOptions, token, (error, data) => { 2685 if (error) { 2686 reject(error); 2687 } else { 2688 resolve(data); 2689 } 2690 }); 2691 } catch (error) { 2692 throwObject.isThrow = true; 2693 throw(error as Error); 2694 } 2695 }); 2696 } 2697 2698 async function publicFinishFunc(handle: number, token: Uint8Array, huksOptions: huks.HuksOptions) { 2699 console.info(`enter callback doFinish`); 2700 let throwObject: throwObject = {isThrow: false}; 2701 try { 2702 await finishSession(handle, huksOptions, token, throwObject) 2703 .then ((data) => { 2704 finishOutData = data.outData as Uint8Array; 2705 console.info(`callback: doFinish success, data = ${JSON.stringify(data)}`); 2706 }) 2707 .catch((error: BusinessError) => { 2708 if (throwObject.isThrow) { 2709 throw(error as Error); 2710 } else { 2711 console.error(`callback: doFinish failed`); 2712 } 2713 }); 2714 } catch (error) { 2715 console.error(`callback: doFinish input arg invalid`); 2716 } 2717 } 2718 2719 async function testSm4Cipher() { 2720 /* 初始化密钥会话获取挑战值 */ 2721 await publicInitFunc(srcKeyAlias, decryptOptions); 2722 2723 /* 调用userIAM进行身份认证 */ 2724 userIAMAuthFinger(challenge); 2725 2726 /* 认证成功后进行解密, 需要传入Auth获取到的authToken值 */ 2727 decryptOptions.inData = StringToUint8Array(cipherText); 2728 await publicFinishFunc(handle, fingerAuthToken, decryptOptions); 2729 } 2730 ``` 2731 2732## 密钥证明 2733 2734HUKS为密钥提供合法性证明能力,主要应用于非对称密钥的公钥的证明。基于PKI证书链技术,HUKS可以为存储在HUKS中的非对称密钥对的公钥签发证书,证明其公钥的合法性。业务可以通过OpenHarmony提供的根CA证书,逐级验证HUKS签发的密钥证明证书,来确保证书中的公钥以及对应的私钥,确实来自合法的硬件设备,且存储管理在HUKS中。 2735 2736**开发流程** 2737 27381. 指定密钥别名和需要证明的密钥属性的标签传入HUKS。 27392. 调用HUKS为应用生成一个依次由根CA证书、设备CA证书、设备证书、密钥证书组成的X.509证书链。 27403. 将证书链传输至受信任的服务器,并在服务器上解析和验证证书链的有效性和单个证书是否吊销。 2741 2742**接口说明** 2743 2744**表8** 密钥认证接口介绍 2745| 接口名 | 描述 | 2746| -------------------------------------- | ----------------------------| 2747|attestKeyItem(keyAlias: string, options: HuksOptions, callback: AsyncCallback\<HuksReturnResult>) : void| 密钥认证| 2748 2749**开发步骤** 2750 2751```ts 2752/* 2753 * 以下以attestKey Callback接口操作验证为例 2754 */ 2755import huks from '@ohos.security.huks'; 2756import { BusinessError } from '@ohos.base'; 2757 2758/* 2759 * 确定密钥别名和封装密钥属性参数集 2760 */ 2761let keyAliasString = "key attest"; 2762let aliasString = keyAliasString; 2763let aliasUint8 = StringToUint8Array(keyAliasString); 2764let securityLevel = StringToUint8Array('sec_level'); 2765let challenge = StringToUint8Array('challenge_data'); 2766let versionInfo = StringToUint8Array('version_info'); 2767let attestCertChain: Array<string>; 2768 2769class throwObject { 2770 isThrow: boolean = false; 2771} 2772 2773class genKeyPropertyType { 2774 tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM; 2775 value: huks.HuksKeyAlg | huks.HuksKeyStorageType | huks.HuksKeySize | huks.HuksKeyPurpose | huks.HuksKeyDigest 2776 | huks.HuksKeyPadding | huks.HuksKeyGenerateType | huks.HuksCipherMode = huks.HuksKeyAlg.HUKS_ALG_RSA 2777} 2778 2779let genKeyProperties: genKeyPropertyType[] = [ 2780 { 2781 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 2782 value: huks.HuksKeyAlg.HUKS_ALG_RSA 2783 }, 2784 { 2785 tag: huks.HuksTag.HUKS_TAG_KEY_STORAGE_FLAG, 2786 value: huks.HuksKeyStorageType.HUKS_STORAGE_PERSISTENT 2787 }, 2788 { 2789 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 2790 value: huks.HuksKeySize.HUKS_RSA_KEY_SIZE_2048 2791 }, 2792 { 2793 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 2794 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_VERIFY 2795 }, 2796 { 2797 tag: huks.HuksTag.HUKS_TAG_DIGEST, 2798 value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256 2799 }, 2800 { 2801 tag: huks.HuksTag.HUKS_TAG_PADDING, 2802 value: huks.HuksKeyPadding.HUKS_PADDING_PSS 2803 }, 2804 { 2805 tag: huks.HuksTag.HUKS_TAG_KEY_GENERATE_TYPE, 2806 value: huks.HuksKeyGenerateType.HUKS_KEY_GENERATE_TYPE_DEFAULT 2807 }, 2808 { 2809 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 2810 value: huks.HuksCipherMode.HUKS_MODE_ECB 2811 } 2812] 2813 2814let genOptions: huks.HuksOptions = { 2815 properties: genKeyProperties 2816}; 2817 2818class attestKeypropertyType { 2819 tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ATTESTATION_ID_SEC_LEVEL_INFO; 2820 value: Uint8Array = securityLevel; 2821} 2822 2823let attestKeyproperties: attestKeypropertyType[] = [ 2824 { 2825 tag: huks.HuksTag.HUKS_TAG_ATTESTATION_ID_SEC_LEVEL_INFO, 2826 value: securityLevel 2827 }, 2828 { 2829 tag: huks.HuksTag.HUKS_TAG_ATTESTATION_CHALLENGE, 2830 value: challenge 2831 }, 2832 { 2833 tag: huks.HuksTag.HUKS_TAG_ATTESTATION_ID_VERSION_INFO, 2834 value: versionInfo 2835 }, 2836 { 2837 tag: huks.HuksTag.HUKS_TAG_ATTESTATION_ID_ALIAS, 2838 value: aliasUint8 2839 } 2840] 2841 2842let huksOptions: huks.HuksOptions = { 2843 properties: attestKeyproperties 2844}; 2845 2846function StringToUint8Array(str: string) { 2847 let arr: number[] = []; 2848 for (let i = 0, j = str.length; i < j; ++i) { 2849 arr.push(str.charCodeAt(i)); 2850 } 2851 return new Uint8Array(arr); 2852} 2853 2854function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) { 2855 return new Promise<void>((resolve, reject) => { 2856 try { 2857 huks.generateKeyItem(keyAlias, huksOptions, (error, data) => { 2858 if (error) { 2859 reject(error); 2860 } else { 2861 resolve(data); 2862 } 2863 }); 2864 } catch (error) { 2865 throwObject.isThrow = true; 2866 throw(error as Error); 2867 } 2868 }); 2869} 2870 2871async function publicGenKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 2872 console.info(`enter callback generateKeyItem`); 2873 let throwObject: throwObject = {isThrow: false}; 2874 try { 2875 await generateKeyItem(keyAlias, huksOptions, throwObject) 2876 .then((data) => { 2877 console.info(`callback: generateKeyItem success, data = ${JSON.stringify(data)}`); 2878 }) 2879 .catch((error: BusinessError) => { 2880 if (throwObject.isThrow) { 2881 throw(error as Error); 2882 } else { 2883 console.error(`callback: generateKeyItem failed`); 2884 } 2885 }); 2886 } catch (error) { 2887 console.error(`callback: generateKeyItem input arg invalid`); 2888 } 2889} 2890 2891function attestKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) { 2892 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 2893 try { 2894 huks.attestKeyItem(keyAlias, huksOptions, (error, data) => { 2895 if (error) { 2896 reject(error); 2897 } else { 2898 resolve(data); 2899 } 2900 }); 2901 } catch (error) { 2902 throwObject.isThrow = true; 2903 throw(error as Error); 2904 } 2905 }); 2906} 2907 2908async function publicAttestKey(keyAlias: string, huksOptions: huks.HuksOptions) { 2909 console.info(`enter callback attestKeyItem`); 2910 let throwObject: throwObject = {isThrow: false}; 2911 try { 2912 await attestKeyItem(keyAlias, huksOptions, throwObject) 2913 .then ((data) => { 2914 console.info(`callback: attestKeyItem success, data = ${JSON.stringify(data)}`); 2915 if (data !== null && data.certChains !== null) { 2916 attestCertChain = data.certChains as string[]; 2917 } 2918 }) 2919 .catch((error: BusinessError) => { 2920 if (throwObject.isThrow) { 2921 throw(error as Error); 2922 } else { 2923 console.error(`callback: attestKeyItem failed`); 2924 } 2925 }); 2926 } catch (error) { 2927 console.error(`callback: attestKeyItem input arg invalid`); 2928 } 2929} 2930 2931async function AttestKeyTest() { 2932 await publicGenKeyFunc(aliasString, genOptions); 2933 2934 await publicAttestKey(aliasString, huksOptions); 2935 console.info('attest certChain data: ' + attestCertChain) 2936} 2937``` 2938 2939**常见问题** 2940 29411. Cannot find name 'huks'. 2942 2943 不能找到huks,使用了接口函数但没导入security.huks.d.ts,添加import huks from '@ohos.security.huks';即可。 2944 29452. Property 'finishSession' does not exist on type 'typeof huks'. Did you mean 'finish'? 2946 2947 不能在huks库中找到finishSession,finishSession是API9版本的,请更新SDK版本或替换新版本的security.huks.d.ts文件。 2948 2949## 相关实例 2950 2951针对通用密钥库开发,有以下相关实例可供参考: 2952 2953- [`Huks`:通用密钥库系统(ArkTS)(API9)](https://gitee.com/openharmony/applications_app_samples/tree/OpenHarmony-4.0-Release/code/BasicFeature/Security/Huks)