{"id":553,"date":"2026-07-20T14:43:30","date_gmt":"2026-07-20T14:43:30","guid":{"rendered":"https:\/\/freewebtools.co.in\/?page_id=553"},"modified":"2026-07-22T14:06:21","modified_gmt":"2026-07-22T14:06:21","slug":"steganography","status":"publish","type":"page","link":"https:\/\/freewebtools.co.in\/index.php\/steganography\/","title":{"rendered":"Steganography"},"content":{"rendered":"\n<div class=\"fwt-stego-encrypt-wrapper\" id=\"fwtStegoEncryptWrapper\">\n    <style>\n        .fwt-stego-encrypt-wrapper {\n            all: initial;\n            display: block;\n            font-family: system-ui, -apple-system, sans-serif;\n            color: #1e293b;\n            background-color: #f8fafc;\n            padding: 24px;\n            box-sizing: border-box;\n            width: 100%;\n            max-width: 900px;\n            margin: 0 auto;\n            border-radius: 20px;\n            border: 1px solid #e2e8f0;\n            box-shadow: 0 10px 25px rgba(0,0,0,0.05);\n        }\n        .fwt-stego-encrypt-wrapper *, .fwt-stego-encrypt-wrapper *::before, .fwt-stego-encrypt-wrapper *::after {\n            box-sizing: border-box;\n            margin: 0;\n            padding: 0;\n        }\n        .fwt-stego-container {\n            display: flex;\n            flex-direction: column;\n            gap: 20px;\n        }\n        .fwt-stego-title {\n            font-size: 1.5rem;\n            font-weight: 700;\n            color: #2563eb;\n            text-align: center;\n        }\n        .fwt-stego-panel {\n            background: #ffffff;\n            padding: 20px;\n            border-radius: 16px;\n            border: 1px solid #e2e8f0;\n            display: flex;\n            flex-direction: column;\n            gap: 15px;\n        }\n        .fwt-stego-group {\n            display: flex;\n            flex-direction: column;\n            gap: 6px;\n        }\n        .fwt-stego-label {\n            font-size: 0.85rem;\n            font-weight: 600;\n            color: #64748b;\n        }\n        .fwt-stego-input, .fwt-stego-textarea {\n            width: 100%;\n            padding: 12px;\n            border-radius: 10px;\n            border: 1px solid #cbd5e1;\n            font-size: 0.95rem;\n            outline: none;\n            background: #f8fafc;\n            color: #1e293b;\n        }\n        .fwt-stego-textarea {\n            resize: vertical;\n            min-height: 80px;\n        }\n        .fwt-stego-actions {\n            display: grid;\n            grid-template-columns: 1fr 1fr;\n            gap: 10px;\n        }\n        .fwt-stego-btn {\n            background: #2563eb;\n            color: white;\n            border: none;\n            padding: 12px;\n            border-radius: 10px;\n            font-weight: 700;\n            cursor: pointer;\n            transition: background 0.2s;\n            text-align: center;\n            text-decoration: none;\n            display: flex;\n            justify-content: center;\n            align-items: center;\n        }\n        .fwt-stego-btn:hover { background: #1d4ed8; }\n        .fwt-stego-btn-secondary { background: #475569; }\n        .fwt-stego-btn-secondary:hover { background: #334155; }\n        .fwt-stego-canvas-wrap {\n            display: flex;\n            justify-content: center;\n            align-items: center;\n            background: #f1f5f9;\n            padding: 15px;\n            border-radius: 12px;\n            border: 1px solid #cbd5e1;\n            min-height: 150px;\n            overflow: auto;\n        }\n        .fwt-stego-canvas-wrap canvas {\n            max-width: 100%;\n            height: auto;\n            border-radius: 8px;\n        }\n    <\/style>\n\n    <div class=\"fwt-stego-container\">\n        <h2 class=\"fwt-stego-title\">\ud83d\udd12 Professional Image Steganography Tool<\/h2>\n        \n        <div class=\"fwt-stego-panel\">\n            <div class=\"fwt-stego-group\">\n                <label class=\"fwt-stego-label\">Operation Mode<\/label>\n                <select id=\"fwtStegoMode\" class=\"fwt-stego-input\">\n                    <option value=\"encrypt\">Encrypt &#038; Hide Data<\/option>\n                    <option value=\"decrypt\">Decrypt &#038; Extract Data<\/option>\n                <\/select>\n            <\/div>\n\n            <div class=\"fwt-stego-group\">\n                <label class=\"fwt-stego-label\">1. Upload Source Carrier Image (Drag &#038; Drop or Ctrl+V Paste)<\/label>\n                <input type=\"file\" id=\"fwtStegoFile\" class=\"fwt-stego-input\" accept=\"image\/*\">\n            <\/div>\n\n            <div class=\"fwt-stego-group\" id=\"fwtPasswordGroup\">\n                <label class=\"fwt-stego-label\">Encryption Password (Optional)<\/label>\n                <input type=\"password\" id=\"fwtStegoPassword\" class=\"fwt-stego-input\" placeholder=\"Enter password for secure payload derivation...\">\n            <\/div>\n\n            <div class=\"fwt-stego-group\">\n                <label class=\"fwt-stego-label\">2. Secret Payload Message (UTF-8, Emoji, Hindi Supported)<\/label>\n                <textarea id=\"fwtStegoMessage\" class=\"fwt-stego-textarea\" placeholder=\"Type confidential data to hide inside the image...\"><\/textarea>\n                <div style=\"display:flex; justify-content:space-between; font-size:0.8rem; color:#64748b; margin-top:4px;\">\n                    <span id=\"fwtStegoCapacity\">Max Capacity: 0 bytes<\/span>\n                    <span id=\"fwtStegoRemaining\">Used: 0 bytes<\/span>\n                <\/div>\n                <div style=\"background:#e2e8f0; height:6px; border-radius:3px; overflow:hidden; margin-top:4px;\">\n                    <div id=\"fwtStegoProgressBar\" style=\"background:#2563eb; width:0%; height:100%; transition:width 0.2s;\"><\/div>\n                <\/div>\n            <\/div>\n\n            <div class=\"fwt-stego-actions\">\n                <button type=\"button\" class=\"fwt-stego-btn\" id=\"fwtStegoEncryptBtn\">Encrypt &#038; Embed Data<\/button>\n                <a id=\"fwtStegoDownload\" class=\"fwt-stego-btn fwt-stego-btn-secondary\" style=\"display:none;\">Download Encoded Image<\/a>\n                <button type=\"button\" class=\"fwt-stego-btn fwt-stego-btn-secondary\" id=\"fwtStegoResetBtn\">Reset Tool<\/button>\n            <\/div>\n\n            <div class=\"fwt-stego-group\">\n                <label class=\"fwt-stego-label\">Live Canvas Preview<\/label>\n                <div class=\"fwt-stego-canvas-wrap\">\n                    <canvas id=\"fwtStegoCanvasElement\"><\/canvas>\n                <\/div>\n            <\/div>\n        <\/div>\n    <\/div>\n<\/div>\n\n<script>\n(() => {\n    \"use strict\";\n\n    const rootElement = document.getElementById('fwtStegoEncryptWrapper');\n    if (!rootElement) return;\n\n    const modeSelect = rootElement.querySelector('#fwtStegoMode');\n    const fileInput = rootElement.querySelector('#fwtStegoFile');\n    const passwordInput = rootElement.querySelector('#fwtStegoPassword');\n    const messageInput = rootElement.querySelector('#fwtStegoMessage');\n    const encryptButton = rootElement.querySelector('#fwtStegoEncryptBtn');\n    const downloadButton = rootElement.querySelector('#fwtStegoDownload');\n    const resetBtn = rootElement.querySelector('#fwtStegoResetBtn');\n    const canvasElement = rootElement.querySelector('#fwtStegoCanvasElement');\n    const canvasContext = canvasElement.getContext('2d');\n    const capacitySpan = rootElement.querySelector('#fwtStegoCapacity');\n    const remainingSpan = rootElement.querySelector('#fwtStegoRemaining');\n    const progressBar = rootElement.querySelector('#fwtStegoProgressBar');\n    const passwordGroup = rootElement.querySelector('#fwtPasswordGroup');\n    const canvasWrap = rootElement.querySelector('.fwt-stego-canvas-wrap');\n\n    let isImageLoadedSuccessfully = false;\n    let maxByteCapacity = 0;\n\n    const utf8Encoder = new TextEncoder();\n    const utf8Decoder = new TextDecoder();\n\n    const deriveKey = (password) => {\n        if (!password) return null;\n        let hash = 0;\n        for (let i = 0; i < password.length; i++) {\n            hash = ((hash << 5) - hash) + password.charCodeAt(i);\n            hash |= 0;\n        }\n        return Math.abs(hash);\n    };\n\n    const applyCrypto = (uint8Array, password) => {\n        const key = deriveKey(password);\n        if (key === null) return uint8Array;\n        const out = new Uint8Array(uint8Array.length);\n        for (let i = 0; i < uint8Array.length; i++) {\n            out[i] = uint8Array[i] ^ ((key + i) &#038; 0xFF);\n        }\n        return out;\n    };\n\n    const crcTable = (() => {\n        let c;\n        const table = [];\n        for (let n = 0; n < 256; n++) {\n            c = n;\n            for (let k = 0; k < 8; k++) {\n                c = ((c &#038; 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));\n            }\n            table[n] = c;\n        }\n        return table;\n    })();\n\n    const computeCRC32 = (arr) => {\n        let crc = 0xFFFFFFFF;\n        for (let i = 0; i < arr.length; i++) {\n            crc = (crc >>> 8) ^ crcTable[(crc ^ arr[i]) & 0xFF];\n        }\n        return (crc ^ 0xFFFFFFFF) >>> 0;\n    };\n\n    const updateCapacityMetrics = () => {\n        if (!isImageLoadedSuccessfully) return;\n        const totalPixels = canvasElement.width * canvasElement.height;\n        const availableBytes = Math.floor((totalPixels * 3) \/ 8) - 8;\n        maxByteCapacity = Math.max(0, availableBytes);\n        \n        capacitySpan.textContent = `Max Capacity: ~${maxByteCapacity} bytes`;\n        \n        const textBytes = utf8Encoder.encode(messageInput.value).length;\n        remainingSpan.textContent = `Used: ${textBytes} \/ ${maxByteCapacity} bytes`;\n        \n        const pct = Math.min(100, (textBytes \/ (maxByteCapacity || 1)) * 100);\n        progressBar.style.width = `${pct}%`;\n        progressBar.style.background = textBytes > maxByteCapacity ? '#dc2626' : '#2563eb';\n    };\n\n    modeSelect.addEventListener('change', () => {\n        if (modeSelect.value === 'decrypt') {\n            encryptButton.textContent = 'Decrypt & Extract Data';\n            passwordGroup.style.display = 'flex';\n            messageInput.placeholder = 'Extracted secret message will appear here...';\n            messageInput.readOnly = true;\n        } else {\n            encryptButton.textContent = 'Encrypt & Embed Data';\n            passwordGroup.style.display = 'flex';\n            messageInput.placeholder = 'Type confidential data to hide inside the image...';\n            messageInput.readOnly = false;\n        }\n    });\n\n    const loadImageFromFile = (file) => {\n        const fileReaderInstance = new FileReader();\n        fileReaderInstance.onload = (loadEvent) => {\n            const imageObject = new Image();\n            imageObject.onload = () => {\n                let w = imageObject.width;\n                let h = imageObject.height;\n                canvasElement.width = w;\n                canvasElement.height = h;\n                canvasContext.clearRect(0, 0, w, h);\n                canvasContext.drawImage(imageObject, 0, 0);\n                isImageLoadedSuccessfully = true;\n                updateCapacityMetrics();\n            };\n            imageObject.onerror = () => {\n                alert(\"Corrupted or invalid image file selected.\");\n            };\n            imageObject.src = loadEvent.target.result;\n        };\n        fileReaderInstance.readAsDataURL(file);\n    };\n\n    fileInput.addEventListener('change', (event) => {\n        const uploadedFile = event.target.files[0];\n        if (!uploadedFile) return;\n        loadImageFromFile(uploadedFile);\n    });\n\n    ['dragenter', 'dragover'].forEach(eventName => {\n        canvasWrap.addEventListener(eventName, (e) => { e.preventDefault(); e.stopPropagation(); canvasWrap.style.background = '#e2e8f0'; }, false);\n    });\n    ['dragleave', 'drop'].forEach(eventName => {\n        canvasWrap.addEventListener(eventName, (e) => { e.preventDefault(); e.stopPropagation(); canvasWrap.style.background = '#f1f5f9'; }, false);\n    });\n    canvasWrap.addEventListener('drop', (e) => {\n        const dt = e.dataTransfer;\n        const files = dt.files;\n        if (files && files[0]) {\n            fileInput.files = files;\n            loadImageFromFile(files[0]);\n        }\n    });\n\n    window.addEventListener('paste', (e) => {\n        const items = e.clipboardData.items;\n        for (let i = 0; i < items.length; i++) {\n            if (items[i].type.indexOf('image') !== -1) {\n                const blob = items[i].getAsFile();\n                loadImageFromFile(blob);\n                break;\n            }\n        }\n    });\n\n    messageInput.addEventListener('input', updateCapacityMetrics);\n\n    encryptButton.addEventListener('click', () => {\n        if (!isImageLoadedSuccessfully) {\n            alert(\"Please upload or paste a carrier image file first.\");\n            return;\n        }\n\n        const isDecryptMode = modeSelect.value === 'decrypt';\n\n        if (isDecryptMode) {\n            try {\n                const imgData = canvasContext.getImageData(0, 0, canvasElement.width, canvasElement.height);\n                const data = imgData.data;\n\n                let lengthBits = '';\n                let bitCount = 0;\n                let pixelIdx = 0;\n\n                while (bitCount < 32 &#038;&#038; pixelIdx < data.length) {\n                    for (let c = 0; c < 3; c++) {\n                        if (bitCount < 32) {\n                            lengthBits += (data[pixelIdx + c] &#038; 1).toString();\n                            bitCount++;\n                        }\n                    }\n                    pixelIdx += 4;\n                }\n\n                const payloadLength = parseInt(lengthBits, 2);\n                if (isNaN(payloadLength) || payloadLength <= 0 || payloadLength > (data.length * 3 \/ 8)) {\n                    throw new Error(\"No valid hidden payload found or image is corrupted.\");\n                }\n\n                const totalBytesToExtract = payloadLength + 4;\n                const extractedBytes = new Uint8Array(totalBytesToExtract);\n                let currentByte = 0;\n                let currentBit = 0;\n                let byteVal = 0;\n\n                for (let i = 0; i < totalBytesToExtract * 8; i++) {\n                    if (pixelIdx >= data.length) throw new Error(\"Unexpected end of image data stream.\");\n                    \n                    const channelOffset = (i % 3);\n                    const bitVal = data[pixelIdx + channelOffset] & 1;\n                    \n                    byteVal = (byteVal << 1) | bitVal;\n                    currentBit++;\n\n                    if (currentBit === 8) {\n                        extractedBytes[currentByte] = byteVal;\n                        currentByte++;\n                        currentBit = 0;\n                        byteVal = 0;\n                    }\n\n                    if (channelOffset === 2) {\n                        pixelIdx += 4;\n                    }\n                }\n\n                const actualPayload = extractedBytes.subarray(0, payloadLength);\n                const storedCrcBytes = extractedBytes.subarray(payloadLength);\n                const storedCrc = (storedCrcBytes[0] << 24 | storedCrcBytes[1] << 16 | storedCrcBytes[2] << 8 | storedCrcBytes[3]) >>> 0;\n\n                const decryptedPayload = applyCrypto(actualPayload, passwordInput.value);\n\n                const calculatedCrc = computeCRC32(decryptedPayload);\n                if (calculatedCrc !== storedCrc) {\n                    alert(\"Integrity check failed! Password may be incorrect or image data is corrupted.\");\n                    return;\n                }\n\n                const decodedMessage = utf8Decoder.decode(decryptedPayload);\n                messageInput.value = decodedMessage;\n                alert(\"Data successfully extracted and decrypted!\");\n            } catch (err) {\n                alert(\"Decryption failed: \" + err.message);\n            }\n        } else {\n            const secretTextValue = messageInput.value;\n            if (!secretTextValue) {\n                alert(\"Please enter text payload to embed.\");\n                return;\n            }\n\n            const rawBytes = utf8Encoder.encode(secretTextValue);\n            const encryptedBytes = applyCrypto(rawBytes, passwordInput.value);\n            const payloadLength = encryptedBytes.length;\n\n            const crc = computeCRC32(encryptedBytes);\n\n            let lengthBin = payloadLength.toString(2);\n            lengthBin = '0'.repeat(32 - lengthBin.length) + lengthBin;\n\n            let fullStream = lengthBin;\n            for (let i = 0; i < encryptedBytes.length; i++) {\n                let bStr = encryptedBytes[i].toString(2);\n                fullStream += '0'.repeat(8 - bStr.length) + bStr;\n            }\n            \n            let crcStr = crc.toString(2);\n            crcStr = '0'.repeat(32 - crcStr.length) + crcStr;\n            fullStream += crcStr;\n\n            const sourceImagePixelData = canvasContext.getImageData(0, 0, canvasElement.width, canvasElement.height);\n            const pixelArray = sourceImagePixelData.data;\n\n            if (fullStream.length > pixelArray.length * 3) {\n                alert(\"The encrypted payload exceeds maximum image capacity.\");\n                return;\n            }\n\n            let bitIdx = 0;\n            for (let pixelIndex = 0; pixelIndex < pixelArray.length &#038;&#038; bitIdx < fullStream.length; pixelIndex += 4) {\n                for (let c = 0; c < 3 &#038;&#038; bitIdx < fullStream.length; c++) {\n                    pixelArray[pixelIndex + c] = (pixelArray[pixelIndex + c] &#038; 254) | parseInt(fullStream[bitIdx], 2);\n                    bitIdx++;\n                }\n            }\n\n            canvasContext.putImageData(sourceImagePixelData, 0, 0);\n\n            const finalEncodedDataUrl = canvasElement.toDataURL('image\/png');\n            downloadButton.href = finalEncodedDataUrl;\n            downloadButton.download = 'steganography-encrypted-image.png';\n            downloadButton.style.display = 'flex';\n\n            alert(\"Secure encryption and embedding completed successfully!\");\n        }\n    });\n\n    resetBtn.addEventListener('click', () => {\n        fileInput.value = '';\n        messageInput.value = '';\n        passwordInput.value = '';\n        downloadButton.style.display = 'none';\n        isImageLoadedSuccessfully = false;\n        canvasElement.width = 200;\n        canvasElement.height = 100;\n        canvasContext.fillStyle = \"#e2e8f0\";\n        canvasContext.fillRect(0, 0, 200, 100);\n        canvasContext.fillStyle = \"#64748b\";\n        canvasContext.font = \"12px sans-serif\";\n        canvasContext.fillText(\"No Image Uploaded\", 45, 55);\n        capacitySpan.textContent = \"Max Capacity: 0 bytes\";\n        remainingSpan.textContent = \"Used: 0 bytes\";\n        progressBar.style.width = \"0%\";\n    });\n\n    canvasElement.width = 200;\n    canvasElement.height = 100;\n    canvasContext.fillStyle = \"#e2e8f0\";\n    canvasContext.fillRect(0, 0, 200, 100);\n    canvasContext.fillStyle = \"#64748b\";\n    canvasContext.font = \"12px sans-serif\";\n    canvasContext.fillText(\"No Image Uploaded\", 45, 55);\n})();\n<\/script>\n","protected":false},"excerpt":{"rendered":"<p>\ud83d\udd12 Professional Image Steganography Tool Operation Mode Encrypt &#038; Hide DataDecrypt &#038; Extract Data 1. Upload Source Carrier Image (Drag &#038; Drop or Ctrl+V Paste) Encryption Password (Optional) 2. Secret Payload Message (UTF-8, Emoji, Hindi Supported) Max Capacity: 0 bytes Used: 0 bytes Encrypt &#038; Embed Data Download Encoded Image Reset Tool Live Canvas Preview<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-553","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/pages\/553","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/comments?post=553"}],"version-history":[{"count":11,"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/pages\/553\/revisions"}],"predecessor-version":[{"id":603,"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/pages\/553\/revisions\/603"}],"wp:attachment":[{"href":"https:\/\/freewebtools.co.in\/index.php\/wp-json\/wp\/v2\/media?parent=553"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}