File size: 1,762 Bytes
9b8d6f0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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,
};