Fastify + Prisma backend, React + Vite frontend, Docker deployment. Multi-board feedback platform with anonymous cookie auth, passkey upgrade path, ALTCHA spam protection, plugin system, and full privacy-first architecture.
31 lines
1.1 KiB
TypeScript
31 lines
1.1 KiB
TypeScript
import { createCipheriv, createDecipheriv, createHmac, createHash, randomBytes } from "node:crypto";
|
|
|
|
const IV_LEN = 12;
|
|
const TAG_LEN = 16;
|
|
|
|
export function encrypt(plaintext: string, key: Buffer): string {
|
|
const iv = randomBytes(IV_LEN);
|
|
const cipher = createCipheriv("aes-256-gcm", key, iv);
|
|
const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
|
|
const tag = cipher.getAuthTag();
|
|
return Buffer.concat([iv, encrypted, tag]).toString("base64");
|
|
}
|
|
|
|
export function decrypt(encoded: string, key: Buffer): string {
|
|
const buf = Buffer.from(encoded, "base64");
|
|
const iv = buf.subarray(0, IV_LEN);
|
|
const tag = buf.subarray(buf.length - TAG_LEN);
|
|
const ciphertext = buf.subarray(IV_LEN, buf.length - TAG_LEN);
|
|
const decipher = createDecipheriv("aes-256-gcm", key, iv);
|
|
decipher.setAuthTag(tag);
|
|
return decipher.update(ciphertext) + decipher.final("utf8");
|
|
}
|
|
|
|
export function blindIndex(value: string, key: Buffer): string {
|
|
return createHmac("sha256", key).update(value.toLowerCase()).digest("hex");
|
|
}
|
|
|
|
export function hashToken(token: string): string {
|
|
return createHash("sha256").update(token).digest("hex");
|
|
}
|