• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Refined Key Access Control Development
2
3As an extension of the access control based on user identity authentication, the refined key access control provides fine-grained access control capabilities via secondary identity authentication based on biometric features and lock screen passwords. You can set whether identity authentication is required for a key in one or more scenarios such as encryption, decryption, signing, signature verification, key agreement, and key derivation.
4
5For example, a service needs to use a HUKS key to encrypt the account password information. In this scenario, identity authentication is not required in encryption but required in decryption. To achieve this purpose, you can use the refined access control feature provided by HUKS.
6
7To implement this feature, you only need to set **HuksTag** to **HUKS_TAG_KEY_AUTH_PURPOSE**.
8
9## How to Develop
10
111. Generate a key, set HuksUserAuthType to fingerprint authentication, and set other parameters including **HUKS_TAG_KEY_AUTH_PURPOSE**.
12
13   ```ts
14   import huks from '@ohos.security.huks';
15   import { BusinessError } from '@ohos.base';
16   /*
17    * Set the key alias and encapsulate the key property set.
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    * Generate a key.
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. Use the key. User identity authentication is not required when the key is used for encryption.
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    * Set the key alias and encapsulate the key property set.
125    */
126   let srcKeyAlias = 'sm4_key_fingerprint_access';
127   let cipherInData = 'Hks_SM4_Cipher_Test_101010101010101010110_string'; // Plaintext
128   let IV = '1234567890123456';
129   let handle = 0;
130   let cipherText: Uint8Array; // Ciphertext after encryption.
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   /* Set the key generation parameter set and key encryption parameter set. */
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       /* Initialize the key session to obtain a challenge. */
246       await publicInitFunc(srcKeyAlias, encryptOptions);
247       /** Encryption */
248       encryptOptions.inData = StringToUint8Array(cipherInData);
249       await publicFinishFunc(handle, encryptOptions);
250   }
251   ```
252
2533. Use the key. User identity authentication is required when the key is used for decryption.
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    * Set the key alias and encapsulate the key property set.
261    */
262   let srcKeyAlias = 'sm4_key_fingerprint_access';
263   let cipherText = 'r56ywtTJUQC6JFJ2VV2kZw=='; // Ciphertext obtained, which may vary in actual situation.
264   let IV = '1234567890123456';
265   let handle: number;
266   let finishOutData: Uint8Array; // Plaintext after decryption.
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   /* Set the key generation parameter set and key encryption parameter set. */
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       // Obtain an authentication object.
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: 'Enter password',
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       // Subscribe to the authentication result.
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       // Start user authentication.
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       /* Initialize the key session to obtain a challenge. */
432       await publicInitFunc(srcKeyAlias, decryptOptions);
433       /* Invoke userIAM to perform user identity authentication. */
434       userIAMAuthFinger(challenge);
435       /* Perform decryption after the authentication is successful. The **authToken** value returned after the authentication needs to be passed in. */
436       decryptOptions.inData = StringToUint8Array(cipherText);
437       await publicFinishFunc(handle, fingerAuthToken, decryptOptions);
438   }
439   ```
440