【鸿蒙实战开发】基于密钥库签名验签的用户认证

101 篇文章 0 订阅
101 篇文章 2 订阅

场景描述

密钥库使用过程中除了用于加解密外,还用于程序访问控制认证和签名验签,常见的两个场景问题如下:

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

  • 30
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值