• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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