UNPKG

xypriss-security

Version:

XyPriss Security is an advanced JavaScript security library designed for enterprise applications. It provides military-grade encryption, secure data structures, quantum-resistant cryptography, and comprehensive security utilities for modern web applicatio

287 lines (284 loc) 10.4 kB
import * as crypto from 'crypto'; /** * Hash entropy analysis and quality assessment */ class HashEntropy { /** * Advanced entropy analysis for hash quality assessment * @param data - Data to analyze * @returns Entropy analysis results */ static analyzeHashEntropy(data) { const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data); const recommendations = []; // Shannon entropy calculation const frequency = new Map(); for (const byte of buffer) { frequency.set(byte, (frequency.get(byte) || 0) + 1); } let shannonEntropy = 0; const length = buffer.length; for (const count of frequency.values()) { const probability = count / length; shannonEntropy -= probability * Math.log2(probability); } // Min-entropy (worst-case entropy) const maxFreq = Math.max(...frequency.values()); const minEntropy = -Math.log2(maxFreq / length); // Compression ratio test const compressed = crypto.createHash("sha256").update(buffer).digest(); const compressionRatio = compressed.length / buffer.length; // Chi-square test for randomness const expected = length / 256; let chiSquare = 0; for (let i = 0; i < 256; i++) { const observed = frequency.get(i) || 0; chiSquare += Math.pow(observed - expected, 2) / expected; } const randomnessScore = Math.max(0, 1 - chiSquare / (256 * 4)); // Quality assessment let qualityGrade; if (shannonEntropy > 7.8 && randomnessScore > 0.9) { qualityGrade = "EXCELLENT"; } else if (shannonEntropy > 7.5 && randomnessScore > 0.8) { qualityGrade = "GOOD"; } else if (shannonEntropy > 7.0 && randomnessScore > 0.6) { qualityGrade = "FAIR"; } else { qualityGrade = "POOR"; recommendations.push("Consider using stronger entropy sources"); } if (minEntropy < 6) { recommendations.push("Min-entropy is low, consider additional randomization"); } if (compressionRatio > 0.8) { recommendations.push("Data shows patterns, consider additional mixing"); } return { shannonEntropy, minEntropy, compressionRatio, randomnessScore, qualityGrade, recommendations, }; } /** * Perform statistical randomness tests * @param data - Data to test * @returns Test results */ static performRandomnessTests(data) { // Monobit test (frequency of 1s and 0s in binary representation) const monobitResult = HashEntropy.monobitTest(data); // Runs test (sequences of consecutive identical bits) const runsResult = HashEntropy.runsTest(data); // Frequency test (distribution of byte values) const frequencyResult = HashEntropy.frequencyTest(data); // Serial test (correlation between consecutive bytes) const serialResult = HashEntropy.serialTest(data); // Calculate overall score const scores = [ monobitResult.score, runsResult.score, frequencyResult.score, serialResult.score, ]; const overallScore = scores.reduce((sum, score) => sum + score, 0) / scores.length; return { monobitTest: monobitResult, runsTest: runsResult, frequencyTest: frequencyResult, serialTest: serialResult, overallScore, }; } /** * Monobit test - checks balance of 0s and 1s * @param data - Data to test * @returns Test result */ static monobitTest(data) { let ones = 0; let total = 0; for (const byte of data) { for (let i = 0; i < 8; i++) { if ((byte >> i) & 1) { ones++; } total++; } } const ratio = ones / total; const deviation = Math.abs(ratio - 0.5); const score = Math.max(0, 1 - deviation * 4); // Scale deviation to 0-1 const passed = deviation < 0.1; // Within 10% of expected return { passed, score }; } /** * Runs test - checks for proper distribution of runs * @param data - Data to test * @returns Test result */ static runsTest(data) { const bits = []; // Convert to bit array for (const byte of data) { for (let i = 0; i < 8; i++) { bits.push((byte >> i) & 1); } } // Count runs let runs = 1; for (let i = 1; i < bits.length; i++) { if (bits[i] !== bits[i - 1]) { runs++; } } // Expected number of runs const n = bits.length; const ones = bits.filter((bit) => bit === 1).length; const expectedRuns = (2 * ones * (n - ones)) / n + 1; const deviation = Math.abs(runs - expectedRuns) / expectedRuns; const score = Math.max(0, 1 - deviation); const passed = deviation < 0.2; return { passed, score }; } /** * Frequency test - checks distribution of byte values * @param data - Data to test * @returns Test result */ static frequencyTest(data) { const frequency = new Array(256).fill(0); for (const byte of data) { frequency[byte]++; } const expected = data.length / 256; let chiSquare = 0; for (let i = 0; i < 256; i++) { const observed = frequency[i]; chiSquare += Math.pow(observed - expected, 2) / expected; } // Normalize chi-square value const normalizedChiSquare = chiSquare / (256 - 1); const score = Math.max(0, 1 - normalizedChiSquare / 2); const passed = normalizedChiSquare < 1.5; return { passed, score }; } /** * Serial test - checks correlation between consecutive bytes * @param data - Data to test * @returns Test result */ static serialTest(data) { if (data.length < 2) { return { passed: true, score: 1 }; } const pairs = new Map(); for (let i = 0; i < data.length - 1; i++) { const pair = `${data[i]}-${data[i + 1]}`; pairs.set(pair, (pairs.get(pair) || 0) + 1); } const totalPairs = data.length - 1; const expectedFreq = totalPairs / (256 * 256); let chiSquare = 0; // Check all possible pairs for (let i = 0; i < 256; i++) { for (let j = 0; j < 256; j++) { const pair = `${i}-${j}`; const observed = pairs.get(pair) || 0; chiSquare += Math.pow(observed - expectedFreq, 2) / expectedFreq; } } const normalizedChiSquare = chiSquare / (256 * 256 - 1); const score = Math.max(0, 1 - normalizedChiSquare / 2); const passed = normalizedChiSquare < 1.5; return { passed, score }; } /** * Estimate entropy rate of data * @param data - Data to analyze * @returns Entropy rate in bits per byte */ static estimateEntropyRate(data) { if (data.length === 0) return 0; // Use compression-based entropy estimation const compressed = crypto.createHash("sha256").update(data).digest(); const compressionRatio = compressed.length / data.length; // Estimate entropy based on compression const estimatedEntropy = 8 * (1 - compressionRatio); // Also calculate Shannon entropy for comparison const frequency = new Map(); for (const byte of data) { frequency.set(byte, (frequency.get(byte) || 0) + 1); } let shannonEntropy = 0; const length = data.length; for (const count of frequency.values()) { const probability = count / length; shannonEntropy -= probability * Math.log2(probability); } // Return the more conservative estimate return Math.min(estimatedEntropy, shannonEntropy); } /** * Generate entropy quality report * @param data - Data to analyze * @returns Comprehensive entropy report */ static generateEntropyReport(data) { const analysis = HashEntropy.analyzeHashEntropy(data); const randomnessTests = HashEntropy.performRandomnessTests(data); const entropyRate = HashEntropy.estimateEntropyRate(data); const recommendations = [...analysis.recommendations]; // Add recommendations based on randomness tests if (!randomnessTests.monobitTest.passed) { recommendations.push("Data fails monobit test - check bit balance"); } if (!randomnessTests.runsTest.passed) { recommendations.push("Data fails runs test - check for patterns"); } if (!randomnessTests.frequencyTest.passed) { recommendations.push("Data fails frequency test - improve byte distribution"); } if (!randomnessTests.serialTest.passed) { recommendations.push("Data fails serial test - reduce correlation"); } // Determine overall grade const scores = [ analysis.shannonEntropy / 8, // Normalize to 0-1 analysis.randomnessScore, randomnessTests.overallScore, entropyRate / 8, // Normalize to 0-1 ]; const overallScore = scores.reduce((sum, score) => sum + score, 0) / scores.length; let overallGrade; if (overallScore > 0.9) { overallGrade = "EXCELLENT"; } else if (overallScore > 0.8) { overallGrade = "GOOD"; } else if (overallScore > 0.6) { overallGrade = "FAIR"; } else { overallGrade = "POOR"; } return { analysis, randomnessTests, entropyRate, recommendations: [...new Set(recommendations)], // Remove duplicates overallGrade, }; } } export { HashEntropy }; //# sourceMappingURL=hash-entropy.js.map