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