45 lines
1.6 KiB
TypeScript
45 lines
1.6 KiB
TypeScript
/**
|
|
* AriaEngine Crypto — 页面级 AES-GCM 加密
|
|
* @module engine/aria/crypto
|
|
*
|
|
* 使用 Web Crypto API (SubtleCrypto) 进行 AES-256-GCM 加密。
|
|
*/
|
|
const ALGO = 'AES-GCM';
|
|
const IV_LENGTH = 12;
|
|
|
|
let cryptoKey: CryptoKey | null = null;
|
|
let enabled = false;
|
|
|
|
export async function initCrypto(password: string, salt?: Uint8Array): Promise<Uint8Array> {
|
|
const enc = new TextEncoder();
|
|
const keyMaterial = await crypto.subtle.importKey(
|
|
'raw', enc.encode(password), 'PBKDF2', false, ['deriveKey'],
|
|
);
|
|
const actualSalt: any = salt || crypto.getRandomValues(new Uint8Array(16));
|
|
cryptoKey = await crypto.subtle.deriveKey(
|
|
{ name: 'PBKDF2', salt: actualSalt, iterations: 100000, hash: 'SHA-256' } as any,
|
|
keyMaterial, { name: ALGO, length: 256 } as any, false, ['encrypt', 'decrypt'],
|
|
);
|
|
enabled = true;
|
|
return actualSalt as Uint8Array;
|
|
}
|
|
|
|
export function isCryptoEnabled(): boolean { return enabled; }
|
|
|
|
export async function encryptPage(data: ArrayBuffer): Promise<{ iv: Uint8Array; data: ArrayBuffer }> {
|
|
if (!cryptoKey) throw new Error('Crypto not initialized');
|
|
const iv = crypto.getRandomValues(new Uint8Array(IV_LENGTH)) as any;
|
|
const ciphertext = await crypto.subtle.encrypt({ name: ALGO, iv } as any, cryptoKey, data);
|
|
return { iv: iv as Uint8Array, data: ciphertext };
|
|
}
|
|
|
|
export async function decryptPage(iv: Uint8Array, data: ArrayBuffer): Promise<ArrayBuffer> {
|
|
if (!cryptoKey) throw new Error('Crypto not initialized');
|
|
return crypto.subtle.decrypt({ name: ALGO, iv } as any, cryptoKey, data);
|
|
}
|
|
|
|
export function closeCrypto(): void {
|
|
cryptoKey = null;
|
|
enabled = false;
|
|
}
|