Files
MetonaSqlark/tests/engine/aria-crypto.test.ts
T
thzxx 334067d89e
CI / test (18.x) (push) Successful in 10m10s
CI / test (20.x) (push) Successful in 10m10s
CI / test (22.x) (push) Successful in 10m6s
CI / e2e (push) Successful in 9m51s
CI / test (24.x) (push) Successful in 10m28s
release: v0.5.1 — 存储后端生产级硬化(CRC-32/全库加密/WAL分片/页面化存储/多标签页锁/e2e)+ 深度审查修复(假实现接线/死代码清理)
2026-08-10 12:07:00 +08:00

99 lines
3.3 KiB
TypeScript

/**
* AriaEngine CryptoManager 加解密测试
* @module tests/engine/aria-crypto
*
* v0.2.6 补强:此前仅验证实例化,现在验证真实的加解密往返一致性。
*/
import 'fake-indexeddb/auto';
import { CryptoManager } from '../../src/engine/aria/crypto';
function toBytes(data: ArrayBuffer): number[] {
return Array.from(new Uint8Array(data));
}
describe('AriaEngine — CryptoManager', () => {
test('加解密往返一致', async () => {
const cm = new CryptoManager();
await cm.init('test-password');
expect(cm.enabled).toBe(true);
const original = new TextEncoder().encode('sensitive row data').buffer;
const { iv, data } = await cm.encryptPage(original);
// 密文应为乱码(与原文不同)
expect(toBytes(data)).not.toEqual(toBytes(original));
const decrypted = await cm.decryptPage(iv, data);
expect(toBytes(decrypted)).toEqual(toBytes(original));
cm.close();
expect(cm.enabled).toBe(false);
});
test('错误密码解密失败(密钥不同)', async () => {
const cm1 = new CryptoManager();
await cm1.init('correct-password');
const original = new TextEncoder().encode('top secret').buffer;
const { iv, data } = await cm1.encryptPage(original);
const cm2 = new CryptoManager();
await cm2.init('wrong-password');
await expect(cm2.decryptPage(iv, data)).rejects.toThrow();
cm1.close();
cm2.close();
});
test('不同 salt 派生不同密钥,解密互相失败', async () => {
const cm1 = new CryptoManager();
await cm1.init('pwd', new Uint8Array(16).fill(1));
const cm2 = new CryptoManager();
await cm2.init('pwd', new Uint8Array(16).fill(2));
const original = new TextEncoder().encode('salt matters').buffer;
const { iv, data } = await cm1.encryptPage(original);
await expect(cm2.decryptPage(iv, data)).rejects.toThrow();
cm1.close();
cm2.close();
});
test('未初始化时加密抛错', async () => {
const cm = new CryptoManager();
expect(cm.enabled).toBe(false);
const data = new TextEncoder().encode('x').buffer;
await expect(cm.encryptPage(data)).rejects.toThrow(/not initialized/);
});
test('不同实例互不影响(独立密钥状态)', async () => {
const cm1 = new CryptoManager();
await cm1.init('pwd-a');
const cm2 = new CryptoManager();
await cm2.init('pwd-b');
const original = new TextEncoder().encode('instance isolation').buffer;
const { iv, data } = await cm1.encryptPage(original);
await expect(cm2.decryptPage(iv, data)).rejects.toThrow();
// 各自解密自己的数据
const dec2orig = new TextEncoder().encode('two').buffer;
const enc2 = await cm2.encryptPage(dec2orig);
const dec2 = await cm2.decryptPage(enc2.iv, enc2.data);
expect(toBytes(dec2)).toEqual(toBytes(dec2orig));
cm1.close();
cm2.close();
});
test('大块数据(接近页面大小)往返一致', async () => {
const cm = new CryptoManager();
await cm.init('page-size-test');
// 4KB 页面数据
const original = new Uint8Array(4096);
for (let i = 0; i < 4096; i++) original[i] = i % 251;
const { iv, data } = await cm.encryptPage(original.buffer);
const decrypted = await cm.decryptPage(iv, data);
expect(toBytes(decrypted)).toEqual(toBytes(original.buffer));
cm.close();
});
});