1# HUKS Access Control Development 2 3<!--Kit: Universal Keystore Kit--> 4<!--Subsystem: Security--> 5<!--Owner: @wutiantian-gitee--> 6<!--Designer: @HighLowWorld--> 7<!--Tester: @wxy1234564846--> 8<!--Adviser: @zengyawen--> 9 10For details about scenarios and related concepts, see [HUKS Access Control Overview](huks-identity-authentication-overview.md). 11 12## How to Develop 13 14### Generating a Key 15 16Specify the fingerprint access control type and related properties. 17 18When a key is generated or imported, set [HuksUserAuthType](../../reference/apis-universal-keystore-kit/js-apis-huks.md#huksuserauthtype9), [HuksAuthAccessType](../../reference/apis-universal-keystore-kit/js-apis-huks.md#huksauthaccesstype9), and [HuksChallengeType](../../reference/apis-universal-keystore-kit/js-apis-huks.md#hukschallengetype9). 19 20```ts 21import { huks } from '@kit.UniversalKeystoreKit'; 22 23/* 24 * Set the key alias and encapsulate the key property set. 25 */ 26let keyAlias = 'test_sm4_key_alias'; 27let properties: Array<huks.HuksParam> = [{ 28 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 29 value: huks.HuksKeyAlg.HUKS_ALG_SM4 30}, { 31 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 32 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT 33}, { 34 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 35 value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, 36}, { 37 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 38 value: huks.HuksCipherMode.HUKS_MODE_CBC, 39}, { 40 tag: huks.HuksTag.HUKS_TAG_PADDING, 41 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 42}, 43 // Set HuksUserAuthType to fingerprint authentication. 44 { 45 tag: huks.HuksTag.HUKS_TAG_USER_AUTH_TYPE, 46 value: huks.HuksUserAuthType.HUKS_USER_AUTH_TYPE_FINGERPRINT 47 }, 48 // Set HuksAuthAccessType to HUKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL, which invalidates the key when a new biometric feature (fingerprint) is enrolled. 49 { 50 tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_ACCESS_TYPE, 51 value: huks.HuksAuthAccessType.HUKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL 52 }, 53 // Use the default challenge type. 54 { 55 tag: huks.HuksTag.HUKS_TAG_CHALLENGE_TYPE, 56 value: huks.HuksChallengeType.HUKS_CHALLENGE_TYPE_NORMAL 57 }]; 58 59let huksOptions: huks.HuksOptions = { 60 properties: properties, 61 inData: new Uint8Array(new Array()) 62} 63 64/* 65 * Generate a key. 66 */ 67class ThrowObject { 68 isThrow: boolean = false 69} 70 71function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: ThrowObject) { 72 return new Promise<void>((resolve, reject) => { 73 try { 74 huks.generateKeyItem(keyAlias, huksOptions, (error, data) => { 75 if (error) { 76 reject(error); 77 } else { 78 resolve(data); 79 } 80 }); 81 } catch (error) { 82 throwObject.isThrow = true; 83 throw (error as Error); 84 } 85 }); 86} 87 88async 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 108async function TestGenKeyForFingerprintAccessControl() { 109 await publicGenKeyFunc(keyAlias, huksOptions); 110} 111``` 112 113### Initializing a Key Session 114 115Initiate fingerprint authentication to obtain the access token. 116 117```ts 118import { huks } from '@kit.UniversalKeystoreKit'; 119import { userAuth } from '@kit.UserAuthenticationKit'; 120 121/* 122 * Set the key alias and encapsulate the key property set. 123 */ 124let IV = '1234567890123456'; // Replace this example code with a random value in practice. 125let srcKeyAlias = 'test_sm4_key_alias'; 126let handle: number; 127let challenge: Uint8Array; 128let fingerAuthToken: Uint8Array; 129let authType = userAuth.UserAuthType.FINGERPRINT; 130let authTrustLevel = userAuth.AuthTrustLevel.ATL1; 131/* Set the key generation parameter set and key encryption parameter set. */ 132let properties: Array<huks.HuksParam> = [{ 133 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 134 value: huks.HuksKeyAlg.HUKS_ALG_SM4, 135}, { 136 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 137 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT, 138}, { 139 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 140 value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, 141}, { 142 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 143 value: huks.HuksCipherMode.HUKS_MODE_CBC, 144}, { 145 tag: huks.HuksTag.HUKS_TAG_PADDING, 146 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 147}, { 148 tag: huks.HuksTag.HUKS_TAG_IV, 149 value: StringToUint8Array(IV), 150}]; 151 152function StringToUint8Array(str: string) { 153 let arr: number[] = []; 154 for (let i = 0, j = str.length; i < j; ++i) { 155 arr.push(str.charCodeAt(i)); 156 } 157 return new Uint8Array(arr); 158} 159 160let huksOptions: huks.HuksOptions = { 161 properties: properties, 162 inData: new Uint8Array(new Array()) 163} 164 165class ThrowObject { 166 isThrow: boolean = false 167} 168 169function initSession(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: ThrowObject) { 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/* Initialize the session in the HUKS and obtain the challenge value. */ 186async function publicInitFunc(keyAlias: string, huksOptions: huks.HuksOptions) { 187 console.info(`enter promise doInit`); 188 let throwObject: ThrowObject = { isThrow: false }; 189 try { 190 await initSession(keyAlias, huksOptions, throwObject) 191 .then((data) => { 192 console.info(`promise: doInit success, data = ${JSON.stringify(data)}`); 193 handle = data.handle; 194 challenge = data.challenge as Uint8Array; 195 }) 196 .catch((error: Error) => { 197 if (throwObject.isThrow) { 198 throw (error as Error); 199 } else { 200 console.error(`promise: doInit failed, ` + JSON.stringify(error)); 201 } 202 }); 203 } catch (error) { 204 console.error(`promise: doInit input arg invalid, ` + JSON.stringify(error)); 205 } 206} 207/* Call UserIAM to start fingerprint authentication and trigger the access control process in HUKS. */ 208function userIAMAuthFinger(huksChallenge: Uint8Array) { 209 // Obtain an authentication object. 210 let authTypeList: userAuth.UserAuthType[] = [authType]; 211 const authParam: userAuth.AuthParam = { 212 challenge: huksChallenge, 213 authType: authTypeList, 214 authTrustLevel: userAuth.AuthTrustLevel.ATL1 215 }; 216 const widgetParam: userAuth.WidgetParam = { 217 title: 'Enter password', 218 }; 219 let auth: userAuth.UserAuthInstance; 220 try { 221 auth = userAuth.getUserAuthInstance(authParam, widgetParam); 222 console.info("get auth instance success"); 223 } catch (error) { 224 console.error("get auth instance failed" + JSON.stringify(error)); 225 return; 226 } 227 // Subscribe to the authentication result. 228 try { 229 auth.on("result", { 230 onResult(result) { 231 console.info("[HUKS] -> [IAM] userAuthInstance callback result = " + JSON.stringify(result)); 232 fingerAuthToken = result.token; 233 } 234 }); 235 console.log("subscribe authentication event success"); 236 } catch (error) { 237 console.error("subscribe authentication event failed, " + JSON.stringify(error)); 238 } 239 // Start user authentication. 240 try { 241 auth.start(); 242 console.info("authV9 start auth success"); 243 } catch (error) { 244 console.error("authV9 start auth failed, error = " + JSON.stringify(error)); 245 } 246} 247 248async function testInitAndAuthFinger() { 249 /* Initialize the key session to obtain a challenge. */ 250 await publicInitFunc(srcKeyAlias, huksOptions); 251 /* Invoke userIAM to perform user identity authentication. */ 252 userIAMAuthFinger(challenge); 253} 254``` 255 256### Passing in the Access Token 257 258Perform data operations. 259 260```ts 261/* 262 * The following uses a 128-bit SM4 key as an example. 263 */ 264import { huks } from '@kit.UniversalKeystoreKit'; 265 266/* 267 * Determine the key property set to be encapsulated. 268 */ 269let IV = '1234567890123456'; // Replace this example code with a random value in practice. 270let cipherInData = 'Hks_SM4_Cipher_Test_101010101010101010110_string'; 271let handle: number; 272let fingerAuthToken: Uint8Array; 273let finishOutData: Uint8Array; 274 275class ThrowObject { 276 isThrow: boolean = false; 277} 278 279/* Set the key generation parameter set and key encryption parameter set. */ 280class propertyEncryptType { 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 286let propertiesEncrypt: propertyEncryptType[] = [ 287 { 288 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 289 value: huks.HuksKeyAlg.HUKS_ALG_SM4, 290 }, 291 { 292 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 293 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT, 294 }, 295 { 296 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 297 value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128, 298 }, 299 { 300 tag: huks.HuksTag.HUKS_TAG_PADDING, 301 value: huks.HuksKeyPadding.HUKS_PADDING_NONE, 302 }, 303 { 304 tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE, 305 value: huks.HuksCipherMode.HUKS_MODE_CBC, 306 }, 307 { 308 tag: huks.HuksTag.HUKS_TAG_IV, 309 value: StringToUint8Array(IV), 310 } 311] 312let encryptOptions: huks.HuksOptions = { 313 properties: propertiesEncrypt, 314 inData: new Uint8Array(new Array()) 315} 316 317function StringToUint8Array(str: string) { 318 let arr: number[] = []; 319 for (let i = 0, j = str.length; i < j; ++i) { 320 arr.push(str.charCodeAt(i)); 321 } 322 return new Uint8Array(arr); 323} 324 325function Uint8ArrayToString(dataArray: Uint8Array) { 326 let dataString = ''; 327 for (let i = 0; i < dataArray.length; i++) { 328 dataString += String.fromCharCode(dataArray[i]); 329 } 330 return dataString; 331} 332 333function updateSession(handle: number, huksOptions: huks.HuksOptions, token: Uint8Array, throwObject: ThrowObject) { 334 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 335 try { 336 huks.updateSession(handle, huksOptions, token, (error, data) => { 337 if (error) { 338 reject(error); 339 } else { 340 resolve(data); 341 } 342 }); 343 } catch (error) { 344 throwObject.isThrow = true; 345 throw (error as Error); 346 } 347 }); 348} 349 350async function publicUpdateFunc(handle: number, token: Uint8Array, huksOptions: huks.HuksOptions) { 351 console.info(`enter promise doUpdate`); 352 let throwObject: ThrowObject = { isThrow: false }; 353 try { 354 await updateSession(handle, huksOptions, token, throwObject) 355 .then((data) => { 356 console.info(`promise: doUpdate success, data = ${JSON.stringify(data)}`); 357 }) 358 .catch((error: Error) => { 359 if (throwObject.isThrow) { 360 throw (error as Error); 361 } else { 362 console.error(`promise: doUpdate failed, ` + JSON.stringify(error)); 363 } 364 }); 365 } catch (error) { 366 console.error(`promise: doUpdate input arg invalid, ` + JSON.stringify(error)); 367 } 368} 369 370function finishSession(handle: number, huksOptions: huks.HuksOptions, token: Uint8Array, throwObject: ThrowObject) { 371 return new Promise<huks.HuksReturnResult>((resolve, reject) => { 372 try { 373 huks.finishSession(handle, huksOptions, token, (error, data) => { 374 if (error) { 375 reject(error); 376 } else { 377 resolve(data); 378 } 379 }); 380 } catch (error) { 381 throwObject.isThrow = true; 382 throw (error as Error); 383 } 384 }); 385} 386 387async function publicFinishFunc(handle: number, token: Uint8Array, huksOptions: huks.HuksOptions) { 388 console.info(`enter promise doFinish`); 389 let throwObject: ThrowObject = { isThrow: false }; 390 try { 391 await finishSession(handle, huksOptions, token, throwObject) 392 .then((data) => { 393 finishOutData = data.outData as Uint8Array; 394 console.info(`promise: doFinish success, data = ${JSON.stringify(data)}`); 395 }) 396 .catch((error: Error) => { 397 if (throwObject.isThrow) { 398 throw (error as Error); 399 } else { 400 console.error(`promise: doFinish failed, ` + JSON.stringify(error)); 401 } 402 }); 403 } catch (error) { 404 console.error(`promise: doFinish input arg invalid, ` + JSON.stringify(error)); 405 } 406} 407 408async function testSm4Cipher() { 409 encryptOptions.inData = StringToUint8Array(cipherInData); 410 /* Pass in the access token. */ 411 await publicUpdateFunc(handle, fingerAuthToken, encryptOptions); 412 /* Pass in the access token. */ 413 await publicFinishFunc(handle, fingerAuthToken, encryptOptions); 414 if (Uint8ArrayToString(finishOutData) == cipherInData) { 415 console.info('test finish encrypt error '); 416 } else { 417 console.info('test finish encrypt success'); 418 } 419} 420``` 421