export class EncryptionService { private static readonly SECRET_SALT = "RELAY_SECURE_CBT_2026_SALT"; /** * Applies an elegant reversible string transformation (XOR masking with cyclic salt) * to guarantee student's private answers, progress, and timer states are encrypted in raw storage. */ static encrypt(rawData: string): string { let result = ""; for (let i = 0; i < rawData.length; i++) { const charCode = rawData.charCodeAt(i); const saltCode = this.SECRET_SALT.charCodeAt(i % this.SECRET_SALT.length); // XOR obfuscation & shift result += String.fromCharCode(charCode ^ saltCode); } // Encode to base64 safely try { return btoa(encodeURIComponent(result)); } catch { return btoa(result); } } /** * Decrypts obfuscated values back to standard UTF-8 text strings. */ static decrypt(encryptedData: string): string { if (!encryptedData) return ""; let rawObfuscated = ""; try { rawObfuscated = decodeURIComponent(atob(encryptedData)); } catch { try { rawObfuscated = atob(encryptedData); } catch { return ""; } } let result = ""; for (let i = 0; i < rawObfuscated.length; i++) { const charCode = rawObfuscated.charCodeAt(i); const saltCode = this.SECRET_SALT.charCodeAt(i % this.SECRET_SALT.length); result += String.fromCharCode(charCode ^ saltCode); } return result; } /** * Encrypts any structured JavaScript object safely. */ static encryptObject(obj: any): string { try { const rawString = JSON.stringify(obj); return this.encrypt(rawString); } catch { return ""; } } /** * Decrypts back to a structured JavaScript object. */ static decryptObject(encryptedStr: string): T | null { if (!encryptedStr) return null; try { const rawString = this.decrypt(encryptedStr); return JSON.parse(rawString) as T; } catch { return null; } } }