【HarmonyOS NEXT】关键资产存储开发案例

在 iOS 开发中 Keychain 是一个非常安全的存储系统,用于保存敏感信息,如密码、证书、密钥等。与文件系统不同,Keychain 提供了更高的安全性,因为它对数据进行了加密,并且只有经过授权的应用程序才能访问存储的数据。那么在鸿蒙里面对应的是什么呢?

1、关键资产(@ohos.security.asset)

在鸿蒙里面也有类似的东西,叫做关键资产(@ohos.security.asset),关键资产存储服务提供了用户短敏感数据的安全存储及管理能力。其中,短敏感数据可以是密码类(账号/密码)、Token类(应用凭据)、其他关键明文(如银行卡号)等长度较短的用户敏感数据。

关键资产的安全存储,依赖底层的通用密钥库系统。具体来说,关键资产的加/解密操作以及访问控制校验,都由通用密钥库系统在安全环境(如可信执行环境)中完成,即使系统被攻破,也能保证用户敏感数据不发生泄露。其中,关键资产的加/解密使用AES256-GCM算法。

2、关键资产使用与 asset 的常用操作

关键资产的访问可分为 4 类(可查看本文第4章节),基于属主的访问控制、基于锁屏状态的访问控制、基于锁屏密码设置状态的访问控制、基于用户认证的访问控制,业务可根据实际情况决定是否开启(如扫脸验证、解锁验证、密码验证等),本次文章举例的开发案例均采用默认保护等级。

 2.1 使用关键资产需要导入模块 AssetStoreKit:

import { asset } from '@kit.AssetStoreKit';

2.2 常用操作:

方法描述
asset.add新增一条关键资产。
asset.remove删除符合条件的一条或多条关键资产。
asset.update更新符合条件的一条关键资产。
asset.query查询一条或多条符合条件的关键资产。若查询需要用户认证的关键资产,则需要在本函数前调用asset.preQuery,在本函数后调用asset.postQuery。
asset.preQuery查询的预处理,用于需要用户认证的关键资产。在用户认证成功后,应当随后调用asset.query、asset.postQuery。
asset.postQuery查询的后置处理,用于需要用户认证的关键资产。需与asset.preQuery函数成对出现。

3、常规方法封装

3.1 addSync 设置数据

/*** 新增一条关键资产* @param key* @param value* @returns*/add(key: string, value: string) {let result: Booleanlet attr: asset.AssetMap = new Map();// 关键资产别名,每条关键资产的唯一索引。// 类型为Uint8Array,长度为1-256字节。attr.set(asset.Tag.SECRET, this.string2Array(value));// 关键资产明文。// 类型为Uint8Array,长度为1-1024字节attr.set(asset.Tag.ALIAS, this.string2Array(key))// 关键资产同步类型>THIS_DEVICE只在本设备进行同步,如仅在本设备还原的备份场景。attr.set(asset.Tag.SYNC_TYPE, asset.SyncType.THIS_DEVICE);//枚举,新增关键资产时的冲突(如:别名相同)处理策略。OVERWRITE》抛出异常,由业务进行后续处理。// attr.set(asset.Tag.CONFLICT_RESOLUTION,asset.ConflictResolution.THROW_ERROR)// 在应用卸载时是否需要保留关键资产。// 需要权限: ohos.permission.STORE_PERSISTENT_DATA。// 类型为bool。// attr.set(asset.Tag.IS_PERSISTENT, true);//我项目里面没有使用就先注释了,后续有需要这个再打开,并且要设置对应权限if (this.isHasKey(key)) {result = this.updateAssetMap(attr);} else {try {if (canIUse("SystemCapability.Security.Asset")) {asset.addSync(attr);result = true}result = false} catch (error) {let err = error as BusinessError;LogUtil.e(`Failed to add Asset. Code is ${err.code}, message is ${err.message}`);result = false}}return result}

3.2 querySync 获取数据

/*** 查询* @param key* @returns*/query(key: string) {let query: asset.AssetMap = new Map();// 关键资产别名,每条关键资产的唯一索引。// 类型为Uint8Array,长度为1-256字节。query.set(asset.Tag.ALIAS, this.string2Array(key));//  关键资产查询返回的结果类型。query.set(asset.Tag.RETURN_TYPE, asset.ReturnType.ALL);// query.set(asset.Tag.RETURN_TYPE, asset.ReturnType.ATTRIBUTES); // 此处表示仅返回关键资产属性,不包含关键资产明文try {if (canIUse("SystemCapability.Security.Asset")) {let res: Array<asset.AssetMap> = asset.querySync(query);for (let i = 0; i < res.length; i++) {// parse the attribute.if (res[i] != null) {// parse the secret.let secret: Uint8Array = res[0].get(asset.Tag.SECRET) as Uint8Array;// parse uint8array to stringlet secretStr: string = this.array2String(secret);return secretStr;}}}} catch (error) {let err = error as BusinessError;LogUtil.e(TAG, `Failed to query Asset. Code is ${err.code}, message is ${err.message}`);return "";}return ""}

3.3 querySync 查询 key 数据是否存在

/*** 查询资产key是否存在* @param key* @returns*/isHasKey(key: string): Boolean {if (canIUse("SystemCapability.Security.Asset")) {let query: asset.AssetMap = new Map();// 关键资产别名,每条关键资产的唯一索引。// 类型为Uint8Array,长度为1-256字节。query.set(asset.Tag.ALIAS, this.string2Array(key));//  关键资产查询返回的结果类型。query.set(asset.Tag.RETURN_TYPE, asset.ReturnType.ALL);const res = this.queryAssetMap(query);if (!res || res.length < 1) {return false;}return true;}return false;}
/*** 查询资产 key 的 assetMaps 数据* @param query* @returns*/queryAssetMap(query: asset.AssetMap): Array<asset.AssetMap> {const assetMaps: asset.AssetMap[] = [];try {if (canIUse("SystemCapability.Security.Asset")) {const res: asset.AssetMap[] = asset.querySync(query);return res;}return assetMaps;} catch (error) {const err = error as BusinessError;LogUtil.e(TAG, `Failed to query Asset. Code is ${err.code}, message is ${err.message}`);return assetMaps;}}

3.4 updateSync 修改资产数据

/*** 修改资产数据* @param q* @returns*/updateAssetMap(q: asset.AssetMap): Boolean {try {if (canIUse("SystemCapability.Security.Asset")) {let query: asset.AssetMap = new Map();query.set(asset.Tag.ALIAS, q.get(asset.Tag.ALIAS)!);let attrsToUpdate: asset.AssetMap = new Map();attrsToUpdate.set(asset.Tag.SECRET, q.get(asset.Tag.SECRET)!);asset.updateSync(query, attrsToUpdate);return true}return false} catch (error) {const err = error as BusinessError;LogUtil.e(TAG, `Failed to update Asset. Code is ${err.code}, message is ${err.message}`);return false;}}

3.5 removeSync 删除资产数据

/*** 删除一条关键资产* @param key*/remove(key: string) {let query: asset.AssetMap = new Map();// 关键资产别名,每条关键资产的唯一索引。query.set(asset.Tag.ALIAS, this.string2Array(key));try {if (canIUse("SystemCapability.Security.Asset")) {asset.removeSync(query);return true;}return false;} catch (error) {let err = error as BusinessError;LogUtil.e(TAG, `Failed to remove Asset. Code is ${err.code}, message is ${err.message}`);return false;}}

3.6 string 与 Uint8Array 数据互转换

  string2Array(str: string): Uint8Array {let textEncoder = new util.TextEncoder();return textEncoder.encodeInto(str);}array2String(str: Uint8Array): string {let textDecoder = new util.TextDecoder();return textDecoder.decodeToString(str);}

4、关键资产的访问控制

  • 基于属主的访问控制: 所有的关键资产都受属主访问控制保护,业务无需设置。

    • 只允许关键资产被其属主(写入该关键资产的业务)访问。
    • 关键资产属主身份由ASSET从系统服务中获取,即使业务身份被仿冒,仿冒者也无法获取到其他业务的数据。
    • 关键资产加/解密时,其属主身份参与了完整性保护,即使关键资产属主身份被篡改,攻击者也无法获取到其他业务的数据。
  • 基于锁屏状态的访问控制: 分为以下三种保护等级(安全性依次递增),业务可根据实际情况设置任意一种,若不设置,则默认保护等级为“首次解锁后可访问”。

    • 开机后可访问:关键资产在开机后被允许访问。
    • 首次解锁后可访问:关键资产在首次解锁后被允许访问。
    • 解锁时可访问:关键资产仅在处于解锁状态时被允许访问。
  • 基于锁屏密码设置状态的访问控制: 该访问控制默认不开启,业务可根据实际情况决定是否开启。

    • 在用户设置了锁屏密码后,关键资产才被允许访问。
  • 基于用户认证的访问控制: 该访问控制默认不开启,业务可根据实际情况决定是否开启。

    • 关键资产在用户身份认证通过后被允许访问。
    • 任意一种认证方式(指纹、人脸、PIN码)通过,均可授权本次关键资产的访问。
    • 业务可通过设置认证有效期,达成一次用户认证、授权多个关键资产访问的效果。认证有效期最长可设置10分钟。

5、参考

华为官网:@ohos.security.asset (关键资产存储服务)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/37458.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

git原理与常用命令及其使用

认识工作区、暂存区、版本库 ⼯作区&#xff1a;是在电脑上你要写代码或⽂件的⽬录。 暂存区&#xff1a;英⽂叫 stage 或 index。⼀般存放在 .git ⽬录下的 index ⽂件&#xff08;.git/index&#xff09;中&#xff0c;我们 把暂存区有时也叫作索引&#xff08;index&#xf…

Web-Machine-N7靶机通关攻略

获取靶机ip arp-scan -l 端口扫描 nmap xxxx 访问80端口发现没用 扫描目录 gobuster dir -u http:/192.168.117.160 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium,txt -x php,html,txt ,zip 打开exploit.html 点击F12&#xff0c;修改localhost为靶机ip&#…

2025-03-21 Unity 网络基础3——TCP网络通信准备知识

文章目录 1 IP/端口类1.1 IPAddress1.2 IPEndPoint 2 域名解析2.1 IPHostEntry2.2 Dns 3 序列化与反序列化3.1 序列化3.1.1 内置类型 -> 字节数组3.1.2 字符串 -> 字节数组3.1.3 类对象 -> 字节数组 3.2 反序列化3.2.1 字节数组 -> 内置类型3.2.2 字节数组 -> 字…

Java-servlet(七)详细讲解Servlet注解

Java-servlet&#xff08;七&#xff09;详细讲解Servlet注解 前言一、注解的基本概念二、Override 注解2.1 作用与优势2.2 示例代码 三、Target 注解3.1 定义与用途3.2 示例代码 四、WebServlet 注解4.1 作用4.2 示例代码 五、反射与注解5.1 反射的概念5.2 注解与反射的结合使…

nginx 反向代理 ubuntu

关键字 Nginx&#xff0c;正向代理&#xff0c;方向代理&#xff0c;博客建站 背景环境 我在搭建个人博客的过程中遇到一个问题&#xff0c;我的博客服务的端口是1313&#xff0c;我的域名是qinyangx.top。我希望能够通过qinyangx.top直接访问到服务器上1313端口的博客服务。…

学习threejs,使用TextGeometry文本几何体

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.TextGeometry1.1.1 ☘…

【秣厉科技】LabVIEW工具包——OpenCV 教程(12):机器学习

文章目录 前言机器学习例1&#xff1a;支持向量机&#xff08;SVM&#xff09;做平面向量二分类例2&#xff1a; K邻近算法&#xff08;KNearest&#xff09;实现分类 总结 前言 需要下载安装OpenCV工具包的朋友&#xff0c;请前往 此处 &#xff1b;系统要求&#xff1a;Wind…

企业级AI架构探索:业务驱动,场景优先

企业级AI架构的设计需要兼顾技术先进性、业务适配性、成本效益和长期可维护性。以下从架构设计原则、核心架构层次、基础框架可能性、实施路径四个维度进行系统性阐述&#xff1a; 一、设计原则 业务驱动&#xff0c;场景优先 明确AI解决的业务痛点&#xff08;如降本增效、智…

DCDC36V同步降压 输出可调 2A电流恒压芯片SL1588H 替换LV3842

在当今电子设备飞速发展的时代&#xff0c;电源管理芯片的性能优劣直接关乎设备的稳定性与高效运行。对于诸多需要将 36V 电压进行同步降压、输出电压可调且稳定输出 2A 电流的应用场景&#xff0c;一款卓越的恒压芯片不可或缺。SL1588H 正凭借其领先的技术和出色的性能&#x…

Beans模块之工厂模块注解模块@Qualifier

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

flutter 开发web端的性能优化

参考资料 Flutter for Web 首次首屏优化 ——JS 分片优化_main.dart.js-CSDN博客文章浏览阅读1.4k次。本文介绍了如何通过延迟加载组件和js分片优化Flutter for Web应用的加载速度。在实践中&#xff0c;通过按需加载减少js文件大小&#xff0c;使用并行加载提升加载效率。通过…

【设计模式】三十二、策略模式

系列文章|源码 https://github.com/tyronczt/design-mode-learn 文章目录 系列文章|源码一、模式定义与核心思想二、模式结构与Java实现1. 核心角色2. Java代码示例 三、策略模式的五大核心优势四、适用场景五、与其他模式的对比六、最佳实践建议总结 &#x1f680;进阶版【更…

【Linux 维测专栏 1 -- Hung Task 分析与验证】

文章目录 Linux Hung Task 简介1. Hung Task 概述2. D 状态与 Hung Task3. Hung Task 的工作原理4. Hung Task 的配置5. Hung Task 的典型输出6. Hung Task 的应用场景7. kernel 配置7.1 编译选项7.2 参数控制7.3 验证方法4. 扩展接口 8. 注意事项 Linux Hung Task 简介 1. Hu…

计算机网络精讲day1——计算机网络的性能指标(上)

性能指标1&#xff1a;速率 概念1&#xff1a;比特 英文全称是binary digit&#xff0c;意思是一个二进制数字&#xff0c;因此一个比特就是二进制数字中的1或0&#xff0c;比特也是信息论中使用的信息量单位。 概念2&#xff1a;速率 网络中的速率指的是数据的传送速率&#…

ubuntu20.04使用matlab2024a快捷键调整

一、概述 因为最近在使用ubuntu系统&#xff0c;在上面安装一个matlab比较方便&#xff0c;不用来回在window上面进行跳转&#xff0c;节省不少时间&#xff0c;同时在ubuntu下面启动matlab速度也比较快。 二、问题解决 &#xff08;一&#xff09;问题概述 问题如下&#xf…

【设计模式】装饰模式

六、装饰模式 装饰(Decorator) 模式也称为装饰器模式/包装模式&#xff0c;是一种结构型模式。这是一个非常有趣和值得学习的设计模式&#xff0c;该模式展现出了运行时的一种扩展能力&#xff0c;以及比继承更强大和灵活的设计视角和设计能力&#xff0c;甚至在有些场合下&am…

科技赋能安全:慧通测控的安全带全静态性能测试

汽车的广泛普及给人们的出行带来了极大便利&#xff0c;但交通事故频发也成为严重的社会问题。据世界卫生组织统计&#xff0c;全球每年约有 135 万人死于道路交通事故&#xff0c;而安全带在减少事故伤亡方面起着不可替代的作用。正确使用安全带可使前排驾乘人员的死亡风险降低…

猿大师中间件:如何在最新Chrome浏览器Web网页内嵌本地OCX控件?

OCX控件是ActiveX控件的一种&#xff0c;主要用于在网页中嵌入复杂的功能&#xff0c;如图形渲染、多媒体播放等&#xff0c;可是随着谷歌Chrome等主流浏览器升级&#xff0c;目前已经不支持微软调用ActiveX控件了&#xff0c;如果想调用OCX控件用IE浏览器或者国产双擎浏览器&a…

基于STC89C52的DS1621温度检测系统

摘要 本文设计了一种基于STC89C52单片机的DS1621温度检测系统&#xff0c;通过DS1621传感器采集温度数据&#xff0c;利用STC89C52单片机处理数据&#xff0c;并通过串口将温度信息发送至电脑显示。借助Proteus软件进行仿真验证&#xff0c;实现了温度检测系统的功能演示。该系…

创建自己的github.io

1、创建GitHub账号 GitHub地址&#xff1a;https://github.com/ 点击Sign up创建账号 如果已创建&#xff0c;点击Sign in登录 2、创建仓库 假设Owner为username&#xff0c;则Repository name为username.github.io说明&#xff1a; 1、Owner为用户名 2、Repository name为仓…