diff --git a/package-lock.json b/package-lock.json index 703df311..c7c0a754 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "apexcharts": "^4.5.0", "axios": "^1.7.9", "axios-retry": "^4.5.0", + "crypto-js": "^4.2.0", "date-fns": "^4.1.0", "dotenv": "^16.4.7", "dotenv-webpack": "^8.1.0", @@ -2414,6 +2415,12 @@ "node": ">= 8" } }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", + "license": "MIT" + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", diff --git a/package.json b/package.json index 02c59115..ba616768 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "apexcharts": "^4.5.0", "axios": "^1.7.9", "axios-retry": "^4.5.0", + "crypto-js": "^4.2.0", "date-fns": "^4.1.0", "dotenv": "^16.4.7", "dotenv-webpack": "^8.1.0", diff --git a/src/services/decryptResponse.js b/src/services/decryptResponse.js new file mode 100644 index 00000000..52b8a93a --- /dev/null +++ b/src/services/decryptResponse.js @@ -0,0 +1,47 @@ +// Helper to convert Base64 to ArrayBuffer +const base64ToArrayBuffer = (base64) => { + const binaryString = window.atob(base64); + const len = binaryString.length; + const bytes = new Uint8Array(len); + for (let i = 0; i < len; i++) { + bytes[i] = binaryString.charCodeAt(i); + } + return bytes.buffer; +}; + +// Main Decryption Function +export const decryptResponse = async (encryptedBase64) => { + const keyBase64 = "h9J4kL2mN5pQ8rS1tV3wX6yZ0aB7cD9eF1gH3jK5mN6="; // Same key + + // 1. Parse Key + const keyBytes = base64ToArrayBuffer(keyBase64); + const key = await window.crypto.subtle.importKey( + "raw", + keyBytes, + { name: "AES-GCM" }, + false, + ["decrypt"] + ); + + // 2. Parse Encrypted Data + const encryptedBytes = new Uint8Array(base64ToArrayBuffer(encryptedBase64)); + + // 3. Extract Parts (Nonce is first 12 bytes) + const nonce = encryptedBytes.slice(0, 12); + const ciphertextWithTag = encryptedBytes.slice(12); // Web Crypto expects Tag appended to Ciphertext + + // 4. Decrypt + try { + const decryptedBuffer = await window.crypto.subtle.decrypt( + { name: "AES-GCM", iv: nonce }, + key, + ciphertextWithTag + ); + + const decoded = new TextDecoder().decode(decryptedBuffer); + return JSON.parse(decoded); + } catch (e) { + console.error("Decryption failed:", e); + return null; + } +}; \ No newline at end of file diff --git a/src/utils/axiosClient.jsx b/src/utils/axiosClient.jsx index 40981633..0a4119ca 100644 --- a/src/utils/axiosClient.jsx +++ b/src/utils/axiosClient.jsx @@ -4,6 +4,7 @@ import axiosRetry from "axios-retry"; import showToast from "../services/toastService"; import { startSignalR, stopSignalR } from "../services/signalRService"; import { BASE_URL } from "./constants"; +import { decryptResponse } from "../services/decryptResponse"; const base_Url = BASE_URL; export const axiosClient = axios.create({ @@ -134,7 +135,7 @@ const apiRequest = async (method, url, data = {}, config = {}) => { params: method === "get" ? data : undefined, ...config, }); - return response.data; + return await decryptResponse(response.data); } catch (error) { throw error; } @@ -179,11 +180,10 @@ export const api = { authRequired: true, }), patch: (url, data = {}, customHeaders = {}) => - apiRequest("patch", url, data, { - headers: { ...customHeaders }, - authRequired: true, - }), - + apiRequest("patch", url, data, { + headers: { ...customHeaders }, + authRequired: true, + }), }; // Redirect helper