鸿蒙5生物认证加密日记本开发实战:多设备安全同步方案 原创

进修的泡芙
发布于 2025-6-20 14:14
浏览
0收藏

鸿蒙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);

});
});

六、总结与扩展

本方案实现了:
基于生物认证的安全访问控制

端到端加密的日记存储

多设备安全数据同步

分布式密钥管理

扩展方向:
添加云端备份恢复

开发日记情感分析

集成语音日记功能

支持日记时间线视图

鸿蒙的安全框架为隐私敏感型应用开发提供了坚实基础,开发者可基于此项目框架构建更安全的数据管理应用。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
收藏
回复
举报
回复
    相关推荐