📚鸿蒙开发往期学习笔录✒️:
✒️ 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~
✒️ 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?
✒️ 嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~
✒️ 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?
✒️ 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?
✒️ 记录一场鸿蒙开发岗位面试经历~
✒️ 持续更新中……
场景介绍
为了满足数据库的安全特性,存有敏感信息的应用会在 EL5 (加密路径切换请参考 获取和修改加密分区 EL1-EL4路径切换)路径下创建了一个E类数据库。在锁屏的情况下,满足一定条件时,会触发密钥的销毁,此时E类数据库不可操作。当锁屏解锁后,密钥会恢复,E类数据库恢复正常读写操作。这样的设计可以有效防止用户数据的泄露。
然而,在锁屏的过程中,应用程序仍然可以继续写入数据,由于此时E类数据库不可读写,可能会导致数据丢失。为了解决这个问题,当前提供了一种方案:在锁屏的状态下,将数据存储在EL2路径下的C类数据库中。当解锁后,再将数据迁移到E类数据库中。这样可以确保数据在锁屏期间的安全性和一致性。
键值型数据库和关系型数据库均支持E类加密数据库。
实现机制
通过封装Mover类、Store类、SecretKeyObserver类和ECStoreManager类实现应用数据库密钥加锁和解锁状态下E类数据库和C类数据库的切换和操作。
Mover类:提供数据库数据迁移接口,在锁屏解锁后,若C类数据库中有数据,使用该接口将数据迁移到E类数据库。
Store类:提供访问当前可操作数据库,对数据库进行相关操作的接口。
SecretKeyObserver类:提供了获取当前密钥状态的接口,在密钥销毁后,关闭E类数据库。
ECStoreManager类:用于管理应用的E类数据库和C类数据库。
配置权限
使用EL5路径下的数据库,需要配置ohos.permission.PROTECT_SCREEN_LOCK_DATA权限。
// module.json5
"requestPermissions": [
{
"name": "ohos.permission.PROTECT_SCREEN_LOCK_DATA"
}
]
键值型数据库E类加密
本章节提供键值型数据库的E类加密数据库使用方式,提供 Mover 类、 Store 类、 SecretKeyObserver 类和 ECStoreManager 类的具体实现,并在 EntryAbility 和 index按键事件 中展示这几个类的使用方式。
Mover
提供数据库数据迁移接口,在锁屏解锁后,若C类数据库中存在数据,使用该接口将数据迁移到E类数据库。
// Mover.ts
import { distributedKVStore } from '@kit.ArkData';
export class Mover {
async move(eStore: distributedKVStore.SingleKVStore, cStore: distributedKVStore.SingleKVStore): Promise<void> {
if (eStore != null && cStore != null) {
let entries: distributedKVStore.Entry[] = await cStore.getEntries('key_test_string');
await eStore.putBatch(entries);
console.info(`ECDB_Encry move success`);
}
}
}
Store
提供了获取数据库,在数据库中插入数据、删除数据、更新数据和获取当前数据数量的接口。
// Store.ts
import { distributedKVStore } from '@kit.ArkData';
import { BusinessError } from '@kit.BasicServicesKit';
let kvManager: distributedKVStore.KVManager;
export class StoreInfo {
kvManagerConfig: distributedKVStore.KVManagerConfig;
storeId: string;
option: distributedKVStore.Options;
}
export class Store {
async getECStore(storeInfo: StoreInfo): Promise<distributedKVStore.SingleKVStore> {
try {
kvManager = distributedKVStore.createKVManager(storeInfo.kvManagerConfig);
console.info("Succeeded in creating KVManager");
} catch (e) {
let error = e as BusinessError;
console.error(`Failed to create KVManager.code is ${error.code},message is ${error.message}`);
}
if (kvManager !== undefined) {
kvManager = kvManager as distributedKVStore.KVManager;
let kvStore: distributedKVStore.SingleKVStore | null;
try {
kvStore = await kvManager.getKVStore<distributedKVStore.SingleKVStore>(storeInfo.storeId, storeInfo.option);
if (kvStore != undefined) {
console.info(`ECDB_Encry succeeded in getting store : ${storeInfo.storeId}`);
return kvStore;
}
} catch (e) {
let error = e as BusinessError;
console.error(`An unexpected error occurred.code is ${error.code},message is ${error.message}`);
}
}
}
putOnedata(kvStore: distributedKVStore.SingleKVStore): void {
if (kvStore != undefined) {
const KEY_TEST_STRING_ELEMENT = 'key_test_string' + String(Date.now());
const VALUE_TEST_STRING_ELEMENT = 'value_test_string' + String(Date.now());
try {
kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, (err) => {
if (err !== undefined) {
console.error(`Failed to put data. Code:${err.code},message:${err.message}`);
return;
}
console.info(`ECDB_Encry Succeeded in putting data.${KEY_TEST_STRING_ELEMENT}`);
});
} catch (e) {
let error = e as BusinessError;
console.error(`An unexpected error occurred. Code:${error.code},message:${error.message}`);
}
}
}
getDataNum(kvStore: distributedKVStore.SingleKVStore): void {
if (kvStore != undefined) {
let resultSet: distributedKVStore.KVStoreResultSet;
kvStore.getResultSet("key_test_string").then((result: distributedKVStore.KVStoreResultSet) => {
console.info(`ECDB_Encry Succeeded in getting result set num ${result.getCount()}`);
resultSet = result;
if (kvStore != null) {
kvStore.closeResultSet(resultSet).then(() => {
console.info('Succeeded in closing result set');
}).catch((err: BusinessError) => {
console.error(`Failed to close resultset.code is ${err.code},message is ${err.message}`);
});
}
}).catch((err: BusinessError) => {
console.error(`Failed to get resultset.code is ${err.code},message is ${err.message}`);
});
}
}
deleteOnedata(kvStore: distributedKVStore.SingleKVStore): void {
if (kvStore != undefined) {
kvStore.getEntries('key_test_string', (err: BusinessError, entries: distributedKVStore.Entry[]) => {
if (err != undefined) {
console.error(`Failed to get Entries.code is ${err.code},message is ${err.message}`);
return;
}
if (kvStore != null && entries.length != 0) {
kvStore.delete(entries[0].key, (err: BusinessError) => {
if (err != undefined) {
console.error(`Failed to delete.code is ${err.code},message is ${err.message}`);
return;
}
console.info('ECDB_Encry