PPPAIMT-Crest/backend/test/secrets.test.js

62 lines
2.3 KiB
JavaScript

import { randomUUID } from 'node:crypto';
import { afterEach, describe, expect, it } from 'vitest';
import { db } from '../src/db/knex.js';
import { getApplication, listApplications } from '../src/services/admin.js';
import { decryptField, encryptField, maskSecret, panLookup } from '../src/services/fieldCrypto.js';
import { readPngDataUrl } from '../src/services/png.js';
import { truncateTables } from './truncate.js';
const ONE_PIXEL =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==';
describe('field protection', () => {
afterEach(async () => {
await truncateTables();
});
it('encrypts and masks PAN and account number', async () => {
const pan = encryptField('ABCDE1234F');
const account = encryptField('123456789012');
expect(pan.startsWith('enc:v1:')).toBe(true);
expect(decryptField(pan)).toBe('ABCDE1234F');
expect(maskSecret('ABCDE1234F')).toBe('******234F');
expect(panLookup('abcde1234f')).toBe(panLookup('ABCDE1234F'));
const [id] = await db('applications').insert({
public_id: randomUUID(),
email: 'mask@example.com',
status: 'SUBMITTED',
full_name: 'Asha Rao',
pan,
pan_lookup: panLookup('ABCDE1234F'),
account_number: account,
});
const list = await listApplications({});
expect(list.items.find((item) => item.email === 'mask@example.com')).toMatchObject({
pan: '******234F',
account_number: '******9012',
});
const detail = await getApplication(id);
expect(detail.pan).toBe('ABCDE1234F');
expect(detail.account_number).toBe('123456789012');
const found = await listApplications({ q: 'ABCDE1234F' });
expect(found.total).toBe(1);
});
it('rejects a PNG that is too large in pixels', () => {
const header = Buffer.alloc(24);
header[0] = 0x89;
header[1] = 0x50;
header[2] = 0x4e;
header[3] = 0x47;
header.write('IHDR', 12, 'ascii');
header.writeUInt32BE(2001, 16);
header.writeUInt32BE(1, 20);
const image = `data:image/png;base64,${header.toString('base64')}`;
expect(() => readPngDataUrl(image, 500 * 1024, 'too big')).toThrow(/2000 pixels/);
expect(readPngDataUrl(ONE_PIXEL, 500 * 1024, 'too big').length).toBeGreaterThan(8);
});
});