import { SecurityUtils } from "../../utils/security";
import { StorageError } from "../../utils/errors";
/**
 * 加密工具类
 */ export class EncryptionUtils {
    /**
   * 生成加密密钥
   */ static async generateKey() {
        if (typeof window === 'undefined' || !window.crypto || !window.crypto.subtle) {
            throw new StorageError('加密功能需要浏览器支持 Web Crypto API');
        }
        try {
            return await window.crypto.subtle.generateKey({
                name: 'AES-GCM',
                length: 256
            }, true, [
                'encrypt',
                'decrypt'
            ]);
        } catch (error) {
            throw new StorageError('生成加密密钥失败', error instanceof Error ? error : undefined);
        }
    }
    /**
   * 使用 PBKDF2 派生密钥
   */ static async deriveKey(password, salt, iterations = 100000) {
        if (typeof window === 'undefined' || !window.crypto || !window.crypto.subtle) {
            throw new StorageError('加密功能需要浏览器支持 Web Crypto API');
        }
        try {
            // 导入密码
            const encoder = new TextEncoder();
            const passwordKey = await window.crypto.subtle.importKey('raw', encoder.encode(password), 'PBKDF2', false, [
                'deriveBits',
                'deriveKey'
            ]);
            // 使用 PBKDF2 派生密钥
            // 确保 salt 是 BufferSource 类型（使用类型断言）
            const saltBuffer = salt instanceof Uint8Array ? salt : new Uint8Array(salt);
            return await window.crypto.subtle.deriveKey({
                name: 'PBKDF2',
                salt: saltBuffer,
                iterations: iterations,
                hash: 'SHA-256'
            }, passwordKey, {
                name: 'AES-GCM',
                length: 256
            }, false, [
                'encrypt',
                'decrypt'
            ]);
        } catch (error) {
            throw new StorageError('密钥派生失败', error instanceof Error ? error : undefined);
        }
    }
    /**
   * 从字符串导入密钥（使用 PBKDF2 派生）
   * 
   * 注意：如果没有提供 salt，每次调用都会生成新的 salt，导致密钥不一致。
   * 建议在生产环境中使用固定的 salt 或从安全存储中获取。
   */ static async importKey(keyString, salt) {
        if (typeof window === 'undefined' || !window.crypto || !window.crypto.subtle) {
            throw new StorageError('加密功能需要浏览器支持 Web Crypto API');
        }
        try {
            // 如果没有提供 salt，尝试从 sessionStorage 获取或生成一个固定的
            let keySalt = salt;
            if (!keySalt) {
                // 尝试从 sessionStorage 获取固定的 salt（用于当前会话）
                const saltKey = '__encryption_salt__';
                const storedSalt = sessionStorage.getItem(saltKey);
                if (storedSalt) {
                    // 从存储中恢复 salt
                    const saltArray = Uint8Array.from(JSON.parse(storedSalt));
                    keySalt = saltArray;
                } else {
                    // 生成新的 salt 并存储（用于当前会话）
                    keySalt = window.crypto.getRandomValues(new Uint8Array(16));
                    sessionStorage.setItem(saltKey, JSON.stringify(Array.from(keySalt)));
                }
            }
            // 使用 PBKDF2 派生密钥
            return await this.deriveKey(keyString, keySalt);
        } catch (error) {
            throw new StorageError('导入加密密钥失败', error instanceof Error ? error : undefined);
        }
    }
    /**
   * 加密数据
   */ static async encrypt(data, key) {
        if (typeof window === 'undefined' || !window.crypto || !window.crypto.subtle) {
            throw new StorageError('加密功能需要浏览器支持 Web Crypto API');
        }
        try {
            const encoder = new TextEncoder();
            const dataBuffer = encoder.encode(data);
            // 生成随机 IV
            const iv = window.crypto.getRandomValues(new Uint8Array(12));
            const encrypted = await window.crypto.subtle.encrypt({
                name: 'AES-GCM',
                iv: iv
            }, key, dataBuffer);
            // 将 IV 和加密数据组合
            const combined = new Uint8Array(iv.length + encrypted.byteLength);
            combined.set(iv);
            combined.set(new Uint8Array(encrypted), iv.length);
            // 转换为 Base64
            return btoa(String.fromCharCode(...combined));
        } catch (error) {
            throw new StorageError('加密数据失败', error instanceof Error ? error : undefined);
        }
    }
    /**
   * 解密数据
   */ static async decrypt(encryptedData, key) {
        if (typeof window === 'undefined' || !window.crypto || !window.crypto.subtle) {
            throw new StorageError('解密功能需要浏览器支持 Web Crypto API');
        }
        try {
            // 从 Base64 解码
            const combined = Uint8Array.from(atob(encryptedData), (c)=>c.charCodeAt(0));
            // 提取 IV 和加密数据
            const iv = combined.slice(0, 12);
            const encrypted = combined.slice(12);
            const decrypted = await window.crypto.subtle.decrypt({
                name: 'AES-GCM',
                iv: iv
            }, key, encrypted);
            const decoder = new TextDecoder();
            return decoder.decode(decrypted);
        } catch (error) {
            throw new StorageError('解密数据失败', error instanceof Error ? error : undefined);
        }
    }
    /**
   * 检查字段是否需要加密
   */ static shouldEncrypt(key) {
        return SecurityUtils.isSensitiveField(key);
    }
}

//# sourceMappingURL=encryption.js.map