数据安全深度剖析:本地存储加密与敏感信息保护(鸿蒙5+ 新手指南)
身份信息:姓名、身份证号、手机号;生物特征:指纹、人脸、声纹;位置轨迹:经纬度、移动路径;金融信息:银行卡号、支付密码。应用直接明文存储手机号,攻击者通过文件提取获取;相机应用未脱敏直接上传拍摄的用户身份证照片;位置应用将实时经纬度明文传输至服务器。技术场景核心目标鸿蒙5+ 关键方案本地存储加密防止明文存储泄露TEE存储密钥 + AES-256-GCM加密敏感信息保
引言
在智能设备普及的今天,客户端应用(如笔记、健康、支付类App)往往需要存储大量用户数据(如聊天记录、位置轨迹、支付密码)。若这些数据以明文形式存储,一旦设备丢失或被攻击,用户隐私将直接泄露。鸿蒙(HarmonyOS)5.0及以上版本针对数据安全推出了分级保护机制、硬件级加密引擎、敏感信息脱敏工具等能力,本文将围绕本地存储加密与敏感信息保护两大核心场景,结合新手学习需求,从原理到代码实战展开解析。
一、本地存储加密:让“存”更安全
1.1 本地存储的常见风险
应用本地存储数据的常见方式包括:
- 轻量级存储:
Preferences(键值对)、@Storage装饰的变量(鸿蒙分布式缓存); - 文件存储:内部存储(
/data/accounts/account_0/appdata/<包名>/files)或外部存储(需申请权限); - 数据库:关系型数据库(
@Database)、非关系型数据库(@OHOS.data.rdb)。
这些存储方式的默认风险是:数据以明文形式落盘,攻击者通过文件提取工具(如鸿蒙的hdc shell ls /data)或数据库dump工具可直接获取敏感信息(如用户密码、聊天记录)。
1.2 鸿蒙5+ 本地存储加密的核心能力
鸿蒙5+ 为本地存储提供了全链路加密支持,核心方案包括:
- 应用沙箱隔离:每个应用的数据存储在独立沙箱中,其他应用无权限访问(需系统级权限才能突破);
- 硬件加密引擎:利用设备CPU的AES-NI指令或安全芯片(如SE安全芯片)加速加密;
- 统一加密接口:提供
HwSecuritySDK(鸿蒙安全SDK),支持对文件、数据库、Preferences的透明加密。
1.3 新手实战:Preferences键值对加密存储
Preferences是鸿蒙轻量级存储方案,适合存储少量敏感信息(如用户Token)。以下代码演示如何对Preferences中的数据进行加密存储。
步骤1:添加加密依赖
在oh-package.json5中引入鸿蒙安全SDK:
{
"dependencies": [
{
"name": "@ohos.security",
"version": "5.0.0"
}
]
}
步骤2:实现AES加密工具类
使用鸿蒙提供的Crypto模块实现AES-256-GCM加密(密钥存储于TEE,避免硬编码):
// 加密工具类(ArkTS)
import crypto from '@ohos.security.crypto';
import tee from '@ohos.security.tee'; // TEE接口(用于安全获取密钥)
/**
* 从TEE获取AES密钥(密钥长度32字节,AES-256)
* @returns 密钥字节数组
*/
async function getAesKeyFromTee(): Promise<Uint8Array> {
try {
// 初始化TEE上下文(需设备支持)
const teeContext = await tee.TEEContext.create();
// 从TEE安全存储中读取密钥(假设已预先写入)
const keyBlob = await teeContext.getSecretData('user_aes_key');
return new Uint8Array(keyBlob);
} catch (err) {
console.error('获取密钥失败:', err.message);
throw new Error('密钥获取失败');
}
}
/**
* 加密字符串(AES-256-GCM)
* @param plaintext 明文
* @returns 密文(含IV和认证标签)
*/
async function encryptData(plaintext: string): Promise<Uint8Array> {
const key = await getAesKeyFromTee();
const aesGcm = new crypto.AesGcm(key);
// 生成随机IV(推荐12字节)
const iv = crypto.getRandomValues(new Uint8Array(12));
// 加密并生成认证标签(16字节)
const ciphertext = aesGcm.encrypt(iv, new TextEncoder().encode(plaintext));
// 合并IV、密文、标签(格式:IV(12) + 密文(N) + 标签(16))
const result = new Uint8Array(iv.length + ciphertext.length + 16);
result.set(iv);
result.set(ciphertext, iv.length);
result.set(aesGcm.tag!, iv.length + ciphertext.length);
return result;
}
/**
* 解密字符串(AES-256-GCM)
* @param ciphertext 密文(含IV和标签)
* @returns 明文
*/
async function decryptData(ciphertext: Uint8Array): Promise<string> {
const key = await getAesKeyFromTee();
const aesGcm = new crypto.AesGcm(key);
// 分离IV、密文、标签
const iv = ciphertext.subarray(0, 12);
const encryptedData = ciphertext.subarray(12, ciphertext.length - 16);
const tag = ciphertext.subarray(ciphertext.length - 16);
// 解密
const plaintext = aesGcm.decrypt(iv, encryptedData, tag);
return new TextDecoder().decode(plaintext);
}
步骤3:加密存储Preferences
在业务代码中使用上述工具类,对Preferences的键值对进行加密:
// 用户数据存储模块(ArkTS)
import preferences from '@ohos.data.preferences';
// 初始化Preferences
let pref: preferences.Preferences = null;
async function initPreferences(context: Context) {
pref = await preferences.getPreferences(context, 'user_data');
}
/**
* 存储加密后的用户Token
* @param token 明文Token
*/
async function saveEncryptedToken(token: string) {
if (!pref) await initPreferences(getContext(this));
const encrypted = await encryptData(token);
await pref.put('user_token', encrypted);
await pref.flush();
}
/**
* 获取并解密用户Token
* @returns 明文Token(若不存在返回null)
*/
async function getDecryptedToken(): Promise<string | null> {
if (!pref) await initPreferences(getContext(this));
const encrypted = await pref.get('user_token', null);
if (!encrypted) return null;
return decryptData(encrypted);
}
二、敏感信息保护:让“用”更安全
2.1 敏感信息的定义与风险
敏感信息是指一旦泄露会对用户隐私或设备安全造成严重影响的数据,常见类型包括:
- 身份信息:姓名、身份证号、手机号;
- 生物特征:指纹、人脸、声纹;
- 位置轨迹:经纬度、移动路径;
- 金融信息:银行卡号、支付密码。
风险场景示例:
- 应用直接明文存储手机号,攻击者通过文件提取获取;
- 相机应用未脱敏直接上传拍摄的用户身份证照片;
- 位置应用将实时经纬度明文传输至服务器。
2.2 鸿蒙5+ 敏感信息保护的核心机制
鸿蒙5+ 从权限控制、数据脱敏、生命周期管理三个维度提供保护:
- 最小权限原则:应用仅能获取必要权限(如
ohos.permission.LOCATION),且需用户动态授权; - 数据脱敏API:提供
MaskUtils(掩码)、PseudonymUtils(匿名化)等工具,避免敏感信息明文展示; - 安全传输:强制使用TLS 1.3加密网络传输,防止中间人攻击。
2.3 新手实战:敏感信息脱敏与安全展示
场景1:手机号脱敏展示
用户个人页面需要显示手机号(如13812345678),但需隐藏中间4位(138****5678)。鸿蒙5+ 提供MaskUtils实现快速脱敏。
// 手机号脱敏工具(ArkTS)
import maskUtils from '@ohos.utils.net.maskUtils';
/**
* 对手机号进行脱敏处理
* @param phone 原始手机号(需校验长度)
* @returns 脱敏后字符串(如138****5678)
*/
function desensitizePhone(phone: string): string {
if (!/^1[3-9]\d{9}$/.test(phone)) {
console.error('手机号格式错误');
return '';
}
// 使用鸿蒙MaskUtils的中间替换模式(保留前3位和后4位)
return maskUtils.mask(phone, { type: maskUtils.MaskType.PHONE });
}
// 使用示例
const rawPhone = '13812345678';
const maskedPhone = desensitizePhone(rawPhone); // 输出:138****5678
场景2:位置信息模糊化
应用需要记录用户位置轨迹,但需避免精确坐标泄露。可使用Geolocation模块的setAccuracy方法降低精度,或手动模糊经纬度。
// 位置信息模糊化工具(ArkTS)
import geolocation from '@ohos.geolocation';
/**
* 模糊经纬度(保留小数点后2位)
* @param longitude 原始经度
* @param latitude 原始纬度
* @returns 模糊后坐标(如116.3975°E → 116.40°E)
*/
function blurLocation(longitude: number, latitude: number): { blurredLng: number, blurredLat: number } {
// 保留2位小数(误差约±1km)
const blurredLng = Number(longitude.toFixed(2));
const blurredLat = Number(latitude.toFixed(2));
return { blurredLng, blurredLat };
}
// 使用示例
geolocation.getCurrentLocation({
enableHighAccuracy: false, // 关闭高精度(降低功耗)
timeout: 10000
}).then(location => {
const { blurredLng, blurredLat } = blurLocation(location.longitude, location.latitude);
console.log(`模糊后位置:${blurredLng}, ${blurredLat}`);
}).catch(err => {
console.error('获取位置失败:', err.message);
});
三、总结与最佳实践
核心总结
| 技术场景 | 核心目标 | 鸿蒙5+ 关键方案 |
|---|---|---|
| 本地存储加密 | 防止明文存储泄露 | TEE存储密钥 + AES-256-GCM加密 |
| 敏感信息保护 | 避免隐私数据明文展示/传输 | 数据脱敏API + 最小权限控制 |
新手最佳实践
-
本地存储加密:
- 优先使用鸿蒙提供的
Preferences或数据库加密接口,避免自行实现弱加密算法(如DES); - 密钥必须通过TEE或硬件安全模块(HSM)获取,禁止硬编码在代码中;
- 对敏感数据(如密码)启用“二次加密”(如先AES加密,再用RSA加密密钥)。
- 优先使用鸿蒙提供的
-
敏感信息保护:
- 遵循“最小必要”原则,仅申请应用运行必需的权限(如位置应用仅需
ohos.permission.LOCATION); - 展示敏感信息前强制脱敏(如手机号、身份证号),避免日志或界面意外泄露;
- 传输敏感数据时强制使用HTTPS(鸿蒙5+ 默认启用TLS 1.3,无需额外配置)。
- 遵循“最小必要”原则,仅申请应用运行必需的权限(如位置应用仅需
更多推荐
所有评论(0)