• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 细粒度用户身份认证访问控制开发指导
2
3细粒度用户身份认证访问控制是基于已有用户身份认证访问控制的扩展,提供了基于生物特征和锁屏密码二次身份认证的细粒度访问控制能力,允许设置密钥在加密、解密、签名、验签、密钥协商、密钥派生的单个或多个场景时是否需要进行身份验证。
4
5比如,业务需要使用HUKS密钥加密保存账号密码信息等数据,要求在加密的时候不进行指纹等身份认证,解密的时候需要进行指纹等身份认证,这是就需要依赖HUKS提供细粒度的二次身份认证访问控制机制。
6
7使用该功能仅需在密钥生成阶段,通过额外指定用于细粒度用户身份认证访问控制的HuksTag:HUKS_TAG_KEY_AUTH_PURPOSE,来指定在某种算法用途的情况下需要使用用户身份认证访问控制能力。
8
9## 开发步骤
10
111. 生成密钥,指定指纹类型的访问控制及相关属性,指定HUKS_TAG_KEY_AUTH_PURPOSE值。
12
13   ```ts
14   import huks from '@ohos.security.huks';
15   import { BusinessError } from '@ohos.base';
16   /*
17    * 确定密钥别名和封装密钥属性参数集
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    * 生成密钥
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. 使用密钥,加密时不需要用户身份认证访问控制。
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    * 确定密钥别名和封装密钥属性参数集
125    */
126   let srcKeyAlias = 'sm4_key_fingerprint_access';
127   let cipherInData = 'Hks_SM4_Cipher_Test_101010101010101010110_string'; // 明文数据
128   let IV = '1234567890123456';
129   let handle = 0;
130   let cipherText: Uint8Array; // 加密后的密文数据
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   /* 集成生成密钥参数集 & 加密参数集 */
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       /* 初始化密钥会话获取挑战值 */
246       await publicInitFunc(srcKeyAlias, encryptOptions);
247       /* 加密 */
248       encryptOptions.inData = StringToUint8Array(cipherInData);
249       await publicFinishFunc(handle, encryptOptions);
250   }
251   ```
252
2533. 使用密钥,解密时需要进行用户身份认证访问控制。
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    * 确定密钥别名和封装密钥属性参数集
261    */
262   let srcKeyAlias = 'sm4_key_fingerprint_access';
263   let cipherText = 'r56ywtTJUQC6JFJ2VV2kZw=='; // 加密时得到的密文数据, 业务需根据实际加密结果修改
264   let IV = '1234567890123456';
265   let handle: number;
266   let finishOutData: Uint8Array; // 解密后的明文数据
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   /* 集成生成密钥参数集 & 加密参数集 */
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       // 获取认证对象
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: '请输入密码',
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       // 订阅认证结果
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       // 开始认证
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       /* 初始化密钥会话获取挑战值 */
432       await publicInitFunc(srcKeyAlias, decryptOptions);
433       /* 调用userIAM进行身份认证 */
434       userIAMAuthFinger(challenge);
435       /* 认证成功后进行解密, 需要传入Auth获取到的authToken值 */
436       decryptOptions.inData = StringToUint8Array(cipherText);
437       await publicFinishFunc(handle, fingerAuthToken, decryptOptions);
438   }
439   ```
440