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