场景描述
密钥库使用过程中除了用于加解密外,还用于程序访问控制认证和签名验签,常见的两个场景问题如下:
1、对于密钥库中用户认证以及签名验签的属性配置参数的问题
2、密钥库中细粒度访问控制和普通访问控制的使用问题,以及在访问控制中进行签名验签使用问题
场景一:使用创建的密钥去做用户认证、加签验签以及加解密时,密钥参数如何配置
方案:
1、对于密钥属性的使用,创建的每个密钥对的目的不同,也决定了他的使用方式,例如:加签验签的密钥,不可以用于加解密。
2、对于存在密钥失效的情况,在设置授权访问类型的时候选择密钥总是有效,也可以设置别的类型, 也可以通过校验密钥是否存在来判断设置类型是否生效,以及检查密钥是在什么过程导致的失效。
3、使用ECC加签验签,不可以用于加解密,ECC不支持加解密。
| 算法 | 签名验签 | 支持的规格 | 加解密 | 支持的规格 |
|---|---|---|---|---|
| RSA | 支持签名验签 | RSA/SHA256/PKCS1_V1_5 RSA/SHA384/PKCS1_V1_5 RSA/SHA512/PKCS1_V1_5 RSA/SHA256/PSS RSA/SHA384/PSS RSA/SHA512/PSS | 支持加解密 | RSA/ECB/NoPadding RSA/ECB/PKCS1_V1_5 RSA/ECB/OAEP OAEP (备注:ECB为默认模式,可以不写) |
| SM2 | 支持签名验签 | SM2/SM3 | 支持加解密 | SM2/NoPadding SM2/SM3 |
| AES | 不支持签名验签 | 支持加解密 | AES/CBC/NoPadding AES/CBC/PKCS7 AES/CTR/NoPadding AES/GCM/NoPadding | |
| SM4 | 不支持签名验签 | \ | 支持加解密 | SM4/CTR/NoPadding SM4/CBC/NoPadding |
| ECC | 支持签名验签 | ECC/SHA256 ECC/SHA384 ECC/SHA512 | 不支持加解密 | \ |
效果图:

核心代码:
用于签名验签和加解密的密钥属性(传入对应的huks.HuksKeyPurpose)
//生成密钥属性信息
function getGenerateProperties(purpose: huks.HuksKeyPurpose) {
let properties: Array<huks.HuksParam> = new Array();
let index = 0;
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_SM2
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: purpose
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_DIGEST,
value: huks.HuksKeyDigest.HUKS_DIGEST_SM3
};
return properties;
}
用于用户认证的密钥属性
//生成密钥属性信息
function getGenerateProperties() {
let properties: Array<huks.HuksParam> = new Array();
let index = 0;
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_SM2
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_SIGN | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_VERIFY
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_DIGEST,
value: huks.HuksKeyDigest.HUKS_DIGEST_SM3
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_USER_AUTH_TYPE,
value: huks.HuksUserAuthType.HUKS_USER_AUTH_TYPE_FINGERPRINT
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_ACCESS_TYPE,
value: huks.HuksAuthAccessType.HUKS_AUTH_ACCESS_ALWAYS_VALID
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_CHALLENGE_TYPE,
value: huks.HuksChallengeType.HUKS_CHALLENGE_TYPE_NORMAL
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_SIGN | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_VERIFY
};
return properties;
}
调用方法:在创建密钥对的时候传入
let prop = getGenerateProperties();
let huksOptions: huks.HuksOptions = { properties: prop }
await generateKeyItem(keyAlias, huksOptions)
.then((data) => {
console.info(`huks callback promise: generateKeyItem success, data = ${JSON.stringify(data)}`);
})
.catch((error: BusinessError) => {
console.error(`huks callback promise: generateKeyItem failed` + JSON.stringify(error));
});
场景二:使用细粒度访问控制和普通访问控制做签名验签注意事项以及方案
方案:
1、在使用细粒度访问控制签名验签时和使用普通的访问控制签名验签时要注意需要在创建密钥的时候设置HUKS_TAG_USER_AUTH_TYPE、HUKS_TAG_KEY_AUTH_ACCESS_TYPE、HUKS_TAG_CHALLENGE_TYPE属性,不同处在于细粒度访问控制的签名验签需要设置HUKS_TAG_KEY_AUTH_PURPOSE属性,而在使用普通的访问控制签名验签时不需要设置HUKS_TAG_KEY_AUTH_PURPOSE属性
| 属性 | 用途 |
|---|---|
| HUKS_TAG_USER_AUTH_TYPE | 表示用户认证类型 |
| HUKS_TAG_KEY_AUTH_ACCESS_TYPE | 表示安全访问控制类型 |
| HUKS_TAG_CHALLENGE_TYPE | 表示密钥使用时生成的challenge类型。 |
| HUKS_TAG_KEY_AUTH_PURPOSE | 表示密钥认证用途的tag |
2、细粒度访问控制和普通访问控制的异同:
相同:生成/导入密钥后,即使应用进程被攻击也不会导致未经用户授权的密钥访问,一般用于高敏感且高级别安全保护的场景,比如免密登录、免密支付、自动填充密码保护等。
不同:细粒度用户身份认证访问控制是基于已有用户身份认证访问控制的扩展,提供了基于生物特征和锁屏密码二次身份认证的细粒度访问控制能力,允许设置密钥在加密、解密、签名、验签、密钥协商、密钥派生的单个或多个场景时是否需要进行身份验证。如:业务需要使用HUKS密钥加密保存账号密码信息等数据,要求在加密的时候不进行指纹等身份认证,解密的时候需要进行指纹等身份认证,这是就需要依赖HUKS提供细粒度的二次身份认证访问控制机制。
3、在访问控制时,密钥生成失败有以下两种情况:
a. 设置了对应的AccessType,但没有录入对应的生物特征:
HUKS_AUTH_ACCESS_INVALID_CLEAR_PASSWORD ->需预置PIN码
HUKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL ->需要预置人脸/指纹
b. 设置的认证类型组合不支持。暂不支持 HUKS_USER_AUTH_TYPE_PIN 与 HUKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL的组合
效果图:

核心代码:
第一步:创建细粒度访问控制签名验签的密钥对 创建密钥对对应属性:
/*密钥属性 用于细粒度用户程序访问控制的签名验签创建密钥的属性 */
function getGenerateProperties() {
let properties: Array<huks.HuksParam> = new Array();
let index = properties.length;
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_ECC
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_ECC_KEY_SIZE_256
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_SIGN | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_VERIFY
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_DIGEST,
value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_USER_AUTH_TYPE,
value: huks.HuksUserAuthType.HUKS_USER_AUTH_TYPE_FINGERPRINT
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_ACCESS_TYPE,
value: huks.HuksAuthAccessType.HUKS_AUTH_ACCESS_ALWAYS_VALID
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_CHALLENGE_TYPE,
value: huks.HuksChallengeType.HUKS_CHALLENGE_TYPE_NORMAL
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_KEY_AUTH_PURPOSE,
value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_SIGN | huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_VERIFY
};
return properties;
}
第二步:进行用户认证后签名
1、调用 let prop = getKeyPropV(huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_SIGN, isAuthBio);获取到签名功能对应的属性
/*签名验签属性*/
function getKeyPropV(purpose: huks.HuksKeyPurpose) {
let properties: Array<huks.HuksParam> = new Array();
let index = properties.length;
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
value: huks.HuksKeyAlg.HUKS_ALG_ECC
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
value: huks.HuksKeySize.HUKS_ECC_KEY_SIZE_256
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_PURPOSE,
value: purpose
};
properties[index++] = {
tag: huks.HuksTag.HUKS_TAG_DIGEST,
value: huks.HuksKeyDigest.HUKS_DIGEST_SHA256
};
return properties;
}
2、调用initSession初始化 (传入密钥别名和签名)获取到初始化后的挑战值
3、将拿到的跳转值传入用户认证的方法authBio (传入挑战值) 注:用户认证方法在最后
4、用户认证后得到一个用户标识token
5、将用户标识token传入调用的finishSession接口,进行签名
6、将签名数据(uint8Array数组)转为Hex格式字符串用于保存
//在用户认证后进行签名
async function signature(keyAlias: string, plaintext: Uint8Array, isAuthBio: Boolean): Promise<Uint8Array> {
let prop = getKeyPropV(huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_SIGN, isAuthBio);
let options: huks.HuksOptions = {
properties: prop,
inData: plaintext
}
let handle: number = 0;
let authChallenge: Uint8Array | undefined = new Uint8Array(0);
let authToken: Uint8Array | undefined = undefined;
let outData: Uint8Array | undefined = new Uint8Array(0);
await huks.initSession(keyAlias, options).then((hukHandle) => {
handle = hukHandle.handle;
if (isAuthBio) {
//拿到挑战值,用于用户认证
authChallenge = hukHandle.challenge;
}
}).catch((err: BusinessError) => {
console.error(JSON.stringify(err));
});
if (isAuthBio) {
//用户认证,传入密钥库初始化拿到的挑战值,认证结束后,取出返回结果,拿到用户标识token
authToken = await authBio(authChallenge);
}
//传入用户标识token,进行加签
await huks.finishSession(handle, options, authToken).then((hukRet) => {
//用户认证加签结果,得到Uint8Array数组
outData = hukRet.outData;
}).catch((err: BusinessError) => {
console.error(JSON.stringify(err));
})
return outData;
}
第三步:调用verify方法进行用户访问控制的验签
1、调用 let prop = getKeyPropV(huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_VERIFY isAuthBio);获取到验签功能对应的属性
2、调用initSession初始化 (传入密钥别名和签名)获取到初始化后的挑战值
3、将拿到的跳转值传入用户认证的方法authBio (传入挑战值) 注:用户认证方法在最后
4、用户认证后得到一个用户标识token
5、将用户标识token和签名后数据以及待验签数据传入调用的finishSession接口进行验签
注:调用的finishSession接口中传入的options的数据inData值要和initSession初始化的值区分
6、验签成功后,返回的数组为全是0的数组
//在用户认证后进行验签
async function verify(keyAlias: string, plaintext: Uint8Array, signature: Uint8Array, isAuthBio: Boolean = false): Promise<Boolean> {
let prop = getKeyPropV(huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_VERIFY, isAuthBio);
let options: huks.HuksOptions = {
properties: prop,
inData: plaintext
}
let result: Boolean = false;
let handle: number = 0;
let authChallenge: Uint8Array | undefined = new Uint8Array(0);
await huks.initSession(keyAlias, options).then((hukHandle) => {
handle = hukHandle.handle;
if (isAuthBio) {
//拿到挑战值,用于用户认证
authChallenge = hukHandle.challenge;
}
}).catch((err: BusinessError) => {
console.error(JSON.stringify(err));
result = false;
});
if (isAuthBio) {
console.error(`huks callback authChallenge: ` + authChallenge);
//用户认证,传入密钥库初始化拿到的挑战值,认证结束后,取出返回结果,拿到用户标识token
authToken = await authBio(authChallenge);
console.error(`huks callback authToken: ` + authToken);
}
//这个地方要注意,要传入的是待验签的数据,和上面初始化的inData是不一样的
options.inData = signature;
await huks.finishSession(handle, options, authToken)
.then((hukRet) => {
//用户认证验签结果,得到Uint8Array数组,此时数组数据为全是0的数组,代表验签成功
result = true;
}).catch((err: BusinessError) => {
console.error('finish error: ' + JSON.stringify(err));
result = false;
})
return result;
}
用户认证的方法
async function authBio(authChallenge: Uint8Array): Promise<Uint8Array> {
return new Promise((resolve, reject) => {
// 设置认证参数
const authParam: userIAM_userAuth.AuthParam = {
challenge: authChallenge,
authType: [userIAM_userAuth.UserAuthType.FINGERPRINT],
authTrustLevel: userIAM_userAuth.AuthTrustLevel.ATL4,
};
// 配置认证界面
const widgetParam: userIAM_userAuth.WidgetParam = {
title: '请进行身份认证',
};
try {
// 获取认证对象
let userAuthInstance = userIAM_userAuth.getUserAuthInstance(authParam, widgetParam);
// 订阅认证结果
userAuthInstance.on('result', {
onResult(result) {
console.error('result:' + JSON.stringify(result));
// 可在认证结束或其他业务需要场景,取消订阅认证结果
userAuthInstance.off('result');
if (result.result == userIAM_userAuth.UserAuthResultCode.SUCCESS) {
resolve(result.token);
} else {
reject(result.result);
}
}
});
userAuthInstance.start();
} catch (error) {
const err: BusinessError = error as BusinessError;
console.log(`auth catch error. Code is ${err?.code}, message is ${err?.message}`);
reject(err?.code);
}
});
}
鸿蒙全栈开发全新学习指南
有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以要有一份实用的鸿蒙(HarmonyOS NEXT)学习路线与学习文档用来跟着学习是非常有必要的。
针对一些列因素,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。
本路线共分为四个阶段:
第一阶段:鸿蒙初中级开发必备技能

第二阶段:鸿蒙南北双向高工技能基础:gitee.com/MNxiaona/733GH

第三阶段:应用开发中高级就业技术

第四阶段:全网首发-工业级南向设备开发就业技术:gitee.com/MNxiaona/733GH

《鸿蒙 (Harmony OS)开发学习手册》(共计892页)
如何快速入门?
1.基本概念
2.构建第一个ArkTS应用
3.……

开发基础知识:gitee.com/MNxiaona/733GH
1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

基于ArkTS 开发
1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

鸿蒙开发面试真题(含参考答案):gitee.com/MNxiaona/733GH

鸿蒙入门教学视频:

美团APP实战开发教学:gitee.com/MNxiaona/733GH

写在最后
- 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
- 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
- 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
- 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:
gitee.com/MNxiaona/733GH


1168

被折叠的 条评论
为什么被折叠?



