Wifiv2 / src /utils /paymentSecrets.js
Mbonea's picture
Migrate production app to v2 Omada workflow
9b8d6f0
Raw
History Blame Contribute Delete
1.76 kB
const crypto = require('crypto');
const PREFIX = 'enc:v1';
function getSecretKey() {
const source =
process.env.PAYMENT_CREDENTIAL_SECRET ||
process.env.JWT_SECRET ||
process.env.SNIPPE_API_KEY ||
'development-only-payment-credential-secret';
return crypto.createHash('sha256').update(String(source)).digest();
}
function encryptSecret(value) {
if (!value) return null;
const text = String(value);
if (text.startsWith(`${PREFIX}:`)) return text;
const iv = crypto.randomBytes(12);
const cipher = crypto.createCipheriv('aes-256-gcm', getSecretKey(), iv);
const ciphertext = Buffer.concat([cipher.update(text, 'utf8'), cipher.final()]);
const tag = cipher.getAuthTag();
return [
PREFIX,
iv.toString('base64url'),
tag.toString('base64url'),
ciphertext.toString('base64url'),
].join(':');
}
function decryptSecret(value) {
if (!value) return null;
const text = String(value);
if (!text.startsWith(`${PREFIX}:`)) return text;
const parts = text.split(':');
if (parts.length !== 5) {
throw new Error('Invalid encrypted secret format');
}
const [, , ivValue, tagValue, ciphertextValue] = parts;
const decipher = crypto.createDecipheriv(
'aes-256-gcm',
getSecretKey(),
Buffer.from(ivValue, 'base64url')
);
decipher.setAuthTag(Buffer.from(tagValue, 'base64url'));
return Buffer.concat([
decipher.update(Buffer.from(ciphertextValue, 'base64url')),
decipher.final(),
]).toString('utf8');
}
function maskSecret(value) {
const secret = decryptSecret(value);
if (!secret) return null;
if (secret.length <= 8) return '********';
return `${secret.slice(0, 4)}...${secret.slice(-4)}`;
}
module.exports = {
decryptSecret,
encryptSecret,
maskSecret,
};