feb136ffc1
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
24 lines
1.1 KiB
TypeScript
24 lines
1.1 KiB
TypeScript
// server/crypto/secrets.ts
|
|
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
|
|
|
|
const ALGO = "aes-256-gcm";
|
|
|
|
/** Chiffre une chaîne. Format de sortie: base64(iv).base64(tag).base64(ciphertext). */
|
|
export function encryptSecret(plaintext: string, keyHex: string): string {
|
|
const key = Buffer.from(keyHex, "hex");
|
|
const iv = randomBytes(12);
|
|
const cipher = createCipheriv(ALGO, key, iv);
|
|
const ct = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
|
|
const tag = cipher.getAuthTag();
|
|
return [iv.toString("base64"), tag.toString("base64"), ct.toString("base64")].join(".");
|
|
}
|
|
|
|
export function decryptSecret(blob: string, keyHex: string): string {
|
|
const key = Buffer.from(keyHex, "hex");
|
|
const [ivB64, tagB64, ctB64] = blob.split(".");
|
|
if (!ivB64 || !tagB64 || !ctB64) throw new Error("Blob chiffré invalide");
|
|
const decipher = createDecipheriv(ALGO, key, Buffer.from(ivB64, "base64"));
|
|
decipher.setAuthTag(Buffer.from(tagB64, "base64"));
|
|
return Buffer.concat([decipher.update(Buffer.from(ctB64, "base64")), decipher.final()]).toString("utf8");
|
|
}
|