当前位置: 首页 > article >正文

【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 (关键资产存储服务)

相关文章:

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

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

强化学习(赵世钰版)-学习笔记(9.策略梯度法)

本章是课程的导数第二章&#xff0c;旨在讲解策略的函数化形式。 之前的方法&#xff0c;描述一个策略都是用表格的形式&#xff0c;每一行代表一个状态&#xff0c;每一列代表一个行为&#xff0c;表格中的元素对应相关状态下执行相关行为的概率。 函数化的策略表征形式是指&a…...

ModuleNotFoundError: No module named ‘flask‘ 错误

要解决 ModuleNotFoundError: No module named ‘flask’ 错误&#xff0c;需确保已正确安装 Flask 库。以下是详细步骤&#xff1a; ‌1. 安装 Flask‌ 在终端或命令行中执行以下命令&#xff08;注意权限问题&#xff09;&#xff1a; 使用 pip 安装 pip install flask 若…...

【c++】【STL】unordered_set 底层实现(简略版)

【c】【STL】unordered_set 底层实现&#xff08;简略版&#xff09; ps:这个是我自己看的不保证正确&#xff0c;觉得太长的后面会总结整个调用逻辑 unordered_set 内部实现 template <class _Kty, class _Hasher hash<_Kty>, class _Keyeq equal_to<_Kty>…...

【Zephyr】【一】学习笔记

Zephyr RTOS 示例代码集 1. 基础示例 1.0 基础配置 每个示例都需要一个 prj.conf 文件来配置项目。以下是各个示例所需的配置&#xff1a; 基础示例 prj.conf # 控制台输出 CONFIG_PRINTKy CONFIG_SERIALy CONFIG_UART_CONSOLEy# 日志系统 CONFIG_LOGy CONFIG_LOG_DEFAULT…...

网络安全设备配置与管理-实验4-防火墙AAA服务配置

实验4-p118防火墙AAA服务配置 从这个实验开始&#xff0c;每一个实验都是长篇大论&#x1f613; 不过有好兄弟会替我出手 注意&#xff1a;1. gns3.exe必须以管理员身份打开&#xff0c;否则ping不通虚拟机。 win10虚拟机无法做本次实验&#xff0c;必须用学校给的虚拟机。首…...

后端框架模块化

后端框架的模块化设计旨在简化开发流程、提高可维护性&#xff0c;并通过分层解耦降低复杂性。以下是常见的后端模块及其在不同语言&#xff08;Node.js、Java、Python&#xff09;中的实现方式&#xff1a; 目录 1. 路由&#xff08;Routing&#xff09;2. 中间件&#xff08;…...

【论文阅读】Contrastive Clustering Learning for Multi-Behavior Recommendation

论文地址&#xff1a;Contrastive Clustering Learning for Multi-Behavior Recommendation | ACM Transactions on Information Systems 摘要 近年来&#xff0c;多行为推荐模型取得了显著成功。然而&#xff0c;许多模型未充分考虑不同行为之间的共性与差异性&#xff0c;以…...

视频转音频, 音频转文字

Ubuntu 24 环境准备 # 系统级依赖 sudo apt update && sudo apt install -y ffmpeg python3-venv git build-essential python3-dev# Python虚拟环境 python3 -m venv ~/ai_summary source ~/ai_summary/bin/activate核心工具链 工具用途安装命令Whisper语音识别pip …...

基于协同过滤推荐算法的景点票务数据系统(python-计算机毕设)

摘 要 I ABSTRACT II 第 1 章 引言 1 研究背景及意义 1 研究背景 1研究意义 1 国内外研究现状 2 智慧旅游 3旅游大数据 3 研究内容 4本章小结 4 第 2 章 相关技术概述 5 基于内容的推荐算法 5 基于内容的推荐算法原理 5基于内容的推荐算法实现 5 协同过滤推荐算法 6 协同过…...

QT学习笔记1

** Qt Creator开发环境配置** 安装流程&#xff08;Windows平台&#xff09; 下载与安装 &#xff1a; 访问Qt官网&#xff0c;下载在线安装工具Qt Online Installer。登录或注册Qt账号&#xff0c;选择开源版本&#xff08;需勾选“接受协议”&#xff09;。勾选组件&#xff…...

Ubuntu 24 常用命令方法

文章目录 环境说明1、账号管理1.1、启用 root 2、包管理工具 apt & dpkg2.1、apt 简介 & 阿里源配置2.2、dpkg 简介2.3、apt 和 dpkg 两者之间的关系2.4、常用命令 3、启用 ssh 服务4、防火墙5、开启远程登录6、关闭交换分区7、build-essential&#xff08;编译和开发软…...

Flask多参数模版使用

需要建立目录templates&#xff1b; 把建好的html文件放到templates目录里面&#xff1b; 约定好参数名字&#xff0c;单个名字可以直接使用&#xff1b;多参数使用字典传递&#xff1b; 样例&#xff1a; from flask import render_template # 模板 (Templates) #Flask 使用…...

torcharrow gflags版本问题

问题描述 其实仍然是很简单的编译问题&#xff0c;但是又弄了一整个下午加几乎整个晚上&#xff0c;进度缓慢&#xff0c;又吸取了教训&#xff0c;因而还是来记录一下。 在试图使用torcharrow进行推荐系统模拟的时候&#xff0c;撰写的python程序报错&#xff1a;ERROR: flag…...

自然语言处理|深入解析 PEGASUS:从原理到实践

一、引言 在信息爆炸的时代&#xff0c;互联网上的文本数据以极快的速度增长。无论是新闻资讯、学术论文、社交媒体动态&#xff0c;还是各类报告文档&#xff0c;我们每天接触到的文字信息量巨大。如何快速、准确地提取关键内容成为一项重要任务。文本摘要技术通过将长篇文本…...

Spring AI Alibaba快速使用

AI 时代&#xff0c;Java 程序员也需要与时俱进&#xff0c;这两个框架必须掌握。 一个是 Spring AI一个是 Spring Alibaba AI。 Spring AI 是一个AI工程领域的应用程序框架&#xff0c;它的目标是将 Spring生态系统的设计原则应用于人工智能领域。 但是&#xff0c; Spring…...

socks 协议介绍

SOCKS协议详解 一、基本定义与核心功能 SOCKS&#xff08;Socket Secure&#xff09;是一种网络传输协议&#xff0c;主要用于通过代理服务器转发客户端与目标服务器之间的通信请求。其核心功能包括隐藏用户真实IP地址、穿透防火墙限制以及支持多种网络协议&#xff08;如TCP…...

Linux --centos安装显卡驱动

显卡下载页面 https://www.nvidia.com/en-us/drivers/unix/ 随便下载一个即可 安装过程 查看当前设备的显卡信息 lspci | grep -i vga安装gcc相关依赖 yum update -y yum update gcc yum install build-essential yum install gcc-multilibdkms yum groupinstall "Dev…...

【软件工程】简答题

真题 2024-10 26.需求验证应验证需求规格说明书中每一单一需求是否满足5个性质,这5个性质是什么? 27.简述RUP和UML的关系。 28.简述五种常见的模块间耦合类型。 29.螺旋模型在笛卡尔坐标的4个象限上,分别表达了哪4个方面的活动? 30.为了表达概念模型和软件模型,UML提供了13…...

统信UOS中使用Vscode编程

写在前面&#xff1a;统信UOS其实就是套壳的Linux系统&#xff0c;所以有问题如果搜不到解决方法&#xff0c;可以参考Linux下的解决方法。 1.环境配置 Vscode : 1.85.0 Vscode就直接下载安装就行&#xff0c;然后安装插件&#xff1a;Volar、中文汉化包 node&#xff1a;18…...

K8s认证(CKA/CKAD/CKS)哪家强?主流证书对比

2024年Kubernetes认证全解析&#xff1a;选对证书&#xff0c;薪资翻倍&#xff01; &#xff08;附CKA/CKAD/CKS最新考试攻略&#xff09; 一、K8s认证哪家强&#xff1f;主流证书对比 认证名称颁发机构考试特点适合人群考试费用CKA&#xff08;认证K8s管理员&#xff09;CN…...

HTTP1.0、HTTP1.1、HTTP2.0对比

HTTP 1.0、HTTP 1.1 和 HTTP 2.0 是 HTTP 协议演进中的三个重要版本&#xff0c;每个版本都针对前一代的不足进行了优化和改进。以下是它们的核心区别和关键特性对比&#xff1a; 1. HTTP 1.0&#xff08;1996年&#xff09; 非持久连接 每个请求/响应对都需要单独建立和关闭 T…...

docker安装向量数据库Milvus及可视化工具 Attu

前置条件 1.安装了docker 2.服务器网络正常&#xff0c;可以连接到容器下载地址 3.服务器磁盘空间正常&#xff0c;docker磁盘占用过大&#xff0c;请参考docker容量占用过大解决办法 一、下载yml文件 可在文章资源下载或者自行下载&#xff1a;下载yml 下载这个单机版本的…...

A l密码学(Deepseek)

我&#xff1a;qwertyuiopasdfghjklzxcvbnm deepseek:深度思考中&#xff0e; Okay, lets see. The user input is "qwertyuiopasdfghjklzxcvbnm". At first glance, it looks like a jumbled sequence of letters with some spaces or maybe other characters in …...

DeepSeek + Kimi 自动生成 PPT

可以先用deepseek生成ppt大纲&#xff0c;再把这个大纲复制到Kimi的ppt助手里&#xff1a; https://kimi.moonshot.cn/kimiplus/conpg18t7lagbbsfqksg 选择ppt模板&#xff1a; 点击生成ppt就制作好了。...

Apache Paimon 在抖音集团多场景中的优化实践

资料来源&#xff1a;火山引擎-开发者社区 本文将基于抖音集团内部两大业务的典型实时数仓场景&#xff0c;介绍Paimon在抖音集团内部的生产实践。 作者&#xff1a;李明、苏兴、文杰 抖音集团大数据工程师 目前抖音集团内部主要使用 Lambda 架构进行实时数仓建设&#xff0c;其…...

Uni-App 双栏联动滚动组件开发详解 (电梯导航)

本文基于提供的代码实现一个左右联动的滚动组件&#xff0c;以下是详细的代码解析与实现原理说明&#xff1a; <!--双栏联动滚动组件 - 技术解析功能特性&#xff1a;1. 左侧导航栏与右侧内容区双向联动2. 自适应容器高度3. 平滑滚动定位4. 动态内容位置计算 --> <te…...

当下主流 AI 模型对比:ChatGPT、DeepSeek、Grok 及其他前沿技术

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 1. 引言 人工智能&#xff08;AI&#xff09;领域近年来取得了巨大的突破&#xff0c;特别是在大语言模型&#xff08;LLM&#…...

【自用】NLP算法面经(5)

一、L1、L2正则化 正则化是机器学习中用于防止过拟合并提高模型泛化能力的技术。当模型过拟合时&#xff0c;它已经很好地学习了训练数据&#xff0c;甚至是训练数据中的噪声&#xff0c;所以可能无法在新的、未见过的数据上表现良好。 比如&#xff1a; 其中&#xff0c;x1和…...

体育直播视频源格式解析:M3U8 vs FLV

在体育直播领域&#xff0c;视频源的格式选择直接影响着直播的流畅度、画质以及兼容性。目前&#xff0c;M3U8 和 FLV 是两种最为常见的视频流格式&#xff0c;它们各有优劣&#xff0c;适用于不同的场景。本文将从技术原理、优缺点以及应用场景等方面对 M3U8 和 FLV 进行详细解…...