forked from SmartDropLabs/smartdrop-backend
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwebhookEncryption.test.js
More file actions
97 lines (82 loc) · 3.84 KB
/
Copy pathwebhookEncryption.test.js
File metadata and controls
97 lines (82 loc) · 3.84 KB
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
'use strict';
jest.mock('../src/logger', () => ({
info: jest.fn(), warn: jest.fn(), error: jest.fn(), debug: jest.fn(),
}));
describe('webhookEncryption', () => {
const ORIGINAL_KEY = process.env.WEBHOOK_SECRET_ENCRYPTION_KEY;
afterEach(() => {
if (ORIGINAL_KEY !== undefined) process.env.WEBHOOK_SECRET_ENCRYPTION_KEY = ORIGINAL_KEY;
else delete process.env.WEBHOOK_SECRET_ENCRYPTION_KEY;
jest.resetModules();
});
function load() {
jest.resetModules();
return require('../src/services/webhookEncryption');
}
test('round-trips a secret through encrypt/decrypt', () => {
process.env.WEBHOOK_SECRET_ENCRYPTION_KEY = 'a-test-master-key-value';
const { encryptSecret, decryptSecret } = load();
const plaintext = 'whsec_abcdefabcdefabcdefabcdef';
const encrypted = encryptSecret(plaintext);
expect(decryptSecret(encrypted)).toBe(plaintext);
});
test('encrypted output does not contain the plaintext secret', () => {
process.env.WEBHOOK_SECRET_ENCRYPTION_KEY = 'a-test-master-key-value';
const { encryptSecret } = load();
const plaintext = 'whsec_verysecretvalue123456';
const encrypted = encryptSecret(plaintext);
expect(encrypted).not.toContain(plaintext);
expect(encrypted).not.toContain('verysecretvalue');
});
test('two encryptions of the same secret produce different ciphertext (random IV)', () => {
process.env.WEBHOOK_SECRET_ENCRYPTION_KEY = 'a-test-master-key-value';
const { encryptSecret } = load();
const plaintext = 'whsec_samevalueeverytime000';
expect(encryptSecret(plaintext)).not.toBe(encryptSecret(plaintext));
});
test('decrypting with the wrong key fails', () => {
process.env.WEBHOOK_SECRET_ENCRYPTION_KEY = 'key-one';
const { encryptSecret } = load();
const encrypted = encryptSecret('whsec_topsecret0000000000');
process.env.WEBHOOK_SECRET_ENCRYPTION_KEY = 'key-two';
const { decryptSecret } = load();
expect(() => decryptSecret(encrypted)).toThrow();
});
test('decrypting a malformed payload throws', () => {
process.env.WEBHOOK_SECRET_ENCRYPTION_KEY = 'a-test-master-key-value';
const { decryptSecret } = load();
expect(() => decryptSecret('not-a-valid-payload')).toThrow(/malformed/);
});
test('decrypting a tampered ciphertext throws (auth tag mismatch)', () => {
process.env.WEBHOOK_SECRET_ENCRYPTION_KEY = 'a-test-master-key-value';
const { encryptSecret, decryptSecret } = load();
const encrypted = encryptSecret('whsec_originalvalue0000000');
const [iv, ciphertext, tag] = encrypted.split('.');
const tampered = [iv, Buffer.from('tampered-bytes').toString('base64'), tag].join('.');
expect(() => decryptSecret(tampered)).toThrow();
});
test('falls back to an insecure dev key (and warns) when unset, but still round-trips', () => {
delete process.env.WEBHOOK_SECRET_ENCRYPTION_KEY;
const { encryptSecret, decryptSecret } = load();
const logger = require('../src/logger');
const plaintext = 'whsec_devmode00000000000000';
expect(decryptSecret(encryptSecret(plaintext))).toBe(plaintext);
expect(logger.warn).toHaveBeenCalledWith(expect.stringContaining('insecure fixed development key'));
});
describe('isEncrypted', () => {
test('recognizes an encrypted payload', () => {
process.env.WEBHOOK_SECRET_ENCRYPTION_KEY = 'a-test-master-key-value';
const { encryptSecret, isEncrypted } = load();
expect(isEncrypted(encryptSecret('whsec_abc0000000000000000'))).toBe(true);
});
test('does not misclassify a legacy plaintext whsec_ secret', () => {
const { isEncrypted } = load();
expect(isEncrypted('whsec_legacyplaintextsecret')).toBe(false);
});
test('rejects non-string input', () => {
const { isEncrypted } = load();
expect(isEncrypted(undefined)).toBe(false);
expect(isEncrypted(null)).toBe(false);
});
});
});