25 lines
1.1 KiB
TypeScript
25 lines
1.1 KiB
TypeScript
import { createCipheriv, createDecipheriv, createHash, randomBytes } from 'node:crypto';
|
|
|
|
function encryptionKey() {
|
|
const masterKey = process.env.HTTP_API_MASTER_KEY;
|
|
if (!masterKey || masterKey.length < 32) {
|
|
throw new Error('HTTP_API_MASTER_KEY must be configured with at least 32 characters');
|
|
}
|
|
return createHash('sha256').update(masterKey).digest();
|
|
}
|
|
|
|
export function encryptSecret(value: string) {
|
|
const iv = randomBytes(12);
|
|
const cipher = createCipheriv('aes-256-gcm', encryptionKey(), iv);
|
|
const ciphertext = Buffer.concat([cipher.update(value, 'utf8'), cipher.final()]);
|
|
return `${iv.toString('base64url')}.${cipher.getAuthTag().toString('base64url')}.${ciphertext.toString('base64url')}`;
|
|
}
|
|
|
|
export function decryptSecret(value: string) {
|
|
const [iv, tag, ciphertext] = value.split('.');
|
|
if (!iv || !tag || !ciphertext) throw new Error('Invalid encrypted secret');
|
|
const decipher = createDecipheriv('aes-256-gcm', encryptionKey(), Buffer.from(iv, 'base64url'));
|
|
decipher.setAuthTag(Buffer.from(tag, 'base64url'));
|
|
return Buffer.concat([decipher.update(Buffer.from(ciphertext, 'base64url')), decipher.final()]).toString('utf8');
|
|
}
|