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   let keyAlias = 'test_sm4_key_alias';
22   class throwObject {
23       isThrow: boolean = false;
24   }
25
26   let properties: Array<huks.HuksParam> = [
27       {
28           tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
29           value: huks.HuksKeyAlg.HUKS_ALG_SM4,
30       },
31       {
32           tag: huks.HuksTag.HUKS_TAG_PURPOSE,
33           value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT,
34       },
35       {
36           tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
37           value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128,
38       },
39       {
40           tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
41           value: huks.HuksCipherMode.HUKS_MODE_CBC,
42       },
43       {
44           tag: huks.HuksTag.HUKS_TAG_PADDING,
45           value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
46       },
47       {
48           tag: huks.HuksTag.HUKS_TAG_USER_AUTH_TYPE,
49           value: huks.HuksUserAuthType.HUKS_USER_AUTH_TYPE_FINGERPRINT
50       },
51       {
52           tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_ACCESS_TYPE,
53           value: huks.HuksAuthAccessType.HUKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL
54       },
55       {
56           tag: huks.HuksTag.HUKS_TAG_CHALLENGE_TYPE,
57           value: huks.HuksChallengeType.HUKS_CHALLENGE_TYPE_NORMAL
58       },
59       {
60           tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_PURPOSE,
61           value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT
62       }
63   ];
64
65   let huksOptions: huks.HuksOptions = {
66       properties: properties,
67       inData: new Uint8Array(new Array())
68   }
69   /*
70    * 生成密钥
71    */
72   async function generateKeyItem(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) {
73       return new Promise<void>((resolve, reject) => {
74           try {
75               huks.generateKeyItem(keyAlias, huksOptions, (error, data) => {
76                   if (error) {
77                       reject(error);
78                   } else {
79                       resolve(data);
80                   }
81               });
82           } catch (error) {
83               throwObject.isThrow = true;
84               throw(error as Error);
85           }
86       });
87   }
88   async 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   async function TestGenKeyForFingerprintAccessControl() {
108       await publicGenKeyFunc(keyAlias, huksOptions);
109   }
110   ```
111
1122. 使用密钥,加密时不需要用户身份认证访问控制。
113
114   ```ts
115   import { huks } from "@kit.UniversalKeystoreKit";
116   class HuksProperties {
117       tag: huks.HuksTag = huks.HuksTag.HUKS_TAG_ALGORITHM;
118       value: huks.HuksKeyAlg | huks.HuksKeySize | huks.HuksKeyPurpose | huks.HuksKeyPadding | huks.HuksCipherMode
119           | Uint8Array = huks.HuksKeyAlg.HUKS_ALG_ECC;
120   }
121   /*
122    * 确定密钥别名和封装密钥属性参数集
123    */
124   let cipherInData = 'Hks_SM4_Cipher_Test_101010101010101010110_string'; // 明文数据
125   let IV = '1234567890123456';
126   let handle = 0;
127   let cipherText: Uint8Array; // 加密后的密文数据
128   function StringToUint8Array(str: string) {
129       let arr: number[] = [];
130       for (let i = 0, j = str.length; i < j; ++i) {
131           arr.push(str.charCodeAt(i));
132       }
133       return new Uint8Array(arr);
134   }
135   /* 集成生成密钥参数集 & 加密参数集 */
136   let propertiesEncrypt: HuksProperties[] = [
137       {
138           tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
139           value: huks.HuksKeyAlg.HUKS_ALG_SM4,
140       },
141       {
142           tag: huks.HuksTag.HUKS_TAG_PURPOSE,
143           value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT,
144       },
145       {
146           tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
147           value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128,
148       },
149       {
150           tag: huks.HuksTag.HUKS_TAG_PADDING,
151           value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
152       },
153       {
154           tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
155           value: huks.HuksCipherMode.HUKS_MODE_CBC,
156       },
157       {
158           tag: huks.HuksTag.HUKS_TAG_IV,
159           value: StringToUint8Array(IV),
160       }
161   ];
162   let encryptOptions: huks.HuksOptions = {
163       properties: propertiesEncrypt,
164       inData: new Uint8Array(new Array())
165   }
166   class throwObject1{
167       isThrow: boolean = false;
168   }
169   function initSession(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject1) {
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   async function publicInitFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
186       console.info(`enter promise doInit`);
187       let throwObject: throwObject1 = { isThrow: false };
188       try {
189           await initSession(keyAlias, huksOptions, throwObject)
190           .then((data) => {
191               console.info(`promise: doInit success, data = ${JSON.stringify(data)}`);
192               handle = data.handle as number;
193           })
194           .catch((error: Error) => {
195               if (throwObject.isThrow) {
196                   throw (error as Error);
197               } else {
198                   console.error(`promise: doInit failed` + JSON.stringify(error));
199               }
200           });
201       } catch (error) {
202           console.error(`promise: doInit input arg invalid` + JSON.stringify(error));
203       }
204   }
205   function finishSession(handle: number, huksOptions: huks.HuksOptions, throwObject: throwObject1) {
206       return new Promise<huks.HuksReturnResult>((resolve, reject) => {
207           try {
208               huks.finishSession(handle, huksOptions, (error, data) => {
209                   if (error) {
210                       reject(error);
211                   } else {
212                       resolve(data);
213                   }
214               });
215           } catch (error) {
216               throwObject.isThrow = true;
217               throw (error as Error);
218           }
219       });
220   }
221   async function publicFinishFunc(handle: number, huksOptions: huks.HuksOptions) {
222       console.info(`enter promise doFinish`);
223       let throwObject: throwObject1 = { isThrow: false };
224       try {
225           await finishSession(handle, huksOptions, throwObject)
226           .then((data) => {
227               cipherText = data.outData as Uint8Array;
228               console.info(`promise: doFinish success, data = ${JSON.stringify(data)}`);
229           })
230           .catch((error: Error) => {
231               if (throwObject.isThrow) {
232                   throw (error as Error);
233               } else {
234                   console.error(`promise: doFinish failed` + JSON.stringify(error));
235               }
236           });
237       } catch (error) {
238           console.error(`promise: doFinish input arg invalid` + JSON.stringify(error));
239       }
240   }
241   async function testSm4Cipher() {
242       /* 初始化密钥会话获取挑战值 */
243       await publicInitFunc(keyAlias, encryptOptions);
244       /* 加密 */
245       encryptOptions.inData = StringToUint8Array(cipherInData);
246       await publicFinishFunc(handle, encryptOptions);
247   }
248   ```
249
2503. 使用密钥,解密时需要进行用户身份认证访问控制。
251
252   ```ts
253    import { huks } from "@kit.UniversalKeystoreKit";
254    import { userAuth } from '@kit.UserAuthenticationKit';
255    import { BusinessError } from "@kit.BasicServicesKit"
256
257    let keyAlias = 'test_sm4_key_alias';
258    let IV = '1234567890123456';
259    let handle = 0;
260    let cipherText: Uint8Array; // 密文数据
261    /*
262    * 确定封装密钥属性参数集
263    */
264    let finishOutData: Uint8Array; // 解密后的明文数据
265    let fingerAuthToken: Uint8Array;
266    let challenge: Uint8Array;
267    let authType = userAuth.UserAuthType.FINGERPRINT;
268    let authTrustLevel = userAuth.AuthTrustLevel.ATL1;
269    class throwObject {
270        isThrow: boolean = false;
271    }
272    function StringToUint8Array(str: string) {
273        let arr: number[] = [];
274        for (let i = 0, j = str.length; i < j; ++i) {
275            arr.push(str.charCodeAt(i));
276        }
277        return new Uint8Array(arr);
278    }
279    /* 集成生成密钥参数集 & 加密参数集 */
280    class propertyDecryptType {
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    let propertiesDecrypt: propertyDecryptType[] = [
286        {
287            tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
288            value: huks.HuksKeyAlg.HUKS_ALG_SM4,
289        },
290        {
291            tag: huks.HuksTag.HUKS_TAG_PURPOSE,
292            value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT,
293        },
294        {
295            tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
296            value: huks.HuksKeySize.HUKS_SM4_KEY_SIZE_128,
297        },
298        {
299            tag: huks.HuksTag.HUKS_TAG_PADDING,
300            value: huks.HuksKeyPadding.HUKS_PADDING_NONE,
301        },
302        {
303            tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,
304            value: huks.HuksCipherMode.HUKS_MODE_CBC,
305        },
306        {
307            tag: huks.HuksTag.HUKS_TAG_IV,
308            value: StringToUint8Array(IV),
309        }
310    ]
311    let decryptOptions: huks.HuksOptions = {
312        properties: propertiesDecrypt,
313        inData: new Uint8Array(new Array())
314    }
315    function initSession(keyAlias: string, huksOptions: huks.HuksOptions, throwObject: throwObject) {
316        return new Promise<huks.HuksSessionHandle>((resolve, reject) => {
317            try {
318                huks.initSession(keyAlias, huksOptions, (error, data) => {
319                    if (error) {
320                        reject(error);
321                    } else {
322                        resolve(data);
323                    }
324                });
325            } catch (error) {
326                throwObject.isThrow = true;
327                throw(error as Error);
328            }
329        });
330    }
331    async function publicInitFunc(keyAlias: string, huksOptions: huks.HuksOptions) {
332    console.info(`enter promise doInit`);
333    let throwObject: throwObject = {isThrow: false};
334    try {
335        await initSession(keyAlias, huksOptions, throwObject)
336        .then ((data) => {
337            console.info(`promise: doInit success, data = ${JSON.stringify(data)}`);
338            handle = data.handle;
339            challenge = data.challenge as Uint8Array;
340        })
341        .catch((error: BusinessError) => {
342            if (throwObject.isThrow) {
343            throw(error as Error);
344            } else {
345            console.error(`promise: doInit failed` + JSON.stringify(error));
346            }
347        });
348    } catch (error) {
349        console.error(`promise: doInit input arg invalid` + JSON.stringify(error));
350    }
351    }
352    function userIAMAuthFinger(huksChallenge: Uint8Array) {
353    // 获取认证对象
354    let authTypeList:userAuth.UserAuthType[]= [ authType ];
355    const authParam:userAuth.AuthParam = {
356        challenge: huksChallenge,
357        authType: authTypeList,
358        authTrustLevel: userAuth.AuthTrustLevel.ATL1
359    };
360    const widgetParam:userAuth.WidgetParam = {
361        title: '请输入密码',
362    };
363    let auth : userAuth.UserAuthInstance;
364    try {
365        auth = userAuth.getUserAuthInstance(authParam, widgetParam);
366        console.info("get auth instance success");
367    } catch (error) {
368        console.error("get auth instance failed" + JSON.stringify(error));
369        return;
370    }
371    // 订阅认证结果
372    try {
373        auth.on("result", {
374        onResult(result) {
375            console.info("[HUKS] -> [IAM]  userAuthInstance callback result = " + JSON.stringify(result));
376            fingerAuthToken = result.token;
377        }
378        });
379        console.info("subscribe authentication event success");
380    } catch (error) {
381        console.error("subscribe authentication event failed " + JSON.stringify(error));
382    }
383    // 开始认证
384    try {
385        auth.start();
386        console.info("authV9 start auth success");
387    } catch (error) {
388        console.error("authV9 start auth failed, error = " + JSON.stringify(error));
389    }
390    }
391    function finishSession(handle: number, huksOptions: huks.HuksOptions, token: Uint8Array, throwObject: throwObject) {
392    return new Promise<huks.HuksReturnResult>((resolve, reject) => {
393        try {
394        huks.finishSession(handle, huksOptions, token, (error, data) => {
395            if (error) {
396            reject(error);
397            } else {
398            resolve(data);
399            }
400        });
401        } catch (error) {
402        throwObject.isThrow = true;
403        throw(error as Error);
404        }
405    });
406    }
407    async function publicFinishFunc(handle: number, token: Uint8Array, huksOptions: huks.HuksOptions) {
408    console.info(`enter promise doFinish`);
409    let throwObject: throwObject = {isThrow: false};
410    try {
411        await finishSession(handle, huksOptions, token, throwObject)
412        .then ((data) => {
413            finishOutData = data.outData as Uint8Array;
414            console.info(`promise: doFinish success, data = ${JSON.stringify(data)}`);
415        })
416        .catch((error: BusinessError) => {
417            if (throwObject.isThrow) {
418                throw(error as Error);
419            } else {
420                console.error(`promise: doFinish failed` + JSON.stringify(error));
421            }
422        });
423    } catch (error) {
424        console.error(`promise: doFinish input arg invalid` + JSON.stringify(error));
425    }
426    }
427    async function testSm4CipherInit() {
428        /* 初始化密钥会话获取挑战值 */
429        await publicInitFunc(keyAlias, decryptOptions);
430        /* 调用userIAM进行身份认证 */
431        userIAMAuthFinger(challenge);
432    }
433    async function testSm4CipherFinish() {
434        /* 认证成功后进行解密, 需要传入Auth获取到的authToken值 */
435        decryptOptions.inData = cipherText;
436        await publicFinishFunc(handle, fingerAuthToken, decryptOptions);
437    }
438   ```
439