使用 Crypto.js 与 Dexie.js 实现数据加密存储
结合 Crypto.js 和 Dexie.js 实现数据加密存储,可以让敏感数据在浏览器的 IndexedDB 中更加安全地存储。以下是详细实现步骤和代码示例:
1. 准备工作
- 安装所需库
npm install crypto-js dexie
2. 实现原理
- 数据加密:使用 Crypto.js 对数据进行加密,生成密文存储在 IndexedDB 中。
- 数据解密:从 IndexedDB 读取密文后,用相同的加密密钥解密为明文。
- 结合 Dexie.js:通过 Dexie.js 提供的简便接口管理 IndexedDB 的读写操作。
3. 实现步骤
3.1 初始化 Dexie 数据库
定义一个包含需要存储的字段的 Dexie 数据库。
import Dexie from 'dexie';
const db = new Dexie('EncryptedDatabase');
db.version(1).stores({
items: '++id, name, encryptedData', // id是主键,name用于查询,encryptedData是存储的密文
});
export default db;
3.2 定义加密和解密函数
使用 Crypto.js 进行加密和解密。
import CryptoJS from 'crypto-js';
const SECRET_KEY = 'your-secret-key'; // 加密密钥,建议存储在安全的位置
// 加密数据
export function encryptData(data: any): string {
const stringifiedData = JSON.stringify(data);
return CryptoJS.AES.encrypt(stringifiedData, SECRET_KEY).toString();
}
// 解密数据
export function decryptData(encryptedData: string): any {
const bytes = CryptoJS.AES.decrypt(encryptedData, SECRET_KEY);
const decryptedString = bytes.toString(CryptoJS.enc.Utf8);
return JSON.parse(decryptedString);
}
3.3 插入数据
在存储数据时,先将数据加密,然后存储密文。
import db from './db';
import { encryptData } from './crypto';
export async function addItem(name: string, data: any) {
const encryptedData = encryptData(data); // 加密数据
await db.table('items').add({ name, encryptedData });
console.log('Data added successfully!');
}
3.4 获取数据
从数据库中读取数据后进行解密。
import db from './db';
import { decryptData } from './crypto';
export async function getItemByName(name: string) {
const item = await db.table('items').where({ name }).first();
if (item) {
const decryptedData = decryptData(item.encryptedData); // 解密数据
return decryptedData;
}
return null;
}
3.5 删除数据
支持按条件删除数据。
export async function deleteItemByName(name: string) {
await db.table('items').where({ name }).delete();
console.log(`Item with name "${name}" deleted successfully!`);
}
4. 使用示例
(async () => {
const exampleData = { message: 'Hello, encrypted world!', timestamp: Date.now() };
// 添加数据
await addItem('example', exampleData);
// 获取数据
const retrievedData = await getItemByName('example');
console.log('Retrieved Data:', retrievedData);
// 删除数据
await deleteItemByName('example');
})();
5. 重要注意事项
- 安全性:
- 确保
SECRET_KEY
安全,避免泄露。 - 可以考虑使用更复杂的密钥生成方式(如通过用户密码派生密钥)。
- 确保
- 性能:
- 加密和解密会增加一定的性能开销,对较大的数据集应进行测试。
- 密钥管理:
- 如果需要在用户之间共享数据,必须设计合理的密钥管理方案。
- 数据完整性:
- 可以通过加密数据时附加哈希值来验证数据完整性。
这样,你可以轻松实现基于 Crypto.js 和 Dexie.js 的数据加密存储,同时保持 Dexie.js 操作 IndexedDB 的便捷性和灵活性。