
鸿蒙5生物认证加密日记本开发实战:多设备安全同步方案 原创
鸿蒙5生物认证加密日记本开发实战:多设备安全同步方案
一、项目概述与架构设计
本加密日记本基于鸿蒙5的生物认证和分布式安全能力实现,主要功能包括:
人脸/指纹生物认证登录
日记内容端到端加密
多设备数据安全同步
分布式密钥管理
技术架构图
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
手机设备 │ │ 平板设备 │ │ 电脑设备 │
┌────────┐ │ │ ┌────────┐ │ │ ┌────────┐ │
│ 日记本 │─┼───▶│ │ 日记本 │ │ │ │ 日记本 │ │
└────────┘ │ │ └────────┘ │ │ └────────┘ │
└───────┬─────┘ └───────┬─────┘ └───────┬─────┘
│ │
└─────────┬────────┴─────────┬────────┘
│
┌───────▼───────┐ ┌───────▼───────┐
分布式安全服务 │ │ 密钥管理服务 │
└───────────────┘ └───────────────┘
二、核心代码实现
生物认证服务封装
// BioAuthService.ets
import userIAM_userAuth from ‘@ohos.userIAM.userAuth’;
import cryptoFramework from ‘@ohos.security.cryptoFramework’;
export class BioAuthService {
private authInstance: userIAM_userAuth.UserAuthInstance;
private readonly CHALLENGE = 123456; // 自定义挑战值
async authenticate(): Promise<boolean> {
try {
const config: userIAM_userAuth.AuthConfig = {
authType: [userIAM_userAuth.UserAuthType.FACE, userIAM_userAuth.UserAuthType.FINGERPRINT],
authTrustLevel: userIAM_userAuth.AuthTrustLevel.STRONG
};
this.authInstance = userIAM_userAuth.getAuthInstance(config);
const result = await this.authInstance.auth(this.CHALLENGE);
return result.result === userIAM_userAuth.AuthResultCode.SUCCESS;
catch (err) {
console.error('生物认证失败:', err);
return false;
}
async generateEncryptionKey(): Promise<cryptoFramework.SymKey> {
const authResult = await this.authInstance.getAuthToken();
return this.deriveKeyFromAuthToken(authResult.token);
private async deriveKeyFromAuthToken(token: Uint8Array): Promise<cryptoFramework.SymKey> {
const generator = await cryptoFramework.createSymKeyGenerator('AES256');
return generator.convertKey({ data: token });
}
日记加密服务
// DiaryCryptoService.ets
import cryptoFramework from ‘@ohos.security.cryptoFramework’;
export class DiaryCryptoService {
private symKey: cryptoFramework.SymKey;
async init(key: cryptoFramework.SymKey) {
this.symKey = key;
async encryptDiary(content: string): Promise<EncryptedDiary> {
const cipher = await cryptoFramework.createCipher('AES256GCM
PKCS5’);
const iv = cryptoFramework.getRandomValues(new Uint8Array(12));
await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, this.symKey, { iv });
const input = { data: new TextEncoder().encode(content) };
const output = await cipher.doFinal(input);
return {
cipherText: output.data,
iv,
authTag: output.authTag,
timestamp: new Date().getTime()
};
async decryptDiary(encrypted: EncryptedDiary): Promise<string> {
const cipher = await cryptoFramework.createCipher('AES256GCM
PKCS5’);
await cipher.init(cryptoFramework.CryptoMode.DECRYPT_MODE, this.symKey, {
iv: encrypted.iv,
authTag: encrypted.authTag
});
const input = { data: encrypted.cipherText };
const output = await cipher.doFinal(input);
return new TextDecoder().decode(output.data);
}
分布式数据同步
// DiarySyncService.ets
import distributedData from ‘@ohos.data.distributedData’;
export class DiarySyncService {
private kvStore: distributedData.KVStore;
private readonly STORE_ID = ‘secure_diary_store’;
async init() {
const kvManager = await distributedData.createKVManager({
bundleName: ‘com.example.diary’,
securityLevel: distributedData.SecurityLevel.S1
});
this.kvStore = await kvManager.getKVStore(this.STORE_ID, {
createIfMissing: true,
autoSync: true,
encrypt: true,
backup: false,
kvStoreType: distributedData.KVStoreType.SINGLE_VERSION
});
async syncDiary(diary: EncryptedDiary): Promise<void> {
try {
await this.kvStore.put(diary_${diary.timestamp}, JSON.stringify({
...diary,
deviceId: deviceInfo.deviceId
}));
catch (err) {
console.error('同步日记失败:', err);
}
subscribeDiaryChanges(callback: (diary: EncryptedDiary) => void) {
this.kvStore.on(‘dataChange’, distributedData.SubscribeType.SUBSCRIBE_TYPE_ALL, (changes) => {
changes.forEach(change => {
if (change.key.startsWith(‘diary_’)) {
const data = JSON.parse(change.value);
if (data.deviceId !== deviceInfo.deviceId) {
callback(data);
}
});
});
}
三、关键技术创新点
多设备密钥同步方案
// 安全密钥分发
class KeyDistributionService {
private static readonly KEY_SHARD_COUNT = 3;
async distributeKey(key: cryptoFramework.SymKey, devices: string[]) {
// 1. 分割密钥
const shards = this.splitKey(key, KEY_SHARD_COUNT);
// 2. 分发密钥分片
await Promise.all(
shards.map((shard, i) =>
this.sendKeyShard(shard, devices[i % devices.length])
)
);
private splitKey(key: cryptoFramework.SymKey, parts: number): Uint8Array[] {
const keyData = key.getEncoded();
const shardSize = Math.ceil(keyData.length / parts);
return Array.from({ length: parts }, (_, i) =>
keyData.slice(i shardSize, (i + 1) shardSize)
);
private async recoverKey(shards: Uint8Array[]): Promise<cryptoFramework.SymKey> {
const combined = new Uint8Array(shards.reduce((sum, s) => sum + s.length, 0));
let offset = 0;
shards.forEach(shard => {
combined.set(shard, offset);
offset += shard.length;
});
const generator = await cryptoFramework.createSymKeyGenerator('AES256');
return generator.convertKey({ data: combined });
}
生物认证增强机制
// 多因素认证
class MultiFactorAuth {
private authInstance: userIAM_userAuth.UserAuthInstance;
async authenticateWithFallback(): Promise<boolean> {
try {
// 首选生物认证
const bioResult = await this.tryBiometricAuth();
if (bioResult) return true;
// 备选设备PIN码认证
return await this.tryPinAuth();
catch (err) {
console.error('认证失败:', err);
return false;
}
private async tryBiometricAuth(): Promise<boolean> {
const config: userIAM_userAuth.AuthConfig = {
authType: [userIAM_userAuth.UserAuthType.FACE],
authTrustLevel: userIAM_userAuth.AuthTrustLevel.STRONG
};
this.authInstance = userIAM_userAuth.getAuthInstance(config);
const result = await this.authInstance.auth(this.CHALLENGE);
return result.result === userIAM_userAuth.AuthResultCode.SUCCESS;
private async tryPinAuth(): Promise<boolean> {
const pinAuth = new PinAuthService();
return await pinAuth.verifyPin();
}
数据完整性验证
// 日记完整性检查
class DiaryIntegrityChecker {
private static readonly HMAC_ALG = ‘SHA256’;
async verifyDiary(diary: EncryptedDiary, key: cryptoFramework.SymKey): Promise<boolean> {
// 1. 验证时间戳
if (diary.timestamp > Date.now() + 60000) { // 1分钟容差
return false;
// 2. 验证HMAC
const hmac = await this.computeHMAC(diary.cipherText, key);
return hmac === diary.hmac;
private async computeHMAC(data: Uint8Array, key: cryptoFramework.SymKey): Promise<Uint8Array> {
const hmac = await cryptoFramework.createMac('HMAC|' + this.HMAC_ALG);
await hmac.init(key);
const input: cryptoFramework.DataBlob = { data };
const output = await hmac.doFinal(input);
return output.data;
}
四、完整UI组件实现
日记列表组件
// DiaryListView.ets
@Component
struct DiaryListView {
@Prop diaries: Diary[];
@Prop onSelect: (diary: Diary) => void;
@State unlockedDiaries: Set<string> = new Set();
private cryptoService = new DiaryCryptoService();
build() {
List() {
ForEach(this.diaries, (diary) => {
ListItem() {
DiaryItem({
diary,
isUnlocked: this.unlockedDiaries.has(diary.id),
onUnlock: () => this.unlockDiary(diary)
})
.onClick(() => this.onSelect(diary))
})
.divider({ strokeWidth: 1, color: ‘#F1F1F1’ })
private async unlockDiary(diary: EncryptedDiary) {
try {
const content = await this.cryptoService.decryptDiary(diary);
this.unlockedDiaries.add(diary.id);
catch (err) {
console.error('解密日记失败:', err);
}
日记编辑组件
// DiaryEditor.ets
@Component
struct DiaryEditor {
@State content: string = ‘’;
@State isLocked: boolean = true;
private bioAuth = new BioAuthService();
private cryptoService = new DiaryCryptoService();
build() {
Column() {
if (this.isLocked) {
Button(‘解锁编辑’, { type: ButtonType.Capsule })
.onClick(() => this.unlockEditor())
else {
TextEditor(this.content)
.height('80%')
.onChange((value: string) => {
this.content = value;
})
Button('保存', { type: ButtonType.Capsule })
.margin(10)
.onClick(() => this.saveDiary())
}
.padding(15)
private async unlockEditor() {
const authenticated = await this.bioAuth.authenticate();
if (authenticated) {
this.isLocked = false;
}
private async saveDiary() {
const encrypted = await this.cryptoService.encryptDiary(this.content);
await this.syncService.syncDiary(encrypted);
this.isLocked = true;
}
五、项目部署与测试
权限配置
在module.json5中添加:
“requestPermissions”: [
“name”: “ohos.permission.ACCESS_BIOMETRIC”
},
“name”: “ohos.permission.USE_BIOMETRIC_INTERNAL”
},
“name”: “ohos.permission.DISTRIBUTED_DATASYNC”
},
“name”: “ohos.permission.ACCESS_USER_AUTH_INTERNAL”
},
“name”: “ohos.permission.SECURE_KEY_OPERATION”
]
测试方案
// 生物认证测试
describe(‘BioAuth’, () => {
it(‘should authenticate with valid credentials’, async () => {
const service = new BioAuthService();
const mockResult = { result: userIAM_userAuth.AuthResultCode.SUCCESS };
jest.spyOn(service, ‘authenticate’).mockResolvedValue(mockResult);
const result = await service.authenticate();
expect(result).toBe(true);
});
});
// 加密解密测试
describe(‘DiaryCrypto’, () => {
it(‘should encrypt and decrypt content correctly’, async () => {
const service = new DiaryCryptoService();
await service.init(testKey);
const original = '测试日记内容';
const encrypted = await service.encryptDiary(original);
const decrypted = await service.decryptDiary(encrypted);
expect(decrypted).toEqual(original);
});
});
// 数据同步测试
describe(‘DiarySync’, () => {
it(‘should sync encrypted diary between devices’, async () => {
const device1 = new MockDevice(‘device1’);
const device2 = new MockDevice(‘device2’);
await device1.addDiary('测试日记');
await device2.waitForSync();
expect(device2.getDiaries()).toHaveLength(1);
});
});
六、总结与扩展
本方案实现了:
基于生物认证的安全访问控制
端到端加密的日记存储
多设备安全数据同步
分布式密钥管理
扩展方向:
添加云端备份恢复
开发日记情感分析
集成语音日记功能
支持日记时间线视图
鸿蒙的安全框架为隐私敏感型应用开发提供了坚实基础,开发者可基于此项目框架构建更安全的数据管理应用。
