diff --git a/index.html b/index.html index d276a17..c56d590 100644 --- a/index.html +++ b/index.html @@ -77,9 +77,20 @@ .drop-zone:hover { background: #f0f8ff; } /* TABLE */ - .table-header { background-color: #e9ecef; color: #333; font-weight: 700; border-bottom: 2px solid #ccc; } - .hash-font { font-family: 'Courier New', monospace; font-size: 0.8rem; color: #004085; } - .search-input { border-radius: 4px; padding: 8px 15px; border: 1px solid #ddd; background: white; } + .table-header { background-color: #e9ecef; color: #333; font-weight: 700; border-bottom: 2px solid #ccc; } + .hash-font { font-family: 'Courier New', monospace; font-size: 0.8rem; color: #004085; } + .search-input { border-radius: 4px; padding: 8px 15px; border: 1px solid #ddd; background: white; } + .system-console { + background: #0b1623; + color: #d7e6f5; + border-radius: 8px; + max-height: 150px; + overflow-y: auto; + font-family: 'Courier New', monospace; + font-size: 0.78rem; + } + .system-console-entry { border-bottom: 1px solid rgba(255,255,255,0.08); padding: 6px 10px; } + .system-console-entry:last-child { border-bottom: none; } /* BLOG CARDS */ .news-section { background: #fff; padding: 60px 0; } @@ -237,14 +248,19 @@

Evidence Validation Suite

-
- -
-
- +
+
+ +
+
+
@@ -285,20 +301,31 @@
Drag & Drop Evidence Files Here
- - - - - - - - -
#FilenameMD5 HashSHA-256 (Section 63 BSA Compliant)
-
-
- - - + + # + Filename + MD5 Hash + SHA-256 (Section 63 BSA Compliant) + SHA-3-256 (FIPS 202) + + + + + + + +
+
+
System Console
+ Client-side hash activity +
+
+
Ready. SHA-3-256 logging enabled.
+
+
+ + +
@@ -494,15 +521,17 @@
Yahoo/Outlook:
${file.name} ${isEml ? 'EMAIL' : ''} - - Calculating... - Calculating... - - `); - fileQueue.push({ file, rowId }); - }); - if (!isProcessing) processQueue(); - } + + Calculating... + Calculating... + Calculating... + + `); + fileQueue.push({ file, rowId }); + logSystem(`Queued ${file.name} for MD5, SHA-256, and SHA-3-256 hashing.`); + }); + if (!isProcessing) processQueue(); + } // PROCESS QUEUE async function processQueue() { @@ -516,12 +545,14 @@
Yahoo/Outlook:
reader.onload = function(e) { const wordArray = CryptoJS.lib.WordArray.create(e.target.result); setTimeout(() => { - if (row) { - row.querySelector('.md5').innerText = CryptoJS.MD5(wordArray).toString(); - row.querySelector('.sha256').innerText = CryptoJS.SHA256(wordArray).toString(); - } - processQueue(); - }, 50); + if (row) { + row.querySelector('.md5').innerText = CryptoJS.MD5(wordArray).toString(); + row.querySelector('.sha256').innerText = CryptoJS.SHA256(wordArray).toString(); + row.querySelector('.sha3').innerText = CryptoJS.SHA3(wordArray, { outputLength: 256 }).toString(); + logSystem(`SHA-3-256 calculated for ${file.name}.`); + } + processQueue(); + }, 50); }; reader.readAsArrayBuffer(file); } @@ -610,9 +641,10 @@
Yahoo/Outlook:
for (let i = 0; i < files.length; i++) { doc.addPage(); - const text = await readFile(files[i]); - const emailData = parseEml(text); - const sha256 = await calculateSHA256(files[i]); + const text = await readFile(files[i]); + const emailData = parseEml(text); + const sha256 = await calculateSHA256(files[i]); + const sha3 = await calculateSHA3(files[i]); // HEADER WITH WRAPPED FILENAME doc.setFillColor(0, 51, 102); @@ -644,10 +676,11 @@
Yahoo/Outlook:
['To', emailData.to], ['Date', emailData.date], ['Message-ID', emailData.messageId], - ['Originating IP', emailData.serverIP], - ['DKIM Status', emailData.dkim], - ['SHA-256 Hash', sha256] - ], + ['Originating IP', emailData.serverIP], + ['DKIM Status', emailData.dkim], + ['SHA-256 Hash', sha256], + ['SHA-3-256 Hash', sha3] + ], theme: 'grid', headStyles: { fillColor: [0, 51, 102], @@ -713,12 +746,13 @@
Yahoo/Outlook:
if (tr.querySelector('input').checked) { const cells = tr.querySelectorAll('td'); rows.push([ - cells[1].innerText, - cells[2].innerText, - cells[4].innerText - ]); - } - }); + cells[1].innerText, + cells[2].innerText, + cells[4].innerText, + cells[5].innerText + ]); + } + }); if (rows.length === 0) { alert("Please select files to include in report."); @@ -727,24 +761,25 @@
Yahoo/Outlook:
doc.autoTable({ startY: 70, - head: [['#', 'Filename', 'SHA-256']], - body: rows, - theme: 'grid', + head: [['#', 'Filename', 'SHA-256', 'SHA-3-256']], + body: rows, + theme: 'grid', headStyles: { fillColor: [0, 51, 102], fontSize: 11, fontStyle: 'bold' - }, - bodyStyles: { - fontSize: 9, - font: 'courier' - }, - columnStyles: { - 0: { cellWidth: 40 }, - 1: { cellWidth: 300 }, - 2: { cellWidth: 450, font: 'courier' } - } - }); + }, + bodyStyles: { + fontSize: 8, + font: 'courier' + }, + columnStyles: { + 0: { cellWidth: 40 }, + 1: { cellWidth: 240 }, + 2: { cellWidth: 270, font: 'courier' }, + 3: { cellWidth: 270, font: 'courier' } + } + }); doc.save("Hash_Report.pdf", { compress: true }); } @@ -776,28 +811,38 @@
Yahoo/Outlook:
})], shading: { fill: "003366" } }), - new TableCell({ - children: [new Paragraph({ - children: [new TextRun({ text: "SHA-256", bold: true, color: "FFFFFF" })], - alignment: AlignmentType.CENTER - })], - shading: { fill: "003366" } - }) - ] - })); + new TableCell({ + children: [new Paragraph({ + children: [new TextRun({ text: "SHA-256", bold: true, color: "FFFFFF" })], + alignment: AlignmentType.CENTER + })], + shading: { fill: "003366" } + }), + new TableCell({ + children: [new Paragraph({ + children: [new TextRun({ text: "SHA-3-256", bold: true, color: "FFFFFF" })], + alignment: AlignmentType.CENTER + })], + shading: { fill: "003366" } + }) + ] + })); document.querySelectorAll("#hashTableBody tr").forEach(tr => { if (tr.querySelector('input').checked) { const cells = tr.querySelectorAll('td'); rows.push(new TableRow({ children: [ - new TableCell({ children: [new Paragraph(cells[1].innerText)] }), - new TableCell({ children: [new Paragraph(cells[2].innerText)] }), - new TableCell({ children: [new Paragraph({ - children: [new TextRun({ text: cells[4].innerText, font: "Courier New", size: 18 })] - })] }) - ] - })); + new TableCell({ children: [new Paragraph(cells[1].innerText)] }), + new TableCell({ children: [new Paragraph(cells[2].innerText)] }), + new TableCell({ children: [new Paragraph({ + children: [new TextRun({ text: cells[4].innerText, font: "Courier New", size: 18 })] + })] }), + new TableCell({ children: [new Paragraph({ + children: [new TextRun({ text: cells[5].innerText, font: "Courier New", size: 18 })] + })] }) + ] + })); } }); @@ -835,34 +880,87 @@
Yahoo/Outlook:
}); } - // ===== DOWNLOAD CSV ===== - function downloadSelectedCSV() { - let csv = "#,Subject,From,To,Date,Originating IP,DKIM,SHA-256\n"; - - let counter = 1; - const promises = []; - - document.querySelectorAll("#hashTableBody tr").forEach(tr => { - if (tr.querySelector('input').checked && tr.fileData && tr.fileData.name.toLowerCase().endsWith('.eml')) { - const cells = tr.querySelectorAll('td'); - promises.push( - readFile(tr.fileData).then(text => { - const eml = parseEml(text); - return `${counter++},"${eml.subject}","${eml.from}","${eml.to}","${eml.date}","${eml.serverIP}","${eml.dkim}","${cells[4].innerText}"\n`; - }) - ); - } - }); - - Promise.all(promises).then(rows => { - csv += rows.join(''); + // ===== DOWNLOAD CSV ===== + function downloadSelectedCSV() { + let csv = "#,Filename,MD5,SHA-256,SHA-3-256,Subject,From,To,Date,Originating IP,DKIM\n"; + + let counter = 1; + const promises = []; + + document.querySelectorAll("#hashTableBody tr").forEach(tr => { + if (tr.querySelector('input').checked && tr.fileData) { + const cells = tr.querySelectorAll('td'); + const baseCells = [ + counter++, + cells[2].innerText, + cells[3].innerText, + cells[4].innerText, + cells[5].innerText + ]; + + if (tr.fileData.name.toLowerCase().endsWith('.eml')) { + promises.push(readFile(tr.fileData).then(text => { + const eml = parseEml(text); + return [...baseCells, eml.subject, eml.from, eml.to, eml.date, eml.serverIP, eml.dkim] + .map(csvEscape) + .join(",") + "\n"; + })); + } else { + promises.push(Promise.resolve([...baseCells, "", "", "", "", "", ""].map(csvEscape).join(",") + "\n")); + } + } + }); + + if (promises.length === 0) { + alert("Please select files to include in CSV report."); + return; + } + + Promise.all(promises).then(rows => { + csv += rows.join(''); const blob = new Blob([csv], { type: 'text/csv' }); const a = document.createElement('a'); - a.href = URL.createObjectURL(blob); - a.download = "Email_Report.csv"; - a.click(); - }); - } + a.href = URL.createObjectURL(blob); + a.download = "Hash_Report.csv"; + a.click(); + }); + } + + // ===== DOWNLOAD EXCEL-COMPATIBLE REPORT ===== + function downloadSelectedExcel() { + const rows = []; + document.querySelectorAll("#hashTableBody tr").forEach(tr => { + if (tr.querySelector('input').checked) { + const cells = tr.querySelectorAll('td'); + rows.push([cells[1].innerText, cells[2].innerText, cells[3].innerText, cells[4].innerText, cells[5].innerText]); + } + }); + + if (rows.length === 0) { + alert("Please select files to include in Excel report."); + return; + } + + const tableRows = rows.map(row => ( + "" + row.map(value => `${htmlEscape(value)}`).join("") + "" + )).join(""); + const workbook = ` + + + + + + ${tableRows} +
#FilenameMD5SHA-256SHA-3-256
+ + + `; + const blob = new Blob([workbook], { type: "application/vnd.ms-excel" }); + const a = document.createElement("a"); + a.href = URL.createObjectURL(blob); + a.download = "Hash_Report.xls"; + a.click(); + } // ===== UTILITY FUNCTIONS ===== function getSelectedEmlFiles() { @@ -883,16 +981,51 @@
Yahoo/Outlook:
}); } - async function calculateSHA256(file) { - return new Promise(resolve => { - const reader = new FileReader(); - reader.onload = e => { + async function calculateSHA256(file) { + return new Promise(resolve => { + const reader = new FileReader(); + reader.onload = e => { const wordArray = CryptoJS.lib.WordArray.create(e.target.result); resolve(CryptoJS.SHA256(wordArray).toString()); }; - reader.readAsArrayBuffer(file); - }); - } + reader.readAsArrayBuffer(file); + }); + } + + async function calculateSHA3(file) { + return new Promise(resolve => { + const reader = new FileReader(); + reader.onload = e => { + const wordArray = CryptoJS.lib.WordArray.create(e.target.result); + resolve(CryptoJS.SHA3(wordArray, { outputLength: 256 }).toString()); + }; + reader.readAsArrayBuffer(file); + }); + } + + function csvEscape(value) { + return `"${String(value).replace(/"/g, '""')}"`; + } + + function htmlEscape(value) { + return String(value) + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); + } + + function logSystem(message) { + const consolePanel = document.getElementById('systemConsole'); + if (!consolePanel) return; + const entry = document.createElement('div'); + entry.className = 'system-console-entry'; + entry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`; + consolePanel.appendChild(entry); + consolePanel.scrollTop = consolePanel.scrollHeight; + window.console.info(`[System Console] ${message}`); + } function toggleAll(checkbox) { document.querySelectorAll('input[name="fileSelect"]').forEach(c => c.checked = checkbox.checked);