• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 细粒度用户身份认证访问控制开发指导
2
3细粒度用户身份认证访问控制是基于已有用户身份认证访问控制的扩展,提供了基于生物特征和锁屏密码二次身份认证的细粒度访问控制能力,允许设置密钥在加密、解密、签名、验签、密钥协商、密钥派生的单个或多个场景时是否需要进行身份验证。
4
5比如,业务需要使用HUKS密钥加密保存账号密码信息等数据,要求在加密的时候不进行指纹等身份认证,解密的时候需要进行指纹等身份认证,这是就需要依赖HUKS提供细粒度的二次身份认证访问控制机制。
6
7使用该功能仅需在密钥生成阶段,通过额外指定用于细粒度用户身份认证访问控制的HuksTag:HUKS_TAG_KEY_AUTH_PURPOSE,来指定在某种算法用途的情况下需要使用用户身份认证访问控制能力。
8
9> **说明:**
10> 对于对称加解密场景,仅AES/CBCAES/GCMSM4/CBC模式支持细粒度访问控制。
11
12## 开发步骤
13
141. 生成密钥,指定指纹类型的访问控制及相关属性,指定HUKS_TAG_KEY_AUTH_PURPOSE值。
15
16    ```ts
17    import { huks } from "@kit.UniversalKeystoreKit";
18
19    /*
20     * 确定密钥别名和封装密钥属性参数集
21     */
22    let keyAlias = 'test_sm4_key_alias';
23
24    class throwObject {
25      isThrow: boolean = false;
26    }
27
28    let properties: Array<huks.HuksParam> = [
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
67    let huksOptions: huks.HuksOptions = {
68      properties: properties,
69      inData: new Uint8Array(new Array())
70    }
71
72    /*
73     * 生成密钥
74     */
75    async function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) {
76      return new Promise<void>((resolve, reject) => {
77        try {
78          huks.generateKeyItem(keyAlias, huksOptions, (error, data) => {
79            if (error) {
80              reject(error);
81            } else {
82              resolve(data);
83            }
84          });
85        } catch (error) {
86          throwObject.isThrow = true;
87          throw (error as Error);
88        }
89      });
90    }
91
92    async function publicGenKeyFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
93      console.info(`enter promise generateKeyItem`);
94      let throwObject: throwObject = { isThrow: false };
95      try {
96        await generateKeyItem(keyAlias, huksOptions, throwObject)
97          .then((data) => {
98            console.info(`promise: generateKeyItem success, data = ${JSON.stringify(data)}`);
99          })
100          .catch((error: Error) => {
101            if (throwObject.isThrow) {
102              throw (error as Error);
103            } else {
104              console.error(`promise: generateKeyItem failed` + JSON.stringify(error));
105            }
106          });
107      } catch (error) {
108        console.error(`promise: generateKeyItem input arg invalid` + JSON.stringify(error));
109      }
110    }
111
112    async function TestGenKeyForFingerprintAccessControl() {
113      await publicGenKeyFunc(keyAlias, huksOptions);
114    }
115    ```
116
1172. 使用密钥,加密时不需要用户身份认证访问控制。
118
119    ```ts
120    import { huks } from "@kit.UniversalKeystoreKit";
121
122    class HuksProperties {
123      tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM;
124      value: huks.HuksKeyAlg | huks.HuksKeySize | huks.HuksKeyPurpose | huks.HuksKeyPadding | huks.HuksCipherMode
125        | Uint8Array = huks.HuksKeyAlg.HUKS_ALG_ECC;
126    }
127
128    /*
129     * 确定密钥别名和封装密钥属性参数集
130     */
131    let keyAlias = 'test_sm4_key_alias';
132    let cipherInData = 'Hks_SM4_Cipher_Test_101010101010101010110_string'; // 明文数据。
133    let IV = '1234567890123456'; // 此处为样例代码,实际使用需采用随机值。
134    let handle = 0;
135    let cipherText: Uint8Array; // 加密后的密文数据。
136
137    function StringToUint8Array(str: string) {
138      let arr: number[] = [];
139      for (let i = 0, j = str.length; i < j; ++i) {
140        arr.push(str.charCodeAt(i));
141      }
142      return new Uint8Array(arr);
143    }
144
145    /* 集成生成密钥参数集 & 加密参数集 */
146    let propertiesEncrypt: HuksProperties[] = [
147      {
148        tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
149        value: huks.HuksKeyAlg.HUKS_ALG_SM4,
150      },
151      {
152        tag: huks.HuksTag.HUKS_TAG_PURPOSE,
153        value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT,
154      },
155      {
156        tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
157        value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128,
158      },
159      {
160        tag: huks.HuksTag.HUKS_TAG_PADDING,
161        value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
162      },
163      {
164        tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
165        value: huks.HuksCipherMode.HUKS_MODE_CBC,
166      },
167      {
168        tag: huks.HuksTag.HUKS_TAG_IV,
169        value: StringToUint8Array(IV),
170      }
171    ];
172    let encryptOptions: huks.HuksOptions = {
173      properties: propertiesEncrypt,
174      inData: new Uint8Array(new Array())
175    }
176
177    class throwObject1 {
178      isThrow: boolean = false;
179    }
180
181    function initSession(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject1) {
182      return new Promise<huks.HuksSessionHandle>((resolve, reject) => {
183        try {
184          huks.initSession(keyAlias, huksOptions, (error, data) => {
185            if (error) {
186              reject(error);
187            } else {
188              resolve(data);
189            }
190          });
191        } catch (error) {
192          throwObject.isThrow = true;
193          throw (error as Error);
194        }
195      });
196    }
197
198    async function publicInitFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
199      console.info(`enter promise doInit`);
200      let throwObject: throwObject1 = { isThrow: false };
201      try {
202        await initSession(keyAlias, huksOptions, throwObject)
203          .then((data) => {
204            console.info(`promise: doInit success, data = ${JSON.stringify(data)}`);
205            handle = data.handle as number;
206          })
207          .catch((error: Error) => {
208            if (throwObject.isThrow) {
209              throw (error as Error);
210            } else {
211              console.error(`promise: doInit failed` + JSON.stringify(error));
212            }
213          });
214      } catch (error) {
215        console.error(`promise: doInit input arg invalid` + JSON.stringify(error));
216      }
217    }
218
219    function finishSession(handle: number, huksOptions: huks.HuksOptions, throwObject: throwObject1) {
220      return new Promise<huks.HuksReturnResult>((resolve, reject) => {
221        try {
222          huks.finishSession(handle, huksOptions, (error, data) => {
223            if (error) {
224              reject(error);
225            } else {
226              resolve(data);
227            }
228          });
229        } catch (error) {
230          throwObject.isThrow = true;
231          throw (error as Error);
232        }
233      });
234    }
235
236    async function publicFinishFunc(handle: number, huksOptions: huks.HuksOptions) {
237      console.info(`enter promise doFinish`);
238      let throwObject: throwObject1 = { isThrow: false };
239      try {
240        await finishSession(handle, huksOptions, throwObject)
241          .then((data) => {
242            cipherText = data.outData as Uint8Array;
243            console.info(`promise: doFinish success, data = ${JSON.stringify(data)}`);
244          })
245          .catch((error: Error) => {
246            if (throwObject.isThrow) {
247              throw (error as Error);
248            } else {
249              console.error(`promise: doFinish failed` + JSON.stringify(error));
250            }
251          });
252      } catch (error) {
253        console.error(`promise: doFinish input arg invalid` + JSON.stringify(error));
254      }
255    }
256
257    async function testSm4Cipher() {
258      /* 初始化密钥会话获取挑战值 */
259      await publicInitFunc(keyAlias, encryptOptions);
260      /* 加密 */
261      encryptOptions.inData = StringToUint8Array(cipherInData);
262      await publicFinishFunc(handle, encryptOptions);
263    }
264    ```
265
2663. 使用密钥,解密时需要进行用户身份认证访问控制。
267
268    ```ts
269    import { huks } from "@kit.UniversalKeystoreKit";
270    import { userAuth } from '@kit.UserAuthenticationKit';
271    import { BusinessError } from "@kit.BasicServicesKit"
272
273    let keyAlias = 'test_sm4_key_alias';
274    let IV = '1234567890123456'; // 此处为样例代码,实际使用需采用随机值。
275    let handle = 0;
276    let cipherText: Uint8Array; // 密文数据。
277    /*
278    * 确定封装密钥属性参数集
279    */
280    let finishOutData: Uint8Array; // 解密后的明文数据。
281    let fingerAuthToken: Uint8Array;
282    let challenge: Uint8Array;
283    let authType = userAuth.UserAuthType.FINGERPRINT;
284    let authTrustLevel = userAuth.AuthTrustLevel.ATL1;
285
286    class throwObject {
287      isThrow: boolean = false;
288    }
289
290    function StringToUint8Array(str: string) {
291      let arr: number[] = [];
292      for (let i = 0, j = str.length; i < j; ++i) {
293        arr.push(str.charCodeAt(i));
294      }
295      return new Uint8Array(arr);
296    }
297
298    /* 集成生成密钥参数集 & 加密参数集 */
299    class propertyDecryptType {
300      tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM
301      value: huks.HuksKeyAlg | huks.HuksKeyPurpose | huks.HuksKeySize | huks.HuksKeyPadding | huks.HuksCipherMode
302        | Uint8Array = huks.HuksKeyAlg.HUKS_ALG_SM4
303    }
304
305    let propertiesDecrypt: propertyDecryptType[] = [
306      {
307        tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
308        value: huks.HuksKeyAlg.HUKS_ALG_SM4,
309      },
310      {
311        tag: huks.HuksTag.HUKS_TAG_PURPOSE,
312        value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT,
313      },
314      {
315        tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
316        value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128,
317      },
318      {
319        tag: huks.HuksTag.HUKS_TAG_PADDING,
320        value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
321      },
322      {
323        tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
324        value: huks.HuksCipherMode.HUKS_MODE_CBC,
325      },
326      {
327        tag: huks.HuksTag.HUKS_TAG_IV,
328        value: StringToUint8Array(IV),
329      }
330    ]
331    let decryptOptions: huks.HuksOptions = {
332      properties: propertiesDecrypt,
333      inData: new Uint8Array(new Array())
334    }
335
336    function initSession(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) {
337      return new Promise<huks.HuksSessionHandle>((resolve, reject) => {
338        try {
339          huks.initSession(keyAlias, huksOptions, (error, data) => {
340            if (error) {
341              reject(error);
342            } else {
343              resolve(data);
344            }
345          });
346        } catch (error) {
347          throwObject.isThrow = true;
348          throw (error as Error);
349        }
350      });
351    }
352
353    async function publicInitFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
354      console.info(`enter promise doInit`);
355      let throwObject: throwObject = { isThrow: false };
356      try {
357        await initSession(keyAlias, huksOptions, throwObject)
358          .then((data) => {
359            console.info(`promise: doInit success, data = ${JSON.stringify(data)}`);
360            handle = data.handle;
361            challenge = data.challenge as Uint8Array;
362          })
363          .catch((error: BusinessError) => {
364            if (throwObject.isThrow) {
365              throw (error as Error);
366            } else {
367              console.error(`promise: doInit failed` + JSON.stringify(error));
368            }
369          });
370      } catch (error) {
371        console.error(`promise: doInit input arg invalid` + JSON.stringify(error));
372      }
373    }
374
375    function userIAMAuthFinger(huksChallenge: Uint8Array) {
376      // 获取认证对象。
377      let authTypeList: userAuth.UserAuthType[] = [authType];
378      const authParam: userAuth.AuthParam = {
379        challenge: huksChallenge,
380        authType: authTypeList,
381        authTrustLevel: userAuth.AuthTrustLevel.ATL1
382      };
383      const widgetParam: userAuth.WidgetParam = {
384        title: '请输入密码',
385      };
386      let auth: userAuth.UserAuthInstance;
387      try {
388        auth = userAuth.getUserAuthInstance(authParam, widgetParam);
389        console.info("get auth instance success");
390      } catch (error) {
391        console.error("get auth instance failed" + JSON.stringify(error));
392        return;
393      }
394      // 订阅认证结果。
395      try {
396        auth.on("result", {
397          onResult(result) {
398            console.info("[HUKS] -> [IAM]  userAuthInstance callback result = " + JSON.stringify(result));
399            fingerAuthToken = result.token;
400          }
401        });
402        console.info("subscribe authentication event success");
403      } catch (error) {
404        console.error("subscribe authentication event failed " + JSON.stringify(error));
405      }
406      // 开始认证。
407      try {
408        auth.start();
409        console.info("authV9 start auth success");
410      } catch (error) {
411        console.error("authV9 start auth failed, error = " + JSON.stringify(error));
412      }
413    }
414
415    function finishSession(handle: number, huksOptions: huks.HuksOptions, token: Uint8Array, throwObject: throwObject) {
416      return new Promise<huks.HuksReturnResult>((resolve, reject) => {
417        try {
418          huks.finishSession(handle, huksOptions, token, (error, data) => {
419            if (error) {
420              reject(error);
421            } else {
422              resolve(data);
423            }
424          });
425        } catch (error) {
426          throwObject.isThrow = true;
427          throw (error as Error);
428        }
429      });
430    }
431
432    async function publicFinishFunc(handle: number, token: Uint8Array, huksOptions: huks.HuksOptions) {
433      console.info(`enter promise doFinish`);
434      let throwObject: throwObject = { isThrow: false };
435      try {
436        await finishSession(handle, huksOptions, token, throwObject)
437          .then((data) => {
438            finishOutData = data.outData as Uint8Array;
439            console.info(`promise: doFinish success, data = ${JSON.stringify(data)}`);
440          })
441          .catch((error: BusinessError) => {
442            if (throwObject.isThrow) {
443              throw (error as Error);
444            } else {
445              console.error(`promise: doFinish failed` + JSON.stringify(error));
446            }
447          });
448      } catch (error) {
449        console.error(`promise: doFinish input arg invalid` + JSON.stringify(error));
450      }
451    }
452
453    async function testSm4CipherInit() {
454      /* 初始化密钥会话获取挑战值 */
455      await publicInitFunc(keyAlias, decryptOptions);
456      /* 调用userIAM进行身份认证 */
457      userIAMAuthFinger(challenge);
458    }
459
460    async function testSm4CipherFinish() {
461      /* 认证成功后进行解密, 需要传入Auth获取到的authToken值 */
462      decryptOptions.inData = cipherText;
463      await publicFinishFunc(handle, fingerAuthToken, decryptOptions);
464    }
465    ```
466