@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
JavaScript
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;
}
}