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