1# 细粒度用户身份认证访问控制开发指导 2 3细粒度用户身份认证访问控制是基于已有用户身份认证访问控制的扩展,提供了基于生物特征和锁屏密码二次身份认证的细粒度访问控制能力,允许设置密钥在加密、解密、签名、验签、密钥协商、密钥派生的单个或多个场景时是否需要进行身份验证。 4 5比如,业务需要使用HUKS密钥加密保存账号密码信息等数据,要求在加密的时候不进行指纹等身份认证,解密的时候需要进行指纹等身份认证,这是就需要依赖HUKS提供细粒度的二次身份认证访问控制机制。 6 7使用该功能仅需在密钥生成阶段,通过额外指定用于细粒度用户身份认证访问控制的HuksTag:HUKS_TAG_KEY_AUTH_PURPOSE,来指定在某种算法用途的情况下需要使用用户身份认证访问控制能力。 8 9> **说明:** 10> 对于对称加解密场景,仅AES/CBC、AES/GCM、SM4/CBC模式支持细粒度访问控制。 11 12## 开发步骤 13 141. 生成密钥,指定指纹类型的访问控制及相关属性,指定HUKS_TAG_KEY_AUTH_PURPOSE值。 15 16 ```ts 17 import { huks } from "@kit.UniversalKeystoreKit"; 18 /* 19 * 确定密钥别名和封装密钥属性参数集 20 */ 21 let keyAlias = 'test_sm4_key_alias'; 22 class throwObject { 23 isThrow: boolean = false; 24 } 25 26 let properties: Array<huks.HuksParam> = [ 27 { 28 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 29 value: huks.HuksKeyAlg.HUKS_ALG_SM4, 30 }, 31 { 32 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 33 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT, 34 }, 35 { 36 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 37 value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, 38 }, 39 { 40 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 41 value: huks.HuksCipherMode.HUKS_MODE_CBC, 42 }, 43 { 44 tag: huks.HuksTag.HUKS_TAG_PADDING, 45 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 46 }, 47 { 48 tag: huks.HuksTag.HUKS_TAG_USER_AUTH_TYPE, 49 value: huks.HuksUserAuthType.HUKS_USER_AUTH_TYPE_FINGERPRINT 50 }, 51 { 52 tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_ACCESS_TYPE, 53 value: huks.HuksAuthAccessType.HUKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL 54 }, 55 { 56 tag: huks.HuksTag.HUKS_TAG_CHALLENGE_TYPE, 57 value: huks.HuksChallengeType.HUKS_CHALLENGE_TYPE_NORMAL 58 }, 59 { 60 tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_PURPOSE, 61 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT 62 } 63 ]; 64 65 let huksOptions: huks.HuksOptions = { 66 properties: properties, 67 inData: new Uint8Array(new Array()) 68 } 69 /* 70 * 生成密钥 71 */ 72 async function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) { 73 return new Promise<void>((resolve, reject) => { 74 try { 75 huks.generateKeyItem(keyAlias, huksOptions, (error, data) => { 76 if (error) { 77 reject(error); 78 } else { 79 resolve(data); 80 } 81 }); 82 } catch (error) { 83 throwObject.isThrow = true; 84 throw(error as Error); 85 } 86 }); 87 } 88 async function publicGenKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 89 console.info(`enter promise generateKeyItem`); 90 let throwObject: throwObject = {isThrow: false}; 91 try { 92 await generateKeyItem(keyAlias, huksOptions, throwObject) 93 .then((data) => { 94 console.info(`promise: generateKeyItem success, data = ${JSON.stringify(data)}`); 95 }) 96 .catch((error: Error) => { 97 if (throwObject.isThrow) { 98 throw(error as Error); 99 } else { 100 console.error(`promise: generateKeyItem failed` + JSON.stringify(error)); 101 } 102 }); 103 } catch (error) { 104 console.error(`promise: generateKeyItem input arg invalid` + JSON.stringify(error)); 105 } 106 } 107 async function TestGenKeyForFingerprintAccessControl() { 108 await publicGenKeyFunc(keyAlias, huksOptions); 109 } 110 ``` 111 1122. 使用密钥,加密时不需要用户身份认证访问控制。 113 114 ```ts 115 import { huks } from "@kit.UniversalKeystoreKit"; 116 class HuksProperties { 117 tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM; 118 value: huks.HuksKeyAlg | huks.HuksKeySize | huks.HuksKeyPurpose | huks.HuksKeyPadding | huks.HuksCipherMode 119 | Uint8Array = huks.HuksKeyAlg.HUKS_ALG_ECC; 120 } 121 /* 122 * 确定密钥别名和封装密钥属性参数集 123 */ 124 let cipherInData = 'Hks_SM4_Cipher_Test_101010101010101010110_string'; // 明文数据 125 let IV = '1234567890123456'; 126 let handle = 0; 127 let cipherText: Uint8Array; // 加密后的密文数据 128 function StringToUint8Array(str: string) { 129 let arr: number[] = []; 130 for (let i = 0, j = str.length; i < j; ++i) { 131 arr.push(str.charCodeAt(i)); 132 } 133 return new Uint8Array(arr); 134 } 135 /* 集成生成密钥参数集 & 加密参数集 */ 136 let propertiesEncrypt: HuksProperties[] = [ 137 { 138 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 139 value: huks.HuksKeyAlg.HUKS_ALG_SM4, 140 }, 141 { 142 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 143 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT, 144 }, 145 { 146 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 147 value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, 148 }, 149 { 150 tag: huks.HuksTag.HUKS_TAG_PADDING, 151 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 152 }, 153 { 154 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 155 value: huks.HuksCipherMode.HUKS_MODE_CBC, 156 }, 157 { 158 tag: huks.HuksTag.HUKS_TAG_IV, 159 value: StringToUint8Array(IV), 160 } 161 ]; 162 let encryptOptions: huks.HuksOptions = { 163 properties: propertiesEncrypt, 164 inData: new Uint8Array(new Array()) 165 } 166 class throwObject1{ 167 isThrow: boolean = false; 168 } 169 function initSession(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject1) { 170 return new Promise<huks.HuksSessionHandle>((resolve, reject) => { 171 try { 172 huks.initSession(keyAlias, huksOptions, (error, data) => { 173 if (error) { 174 reject(error); 175 } else { 176 resolve(data); 177 } 178 }); 179 } catch (error) { 180 throwObject.isThrow = true; 181 throw (error as Error); 182 } 183 }); 184 } 185 async function publicInitFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 186 console.info(`enter promise doInit`); 187 let throwObject: throwObject1 = { isThrow: false }; 188 try { 189 await initSession(keyAlias, huksOptions, throwObject) 190 .then((data) => { 191 console.info(`promise: doInit success, data = ${JSON.stringify(data)}`); 192 handle = data.handle as number; 193 }) 194 .catch((error: Error) => { 195 if (throwObject.isThrow) { 196 throw (error as Error); 197 } else { 198 console.error(`promise: doInit failed` + JSON.stringify(error)); 199 } 200 }); 201 } catch (error) { 202 console.error(`promise: doInit input arg invalid` + JSON.stringify(error)); 203 } 204 } 205 function finishSession(handle: number, huksOptions: huks.HuksOptions, throwObject: throwObject1) { 206 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 207 try { 208 huks.finishSession(handle, huksOptions, (error, data) => { 209 if (error) { 210 reject(error); 211 } else { 212 resolve(data); 213 } 214 }); 215 } catch (error) { 216 throwObject.isThrow = true; 217 throw (error as Error); 218 } 219 }); 220 } 221 async function publicFinishFunc(handle: number, huksOptions: huks.HuksOptions) { 222 console.info(`enter promise doFinish`); 223 let throwObject: throwObject1 = { isThrow: false }; 224 try { 225 await finishSession(handle, huksOptions, throwObject) 226 .then((data) => { 227 cipherText = data.outData as Uint8Array; 228 console.info(`promise: doFinish success, data = ${JSON.stringify(data)}`); 229 }) 230 .catch((error: Error) => { 231 if (throwObject.isThrow) { 232 throw (error as Error); 233 } else { 234 console.error(`promise: doFinish failed` + JSON.stringify(error)); 235 } 236 }); 237 } catch (error) { 238 console.error(`promise: doFinish input arg invalid` + JSON.stringify(error)); 239 } 240 } 241 async function testSm4Cipher() { 242 /* 初始化密钥会话获取挑战值 */ 243 await publicInitFunc(keyAlias, encryptOptions); 244 /* 加密 */ 245 encryptOptions.inData = StringToUint8Array(cipherInData); 246 await publicFinishFunc(handle, encryptOptions); 247 } 248 ``` 249 2503. 使用密钥,解密时需要进行用户身份认证访问控制。 251 252 ```ts 253 import { huks } from "@kit.UniversalKeystoreKit"; 254 import { userAuth } from '@kit.UserAuthenticationKit'; 255 import { BusinessError } from "@kit.BasicServicesKit" 256 257 let keyAlias = 'test_sm4_key_alias'; 258 let IV = '1234567890123456'; 259 let handle = 0; 260 let cipherText: Uint8Array; // 密文数据 261 /* 262 * 确定封装密钥属性参数集 263 */ 264 let finishOutData: Uint8Array; // 解密后的明文数据 265 let fingerAuthToken: Uint8Array; 266 let challenge: Uint8Array; 267 let authType = userAuth.UserAuthType.FINGERPRINT; 268 let authTrustLevel = userAuth.AuthTrustLevel.ATL1; 269 class throwObject { 270 isThrow: boolean = false; 271 } 272 function StringToUint8Array(str: string) { 273 let arr: number[] = []; 274 for (let i = 0, j = str.length; i < j; ++i) { 275 arr.push(str.charCodeAt(i)); 276 } 277 return new Uint8Array(arr); 278 } 279 /* 集成生成密钥参数集 & 加密参数集 */ 280 class propertyDecryptType { 281 tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM 282 value: huks.HuksKeyAlg | huks.HuksKeyPurpose | huks.HuksKeySize | huks.HuksKeyPadding | huks.HuksCipherMode 283 | Uint8Array = huks.HuksKeyAlg.HUKS_ALG_SM4 284 } 285 let propertiesDecrypt: propertyDecryptType[] = [ 286 { 287 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 288 value: huks.HuksKeyAlg.HUKS_ALG_SM4, 289 }, 290 { 291 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 292 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT, 293 }, 294 { 295 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 296 value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, 297 }, 298 { 299 tag: huks.HuksTag.HUKS_TAG_PADDING, 300 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 301 }, 302 { 303 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 304 value: huks.HuksCipherMode.HUKS_MODE_CBC, 305 }, 306 { 307 tag: huks.HuksTag.HUKS_TAG_IV, 308 value: StringToUint8Array(IV), 309 } 310 ] 311 let decryptOptions: huks.HuksOptions = { 312 properties: propertiesDecrypt, 313 inData: new Uint8Array(new Array()) 314 } 315 function initSession(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) { 316 return new Promise<huks.HuksSessionHandle>((resolve, reject) => { 317 try { 318 huks.initSession(keyAlias, huksOptions, (error, data) => { 319 if (error) { 320 reject(error); 321 } else { 322 resolve(data); 323 } 324 }); 325 } catch (error) { 326 throwObject.isThrow = true; 327 throw(error as Error); 328 } 329 }); 330 } 331 async function publicInitFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 332 console.info(`enter promise doInit`); 333 let throwObject: throwObject = {isThrow: false}; 334 try { 335 await initSession(keyAlias, huksOptions, throwObject) 336 .then ((data) => { 337 console.info(`promise: doInit success, data = ${JSON.stringify(data)}`); 338 handle = data.handle; 339 challenge = data.challenge as Uint8Array; 340 }) 341 .catch((error: BusinessError) => { 342 if (throwObject.isThrow) { 343 throw(error as Error); 344 } else { 345 console.error(`promise: doInit failed` + JSON.stringify(error)); 346 } 347 }); 348 } catch (error) { 349 console.error(`promise: doInit input arg invalid` + JSON.stringify(error)); 350 } 351 } 352 function userIAMAuthFinger(huksChallenge: Uint8Array) { 353 // 获取认证对象 354 let authTypeList:userAuth.UserAuthType[]= [ authType ]; 355 const authParam:userAuth.AuthParam = { 356 challenge: huksChallenge, 357 authType: authTypeList, 358 authTrustLevel: userAuth.AuthTrustLevel.ATL1 359 }; 360 const widgetParam:userAuth.WidgetParam = { 361 title: '请输入密码', 362 }; 363 let auth : userAuth.UserAuthInstance; 364 try { 365 auth = userAuth.getUserAuthInstance(authParam, widgetParam); 366 console.info("get auth instance success"); 367 } catch (error) { 368 console.error("get auth instance failed" + JSON.stringify(error)); 369 return; 370 } 371 // 订阅认证结果 372 try { 373 auth.on("result", { 374 onResult(result) { 375 console.info("[HUKS] -> [IAM] userAuthInstance callback result = " + JSON.stringify(result)); 376 fingerAuthToken = result.token; 377 } 378 }); 379 console.info("subscribe authentication event success"); 380 } catch (error) { 381 console.error("subscribe authentication event failed " + JSON.stringify(error)); 382 } 383 // 开始认证 384 try { 385 auth.start(); 386 console.info("authV9 start auth success"); 387 } catch (error) { 388 console.error("authV9 start auth failed, error = " + JSON.stringify(error)); 389 } 390 } 391 function finishSession(handle: number, huksOptions: huks.HuksOptions, token: Uint8Array, throwObject: throwObject) { 392 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 393 try { 394 huks.finishSession(handle, huksOptions, token, (error, data) => { 395 if (error) { 396 reject(error); 397 } else { 398 resolve(data); 399 } 400 }); 401 } catch (error) { 402 throwObject.isThrow = true; 403 throw(error as Error); 404 } 405 }); 406 } 407 async function publicFinishFunc(handle: number, token: Uint8Array, huksOptions: huks.HuksOptions) { 408 console.info(`enter promise doFinish`); 409 let throwObject: throwObject = {isThrow: false}; 410 try { 411 await finishSession(handle, huksOptions, token, throwObject) 412 .then ((data) => { 413 finishOutData = data.outData as Uint8Array; 414 console.info(`promise: doFinish success, data = ${JSON.stringify(data)}`); 415 }) 416 .catch((error: BusinessError) => { 417 if (throwObject.isThrow) { 418 throw(error as Error); 419 } else { 420 console.error(`promise: doFinish failed` + JSON.stringify(error)); 421 } 422 }); 423 } catch (error) { 424 console.error(`promise: doFinish input arg invalid` + JSON.stringify(error)); 425 } 426 } 427 async function testSm4CipherInit() { 428 /* 初始化密钥会话获取挑战值 */ 429 await publicInitFunc(keyAlias, decryptOptions); 430 /* 调用userIAM进行身份认证 */ 431 userIAMAuthFinger(challenge); 432 } 433 async function testSm4CipherFinish() { 434 /* 认证成功后进行解密, 需要传入Auth获取到的authToken值 */ 435 decryptOptions.inData = cipherText; 436 await publicFinishFunc(handle, fingerAuthToken, decryptOptions); 437 } 438 ``` 439