UNPKG

@elhamdev/tracejs

Version:

A modern, privacy-conscious alternative to browser fingerprinting for unique user identification.

100 lines (99 loc) 3.35 kB
"use strict"; /** * Utilities for measuring fingerprint entropy and uniqueness */ Object.defineProperty(exports, "__esModule", { value: true }); exports.calculateStringEntropy = calculateStringEntropy; exports.estimateFingerprintEntropy = estimateFingerprintEntropy; exports.getFingerprintQuality = getFingerprintQuality; /** * Calculate Shannon entropy of a string * Higher values indicate more randomness/uniqueness */ function calculateStringEntropy(str) { const len = str.length; // Count character frequencies const charFreq = {}; for (let i = 0; i < len; i++) { const char = str[i]; charFreq[char] = (charFreq[char] || 0) + 1; } // Calculate entropy using Shannon formula let entropy = 0; for (const char in charFreq) { const freq = charFreq[char] / len; entropy -= freq * Math.log2(freq); } return entropy; } /** * Estimate bit entropy of a fingerprint * @param fingerprint The fingerprint string * @param characteristics The collected fingerprint characteristics * @returns Estimated bits of entropy */ function estimateFingerprintEntropy(fingerprint, characteristics) { // Base entropy from string randomness const baseEntropy = calculateStringEntropy(fingerprint); // Add entropy based on available characteristics let featureEntropy = 0; // Battery adds ~2-4 bits depending on whether level is included if (characteristics.battery) { featureEntropy += 2; try { const batteryData = JSON.parse(characteristics.battery); if (batteryData.level !== undefined) featureEntropy += 2; } catch (e) { // Invalid JSON, use default featureEntropy += 1; } } // Screen adds ~4-8 bits if (characteristics.screen) featureEntropy += 6; // Canvas fingerprinting adds ~8-16 bits if (characteristics.canvas) featureEntropy += 12; // WebGL adds ~10-14 bits if (characteristics.webglParams) featureEntropy += 12; // Audio adds ~4-8 bits if (characteristics.audio) featureEntropy += 6; // User agent adds ~6-10 bits if (characteristics.userAgent) featureEntropy += 8; // Combine base entropy with feature entropy return Math.min(128, baseEntropy * 8 + featureEntropy); } /** * Get a qualitative assessment of fingerprint strength */ function getFingerprintQuality(entropyBits) { if (entropyBits < 20) { return { rating: "weak", description: "This fingerprint provides minimal identification capability and could apply to many devices.", }; } else if (entropyBits < 40) { return { rating: "moderate", description: "This fingerprint provides reasonable identification but may not be unique across a large user base.", }; } else if (entropyBits < 70) { return { rating: "strong", description: "This fingerprint provides strong identification and is likely unique for most practical purposes.", }; } else { return { rating: "very strong", description: "This fingerprint provides excellent identification and is highly unique even across large user populations.", }; } }