/** * Share Encryption Domain Service Unit Tests */ import { ShareEncryptionDomainService } from '../../../src/domain/services/share-encryption.domain-service'; import { ShareData } from '../../../src/domain/value-objects'; describe('ShareEncryptionDomainService', () => { let service: ShareEncryptionDomainService; beforeEach(() => { service = new ShareEncryptionDomainService(); }); describe('encrypt/decrypt', () => { it('should encrypt and decrypt data correctly', () => { const rawData = Buffer.from('This is the raw share data to encrypt'); const masterKey = service.generateMasterKey(); const encrypted = service.encrypt(rawData, masterKey); const decrypted = service.decrypt(encrypted, masterKey); expect(decrypted).toEqual(rawData); }); it('should produce different ciphertexts for same plaintext', () => { const rawData = Buffer.from('Same plaintext data'); const masterKey = service.generateMasterKey(); const encrypted1 = service.encrypt(rawData, masterKey); const encrypted2 = service.encrypt(rawData, masterKey); // IV is random, so ciphertexts should be different expect(encrypted1.encryptedData).not.toEqual(encrypted2.encryptedData); expect(encrypted1.iv).not.toEqual(encrypted2.iv); }); it('should fail decryption with wrong key', () => { const rawData = Buffer.from('Secret data'); const correctKey = service.generateMasterKey(); const wrongKey = service.generateMasterKey(); const encrypted = service.encrypt(rawData, correctKey); expect(() => service.decrypt(encrypted, wrongKey)).toThrow(); }); it('should fail decryption with tampered ciphertext', () => { const rawData = Buffer.from('Secret data'); const masterKey = service.generateMasterKey(); const encrypted = service.encrypt(rawData, masterKey); // Tamper with the ciphertext const tamperedData = Buffer.from(encrypted.encryptedData); tamperedData[0] ^= 0xFF; const tampered = ShareData.create(tamperedData, encrypted.iv, encrypted.authTag); expect(() => service.decrypt(tampered, masterKey)).toThrow(); }); it('should fail decryption with tampered authTag', () => { const rawData = Buffer.from('Secret data'); const masterKey = service.generateMasterKey(); const encrypted = service.encrypt(rawData, masterKey); // Tamper with the auth tag const tamperedTag = Buffer.from(encrypted.authTag); tamperedTag[0] ^= 0xFF; const tampered = ShareData.create(encrypted.encryptedData, encrypted.iv, tamperedTag); expect(() => service.decrypt(tampered, masterKey)).toThrow(); }); }); describe('generateMasterKey', () => { it('should generate 32-byte key', () => { const key = service.generateMasterKey(); expect(key).toHaveLength(32); }); it('should generate unique keys', () => { const key1 = service.generateMasterKey(); const key2 = service.generateMasterKey(); expect(key1).not.toEqual(key2); }); }); describe('deriveKeyFromPassword', () => { it('should derive consistent key from password', () => { const password = 'my-secure-password'; const salt = service.generateSalt(); const key1 = service.deriveKeyFromPassword(password, salt); const key2 = service.deriveKeyFromPassword(password, salt); expect(key1).toEqual(key2); expect(key1).toHaveLength(32); }); it('should derive different keys for different passwords', () => { const salt = service.generateSalt(); const key1 = service.deriveKeyFromPassword('password1', salt); const key2 = service.deriveKeyFromPassword('password2', salt); expect(key1).not.toEqual(key2); }); it('should derive different keys for different salts', () => { const password = 'my-password'; const salt1 = service.generateSalt(); const salt2 = service.generateSalt(); const key1 = service.deriveKeyFromPassword(password, salt1); const key2 = service.deriveKeyFromPassword(password, salt2); expect(key1).not.toEqual(key2); }); it('should throw error for empty password', () => { const salt = service.generateSalt(); expect(() => service.deriveKeyFromPassword('', salt)).toThrow(); }); it('should throw error for short salt', () => { expect(() => service.deriveKeyFromPassword('password', Buffer.alloc(8))).toThrow(); }); }); describe('validateMasterKey', () => { it('should throw error for invalid key length', () => { const rawData = Buffer.from('data'); const shortKey = Buffer.alloc(16); expect(() => service.encrypt(rawData, shortKey)).toThrow(); }); }); describe('computeHmac/verifyHmac', () => { it('should compute and verify HMAC', () => { const data = Buffer.from('data to authenticate'); const key = service.generateMasterKey(); const hmac = service.computeHmac(data, key); const isValid = service.verifyHmac(data, key, hmac); expect(isValid).toBe(true); }); it('should fail verification with wrong key', () => { const data = Buffer.from('data to authenticate'); const correctKey = service.generateMasterKey(); const wrongKey = service.generateMasterKey(); const hmac = service.computeHmac(data, correctKey); const isValid = service.verifyHmac(data, wrongKey, hmac); expect(isValid).toBe(false); }); it('should fail verification with tampered data', () => { const data = Buffer.from('original data'); const key = service.generateMasterKey(); const hmac = service.computeHmac(data, key); const tamperedData = Buffer.from('tampered data'); const isValid = service.verifyHmac(tamperedData, key, hmac); expect(isValid).toBe(false); }); }); });