// box-nestjs-monorepo/libs/common/src/utils/image-lib.ts // You can extend this array with more headers if needed. export const ENCRYPTED_HEADERS: Uint8Array[] = [ // Header from the Dart code: [0x88, 0xA8, 0x30, 0xCB, 0x10, 0x76] new Uint8Array([0x88, 0xa8, 0x30, 0xcb, 0x10, 0x76]), // Example: add more if their system uses multiple variants. // new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC]), ]; /** * Pick a header index: * - if headerIndex is provided, use that * - otherwise pick one randomly from ENCRYPTED_HEADERS */ function pickHeaderIndex(headerIndex?: number): number { if ( typeof headerIndex === 'number' && headerIndex >= 0 && headerIndex < ENCRYPTED_HEADERS.length ) { return headerIndex; } if (ENCRYPTED_HEADERS.length === 0) { throw new Error( 'ENCRYPTED_HEADERS is empty; configure at least one header.', ); } return Math.floor(Math.random() * ENCRYPTED_HEADERS.length); } /** * Encrypt image bytes by prefixing a chosen header. * * This is *obfuscation*, not real cryptography. * * @param imageBytes - original image content as Uint8Array * @param headerIndex - optional index into ENCRYPTED_HEADERS; if omitted, random header is used */ export function encryptImageWithHeader( imageBytes: Uint8Array, headerIndex?: number, ): Uint8Array { if (!imageBytes || imageBytes.length === 0) { return imageBytes; } const idx = pickHeaderIndex(headerIndex); const header = ENCRYPTED_HEADERS[idx]; // Allocate new array: [HEADER][IMAGE] const result = new Uint8Array(header.length + imageBytes.length); // Copy header result.set(header, 0); // Copy original image bytes after header result.set(imageBytes, header.length); return result; } /** * Try to detect which header (if any) the given bytes start with. * * @returns { headerIndex: number; header: Uint8Array } if matched, otherwise null. */ function detectHeaderPrefix( bytes: Uint8Array, ): { headerIndex: number; header: Uint8Array } | null { if (!bytes || bytes.length === 0) return null; for (let i = 0; i < ENCRYPTED_HEADERS.length; i++) { const header = ENCRYPTED_HEADERS[i]; if (bytes.length < header.length) continue; let match = true; for (let j = 0; j < header.length; j++) { if (bytes[j] !== header[j]) { match = false; break; } } if (match) { return { headerIndex: i, header }; } } return null; } /** * Decrypt image bytes by stripping a known header if present. * * If no known header is found, the original bytes are returned unchanged. * * @param encryptedBytes - stored bytes (possibly with header) */ export function decryptImageWithHeader(encryptedBytes: Uint8Array): Uint8Array { if (!encryptedBytes || encryptedBytes.length === 0) { return encryptedBytes; } const detected = detectHeaderPrefix(encryptedBytes); if (!detected) { // Not "encrypted" with our header scheme → return as-is. return encryptedBytes; } const { header } = detected; const start = header.length; // Slice bytes after the header, preserving the original image content. return encryptedBytes.subarray(start); }