UNPKG

@reliverse/rse

Version:

@reliverse/rse is your all-in-one companion for bootstrapping and improving any kind of projects (especially web apps built with frameworks like Next.js) — whether you're kicking off something new or upgrading an existing app. It is also a little AI-power

73 lines (72 loc) 2.3 kB
import { relinka } from "@reliverse/relinka"; import { subtle, getRandomValues } from "uncrypto"; async function getDerivedKey() { const machineId = `${process.platform}-${process.arch}-${process.env.USERNAME ?? process.env.USER}`; const encoder = new TextEncoder(); const data = encoder.encode(machineId); const hashBuffer = await subtle.digest("SHA-256", data); return subtle.importKey( "raw", hashBuffer, { name: "AES-CBC", length: 256 }, false, ["encrypt", "decrypt"] ); } export async function encrypt(text) { try { if (text === null || text === void 0) { throw new Error("Cannot encrypt null or undefined value"); } const textToEncrypt = String(text); const iv = new Uint8Array(16); getRandomValues(iv); const key = await getDerivedKey(); const encoder = new TextEncoder(); const data = encoder.encode(textToEncrypt); const encryptedBuffer = await subtle.encrypt( { name: "AES-CBC", iv }, key, data ); const ivHex = Array.from(iv).map((b) => b.toString(16).padStart(2, "0")).join(""); const encryptedHex = Array.from(new Uint8Array(encryptedBuffer)).map((b) => b.toString(16).padStart(2, "0")).join(""); return `${ivHex}:${encryptedHex}`; } catch (error) { relinka( "error", "Error encrypting value:", `${error instanceof Error ? error.message : String(error)} (type: ${typeof text}, value: ${text})` ); throw error; } } export async function decrypt(text) { try { const [ivHex, encryptedHex] = text.split(":"); if (!ivHex || !encryptedHex) { throw new Error("Invalid encrypted text format"); } const iv = new Uint8Array( ivHex.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)) ); const encryptedData = new Uint8Array( encryptedHex.match(/.{1,2}/g).map((byte) => parseInt(byte, 16)) ); const key = await getDerivedKey(); const decryptedBuffer = await subtle.decrypt( { name: "AES-CBC", iv }, key, encryptedData ); const decoder = new TextDecoder(); return decoder.decode(decryptedBuffer); } catch (error) { relinka( "error", "Error decrypting value:", error instanceof Error ? error.message : String(error) ); throw error; } }