import { ICryptoEncrypted, ICryptoData } from "./types"; const importKey = async (key: Uint8Array): Promise => { return await crypto.subtle.importKey( "raw", key, { name: "AES-GCM" }, false, ["encrypt", "decrypt"], ); }; const deriveKey = async (password: string): Promise => { const salt = "NEXLINK_FIXED_SALT"; const encoder = new TextEncoder(); const passwordKey = await crypto.subtle.importKey( "raw", encoder.encode(password), "PBKDF2", false, ["deriveKey"], ); return crypto.subtle.deriveKey( { name: "PBKDF2", salt: encoder.encode(salt), iterations: 100000, hash: "SHA-256", }, passwordKey, { name: "AES-GCM", length: 256 }, true, ["encrypt", "decrypt"], ); }; const encryptData = async ( cryptoData: ICryptoData, ): Promise => { const encoded = new TextEncoder().encode(JSON.stringify(cryptoData.data)); const encrypted = await crypto.subtle.encrypt( { name: "AES-GCM", iv: cryptoData.iv }, cryptoData.key, encoded, ); return encrypted; }; const decryptData = async (cryptoData: ICryptoEncrypted): Promise => { const decrypted = await crypto.subtle.decrypt( { name: "AES-GCM", iv: cryptoData.iv }, cryptoData.key, cryptoData.encryptedData, ); const decoded = JSON.parse(new TextDecoder().decode(decrypted)); return decoded as T; }; const encryptBytes = async ( cryptoData: ICryptoData, ): Promise => { const encrypted = await crypto.subtle.encrypt( { name: "AES-GCM", iv: cryptoData.iv }, cryptoData.key, cryptoData.data, ); return encrypted; }; const decryptBytes = async ( cryptoData: ICryptoEncrypted, ): Promise => { return await crypto.subtle.decrypt( { name: "AES-GCM", iv: cryptoData.iv }, cryptoData.key, cryptoData.encryptedData, ); }; const generateIv = (): Uint8Array => { return crypto.getRandomValues(new Uint8Array(12)); }; const hexToBytes = (hex: string): ArrayBuffer | undefined => { if (hex.length % 2 !== 0) { return; } const bytes = new Uint8Array(hex.length / 2); for (let i = 0; i < hex.length; i++) { bytes[i] = parseInt(hex.substring(i * 2, i * 2 + 2), 16); } return bytes.buffer; }; const bytesToHex = (bytes: ArrayBuffer): string => { const bytesUint8 = new Uint8Array(bytes); let hex = ""; for (const byte of bytesUint8) { hex += byte.toString(16).padStart(2, "0"); } return hex; }; const bufferToBase64 = (buffer: ArrayBuffer): string => { const bytes = new Uint8Array(buffer); let binary = ""; for (let i = 0; i < bytes.length; i++) { binary += String.fromCharCode(bytes[i]); } return btoa(binary); }; const base64ToBuffer = (base64: string): ArrayBuffer => { const binary = atob(base64); const len = binary.length; const bytes = new Uint8Array(len); for (let i = 0; i < len; i++) { bytes[i] = binary.charCodeAt(i); } return bytes.buffer; }; export { importKey, deriveKey, encryptData, decryptData, encryptBytes, decryptBytes, generateIv, hexToBytes, bytesToHex, bufferToBase64, base64ToBuffer, };