HarmonyOS 鸿蒙Next中如何实现数据加密、安全存储和权限管理?
HarmonyOS 鸿蒙Next中如何实现数据加密、安全存储和权限管理? 在HarmonyOS应用中如何保护用户数据安全?如何实现数据加密、安全存储和权限管理?
3 回复
解决方案
1. 密码加密存储
import cryptoFramework from '@ohos.security.cryptoFramework'
import { BusinessError } from '@ohos.base'
import util from '@ohos.util'
export class PasswordUtil {
/**
* MD5哈希
*/
static async md5(data: string): Promise<string> {
try {
const mdAlg = cryptoFramework.createMd('MD5')
await mdAlg.update({ data: new Uint8Array(this.stringToArray(data)) })
const result = await mdAlg.digest()
return this.arrayToHexString(new Uint8Array(result.data))
} catch (error) {
const err = error as BusinessError
console.error('MD5加密失败:', err.message)
return ''
}
}
/**
* SHA256哈希(推荐)
*/
static async sha256(data: string): Promise<string> {
try {
const mdAlg = cryptoFramework.createMd('SHA256')
await mdAlg.update({ data: new Uint8Array(this.stringToArray(data)) })
const result = await mdAlg.digest()
return this.arrayToHexString(new Uint8Array(result.data))
} catch (error) {
const err = error as BusinessError
console.error('SHA256加密失败:', err.message)
return ''
}
}
/**
* 加盐哈希(更安全)
*/
static async hashWithSalt(password: string, salt?: string): Promise<{ hash: string, salt: string }> {
// 生成盐值
if (!salt) {
salt = this.generateSalt()
}
// 组合密码和盐值
const combined = password + salt
const hash = await this.sha256(combined)
return { hash, salt }
}
/**
* 验证密码
*/
static async verifyPassword(
password: string,
hash: string,
salt: string
): Promise<boolean> {
const result = await this.hashWithSalt(password, salt)
return result.hash === hash
}
/**
* 生成随机盐值
*/
private static generateSalt(length: number = 16): string {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
let salt = ''
for (let i = 0; i < length; i++) {
salt += chars.charAt(Math.floor(Math.random() * chars.length))
}
return salt
}
private static stringToArray(str: string): number[] {
const arr: number[] = []
for (let i = 0; i < str.length; i++) {
arr.push(str.charCodeAt(i))
}
return arr
}
private static arrayToHexString(arr: Uint8Array): string {
let hexString = ''
for (let i = 0; i < arr.length; i++) {
const hex = arr[i].toString(16)
hexString += hex.length === 1 ? '0' + hex : hex
}
return hexString
}
}
// 使用示例
@Entry
@Component
struct PasswordDemo {
@State password: string = ''
@State hashedPassword: string = ''
@State salt: string = ''
build() {
Column({ space: 16 }) {
Text('密码加密')
.fontSize(20)
.fontWeight(FontWeight.Bold)
TextInput({
text: this.password,
placeholder: '请输入密码'
})
.width('100%')
.type(InputType.Password)
.onChange((value) => {
this.password = value
})
Button('加密密码')
.width('100%')
.onClick(async () => {
const result = await PasswordUtil.hashWithSalt(this.password)
this.hashedPassword = result.hash
this.salt = result.salt
})
if (this.hashedPassword) {
Column({ space: 8 }) {
Text('哈希值:')
.fontSize(14)
.fontWeight(FontWeight.Bold)
Text(this.hashedPassword)
.fontSize(12)
.fontColor('#666666')
.maxLines(2)
Text('盐值:')
.fontSize(14)
.fontWeight(FontWeight.Bold)
Text(this.salt)
.fontSize(12)
.fontColor('#666666')
}
.width('100%')
.padding(12)
.backgroundColor('#f5f5f5')
.borderRadius(8)
.alignItems(HorizontalAlign.Start)
}
Button('验证密码')
.width('100%')
.enabled(this.hashedPassword.length > 0)
.onClick(async () => {
const isValid = await PasswordUtil.verifyPassword(
this.password,
this.hashedPassword,
this.salt
)
console.log('密码验证结果:', isValid)
})
}
.padding(16)
}
}
2. AES数据加密
import cryptoFramework from '@ohos.security.cryptoFramework'
import { BusinessError } from '@ohos.base'
export class AESUtil {
private static readonly ALGORITHM = 'AES256|GCM|PKCS7'
private static readonly KEY_SIZE = 256
/**
* 生成密钥
*/
static async generateKey(): Promise<cryptoFramework.SymKey> {
try {
const symKeyGenerator = cryptoFramework.createSymKeyGenerator(this.ALGORITHM)
return await symKeyGenerator.generateSymKey()
} catch (error) {
const err = error as BusinessError
console.error('生成密钥失败:', err.message)
throw error
}
}
/**
* AES加密
*/
static async encrypt(
plainText: string,
key: cryptoFramework.SymKey
): Promise<{ cipherText: string, iv: string }> {
try {
const cipher = cryptoFramework.createCipher(this.ALGORITHM)
// 生成随机IV
const iv = this.generateIV()
const ivData = new Uint8Array(this.hexStringToArray(iv))
// 初始化加密器
await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, key, { data: ivData })
// 加密数据
const plainData = new Uint8Array(this.stringToArray(plainText))
await cipher.update({ data: plainData })
const encryptResult = await cipher.doFinal(null)
const cipherText = this.arrayToHexString(new Uint8Array(encryptResult.data))
return { cipherText, iv }
} catch (error) {
const err = error as BusinessError
console.error('加密失败:', err.message)
throw error
}
}
/**
* AES解密
*/
static async decrypt(
cipherText: string,
key: cryptoFramework.SymKey,
iv: string
): Promise<string> {
try {
const cipher = cryptoFramework.createCipher(this.ALGORITHM)
// 初始化解密器
const ivData = new Uint8Array(this.hexStringToArray(iv))
await cipher.init(cryptoFramework.CryptoMode.DECRYPT_MODE, key, { data: ivData })
// 解密数据
const cipherData = new Uint8Array(this.hexStringToArray(cipherText))
await cipher.update({ data: cipherData })
const decryptResult = await cipher.doFinal(null)
return this.arrayToString(new Uint8Array(decryptResult.data))
} catch (error) {
const err = error as BusinessError
console.error('解密失败:', err.message)
throw error
}
}
private static generateIV(): string {
const iv = new Uint8Array(16)
for (let i = 0; i < 16; i++) {
iv[i] = Math.floor(Math.random() * 256)
}
return this.arrayToHexString(iv)
}
private static stringToArray(str: string): number[] {
const arr: number[] = []
for (let i = 0; i < str.length; i++) {
arr.push(str.charCodeAt(i))
}
return arr
}
private static arrayToString(arr: Uint8Array): string {
return String.fromCharCode(...arr)
}
private static arrayToHexString(arr: Uint8Array): string {
let hexString = ''
for (let i = 0; i < arr.length; i++) {
const hex = arr[i].toString(16)
hexString += hex.length === 1 ? '0' + hex : hex
}
return hexString
}
private static hexStringToArray(hexString: string): number[] {
const arr: number[] = []
for (let i = 0; i < hexString.length; i += 2) {
arr.push(parseInt(hexString.substr(i, 2), 16))
}
return arr
}
}
// 使用示例
@Entry
@Component
struct AESDemo {
@State plainText: string = ''
@State encryptedText: string = ''
@State decryptedText: string = ''
private key?: cryptoFramework.SymKey
private iv: string = ''
async aboutToAppear() {
// 生成密钥
this.key = await AESUtil.generateKey()
}
build() {
Column({ space: 16 }) {
Text('AES加密')
.fontSize(20)
.fontWeight(FontWeight.Bold)
TextInput({
text: this.plainText,
placeholder: '请输入要加密的文本'
})
.width('100%')
.onChange((value) => {
this.plainText = value
})
Button('加密')
.width('100%')
.onClick(async () => {
if (this.key) {
const result = await AESUtil.encrypt(this.plainText, this.key)
this.encryptedText = result.cipherText
this.iv = result.iv
}
})
if (this.encryptedText) {
Text('加密结果:')
.fontSize(14)
.fontWeight(FontWeight.Bold)
Text(this.encryptedText)
.fontSize(12)
.fontColor('#666666')
.maxLines(3)
}
Button('解密')
.width('100%')
.enabled(this.encryptedText.length > 0)
.onClick(async () => {
if (this.key) {
this.decryptedText = await AESUtil.decrypt(
this.encryptedText,
this.key,
this.iv
)
}
})
if (this.decryptedText) {
Text('解密结果:')
.fontSize(14)
.fontWeight(FontWeight.Bold)
Text(this.decryptedText)
.fontSize(12)
.fontColor('#666666')
}
}
.padding(16)
}
}
3. 安全存储工具类
import preferences from '@ohos.data.preferences'
import cryptoFramework from '@ohos.security.cryptoFramework'
export class SecureStorage {
private static pref?: preferences.Preferences
private static key?: cryptoFramework.SymKey
/**
* 初始化
*/
static async init(): Promise<void> {
this.pref = await preferences.getPreferences(
getContext(),
'secure_storage'
)
this.key = await AESUtil.generateKey()
}
/**
* 安全存储数据
*/
static async setSecure(key: string, value: string): Promise<void> {
if (!this.pref || !this.key) {
await this.init()
}
try {
// 加密数据
const encrypted = await AESUtil.encrypt(value, this.key!)
// 存储加密数据和IV
await this.pref!.put(key, encrypted.cipherText)
await this.pref!.put(`${key}_iv`, encrypted.iv)
await this.pref!.flush()
} catch (error) {
console.error('安全存储失败:', error)
throw error
}
}
/**
* 安全读取数据
*/
static async getSecure(key: string): Promise<string | null> {
if (!this.pref || !this.key) {
await this.init()
}
try {
const cipherText = await this.pref!.get(key, '') as string
const iv = await this.pref!.get(`${key}_iv`, '') as string
if (!cipherText || !iv) {
return null
}
// 解密数据
return await AESUtil.decrypt(cipherText, this.key!, iv)
} catch (error) {
console.error('安全读取失败:', error)
return null
}
}
/**
* 删除数据
*/
static async remove(key: string): Promise<void> {
if (!this.pref) {
await this.init()
}
await this.pref!.delete(key)
await this.pref!.delete(`${key}_iv`)
await this.pref!.flush()
}
/**
* 清空所有数据
*/
static async clear(): Promise<void> {
if (!this.pref) {
await this.init()
}
await this.pref!.clear()
await this.pref!.flush()
}
}
// 使用示例
@Entry
@Component
struct SecureStorageDemo {
@State username: string = ''
@State password: string = ''
@State storedPassword: string = ''
async aboutToAppear() {
await SecureStorage.init()
}
build() {
Column({ space: 16 }) {
Text('安全存储')
.fontSize(20)
.fontWeight(FontWeight.Bold)
TextInput({
text: this.username,
placeholder: '用户名'
})
.width('100%')
.onChange((value) => {
this.username = value
})
TextInput({
text: this.password,
placeholder: '密码'
})
.width('100%')
.type(InputType.Password)
.onChange((value) => {
this.password = value
})
Button('安全保存')
.width('100%')
.onClick(async () => {
await SecureStorage.setSecure('username', this.username)
await SecureStorage.setSecure('password', this.password)
console.log('数据已安全保存')
})
Button('读取密码')
.width('100%')
.onClick(async () => {
this.storedPassword = await SecureStorage.getSecure('password') || ''
console.log('读取的密码:', this.storedPassword)
})
if (this.storedPassword) {
Text(`存储的密码: ${this.storedPassword}`)
.fontSize(14)
}
}
.padding(16)
}
}
4. Token安全管理
export interface TokenInfo {
accessToken: string
refreshToken: string
expiresAt: number
}
export class TokenManager {
private static readonly TOKEN_KEY = 'auth_token'
private static readonly REFRESH_KEY = 'refresh_token'
private static readonly EXPIRES_KEY = 'token_expires'
/**
* 保存Token
*/
static async saveToken(token: TokenInfo): Promise<void> {
await SecureStorage.setSecure(this.TOKEN_KEY, token.accessToken)
await SecureStorage.setSecure(this.REFRESH_KEY, token.refreshToken)
await SecureStorage.setSecure(this.EXPIRES_KEY, token.expiresAt.toString())
}
/**
* 获取Token
*/
static async getToken(): Promise<TokenInfo | null> {
const accessToken = await SecureStorage.getSecure(this.TOKEN_KEY)
const refreshToken = await SecureStorage.getSecure(this.REFRESH_KEY)
const expiresStr = await SecureStorage.getSecure(this.EXPIRES_KEY)
if (!accessToken || !refreshToken || !expiresStr) {
return null
}
return {
accessToken,
refreshToken,
expiresAt: parseInt(expiresStr)
}
}
/**
* 检查Token是否过期
*/
static async isTokenExpired(): Promise<boolean> {
const token = await this.getToken()
if (!token) {
return true
}
return Date.now() >= token.expiresAt
}
/**
* 清除Token
*/
static async clearToken(): Promise<void> {
await SecureStorage.remove(this.TOKEN_KEY)
await SecureStorage.remove(this.REFRESH_KEY)
await SecureStorage.remove(this.EXPIRES_KEY)
}
/**
* 获取有效Token
*/
static async getValidToken(): Promise<string | null> {
if (await this.isTokenExpired()) {
// Token已过期,需要刷新
await this.refreshToken()
}
const token = await this.getToken()
return token?.accessToken || null
}
/**
* 刷新Token
*/
private static async refreshToken(): Promise<void> {
// 实现Token刷新逻辑
console.log('刷新Token')
}
}
关键要点
- 密码安全: 使用SHA256+盐值哈希,不存储明文
- 数据加密: 使用AES加密敏感数据
- 密钥管理: 安全生成和存储加密密钥
- Token管理: 加密存储、过期检查、自动刷新
- 权限最小化: 只申请必要权限
最佳实践
- 不信任输入: 验证所有用户输入
- HTTPS通信: 网络传输使用HTTPS
- 敏感数据: 内存中不长期保留
- 日志安全: 不在日志中输出敏感信息
- 安全审计: 定期检查安全漏洞
更多关于HarmonyOS 鸿蒙Next中如何实现数据加密、安全存储和权限管理?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
鸿蒙Next通过分布式数据管理框架实现数据加密,支持端到端加密传输。安全存储基于密钥管理系统和硬件级安全芯片,提供文件级加密存储。权限管理采用最小权限原则,通过动态权限申请和细粒度访问控制确保应用权限安全。
在HarmonyOS Next中,数据安全通过系统级能力与应用层开发结合实现,以下是核心方案:
1. 数据加密
- 使用
@ohos.security.cryptoFramework加密框架,支持AES、RSA、ECC等算法。 - 通过
crypto.createCipher创建加密实例,结合密钥生成器(KeyGenerator)保障数据加密强度。 - 敏感数据(如密码)推荐使用非对称加密,本地存储结合密钥库(KeyStore)保护密钥。
2. 安全存储
- 用户数据:使用
@ohos.data.preferences持久化存储,数据以加密形式保存在应用沙箱内。 - 敏感信息:通过
@ohos.security.keystore密钥系统管理,密钥由TEE(可信执行环境)保护,避免明文泄露。 - 数据库加密:
@ohos.data.relationalStore支持数据库级加密,通过encrypt参数开启,数据文件自动加密。
3. 权限管理
- 声明权限:在
module.json5中按需声明权限(如ohos.permission.READ_CONTACTS)。 - 动态授权:使用
@ohos.abilityAccessCtrl的requestPermissionsFromUser接口触发动态授权弹窗。 - 最小化权限原则:仅申请必要权限,通过
verifyAccessToken接口校验权限状态。
实践建议
- 加密密钥与设备绑定,避免导出。
- 定期清理内存中的敏感数据临时对象。
- 使用
@ohos.security.huks统一密钥系统管理全生命周期密钥。
以上能力均需在ArkTS中调用对应API,并遵循HarmonyOS安全开发规范。

