/** * Security-Focused Test Suite * Tests certificate pinning, TLS downgrade prevention, and security features */ import * as tls from 'tls'; import { TLSClient } from '@/transport/tls-client/tls-client'; import { receiverConfig } from '@/config/receiver-config'; describe('Security Tests', () => { const RECEIVER_IP = '172.67.157.88'; const RECEIVER_PORT = 443; const RECEIVER_SNI = 'devmindgroup.com'; const EXPECTED_FINGERPRINT = 'b19f2a94eab4cd3b92f1e3e0dce9d5e41c8b7aa3fdbe6e2f4ac3c91a5fbb2f44'; describe('Certificate Pinning Enforcement', () => { let tlsClient: TLSClient; beforeEach(() => { tlsClient = new TLSClient(); }); afterEach(async () => { await tlsClient.close(); }); it('should enforce certificate pinning when enabled', async () => { // Verify pinning is enabled by default expect(receiverConfig.enforceCertificatePinning).toBe(true); expect(receiverConfig.certificateFingerprint).toBeDefined(); }); it('should reject connection with wrong certificate fingerprint', async () => { // Temporarily set wrong fingerprint const originalFingerprint = receiverConfig.certificateFingerprint; (receiverConfig as any).certificateFingerprint = '0000000000000000000000000000000000000000000000000000000000000000'; (receiverConfig as any).enforceCertificatePinning = true; try { await expect(tlsClient.connect()).rejects.toThrow(/Certificate fingerprint mismatch/); } finally { (receiverConfig as any).certificateFingerprint = originalFingerprint; } }, 60000); it('should accept connection with correct certificate fingerprint', async () => { // Set correct fingerprint const originalFingerprint = receiverConfig.certificateFingerprint; (receiverConfig as any).certificateFingerprint = EXPECTED_FINGERPRINT; (receiverConfig as any).enforceCertificatePinning = true; try { const connection = await tlsClient.connect(); expect(connection.connected).toBe(true); expect(connection.fingerprint.toLowerCase()).toBe(EXPECTED_FINGERPRINT.toLowerCase()); } finally { (receiverConfig as any).certificateFingerprint = originalFingerprint; } }, 60000); it('should allow connection when pinning is disabled', async () => { const originalPinning = receiverConfig.enforceCertificatePinning; (receiverConfig as any).enforceCertificatePinning = false; try { const connection = await tlsClient.connect(); expect(connection.connected).toBe(true); } finally { (receiverConfig as any).enforceCertificatePinning = originalPinning; } }, 60000); }); describe('TLS Version Security', () => { it('should use TLSv1.2 or higher', async () => { const tlsClient = new TLSClient(); try { const connection = await tlsClient.connect(); const protocol = connection.socket.getProtocol(); expect(protocol).toBeDefined(); expect(['TLSv1.2', 'TLSv1.3']).toContain(protocol); expect(protocol).not.toBe('TLSv1'); expect(protocol).not.toBe('TLSv1.1'); } finally { await tlsClient.close(); } }, 60000); it('should prevent TLSv1.0 and TLSv1.1', async () => { // Verify minVersion is set to TLSv1.2 const tlsOptions: tls.ConnectionOptions = { host: RECEIVER_IP, port: RECEIVER_PORT, servername: RECEIVER_SNI, rejectUnauthorized: false, minVersion: 'TLSv1.2', }; await new Promise((resolve, reject) => { const socket = tls.connect(tlsOptions, () => { const protocol = socket.getProtocol(); expect(['TLSv1.2', 'TLSv1.3']).toContain(protocol); socket.end(); resolve(); }); socket.on('error', reject); socket.setTimeout(30000); socket.on('timeout', () => { socket.destroy(); reject(new Error('Connection timeout')); }); }); }, 60000); it('should prefer TLSv1.3 when available', async () => { const tlsClient = new TLSClient(); try { const connection = await tlsClient.connect(); const protocol = connection.socket.getProtocol(); // Should use TLSv1.3 if receiver supports it expect(['TLSv1.2', 'TLSv1.3']).toContain(protocol); } finally { await tlsClient.close(); } }, 60000); }); describe('Cipher Suite Security', () => { it('should use strong cipher suites', async () => { const tlsClient = new TLSClient(); try { const connection = await tlsClient.connect(); const cipher = connection.socket.getCipher(); expect(cipher).toBeDefined(); expect(cipher.name).toBeDefined(); // Should not use weak ciphers const weakCiphers = ['RC4', 'DES', 'MD5', 'NULL', 'EXPORT']; const cipherName = cipher.name.toUpperCase(); for (const weak of weakCiphers) { expect(cipherName).not.toContain(weak); } } finally { await tlsClient.close(); } }, 60000); it('should use authenticated encryption', async () => { const tlsClient = new TLSClient(); try { const connection = await tlsClient.connect(); const cipher = connection.socket.getCipher(); // Modern ciphers should use AEAD (Authenticated Encryption with Associated Data) // Examples: AES-GCM, ChaCha20-Poly1305 expect(cipher.name).toBeDefined(); expect(cipher.name.length).toBeGreaterThan(0); } finally { await tlsClient.close(); } }, 60000); }); describe('Certificate Validation', () => { it('should verify certificate is not expired', async () => { const tlsClient = new TLSClient(); try { const connection = await tlsClient.connect(); const cert = connection.socket.getPeerCertificate(); if (cert && cert.valid_to) { const validTo = new Date(cert.valid_to); const now = new Date(); expect(validTo.getTime()).toBeGreaterThan(now.getTime()); } } finally { await tlsClient.close(); } }, 60000); it('should verify certificate subject matches SNI', async () => { const tlsClient = new TLSClient(); try { const connection = await tlsClient.connect(); const cert = connection.socket.getPeerCertificate(); // Certificate should be valid for the SNI expect(cert).toBeDefined(); // Check subject alternative names or CN const subject = cert?.subject; const altNames = cert?.subjectaltname; expect(subject || altNames).toBeDefined(); } finally { await tlsClient.close(); } }, 60000); it('should verify certificate chain', async () => { const tlsClient = new TLSClient(); try { const connection = await tlsClient.connect(); const cert = connection.socket.getPeerCertificate(true); expect(cert).toBeDefined(); expect(cert.issuer).toBeDefined(); } finally { await tlsClient.close(); } }, 60000); }); describe('Man-in-the-Middle Attack Prevention', () => { it('should detect certificate fingerprint mismatch', async () => { // This test verifies that certificate pinning prevents MITM const originalFingerprint = receiverConfig.certificateFingerprint; (receiverConfig as any).certificateFingerprint = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; (receiverConfig as any).enforceCertificatePinning = true; const tlsClient = new TLSClient(); try { await expect(tlsClient.connect()).rejects.toThrow(/Certificate fingerprint mismatch/); } finally { (receiverConfig as any).certificateFingerprint = originalFingerprint; await tlsClient.close(); } }, 60000); it('should log certificate pinning failures for security audit', async () => { // Certificate pinning failures should be logged // This is verified through the TLS client implementation expect(receiverConfig.enforceCertificatePinning).toBeDefined(); }); }); describe('Connection Security', () => { it('should use secure renegotiation', async () => { const tlsClient = new TLSClient(); try { const connection = await tlsClient.connect(); const socket = connection.socket; // Secure renegotiation should be enabled by default in Node.js expect(socket.authorized !== false || true).toBe(true); } finally { await tlsClient.close(); } }, 60000); it('should not allow insecure protocols', async () => { // Verify configuration prevents SSLv2, SSLv3 expect(receiverConfig.tlsVersion).not.toBe('SSLv2'); expect(receiverConfig.tlsVersion).not.toBe('SSLv3'); expect(['TLSv1.2', 'TLSv1.3']).toContain(receiverConfig.tlsVersion); }); }); });