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

【HarmonyOS 5】敏感信息本地存储详解

【HarmonyOS 5】敏感信息本地存储详解

前言

鸿蒙其实自身已经通过多层次的安全机制,确保用户敏感信息本地存储安全。不过再此基础上,用户敏感信息一般三方应用还需要再进行加密存储。

本文章会从鸿蒙自身的安全机制进行展开,最后再说明本地敏感信息常规存储的方案。

一、硬件级安全隔离与加密

可信执行环境(TEE)
TEE 作为独立的安全区域,与主操作系统隔离,用于存储加密密钥、生物特征模板等核心敏感数据。例如,用户指纹信息在 TEE 内完成验证,防止中间人攻击。
密钥管理:密钥生成、存储和使用均在 TEE 中完成。例如,AES 加密密钥通过硬件随机数生成器生成,并存储于 TEE 的安全存储区域,确保密钥不暴露于主系统。
全盘加密(FDE)
设备存储的所有数据默认加密,包括用户文件、应用数据等。即使设备丢失或被破解,攻击者也无法直接读取原始数据。
动态加密:数据在写入存储介质时实时加密,读取时自动解密,对用户透明。

二、软件层安全机制

沙箱隔离
每个应用拥有专属沙箱目录(/data/data/<包名>),其他应用无法直接访问。例如,银行应用的交易记录存储在沙箱内,社交应用无法读取。
路径隔离
应用只能访问自身沙箱内的文件,系统文件和其他应用数据被严格限制。
数据加密与密钥管理
对称加密
使用 AES 算法对本地文件、数据库等进行加密。例如,用户的聊天记录通过 AES-256 加密存储,密钥由 TEE 管理。
非对称加密
用于密钥交换和数字签名。例如,应用在跨设备同步数据时,使用 RSA 加密会话密钥,确保传输安全。
密钥全生命周期管理
密钥生成、分发、更新和销毁由系统统一管理。例如,定期轮换加密密钥,降低泄露风险。
动态权限管理
最小权限原则:应用仅能申请必要权限。例如,地图应用请求位置权限时,系统默认推荐模糊位置(1km 精度)替代精确位置。
实时权限监控
后台应用异常调用摄像头或麦克风时,系统触发 “隐私盾牌” 拦截,并通知用户。
权限透明化:用户可在控制中心查看应用 24 小时内的设备使用记录,包括摄像头、麦克风激活时长。

三、隐私增强技术

隐私空间
独立加密存储:用户可创建隐私空间,通过指纹或密码访问,存储高敏感数据(如身份证、银行卡信息)。隐私空间与主空间完全隔离,数据加密存储。
隐藏入口:隐私空间入口可隐藏,仅通过特定指纹或密码唤醒,提升隐蔽性。
安全擦除
物理销毁:删除数据时,系统采用安全擦除技术(如多次覆写),确保数据不可恢复。例如,用户删除聊天记录后,存储块被随机数据覆盖。
云端同步擦除:设备丢失时,用户可通过 “查找设备” 功能远程擦除本地数据,防止泄露。

四、分布式安全与合规

跨设备数据同步
加密传输:数据在设备间同步时,使用 TLS 协议加密。例如,手机与平板同步联系人时,数据通过 SSL 加密传输。

设备安全级别匹配
根据设备安全等级(如手机为 SL2,手表为 SL1),限制可同步的数据安全标签。例如,手表无法同步机密级数据。

五、开发者本地敏感信息存储方案

综上所述,鸿蒙通过硬件隔离、加密技术、动态权限、隐私空间等多维度安全机制,构建了端到端的敏感信息防护体系。其核心设计理念是 “最小权限、深度隔离、硬件加密、用户可控”,确保用户数据在存储、传输和使用过程中的安全性与隐私性。开发者可通过系统提供的安全 API 和工具链,便捷地实现符合最高安全标准的应用。

1. 使用系统加密库对数据加密
HarmonyOS 提供了加密和解密模块,支持 AES、RSA 等算法,详情参见官方文档:加密/解密介绍及算法规格
image.png

格式转化,请参考:@ohos.util (util工具函数)
image.png
金融业一般会通过国密或者三方加密SDK实现。操作逻辑一致,可参考加密逻辑。以首选项存储用户的id为例,下面是一个参考国密 SM2 加密方式,结合首选项存储,对本地存储用户 ID 进行加密和解密的完整 DEMO。这个 DEMO 会生成 SM2 密钥对,使用公钥加密用户 ID 并存储到首选项中,之后使用私钥从首选项读取加密数据并解密:

import { preferences } from '@kit.ArkData';
import { BusinessError } from '@kit.BasicServicesKit';
import { huks } from '@kit.UniversalKeystoreKit';
import { util } from '@kit.ArkTS';
import { common } from '@kit.AbilityKit';// 首选项名称
const PRE_FS_NAME = 'user_id_storage';// 加密算法枚举
enum EncryptionAlgorithm {SM2 = 'SM2',// 可根据需求添加更多算法
}/*** 加密工具类*/
class EncryptionUtils {private keyAlias: string;constructor(keyAlias: string) {this.keyAlias = keyAlias;}/*** 生成密钥* @param algorithm 加密算法*/async generateKey(algorithm: EncryptionAlgorithm) {let properties: Array<huks.HuksParam>;switch (algorithm) {case EncryptionAlgorithm.SM2:properties = [{tag: huks.HuksTag.HUKS_TAG_ALGORITHM,value: huks.HuksKeyAlg.HUKS_ALG_SM2},{tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,value: huks.HuksKeySize.HUKS_SM2_KEY_SIZE_256},{tag: huks.HuksTag.HUKS_TAG_PURPOSE,value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT |huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT}];break;default:throw new Error(`Unsupported algorithm: ${algorithm}`);}const options: huks.HuksOptions = {properties};await huks.generateKeyItem(this.keyAlias, options).then((data) => {console.info(`Generate ${algorithm} key success, data = ${JSON.stringify(data)}`);}).catch((error: Error) => {console.error(`Generate ${algorithm} key failed, ${JSON.stringify(error)}`);throw error;});}/*** 加密数据* @param data 待加密的数据* @param algorithm 加密算法* @returns 加密后的数据*/async encrypt(data: string, algorithm: EncryptionAlgorithm): Promise<string> {let properties: Array<huks.HuksParam>;switch (algorithm) {case EncryptionAlgorithm.SM2:properties = [{tag: huks.HuksTag.HUKS_TAG_ALGORITHM,value: huks.HuksKeyAlg.HUKS_ALG_SM2},{tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,value: huks.HuksKeySize.HUKS_SM2_KEY_SIZE_256},{tag: huks.HuksTag.HUKS_TAG_PURPOSE,value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT},{tag: huks.HuksTag.HUKS_TAG_DIGEST,value: huks.HuksKeyDigest.HUKS_DIGEST_SM3}];break;default:throw new Error(`Unsupported algorithm: ${algorithm}`);}const options: huks.HuksOptions = {properties,inData: new Uint8Array(data.split('').map(c => c.charCodeAt(0)))};let handleObj = await huks.initSession(this.keyAlias, options)const result = await huks.finishSession(handleObj.handle, options).catch((error: Error) => {console.error(`Finish ${algorithm} encryption session failed: ${JSON.stringify(error)}`);throw error;});let base64Helper = new util.Base64Helper();let retStr = base64Helper.encodeToStringSync(result.outData as Uint8Array);return retStr;}/*** 解密数据* @param encryptedData 加密后的数据* @param algorithm 加密算法* @returns 解密后的数据*/async decrypt(encryptedData: string, algorithm: EncryptionAlgorithm): Promise<string> {let properties: Array<huks.HuksParam>;switch (algorithm) {case EncryptionAlgorithm.SM2:properties = [{tag: huks.HuksTag.HUKS_TAG_ALGORITHM,value: huks.HuksKeyAlg.HUKS_ALG_SM2},{tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,value: huks.HuksKeySize.HUKS_SM2_KEY_SIZE_256},{tag: huks.HuksTag.HUKS_TAG_PURPOSE,value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT},{tag: huks.HuksTag.HUKS_TAG_DIGEST,value: huks.HuksKeyDigest.HUKS_DIGEST_SM3}];break;default:throw new Error(`Unsupported algorithm: ${algorithm}`);}let base64Helper = new util.Base64Helper();let inData = base64Helper.decodeSync(encryptedData);const options: huks.HuksOptions = {properties,inData};let handleObj = await huks.initSession(this.keyAlias, options)const result = await huks.finishSession(handleObj.handle, options).catch((error: Error) => {console.error(`Finish ${algorithm} decryption session failed: ${JSON.stringify(error)}`);throw error;});let retStr = base64Helper.encodeToStringSync(result.outData as Uint8Array);return retStr;}
}/*** 首选项工具类*/
class PreferencesUtils {private preFs: preferences.Preferences | null = null;private context: common.UIAbilityContext;constructor(context: common.UIAbilityContext) {this.context = context;}/*** 初始化首选项实例*/async init() {let options: preferences.Options = { name: PRE_FS_NAME };this.preFs = preferences.getPreferencesSync(this.context, options);}/*** 存储数据* @param key 键* @param value 值*/async put(key: string, value: string) {await this.preFs?.put(key, value).then(() => console.info(`数据 ${key} 存储成功`)).catch((err: BusinessError) => {console.error(`存储失败: ${err.code}, ${err.message}`);});await this.preFs?.flush();}/*** 读取数据* @param key 键* @returns 值或 null*/async get(key: string): Promise<preferences.ValueType> {let res = await this.preFs?.get(key, 'default') ?? "";return res;}
}

相关文章:

【HarmonyOS 5】敏感信息本地存储详解

【HarmonyOS 5】敏感信息本地存储详解 前言 鸿蒙其实自身已经通过多层次的安全机制&#xff0c;确保用户敏感信息本地存储安全。不过再此基础上&#xff0c;用户敏感信息一般三方应用还需要再进行加密存储。 本文章会从鸿蒙自身的安全机制进行展开&#xff0c;最后再说明本地…...

大厂面试:六大排序

前言 本篇博客集中了冒泡&#xff0c;选择&#xff0c;二分插入&#xff0c;快排&#xff0c;归并&#xff0c;堆排&#xff0c;六大排序算法 如果觉得对你有帮助&#xff0c;可以点点关注&#xff0c;点点赞&#xff0c;谢谢你&#xff01; 1.冒泡排序 //冒泡排序&#xff…...

.exe变成Windows服务

.exe变成Windows服务&#xff09; 场景步骤 1: 安装 PyInstaller和win32serviceutil步骤 2: 使用 PyInstaller 创建 .exe 文件步骤 3: 检查生成的 .exe 文件步骤 4: 安装服务步骤 5: 启动服务步骤 6: 配置服务自动启动&#xff08;可选&#xff09;步骤 7: 检查服务状态完整示例…...

探索鸿蒙沉浸式:打造无界交互体验

一、鸿蒙沉浸式简介 在鸿蒙系统中&#xff0c;沉浸式是一种极具特色的设计理念&#xff0c;它致力于让用户在使用应用时能够全身心投入到内容本身&#xff0c;而尽可能减少被系统界面元素的干扰。通常来说&#xff0c;就是将应用的内容区巧妙地延伸到状态栏和导航栏所在的界面…...

el-tree组件使用过滤时,不展示筛选目标的子节点

1.el官方示例过滤方法 const filterNode (value: string, data: Tree) > {if (!value) return truereturn data.label.includes(value) }2.修改后的过滤方法 /*** 树节点过滤*/ const filterNode (value, data, node) > {if (!value) return true;let parentNode no…...

超详细!Android 面试题大汇总与深度解析

一、Java 与 Kotlin 基础 1. Java 的多态是如何实现的&#xff1f; 多态是指在 Java 中&#xff0c;同一个行为具有多个不同表现形式或形态的能力。它主要通过方法重载&#xff08;Overloading&#xff09;和方法重写&#xff08;Overriding&#xff09;来实现。 方法重载&a…...

网站301搬家后谷歌一直不收录新页面怎么办?

当网站因更换域名或架构调整启用301重定向后&#xff0c;许多站长发现谷歌迟迟不收录新页面&#xff0c;甚至流量大幅下滑。 例如&#xff0c;301跳转设置错误可能导致权重传递失效&#xff0c;而新站内容与原站高度重复则可能被谷歌判定为“低价值页面”。 即使技术层面无误&a…...

在Mac上离线安装k3s

目录 首先是安装multipass。 1. 系统要求 2. 环境准备 本来想照着网上文档学习安装一下k3s&#xff0c;没想到在docker被封了之后&#xff0c;现在想通过命令行去下载github的资源也不行了&#xff08;如果有网友看到这个文档、并且知道问题原因的&#xff0c;请留言告知&am…...

无锁队列--知识分享

目录 无锁队列 无锁队列是什么 为什么需要无锁队列 队列的类型 无锁队列的分类 ringbuffer&#xff08;SPSC&#xff09; ret_ring&#xff08;MPMC&#xff09; 无锁队列 无锁队列是什么 无锁队列通过原子操作来实现线程安全的队列&#xff0c;属于非阻塞队列 …...

玩转Docker | 使用Docker部署Memos笔记工具

玩转Docker | 使用Docker部署Memos笔记工具 前言一、Memos介绍Memos简介主要特点二、系统要求环境要求环境检查Docker版本检查检查操作系统版本三、部署Memos服务下载镜像创建容器创建容器检查容器状态检查服务端口安全设置四、访问Memos服务访问Memos首页注册账号五、基本使用…...

2025低代码平台选型策略:ROI导向下的功能与成本权衡

在当今快速变化的商业环境中&#xff0c;企业面临着前所未有的挑战与机遇。数字化转型已成为企业提升竞争力的关键&#xff0c;而软件开发的高成本和长周期无疑是实现这一转型的绊脚石。 低代码平台的兴起&#xff0c;为企业提供了一种高效、灵活的解决方案&#xff0c;使得非…...

Redis的IO多路复用

1 传统的socket编码模型 传统 Socket 模型通常采用 多线程/多进程 或 阻塞 I/O 的方式处理网络请求。以下是典型实现步骤&#xff1a; 创建套接字&#xff08;Socket&#xff09; 步骤&#xff1a;调用 socket() 创建一个 TCP/UDP 套接字。通常把这个套接字称为【主动套接字】…...

充电宝项目:规则引擎Drools学习

文章目录 规则引擎 Drools1 问题2 规则引擎概述2.1 规则引擎2.2 使用规则引擎的优势2.3 规则引擎应用场景2.4 Drools介绍 3 Drools入门案例3.1 创建springboot项目 引入依赖3.2 添加Drools配置类3.4 创建实体类Order3.5 orderScore.drl3.6 编写测试类 4 Drools基础语法4.1 规则…...

基于YOLOv9的课堂行为检测系统

基于YOLOv9的课堂行为检测系统 项目概述 本项目是一个基于YOLOv9深度学习模型的课堂行为检测系统&#xff0c;旨在通过计算机视觉技术自动识别和监测课堂中学生的各种行为状态&#xff0c;帮助教师更好地了解课堂教学效果。 项目结构 课堂行为检测/ ├── data/ │ ├──…...

端、管、云一体化原生安全架构 告别外挂式防护!

面对数字化转型浪潮&#xff0c;企业网络安全风险日益凸显。数据泄露、黑客勒索等事件频发&#xff0c;合规要求加速推进。尽管企业纷纷部署了防病毒、身份认证、文件加密、入侵防护、流量监控等多种安全系统&#xff0c;但分散且孤立的架构非但没有有效抵御风险&#xff0c;反…...

BI面向模型开发和面向报表开发,有什么区别?

在数字化时代&#xff0c;商业智能&#xff08;BI&#xff09;已成为企业决策不可或缺的工具。BI项目实施时&#xff0c;通常有两种开发模式&#xff1a;面向模型开发和面向报表开发。虽然两者都旨在通过数据驱动决策&#xff0c;但在开发逻辑、目标价值和技术路径上存在显著差…...

进程控制(上)【Linux操作系统】

进程控制 写时拷贝 本质是一种减少深拷贝的方法 Linux中有很多拷贝的场景都用得上写时拷贝&#xff0c;下面以创建子进程时的写时拷贝为例&#xff1a; 子进程被创建的时候&#xff1a; 会继承父进程的mm_struct和页表 所以子进程刚刚继承时&#xff0c;父子进程的代码和数据…...

5G网络下客户端数据业务掉线频繁

上层应用的日志和界面在待机状态下&#xff08;即没有做通话等业务操作&#xff09;&#xff0c;会频繁提示“离线”。 主要先看有没有丢网&#xff0c;UL BLER有没有问题。确认没有问题。看到业务信道释放后也可以成功重新建链。所以以为这个只是终端业务进入dormant态的提示…...

【Docker项目实战】使用Docker部署Gitblit服务器

【Docker项目实战】使用Docker部署Gitblit服务器 一、Gitblit介绍1.1 Gitblit 介绍1.2 主要特点 二、本次实践规划2.1 本地环境规划2.2 本次实践介绍 三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本 四、下载Gitblit镜像五、部署Gitbli…...

Vitis: 使用自定义IP时 Makefile错误 导致编译报错

参考文章: 【小梅哥FPGA】 Vitis开发中自定义IP的Makefile路径问题解决方案 Vitis IDE自定义IP Makefile错误&#xff08;arm-xilinx-eabi-gcc.exe: error: *.c: Invalid argument&#xff09;解决方法 Vitis 使用自定义IP时: Makefile 文件里的语句是需要修改的&#xff0c;…...

helm的go模板语法学习

1、helm chart 1.0、什么是helm&#xff1f; 介绍&#xff1a;就是个包管理器。理解为java的maven、linux的yum就好。 安装方法也可参见官网&#xff1a; https://helm.sh/docs/intro/install 通过前面的演示我们知道&#xff0c;有了helm之后应用的安装、升级、查看、停止都…...

AI 语音公司 ElevenLabs 进军亚太市场设立东京子公司;EverTutor Live :语音交互 AI 教育平台丨日报

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE&#xff08;Real-Time Engagement&#xff09; 领域内「有话题的 技术 」、「有亮点的 产品 」、「有思考的 文章 」、「有态度的 观…...

STM32启动流程详解

STM32启动流程详解 本文档详细介绍STM32微控制器从上电到main函数执行的完整启动流程。 1. 上电与复位过程 当STM32芯片上电或复位时&#xff0c;硬件会执行以下步骤&#xff1a; 上电复位(POR)/低电平复位(PDR): 芯片接通电源或NRST引脚置低时触发初始PC值设置: 程序计数器…...

Langchain + Gemini API调用基本操作

本文参考Langchain中ChatGoogleGenerativeAI的官方文档&#xff0c;在本地的jupyter notebook中运行。 关于API的细节在官方文档最开头给出&#xff1a; 我们在使用时&#xff0c;可以选择model"gemini-2.0-flash-001"或者生成图片的ChatGoogleGenerativeAI(model“…...

利用 Python 和 AI 技术创作独特的图像艺术作品

1. 项目目标 生成艺术作品&#xff1a;利用 AI 模型&#xff08;如 Stable Diffusion&#xff09;生成具有艺术风格的图像。自定义风格&#xff1a;通过文本提示&#xff08;prompt&#xff09;控制图像的艺术风格&#xff08;如赛博朋克、印象派、超现实主义等&#xff09;。…...

Matlab绘图(三)——设置图例的位置

❤️1. 使用 Location 参数设置图例位置 h_legend legend({系列 A, 系列 B, 系列 C}, ...FontName, Arial, ... % 指定字体名称FontSize, 10, ... % 指定字体大小Location, northeast); % 指定初始位置在右上角调用 legend 函数&#xff0c;并通过 Location 参数指定图例放…...

【数据结构】4.单链表实现通讯录

在上一篇文章我们学会了用单链表来实现各种方法&#xff0c;在这一篇文章我们将在单链表的基础上实现通讯录。 0、准备工作 实现通讯录之前&#xff0c;我们还需要在单链表的基础上添加2个文件&#xff0c;头文件Contact.h和源文件Contact.c。Contact.c来实现通讯录方法的声明…...

接口自动化测试(一)

一、HTTP请求的核心概念及原理详解 HTML:超文本标记语言-----通过<标记符>内容</标记符>格式-------页面 URL:统一资源定位符 返回数据有很多&#xff1a;页面、图片、视频&#xff0c;都可以进行返回---统称为&#xff1a;资源HTTP:超文本传输协议(请求-响应的协…...

【JavaEE】Spring AOP的注解实现

目录 一、AOP 与 Spring AOP二、Spring AOP简单实现三、详解Spring AOP3.1 Spring AOP 核心概念3.1.1 切点&#xff08;Pointcut&#xff09;3.1.2 连接点&#xff08;Join Point&#xff09;3.1.3 通知&#xff08;Advice&#xff09;3.1.4 切面&#xff08;Aspect&#xff09…...

从零开始实现 MobileViT 注意力机制——轻量级Transformer Vision Model 的新思路

从零开始实现 MobileViT 注意力机制——轻量级Transformer Vision Model 的新思路 近年来&#xff0c;计算机视觉领域中 Transformer 模型的崛起为图像处理带来了新的活力。特别是在 ViT&#xff08;Vision Transformer&#xff09;模型提出之后&#xff0c;Transformer 在图像…...