175 lines
5.9 KiB
TypeScript
175 lines
5.9 KiB
TypeScript
/**
|
|
* 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);
|
|
});
|
|
});
|
|
});
|