UNPKG

fortify2-js

Version:

MOST POWERFUL JavaScript Security Library! Military-grade cryptography + 19 enhanced object methods + quantum-resistant algorithms + perfect TypeScript support. More powerful than Lodash with built-in security.

337 lines (335 loc) 12.8 kB
/** * Advanced Entropy Analyzer Module * Provides sophisticated entropy analysis for SecureString */ /** * Advanced entropy analyzer for strings */ class EntropyAnalyzer { /** * Performs comprehensive entropy analysis */ static analyzeEntropy(content) { const shannonEntropy = this.calculateShannonEntropy(content); const minEntropy = this.calculateMinEntropy(content); const maxEntropy = Math.log2(this.getUniqueCharacters(content).length); const compressionRatio = this.calculateCompressionRatio(content); const characterDistribution = this.getCharacterDistribution(content); const bigramEntropy = this.calculateNGramEntropy(content, 2); const trigramEntropy = this.calculateNGramEntropy(content, 3); const patternComplexity = this.calculatePatternComplexity(content); const predictability = this.calculatePredictability(content); const randomnessScore = this.calculateRandomnessScore(content); const recommendations = this.generateRecommendations(content, shannonEntropy, patternComplexity); return { shannonEntropy, minEntropy, maxEntropy, compressionRatio, patternComplexity, characterDistribution, bigramEntropy, trigramEntropy, predictability, randomnessScore, recommendations, }; } /** * Analyzes patterns in the string */ static analyzePatterns(content) { const repeatingPatterns = this.findRepeatingPatterns(content); const sequentialPatterns = this.findSequentialPatterns(content); const keyboardPatterns = this.findKeyboardPatterns(content); const dictionaryWords = this.findDictionaryWords(content); const commonSubstitutions = this.findCommonSubstitutions(content); const overallComplexity = this.calculateOverallComplexity(content); return { repeatingPatterns, sequentialPatterns, keyboardPatterns, dictionaryWords, commonSubstitutions, overallComplexity, }; } /** * Calculates Shannon entropy */ static calculateShannonEntropy(content) { const frequencies = this.getCharacterFrequencies(content); const length = content.length; let entropy = 0; for (const count of Object.values(frequencies)) { const probability = count / length; entropy -= probability * Math.log2(probability); } return entropy; } /** * Calculates min-entropy (worst-case entropy) */ static calculateMinEntropy(content) { const frequencies = this.getCharacterFrequencies(content); const maxFrequency = Math.max(...Object.values(frequencies)); const probability = maxFrequency / content.length; return -Math.log2(probability); } /** * Calculates n-gram entropy */ static calculateNGramEntropy(content, n) { if (content.length < n) return 0; const ngrams = {}; const totalNgrams = content.length - n + 1; for (let i = 0; i <= content.length - n; i++) { const ngram = content.substring(i, i + n); ngrams[ngram] = (ngrams[ngram] || 0) + 1; } let entropy = 0; for (const count of Object.values(ngrams)) { const probability = count / totalNgrams; entropy -= probability * Math.log2(probability); } return entropy; } /** * Calculates compression ratio as entropy indicator */ static calculateCompressionRatio(content) { // Simulate compression by counting unique substrings const substrings = new Set(); for (let len = 1; len <= Math.min(content.length, 10); len++) { for (let i = 0; i <= content.length - len; i++) { substrings.add(content.substring(i, i + len)); } } return substrings.size / content.length; } /** * Calculates pattern complexity */ static calculatePatternComplexity(content) { let complexity = 0; // Character variety const uniqueChars = this.getUniqueCharacters(content); complexity += uniqueChars.length / content.length; // Case variation const hasUpper = /[A-Z]/.test(content); const hasLower = /[a-z]/.test(content); const hasDigits = /\d/.test(content); const hasSpecial = /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(content); complexity += (Number(hasUpper) + Number(hasLower) + Number(hasDigits) + Number(hasSpecial)) / 4; // Pattern disruption const patterns = this.findRepeatingPatterns(content); complexity -= patterns.length / content.length; return Math.max(0, Math.min(1, complexity)); } /** * Calculates predictability score */ static calculatePredictability(content) { let predictability = 0; // Sequential characters let sequential = 0; for (let i = 1; i < content.length; i++) { const diff = content.charCodeAt(i) - content.charCodeAt(i - 1); if (Math.abs(diff) === 1) sequential++; } predictability += sequential / (content.length - 1); // Repeated characters let repeated = 0; for (let i = 1; i < content.length; i++) { if (content[i] === content[i - 1]) repeated++; } predictability += repeated / (content.length - 1); return Math.min(1, predictability); } /** * Calculates overall randomness score */ static calculateRandomnessScore(content) { const entropy = this.calculateShannonEntropy(content); const maxPossibleEntropy = Math.log2(256); // Assuming byte-level entropy const normalizedEntropy = entropy / maxPossibleEntropy; const complexity = this.calculatePatternComplexity(content); const predictability = this.calculatePredictability(content); return (normalizedEntropy + complexity + (1 - predictability)) / 3; } /** * Finds repeating patterns */ static findRepeatingPatterns(content) { const patterns = {}; for (let len = 2; len <= Math.min(content.length / 2, 10); len++) { for (let i = 0; i <= content.length - len; i++) { const pattern = content.substring(i, i + len); if (!patterns[pattern]) { patterns[pattern] = { count: 0, positions: [] }; } patterns[pattern].count++; patterns[pattern].positions.push(i); } } return Object.entries(patterns) .filter(([, data]) => data.count > 1) .map(([pattern, data]) => ({ pattern, ...data })) .sort((a, b) => b.count - a.count) .slice(0, 10); } /** * Finds sequential patterns */ static findSequentialPatterns(content) { const patterns = []; for (let len = 3; len <= Math.min(content.length, 8); len++) { for (let i = 0; i <= content.length - len; i++) { const substring = content.substring(i, i + len); if (this.isSequential(substring)) { const type = this.getSequentialType(substring); patterns.push({ pattern: substring, type }); } } } return patterns; } /** * Finds keyboard patterns */ static findKeyboardPatterns(content) { const patterns = []; for (const [layout, layoutPatterns] of Object.entries(this.KEYBOARD_PATTERNS)) { for (const keyPattern of layoutPatterns) { for (let len = 3; len <= keyPattern.length; len++) { for (let i = 0; i <= keyPattern.length - len; i++) { const pattern = keyPattern.substring(i, i + len); if (content.toLowerCase().includes(pattern)) { patterns.push({ pattern, layout }); } } } } } return patterns; } /** * Finds dictionary words */ static findDictionaryWords(content) { const words = []; const lowerContent = content.toLowerCase(); for (const word of this.COMMON_WORDS) { let position = lowerContent.indexOf(word); while (position !== -1) { const confidence = word.length / content.length; words.push({ word, position, confidence }); position = lowerContent.indexOf(word, position + 1); } } return words.sort((a, b) => b.confidence - a.confidence); } /** * Finds common substitutions (like @ for a, 3 for e) */ static findCommonSubstitutions(content) { const substitutions = [ { original: 'a', substituted: '@' }, { original: 'e', substituted: '3' }, { original: 'i', substituted: '1' }, { original: 'o', substituted: '0' }, { original: 's', substituted: '$' }, { original: 't', substituted: '7' }, ]; const found = []; for (const sub of substitutions) { if (content.includes(sub.substituted)) { found.push(sub); } } return found; } /** * Helper methods */ static getCharacterFrequencies(content) { const frequencies = {}; for (const char of content) { frequencies[char] = (frequencies[char] || 0) + 1; } return frequencies; } static getCharacterDistribution(content) { const frequencies = this.getCharacterFrequencies(content); const distribution = {}; for (const [char, count] of Object.entries(frequencies)) { distribution[char] = count / content.length; } return distribution; } static getUniqueCharacters(content) { return Array.from(new Set(content)); } static isSequential(str) { if (str.length < 3) return false; const ascending = str.split('').every((char, i) => i === 0 || char.charCodeAt(0) === str.charCodeAt(i - 1) + 1); const descending = str.split('').every((char, i) => i === 0 || char.charCodeAt(0) === str.charCodeAt(i - 1) - 1); return ascending || descending; } static getSequentialType(str) { return str.charCodeAt(1) > str.charCodeAt(0) ? 'ascending' : 'descending'; } static calculateOverallComplexity(content) { const entropy = this.calculateShannonEntropy(content); const patterns = this.findRepeatingPatterns(content); const sequential = this.findSequentialPatterns(content); let complexity = entropy / Math.log2(256); // Normalize to 0-1 complexity -= patterns.length / content.length; // Reduce for patterns complexity -= sequential.length / content.length; // Reduce for sequences return Math.max(0, Math.min(1, complexity)); } static generateRecommendations(content, entropy, complexity) { const recommendations = []; if (entropy < 3) { recommendations.push("Increase character variety to improve entropy"); } if (complexity < 0.5) { recommendations.push("Reduce predictable patterns"); } if (content.length < 12) { recommendations.push("Consider increasing length for better security"); } if (!/[A-Z]/.test(content)) { recommendations.push("Add uppercase letters"); } if (!/[a-z]/.test(content)) { recommendations.push("Add lowercase letters"); } if (!/\d/.test(content)) { recommendations.push("Add numbers"); } if (!/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(content)) { recommendations.push("Add special characters"); } return recommendations; } } EntropyAnalyzer.KEYBOARD_PATTERNS = { qwerty: [ 'qwertyuiop', 'asdfghjkl', 'zxcvbnm', 'qwerty', 'asdf', 'zxcv', '123456789', '1234567890' ], dvorak: [ 'pyfgcrl', 'aoeuidhtns', 'qjkxbmwvz' ] }; EntropyAnalyzer.COMMON_WORDS = [ 'password', 'admin', 'user', 'login', 'secret', 'test', 'demo', 'welcome', 'hello', 'world', 'company', 'system', 'access' ]; export { EntropyAnalyzer }; //# sourceMappingURL=entropy-analyzer.js.map