panels-origin/api/docs_crypto.ts
2026-08-21 16:55:01 -05:00

27 lines
959 B
TypeScript

import { fromHex, toHex } from "./crypto.ts";
import { config } from "./config.ts";
async function docsKey(): Promise<CryptoKey> {
const raw = fromHex(config.docsKeyHex);
if (raw.length !== 32) {
throw new Error("DOCS_KEY must be 64 hex chars (32 bytes)");
}
return await crypto.subtle.importKey("raw", raw, "AES-GCM", false, ["encrypt", "decrypt"]);
}
export async function encryptBytes(plain: Uint8Array): Promise<{ iv: string; cipher: Uint8Array }> {
const key = await docsKey();
const iv = crypto.getRandomValues(new Uint8Array(12));
const cipher = new Uint8Array(
await crypto.subtle.encrypt({ name: "AES-GCM", iv }, key, plain),
);
return { iv: toHex(iv), cipher };
}
export async function decryptBytes(ivHex: string, cipher: Uint8Array): Promise<Uint8Array> {
const key = await docsKey();
const iv = fromHex(ivHex);
return new Uint8Array(
await crypto.subtle.decrypt({ name: "AES-GCM", iv }, key, cipher),
);
}