Appearance
安全存储
HarmonyOS 提供多种安全存储机制,保护敏感数据如 Token、密码、密钥等。
1. 安全存储方案对比
| 方案 | 适用场景 | 安全等级 | API 模块 |
|---|---|---|---|
| Preferences | 普通配置 | 低 | @kit.ArkDataShare |
| 加密 Preferences | 敏感配置 | 中 | Crypto + Preferences |
| KeyStore | 密钥存储 | 高 | @kit.CryptoArchitectureKit |
| RDB 加密 | 数据库 | 高 | Rdb + 加密 |
| TEE 环境 | 生物特征 | 最高 | TEE API |
2. KeyStore 密钥管理
生成密钥
typescript
import { cryptoFramework } from '@kit.CryptoArchitectureKit';
async function generateKey(): Promise<void> {
// 创建密钥生成器
let keyGen = await cryptoFramework.createKeyGen('RSA2048', 'user_id');
// 设置参数
let param = {
alias: 'my_key_alias',
authType: cryptoFramework.AuthType.PIN,
aesKeyLength: 256
};
// 生成密钥(存储在 KeyStore)
await keyGen.generateKey(param);
}使用密钥加密
typescript
async function encryptData(plainText: string): Promise<string> {
// 创建加密器
let encryptor = await cryptoFramework.createEncryptor('AES256', 'user_id');
// 使用 KeyStore 中的密钥加密
let encrypted = await encryptor.encrypt(plainText, {
keyAlias: 'my_key_alias'
});
return encrypted;
}
async function decryptData(cipherText: string): Promise<string> {
let decryptor = await cryptoFramework.createDecryptor('AES256', 'user_id');
let decrypted = await decryptor.decrypt(cipherText, {
keyAlias: 'my_key_alias'
});
return decrypted;
}3. 首选项加密存储
加密 Preferences 封装
typescript
import { preferences } from '@kit.ArkDataShare';
import { cryptoFramework } from '@kit.CryptoArchitectureKit';
class SecurePreferences {
private prefs: preferences.Preferences;
private encryptor: any;
private decryptor: any;
constructor(private context: common.Context) {}
async init(): Promise<void> {
// 初始化加解密器
this.encryptor = await cryptoFramework.createEncryptor('AES256');
this.decryptor = await cryptoFramework.createDecryptor('AES256');
// 加载 Preferences
this.prefs = await preferences.getPreferences(this.context, 'secure_prefs');
}
async put(key: string, value: string): Promise<void> {
// 加密后存储
let encrypted = await this.encryptor.encrypt(value, {
keyAlias: 'prefs_key'
});
await this.prefs.put(key, encrypted);
await this.prefs.flush();
}
async get(key: string): Promise<string | null> {
let encrypted = this.prefs.getSync(key) as string;
if (!encrypted) return null;
try {
return await this.decryptor.decrypt(encrypted, {
keyAlias: 'prefs_key'
});
} catch {
return null; // 解密失败
}
}
async remove(key: string): Promise<void> {
await this.prefs.delete(key);
await this.prefs.flush();
}
}
// 使用
let securePrefs = new SecurePreferences(context);
await securePrefs.init();
await securePrefs.put('auth_token', 'secret_token_123');
let token = await securePrefs.get('auth_token');4. Token/密码安全存储
Token 存储最佳实践
typescript
class TokenManager {
private static instance: TokenManager;
private securePrefs: SecurePreferences;
private constructor(context: common.Context) {
this.securePrefs = new SecurePreferences(context);
}
static getInstance(context: common.Context): TokenManager {
if (!TokenManager.instance) {
TokenManager.instance = new TokenManager(context);
}
return TokenManager.instance;
}
async saveToken(token: string): Promise<void> {
// 1. 加密存储
await this.securePrefs.put('access_token', token);
// 2. 可选:同时存储过期时间
let expireTime = Date.now() + 7 * 24 * 60 * 60 * 1000; // 7 天
await this.securePrefs.put('token_expire', expireTime.toString());
}
async getToken(): Promise<string | null> {
// 检查是否过期
let expireStr = await this.securePrefs.get('token_expire');
if (expireStr && Date.now() > parseInt(expireStr)) {
await this.clearToken();
return null;
}
return await this.securePrefs.get('access_token');
}
async clearToken(): Promise<void> {
await this.securePrefs.remove('access_token');
await this.securePrefs.remove('token_expire');
}
}密码存储(不推荐明文)
typescript
// ❌ 绝对不要明文存储密码
// await prefs.put('password', '123456');
// ✅ 只存储密码哈希或完全不存
import { cryptoFramework } from '@kit.CryptoArchitectureKit';
async function hashPassword(password: string): Promise<string> {
let digest = await cryptoFramework.createDigest('SHA256');
return await digest.digest(password);
}
// 验证时使用哈希比对
async function verifyPassword(input: string, storedHash: string): Promise<boolean> {
let inputHash = await hashPassword(input);
return inputHash === storedHash;
}5. 数据库加密
RDB 加密配置
typescript
import { relationalStore } from '@kit.ArkRdb';
async function createEncryptedRdb(): Promise<relationalStore.RdbStore> {
let config = {
name: 'secure.db',
securityLevel: relationalStore.SecurityLevel.SECRECY_LEVEL_HIGH,
encryptCipher: relationalStore.EncryptCipher.AES_256_GCM
};
let rdbStore = await relationalStore.getRdbStore(context, config);
return rdbStore;
}
// 使用加密数据库
let store = await createEncryptedRdb();
await store.insert({
table: 'users',
values: {
'username': 'admin',
'password_hash': 'hashed_value'
}
});6. 生物识别认证
指纹/面部识别
typescript
import { userIAM } from '@kit.UserIAM';
async function authenticateWithBiometrics(): Promise<boolean> {
let authenticator = userIAM.getAuthenticator(userIAM.AuthType.FINGERPRINT);
let result = await authenticator.authenticate({
timeout: 60000, // 60 秒超时
challenge: 'random_challenge' // 防止重放攻击
});
return result.result === userIAM.AuthResult.SUCCESS;
}
// 结合加密
async function secureOperation(): Promise<void> {
let authenticated = await authenticateWithBiometrics();
if (!authenticated) {
throw new Error('生物识别失败');
}
// 认证通过后才能访问敏感数据
let token = await TokenManager.getInstance(context).getToken();
}7. 面试高频问题
Q1: 如何安全存储 Token?
答:使用 KeyStore 生成密钥 → 加密 Token → 存储在加密的 Preferences 中 → 定期轮换 Token。
Q2: KeyStore 的作用是什么?
答:KeyStore 是系统级的安全密钥存储服务,密钥在 TEE(可信执行环境)中生成和存储,应用无法直接导出。
Q3: 密码应该如何存储?
答:永远不要明文存储密码。应该存储密码的哈希值(如 SHA256),验证时比对哈希值。更好的方式是使用 OAuth 等免密码方案。
8. 与 Android 对照
| 概念 | HarmonyOS | Android |
|---|---|---|
| KeyStore | cryptoFramework.KeyGen | KeyStore |
| 加密存储 | AES256 + Preferences | EncryptedSharedPreferences |
| 生物识别 | userIAM.Authenticator | BiometricPrompt |
| 数据库加密 | RdbStore.securityLevel | SQLCipher |
面试提示:安全存储是应用安全的核心,需掌握 KeyStore 使用和加密存储方案。