鸿蒙5生物认证加密日记本开发实战 原创

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

鸿蒙5生物认证加密日记本开发实战

一、项目概述与架构设计

本日记本应用基于鸿蒙5的生物认证和加密技术实现,主要功能包括:
人脸/指纹生物认证登录

日记内容本地加密存储

多设备间加密数据同步

分布式身份验证管理

技术架构图

┌─────────────┐ ┌─────────────┐ ┌─────────────┐
手机设备 │ │ 平板设备 │ │ 手表设备 │

┌────────┐ │ │ ┌────────┐ │ │ ┌────────┐ │

│ 生物认证 │─┼───▶│ │ 数据解密 │ │ │ │ 快速预览 │ │

└────────┘ │ │ └────────┘ │ │ └────────┘ │

└───────┬─────┘ └───────┬─────┘ └───────┬─────┘
│ │

    └─────────┬────────┴─────────┬────────┘

      ┌───────▼───────┐   ┌───────▼───────┐

分布式数据服务 │ │ 加密安全服务 │

      └───────────────┘   └───────────────┘

二、核心代码实现
生物认证服务封装

// BioAuthService.ets
import userIAM_userAuth from ‘@ohos.userIAM.userAuth’;

export class BioAuthService {
private authInstance: userIAM_userAuth.UserAuthInstance;
private readonly CHALLENGE = 123456; // 自定义挑战值

constructor() {
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);
async authenticate(): Promise<boolean> {

try {
  const result = await this.authInstance.auth(this.CHALLENGE);
  return result.result === userIAM_userAuth.AuthResultCode.SUCCESS;

catch (err) {

  console.error('Authentication failed:', err);
  return false;

}

async checkAuthSupport(): Promise<boolean> {
const types = await userIAM_userAuth.getAvailableAuthType();
return types.length > 0;
}

文件加密服务实现

// CryptoService.ets
import cryptoFramework from ‘@ohos.security.cryptoFramework’;

export class CryptoService {
private static readonly ALGORITHM = ‘AES256’;
private static readonly TRANSFORMATION = ‘AES256/GCM/PKCS5Padding’;
private static readonly IV_LENGTH = 12; // GCM推荐12字节IV

async encryptData(data: string, key: string): Promise<EncryptedData> {
try {
const cipher = await cryptoFramework.createCipher(this.TRANSFORMATION);
const secretKey = await this.generateSecretKey(key);

  const iv = await this.generateIv();
  await cipher.init(cryptoFramework.CryptoMode.ENCRYPT_MODE, secretKey, {
    iv: iv,
    authTag: true
  });
  
  const input = { data: data };
  const output = await cipher.doFinal(input);
  
  return {
    cipherText: output.data,
    iv: iv,
    authTag: output.authTag
  };

catch (err) {

  console.error('Encryption failed:', err);
  throw err;

}

private async generateSecretKey(password: string): Promise<cryptoFramework.SymKey> {
const generator = await cryptoFramework.createSymKeyGenerator(this.ALGORITHM);
const keyData = new Uint8Array(new TextEncoder().encode(password));
return generator.convertKey({ data: keyData });
private async generateIv(): Promise<Uint8Array> {

const iv = new Uint8Array(this.IV_LENGTH);
return cryptoFramework.getRandomValues(iv);

}

日记管理主页面

// DiaryMainPage.ets
@Entry
@Component
struct DiaryMainPage {
@State diaries: Array<Diary> = [];
@State isAuthenticated: boolean = false;

private bioAuth = new BioAuthService();
private crypto = new CryptoService();
private syncService = new DiarySyncService();

aboutToAppear() {
this.checkAuth();
build() {

Column() {
  if (this.isAuthenticated) {
    DiaryListView({
      diaries: this.diaries,
      onAdd: this.addDiary.bind(this),
      onOpen: this.openDiary.bind(this)
    })

else {

    AuthPrompt({
      onAuthRequest: this.authenticate.bind(this)
    })

}

private async authenticate() {

const success = await this.bioAuth.authenticate();
if (success) {
  this.isAuthenticated = true;
  this.loadDiaries();

}

private async loadDiaries() {
const encrypted = await DiaryStorage.loadAll();
this.diaries = await Promise.all(encrypted.map(async e => {
const decrypted = await this.crypto.decryptData(e.content, this.getEncryptionKey());
return { …e, content: decrypted };
}));
private getEncryptionKey(): string {

// 实际应用中应从安全存储获取
return 'user_secret_key';

}

三、分布式数据同步实现
加密数据同步服务

// DiarySyncService.ets
import distributedData from ‘@ohos.data.distributedData’;

export class DiarySyncService {
private kvStore: distributedData.KVStore;
private readonly STORE_ID = ‘diary_sync_store’;

async init() {
const kvManager = await distributedData.createKVManager({
bundleName: ‘com.example.diary’
});

this.kvStore = await kvManager.getKVStore(this.STORE_ID, {
  createIfMissing: true,
  encrypt: true,
  autoSync: true,
  kvStoreType: distributedData.KVStoreType.SINGLE_VERSION
});

async syncDiary(diary: Diary, crypto: CryptoService) {

try {
  const encrypted = await crypto.encryptData(diary.content, this.getSyncKey());
  const syncData = {
    id: diary.id,
    title: diary.title,
    encryptedContent: encrypted.cipherText,
    iv: encrypted.iv,
    authTag: encrypted.authTag,
    timestamp: diary.timestamp,
    deviceId: deviceInfo.deviceId
  };
  
  await this.kvStore.put(diary_${diary.id}, JSON.stringify(syncData));

catch (err) {

  console.error('Sync failed:', err);

}

subscribeDiaryChanges(callback: (diary: Diary) => void, crypto: CryptoService) {
this.kvStore.on(‘dataChange’, distributedData.SubscribeType.SUBSCRIBE_TYPE_ALL, async (changes) => {
for (const change of changes) {
if (change.key.startsWith(‘diary_’)) {
const data = JSON.parse(change.value);
if (data.deviceId !== deviceInfo.deviceId) {
const decrypted = await crypto.decryptData({
cipherText: data.encryptedContent,
iv: data.iv,
authTag: data.authTag
}, this.getSyncKey());

        callback({
          id: data.id,
          title: data.title,
          content: decrypted,
          timestamp: data.timestamp
        });

}

});

private getSyncKey(): string {

// 实际应用中应从安全存储获取
return 'shared_sync_key';

}

多设备认证管理

// DeviceAuthManager.ets
import deviceManager from ‘@ohos.distributedHardware.deviceManager’;

export class DeviceAuthManager {
private trustedDevices: Array<string> = [];

async init() {
const manager = await deviceManager.createDeviceManager(‘com.example.diary’);
manager.on(‘deviceStateChange’, this.handleDeviceChange.bind(this));
manager.startDeviceDiscovery([‘diary_sync’]);
async authorizeNewDevice(deviceId: string): Promise<boolean> {

try {
  const authRequest = {
    authType: 1, // PIN码认证
    extraInfo: {}
  };
  
  await deviceManager.authenticateDevice(deviceId, authRequest);
  this.trustedDevices.push(deviceId);
  return true;

catch (err) {

  console.error('Device auth failed:', err);
  return false;

}

isDeviceTrusted(deviceId: string): boolean {
return this.trustedDevices.includes(deviceId);
private handleDeviceChange(data: deviceManager.DeviceStateChangeData) {

if (data.action === 0 && !this.isDeviceTrusted(data.device.deviceId)) {
  this.promptForAuthorization(data.device);

}

四、关键安全技术实现
密钥安全管理

// KeyManager.ets
import huks from ‘@ohos.security.huks’;

export class KeyManager {
private static readonly KEY_ALIAS = ‘diary_enc_key’;
private static readonly KEY_PARAMS: huks.HuksOptions = {
properties: [
tag: huks.HuksTag.HUKS_TAG_ALGORITHM,

    value: huks.HuksKeyAlg.HUKS_ALG_AES
  },

tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,

    value: huks.HuksKeySize.HUKS_AES_KEY_SIZE_256
  },

tag: huks.HuksTag.HUKS_TAG_PURPOSE,

    value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_ENCRYPT |
           huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_DECRYPT
  },

tag: huks.HuksTag.HUKS_TAG_BLOCK_MODE,

    value: huks.HuksCipherMode.HUKS_MODE_GCM

]

};

async generateOrGetKey(): Promise<huks.HuksKey> {
try {
if (!await this.keyExists()) {
await huks.generateKey(this.KEY_ALIAS, this.KEY_PARAMS);
return await huks.importKey(this.KEY_ALIAS, this.KEY_PARAMS);

catch (err) {

  console.error('Key operation failed:', err);
  throw err;

}

private async keyExists(): Promise<boolean> {
try {
await huks.getKeyProperties(this.KEY_ALIAS);
return true;
catch {

  return false;

}

安全存储实现

// SecureStorage.ets
import dataPreferences from ‘@ohos.data.preferences’;

export class SecureStorage {
private static readonly STORE_NAME = ‘diary_secure_store’;
private preferences: dataPreferences.Preferences;

async init() {
this.preferences = await dataPreferences.getPreferences(
getContext(this),
this.STORE_NAME
);
async put(key: string, value: string): Promise<void> {

await this.preferences.put(key, value);
await this.preferences.flush();

async get(key: string): Promise<string | undefined> {

return await this.preferences.get(key, '');

}

五、完整UI组件实现
生物认证提示组件

// AuthPrompt.ets
@Component
struct AuthPrompt {
@Prop onAuthRequest: () => void;
@State authTypes: Array<string> = [];

aboutToAppear() {
this.checkAvailableAuth();
build() {

Column() {
  Image('secure_diary.png')
    .width(120)
    .height(120)
    .margin({ bottom: 30 })
  
  Text('请验证身份以访问日记')
    .fontSize(20)
    .margin({ bottom: 10 })
  
  if (this.authTypes.length > 0) {
    ForEach(this.authTypes, (type) => {
      Button(使用${type}验证, { type: ButtonType.Capsule })
        .width('80%')
        .height(50)
        .margin({ top: 10 })
        .onClick(() => this.onAuthRequest())
    })

else {

    Text('未找到可用的生物认证方式')
      .fontColor(Color.Gray)

}

private async checkAvailableAuth() {

const bioAuth = new BioAuthService();
if (await bioAuth.checkAuthSupport()) {
  this.authTypes = ['人脸或指纹'];

}

日记列表组件

// DiaryListView.ets
@Component
struct DiaryListView {
@Prop diaries: Array<Diary>;
@Prop onAdd: () => void;
@Prop onOpen: (id: string) => void;

build() {
Column() {
// 添加按钮
Button(‘新建日记’, { type: ButtonType.Normal })
.width(‘90%’)
.margin(10)
.onClick(() => this.onAdd())

  // 日记列表
  List() {
    ForEach(this.diaries, (diary) => {
      ListItem() {
        DiaryItem({
          diary,
          onClick: () => this.onOpen(diary.id)
        })

})

.layoutWeight(1)

  .divider({ strokeWidth: 1, color: '#F1F1F1' })

}

@Component

struct DiaryItem {
@Prop diary: Diary;
@Prop onClick: () => void;

build() {
Row() {
Column() {
Text(this.diary.title)
.fontSize(18)
Text(this.formatDate(this.diary.timestamp))
.fontSize(12)
.opacity(0.6)
.layoutWeight(1)

  Image('arrow_right.png')
    .width(20)
    .height(20)

.padding(15)

.onClick(() => this.onClick())

}

六、项目部署与测试
权限配置

在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”

]

测试方案

// 生物认证测试
describe(‘BioAuth’, () => {
it(‘should authenticate with valid credentials’, async () => {
const bioAuth = new BioAuthService();
const mockResult = { result: userIAM_userAuth.AuthResultCode.SUCCESS };
jest.spyOn(bioAuth, ‘authenticate’).mockResolvedValue(mockResult);

const result = await bioAuth.authenticate();
expect(result).toBe(true);

});
});

// 加密测试
describe(‘Encryption’, () => {
it(‘should encrypt and decrypt data correctly’, async () => {
const crypto = new CryptoService();
const original = ‘这是我的秘密日记’;

const encrypted = await crypto.encryptData(original, 'test_key');
const decrypted = await crypto.decryptData(encrypted, 'test_key');

expect(decrypted).toEqual(original);

});
});

七、总结与扩展

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

端到端的日记内容加密保护

多设备间的安全数据同步

完整的密钥生命周期管理

扩展方向:
添加云备份与恢复功能

实现日记情感分析

开发时间轴视图

集成图片和语音日记

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

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