UNPKG

tl-shared-security

Version:

Enterprise-grade security module for frontend and backend applications with comprehensive protection against XSS, CSRF, SQL injection, and other security vulnerabilities

219 lines 10.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const crypto_service_1 = require("./crypto.service"); describe('CryptoService', () => { let service; beforeEach(() => { service = new crypto_service_1.CryptoService(); }); it('should be defined', () => { expect(service).toBeDefined(); }); describe('encrypt/decrypt', () => { it('should encrypt and decrypt data correctly', () => { const data = 'Hello, World!'; const password = 'test-password'; const encrypted = service.encrypt(data, password); expect(encrypted).toBeDefined(); expect(encrypted).not.toBe(data); expect(encrypted.split(':').length).toBe(4); // iv:salt:authTag:encryptedData const decrypted = service.decrypt(encrypted, password); expect(decrypted).toBe(data); }); it('should encrypt same data differently each time', () => { const data = 'Hello, World!'; const password = 'test-password'; const encrypted1 = service.encrypt(data, password); const encrypted2 = service.encrypt(data, password); expect(encrypted1).not.toBe(encrypted2); expect(service.decrypt(encrypted1, password)).toBe(data); expect(service.decrypt(encrypted2, password)).toBe(data); }); it('should fail to decrypt with wrong password', () => { const data = 'Hello, World!'; const password = 'test-password'; const wrongPassword = 'wrong-password'; const encrypted = service.encrypt(data, password); expect(() => { service.decrypt(encrypted, wrongPassword); }).toThrow(); }); it('should fail to decrypt malformed data', () => { const password = 'test-password'; expect(() => { service.decrypt('invalid-format', password); }).toThrow('Invalid encrypted data format'); }); it('should handle empty data', () => { const data = ''; const password = 'test-password'; const encrypted = service.encrypt(data, password); const decrypted = service.decrypt(encrypted, password); expect(decrypted).toBe(data); }); it('should handle unicode data', () => { const data = '🔐 Unicode test with émojis and spëcial chars 中文'; const password = 'test-password'; const encrypted = service.encrypt(data, password); const decrypted = service.decrypt(encrypted, password); expect(decrypted).toBe(data); }); }); describe('hashPassword/verifyPassword (bcrypt)', () => { it('should hash and verify password correctly', () => { const password = 'test-password'; const hashed = service.hashPassword(password); expect(hashed).toBeDefined(); expect(hashed).not.toBe(password); expect(hashed.startsWith('$2b$')).toBe(true); // bcrypt format const isValid = service.verifyPassword(password, hashed); expect(isValid).toBe(true); }); it('should hash same password differently each time', () => { const password = 'test-password'; const hashed1 = service.hashPassword(password); const hashed2 = service.hashPassword(password); expect(hashed1).not.toBe(hashed2); expect(service.verifyPassword(password, hashed1)).toBe(true); expect(service.verifyPassword(password, hashed2)).toBe(true); }); it('should fail to verify with wrong password', () => { const password = 'test-password'; const wrongPassword = 'wrong-password'; const hashed = service.hashPassword(password); const isValid = service.verifyPassword(wrongPassword, hashed); expect(isValid).toBe(false); }); it('should handle different salt rounds', () => { const password = 'test-password'; const hashed10 = service.hashPassword(password, 10); const hashed12 = service.hashPassword(password, 12); expect(service.verifyPassword(password, hashed10)).toBe(true); expect(service.verifyPassword(password, hashed12)).toBe(true); }); it('should work with async methods', async () => { const password = 'test-password'; const hashed = await service.hashPasswordAsync(password); expect(hashed).toBeDefined(); expect(hashed.startsWith('$2b$')).toBe(true); const isValid = await service.verifyPasswordAsync(password, hashed); expect(isValid).toBe(true); const isInvalid = await service.verifyPasswordAsync('wrong', hashed); expect(isInvalid).toBe(false); }); it('should fallback to PBKDF2 for legacy hashes', () => { const password = 'test-password'; // Create PBKDF2 hash const pbkdf2Hash = service.hashPasswordPBKDF2(password); expect(pbkdf2Hash.split(':').length).toBe(3); // salt:iterations:hash // Should verify with main method (fallback) const isValid = service.verifyPassword(password, pbkdf2Hash); expect(isValid).toBe(true); }); }); describe('generateToken', () => { it('should generate random tokens', () => { const token1 = service.generateToken(); const token2 = service.generateToken(); expect(token1).toBeDefined(); expect(token2).toBeDefined(); expect(token1).not.toBe(token2); expect(token1.length).toBe(64); // 32 bytes * 2 (hex) }); it('should generate tokens of specified length', () => { const token = service.generateToken(16); expect(token.length).toBe(32); // 16 bytes * 2 (hex) }); it('should generate cryptographically secure tokens', () => { const tokens = new Set(); // Generate 1000 tokens and ensure they're all unique for (let i = 0; i < 1000; i++) { tokens.add(service.generateToken()); } expect(tokens.size).toBe(1000); }); }); describe('sign/verifySignature', () => { it('should sign and verify data correctly', () => { const data = 'Hello, World!'; const secret = 'test-secret'; const signature = service.sign(data, secret); expect(signature).toBeDefined(); expect(signature.length).toBe(64); // SHA256 hex = 64 chars const isValid = service.verifySignature(data, signature, secret); expect(isValid).toBe(true); }); it('should generate same signature for same data', () => { const data = 'Hello, World!'; const secret = 'test-secret'; const signature1 = service.sign(data, secret); const signature2 = service.sign(data, secret); expect(signature1).toBe(signature2); }); it('should fail to verify with wrong secret', () => { const data = 'Hello, World!'; const secret = 'test-secret'; const wrongSecret = 'wrong-secret'; const signature = service.sign(data, secret); const isValid = service.verifySignature(data, signature, wrongSecret); expect(isValid).toBe(false); }); it('should fail to verify with wrong data', () => { const data = 'Hello, World!'; const wrongData = 'Wrong data'; const secret = 'test-secret'; const signature = service.sign(data, secret); const isValid = service.verifySignature(wrongData, signature, secret); expect(isValid).toBe(false); }); it('should handle different algorithms', () => { const data = 'Hello, World!'; const secret = 'test-secret'; const sha256Sig = service.sign(data, secret, { algorithm: 'sha256' }); const sha512Sig = service.sign(data, secret, { algorithm: 'sha512' }); expect(sha256Sig).not.toBe(sha512Sig); expect(service.verifySignature(data, sha256Sig, secret, { algorithm: 'sha256' })).toBe(true); expect(service.verifySignature(data, sha512Sig, secret, { algorithm: 'sha512' })).toBe(true); }); }); describe('generateSecureRandomString', () => { it('should generate random strings with different encodings', () => { const hexString = service.generateSecureRandomString(16, 'hex'); const base64String = service.generateSecureRandomString(16, 'base64'); expect(hexString.length).toBe(32); // 16 bytes * 2 expect(base64String.length).toBe(24); // Base64 encoding expect(/^[0-9a-f]+$/.test(hexString)).toBe(true); }); }); describe('generateUUID', () => { it('should generate valid UUIDs', () => { const uuid1 = service.generateUUID(); const uuid2 = service.generateUUID(); expect(uuid1).not.toBe(uuid2); expect(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(uuid1)).toBe(true); expect(/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(uuid2)).toBe(true); }); }); describe('performance and security', () => { it('should handle large data encryption efficiently', () => { const largeData = 'x'.repeat(10000); const password = 'test-password'; const start = Date.now(); const encrypted = service.encrypt(largeData, password); const decrypted = service.decrypt(encrypted, password); const end = Date.now(); expect(decrypted).toBe(largeData); expect(end - start).toBeLessThan(1000); // Should complete within 1 second }); it('should use timing-safe comparison for signatures', () => { const data = 'Hello, World!'; const secret = 'test-secret'; const signature = service.sign(data, secret); // This test ensures timing-safe comparison is used // by verifying that wrong signatures of same length are handled correctly const wrongSignature = 'a'.repeat(signature.length); expect(service.verifySignature(data, wrongSignature, secret)).toBe(false); }); }); }); //# sourceMappingURL=crypto.service.spec.js.map