fix: security and build improvements
- Fixed biased cryptographic random with modulo operations - Corrected biased cryptographic random with addition operations - Resolved infinite page loading issue - Rebuilt all distribution files
This commit is contained in:
1 parent
9d0372484a
commit
49e5a054cb
4 files changed
+173
-63
No files matched your search
Vendored
+75
-26
@@ -903,12 +903,15 @@ var EnhancedSecureCryptoUtils = class _EnhancedSecureCryptoUtils {
|
||||
// Generate secure password for data exchange
|
||||
static generateSecurePassword() {
|
||||
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+-=[]{}|;:,.<>?";
|
||||
const charCount = chars.length;
|
||||
const length = 32;
|
||||
const randomValues = new Uint32Array(length);
|
||||
crypto.getRandomValues(randomValues);
|
||||
let password = "";
|
||||
for (let i = 0; i < length; i++) {
|
||||
password += chars[randomValues[i] % chars.length];
|
||||
let randomValue;
|
||||
do {
|
||||
randomValue = crypto.getRandomValues(new Uint32Array(1))[0];
|
||||
} while (randomValue >= 4294967296 - 4294967296 % charCount);
|
||||
password += chars[randomValue % charCount];
|
||||
}
|
||||
return password;
|
||||
}
|
||||
@@ -2591,10 +2594,14 @@ var EnhancedSecureCryptoUtils = class _EnhancedSecureCryptoUtils {
|
||||
// Generate verification code for out-of-band authentication
|
||||
static generateVerificationCode() {
|
||||
const chars = "0123456789ABCDEF";
|
||||
const charCount = chars.length;
|
||||
let result = "";
|
||||
const values = crypto.getRandomValues(new Uint8Array(6));
|
||||
for (let i = 0; i < 6; i++) {
|
||||
result += chars[values[i] % chars.length];
|
||||
let randomByte;
|
||||
do {
|
||||
randomByte = crypto.getRandomValues(new Uint8Array(1))[0];
|
||||
} while (randomByte >= 256 - 256 % charCount);
|
||||
result += chars[randomByte % charCount];
|
||||
}
|
||||
return result.match(/.{1,2}/g).join("-");
|
||||
}
|
||||
@@ -4875,12 +4882,13 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager {
|
||||
preserveMessageSize: this._config.packetPadding.preserveMessageSize
|
||||
};
|
||||
this.fakeTrafficConfig = {
|
||||
enabled: this._config.fakeTraffic.enabled,
|
||||
minInterval: this._config.fakeTraffic.minInterval,
|
||||
maxInterval: this._config.fakeTraffic.maxInterval,
|
||||
minSize: this._config.fakeTraffic.minSize,
|
||||
maxSize: this._config.fakeTraffic.maxSize,
|
||||
patterns: this._config.fakeTraffic.patterns
|
||||
enabled: this._config.fakeTraffic?.enabled || false,
|
||||
minInterval: this._config.fakeTraffic?.minInterval || 15e3,
|
||||
maxInterval: this._config.fakeTraffic?.maxInterval || 3e4,
|
||||
minSize: this._config.fakeTraffic?.minSize || 64,
|
||||
maxSize: this._config.fakeTraffic?.maxSize || 1024,
|
||||
patterns: this._config.fakeTraffic?.patterns || ["heartbeat", "status", "ping"],
|
||||
randomDecoyIntervals: this._config.fakeTraffic?.randomDecoyIntervals || true
|
||||
};
|
||||
this.fakeTrafficTimer = null;
|
||||
this.lastFakeTraffic = 0;
|
||||
@@ -7447,7 +7455,11 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager {
|
||||
);
|
||||
const dv = new DataView(bits);
|
||||
const n = (dv.getUint32(0) ^ dv.getUint32(4)) >>> 0;
|
||||
const sasCode = String(n % 1e7).padStart(7, "0");
|
||||
let sasValue;
|
||||
do {
|
||||
sasValue = crypto.getRandomValues(new Uint32Array(1))[0];
|
||||
} while (sasValue >= 4294967296 - 4294967296 % 1e7);
|
||||
const sasCode = String(sasValue % 1e7).padStart(7, "0");
|
||||
this._secureLog("info", "SAS code computed successfully", {
|
||||
localFP: localFP.substring(0, 16) + "...",
|
||||
remoteFP: remoteFP.substring(0, 16) + "...",
|
||||
@@ -8121,13 +8133,36 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager {
|
||||
this._secureLog("error", "\u274C Failed to initialize enhanced security", { errorType: error.constructor.name });
|
||||
}
|
||||
}
|
||||
// Helper function to generate unbiased random values in a range
|
||||
getUnbiasedRandomInRange(min, max) {
|
||||
const range = max - min + 1;
|
||||
if (range > 256) {
|
||||
const bytesNeeded = Math.ceil(Math.log2(range) / 8);
|
||||
const maxValue = Math.pow(256, bytesNeeded);
|
||||
const threshold = maxValue - maxValue % range;
|
||||
let randomValue2;
|
||||
do {
|
||||
const randomBytes = crypto.getRandomValues(new Uint8Array(bytesNeeded));
|
||||
randomValue2 = 0;
|
||||
for (let i = 0; i < bytesNeeded; i++) {
|
||||
randomValue2 = (randomValue2 << 8) + randomBytes[i];
|
||||
}
|
||||
} while (randomValue2 >= threshold);
|
||||
return randomValue2 % range + min;
|
||||
}
|
||||
let randomValue;
|
||||
do {
|
||||
randomValue = crypto.getRandomValues(new Uint8Array(1))[0];
|
||||
} while (randomValue >= 256 - 256 % range);
|
||||
return randomValue % range + min;
|
||||
}
|
||||
// Generate fingerprint mask for anti-fingerprinting with enhanced randomization
|
||||
generateFingerprintMask() {
|
||||
const cryptoRandom = crypto.getRandomValues(new Uint8Array(128));
|
||||
const mask = {
|
||||
timingOffset: cryptoRandom[0] % 1e3 + cryptoRandom[1] % 500,
|
||||
timingOffset: this.getUnbiasedRandomInRange(0, 1500),
|
||||
// 0-1500ms
|
||||
sizeVariation: (cryptoRandom[2] % 50 + 75) / 100,
|
||||
sizeVariation: this.getUnbiasedRandomInRange(75, 125) / 100,
|
||||
// 0.75 to 1.25
|
||||
noisePattern: Array.from(crypto.getRandomValues(new Uint8Array(64))),
|
||||
// Increased size
|
||||
@@ -8144,11 +8179,11 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager {
|
||||
"X-Anonymous",
|
||||
"X-Private"
|
||||
],
|
||||
noiseIntensity: cryptoRandom[3] % 100 + 50,
|
||||
noiseIntensity: this.getUnbiasedRandomInRange(50, 150),
|
||||
// 50-150%
|
||||
sizeMultiplier: (cryptoRandom[4] % 50 + 75) / 100,
|
||||
sizeMultiplier: this.getUnbiasedRandomInRange(75, 125) / 100,
|
||||
// 0.75-1.25
|
||||
timingVariation: cryptoRandom[5] % 1e3 + 100
|
||||
timingVariation: this.getUnbiasedRandomInRange(100, 1100)
|
||||
// 100-1100ms
|
||||
};
|
||||
return mask;
|
||||
@@ -8478,7 +8513,10 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager {
|
||||
try {
|
||||
const fakeMessage = this.generateFakeMessage();
|
||||
await this.sendFakeMessage(fakeMessage);
|
||||
const nextInterval = this.fakeTrafficConfig.randomDecoyIntervals ? Math.random() * (this.fakeTrafficConfig.maxInterval - this.fakeTrafficConfig.minInterval) + this.fakeTrafficConfig.minInterval : this.fakeTrafficConfig.minInterval;
|
||||
const nextInterval = this.fakeTrafficConfig.randomDecoyIntervals ? this.getUnbiasedRandomInRange(this.fakeTrafficConfig.minInterval, Math.min(this.fakeTrafficConfig.maxInterval, 6e4)) : (
|
||||
// Cap at 60 seconds
|
||||
this.fakeTrafficConfig.minInterval
|
||||
);
|
||||
const safeInterval = Math.max(nextInterval, _EnhancedSecureWebRTCManager.TIMEOUTS.FAKE_TRAFFIC_MIN_INTERVAL);
|
||||
this.fakeTrafficTimer = setTimeout(sendFakeMessage, safeInterval);
|
||||
} catch (error) {
|
||||
@@ -8488,7 +8526,9 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager {
|
||||
this.stopFakeTrafficGeneration();
|
||||
}
|
||||
};
|
||||
const initialDelay = Math.random() * this.fakeTrafficConfig.maxInterval + _EnhancedSecureWebRTCManager.TIMEOUTS.DECOY_INITIAL_DELAY;
|
||||
const minDelay = _EnhancedSecureWebRTCManager.TIMEOUTS.DECOY_INITIAL_DELAY;
|
||||
const maxDelay = Math.min(this.fakeTrafficConfig.maxInterval, 3e4);
|
||||
const initialDelay = this.getUnbiasedRandomInRange(minDelay, maxDelay);
|
||||
this.fakeTrafficTimer = setTimeout(sendFakeMessage, initialDelay);
|
||||
}
|
||||
stopFakeTrafficGeneration() {
|
||||
@@ -8498,8 +8538,9 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager {
|
||||
}
|
||||
}
|
||||
generateFakeMessage() {
|
||||
const pattern = this.fakeTrafficConfig.patterns[Math.floor(Math.random() * this.fakeTrafficConfig.patterns.length)];
|
||||
const size = Math.floor(Math.random() * (this.fakeTrafficConfig.maxSize - this.fakeTrafficConfig.minSize + 1)) + this.fakeTrafficConfig.minSize;
|
||||
const patternIndex = this.getUnbiasedRandomInRange(0, this.fakeTrafficConfig.patterns.length - 1);
|
||||
const pattern = this.fakeTrafficConfig.patterns[patternIndex];
|
||||
const size = this.getUnbiasedRandomInRange(this.fakeTrafficConfig.minSize, this.fakeTrafficConfig.maxSize);
|
||||
const fakeData = crypto.getRandomValues(new Uint8Array(size));
|
||||
return {
|
||||
type: _EnhancedSecureWebRTCManager.MESSAGE_TYPES.FAKE,
|
||||
@@ -8961,7 +9002,7 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager {
|
||||
}
|
||||
addNoise(data) {
|
||||
const dataArray = new Uint8Array(data);
|
||||
const noiseSize = Math.floor(Math.random() * 32) + 8;
|
||||
const noiseSize = this.getUnbiasedRandomInRange(8, 40);
|
||||
const noise = crypto.getRandomValues(new Uint8Array(noiseSize));
|
||||
const result = new Uint8Array(dataArray.length + noiseSize);
|
||||
result.set(dataArray, 0);
|
||||
@@ -8994,16 +9035,24 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager {
|
||||
}
|
||||
addRandomHeaders(data) {
|
||||
const dataArray = new Uint8Array(data);
|
||||
const headerCount = Math.floor(Math.random() * 3) + 1;
|
||||
const headerCount = this.getUnbiasedRandomInRange(1, 3);
|
||||
let totalHeaderSize = 0;
|
||||
for (let i = 0; i < headerCount; i++) {
|
||||
totalHeaderSize += 4 + Math.floor(Math.random() * 16) + 4;
|
||||
totalHeaderSize += 4 + this.getUnbiasedRandomInRange(0, 15) + 4;
|
||||
}
|
||||
const result = new Uint8Array(totalHeaderSize + dataArray.length);
|
||||
let offset = 0;
|
||||
for (let i = 0; i < headerCount; i++) {
|
||||
const headerName = this.fingerprintMask.headerVariations[Math.floor(Math.random() * this.fingerprintMask.headerVariations.length)];
|
||||
const headerData = crypto.getRandomValues(new Uint8Array(Math.floor(Math.random() * 16) + 4));
|
||||
let headerIndex;
|
||||
do {
|
||||
headerIndex = crypto.getRandomValues(new Uint8Array(1))[0];
|
||||
} while (headerIndex >= 256 - 256 % this.fingerprintMask.headerVariations.length);
|
||||
const headerName = this.fingerprintMask.headerVariations[headerIndex % this.fingerprintMask.headerVariations.length];
|
||||
let headerSize;
|
||||
do {
|
||||
headerSize = crypto.getRandomValues(new Uint8Array(1))[0];
|
||||
} while (headerSize >= 256 - 256 % 16);
|
||||
const headerData = crypto.getRandomValues(new Uint8Array(headerSize % 16 + 4));
|
||||
const headerView = new DataView(result.buffer, offset);
|
||||
headerView.setUint32(0, headerData.length + 8, false);
|
||||
headerView.setUint32(4, this.hashString(headerName), false);
|
||||
|
||||
Vendored
+3
-3
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": 3,
|
||||
"sources": ["../src/notifications/SecureNotificationManager.js", "../src/notifications/NotificationIntegration.js", "../src/crypto/EnhancedSecureCryptoUtils.js", "../src/transfer/EnhancedSecureFileTransfer.js", "../src/network/EnhancedSecureWebRTCManager.js", "../src/scripts/app-boot.js", "../src/components/ui/Header.jsx", "../src/components/ui/DownloadApps.jsx", "../src/components/ui/UniqueFeatureSlider.jsx", "../src/components/ui/SecurityFeatures.jsx", "../src/components/ui/Testimonials.jsx", "../src/components/ui/ComparisonTable.jsx", "../src/components/ui/Roadmap.jsx", "../src/components/ui/FileTransfer.jsx"],
|
||||
"sourcesContent": ["/**\n * Secure and Reliable Notification Manager for P2P WebRTC Chat\n * Follows best practices: OWASP, MDN, Chrome DevRel\n * \n * @version 1.0.0\n * @author SecureBit Team\n * @license MIT\n */\n\nclass SecureChatNotificationManager {\n constructor(config = {}) {\n // Safely read Notification permission (iOS Safari may not define Notification)\n this.permission = (typeof Notification !== 'undefined' && Notification && typeof Notification.permission === 'string')\n ? Notification.permission\n : 'denied';\n this.isTabActive = this.checkTabActive(); // Initialize with proper check\n this.unreadCount = 0;\n this.originalTitle = document.title;\n this.notificationQueue = [];\n this.maxQueueSize = config.maxQueueSize || 5;\n this.rateLimitMs = config.rateLimitMs || 2000; // Spam protection\n this.lastNotificationTime = 0;\n this.trustedOrigins = config.trustedOrigins || [];\n \n // Secure context flag\n this.isSecureContext = window.isSecureContext;\n \n // Cross-browser compatibility for Page Visibility API\n this.hidden = this.getHiddenProperty();\n this.visibilityChange = this.getVisibilityChangeEvent();\n \n this.initVisibilityTracking();\n this.initSecurityChecks();\n }\n\n /**\n * Initialize security checks and validation\n * @private\n */\n initSecurityChecks() {\n // Security checks are performed silently\n }\n\n /**\n * Get hidden property name for cross-browser compatibility\n * @returns {string} Hidden property name\n * @private\n */\n getHiddenProperty() {\n if (typeof document.hidden !== \"undefined\") {\n return \"hidden\";\n } else if (typeof document.msHidden !== \"undefined\") {\n return \"msHidden\";\n } else if (typeof document.webkitHidden !== \"undefined\") {\n return \"webkitHidden\";\n }\n return \"hidden\"; // fallback\n }\n\n /**\n * Get visibility change event name for cross-browser compatibility\n * @returns {string} Visibility change event name\n * @private\n */\n getVisibilityChangeEvent() {\n if (typeof document.hidden !== \"undefined\") {\n return \"visibilitychange\";\n } else if (typeof document.msHidden !== \"undefined\") {\n return \"msvisibilitychange\";\n } else if (typeof document.webkitHidden !== \"undefined\") {\n return \"webkitvisibilitychange\";\n }\n return \"visibilitychange\"; // fallback\n }\n\n /**\n * Check if tab is currently active using multiple methods\n * @returns {boolean} True if tab is active\n * @private\n */\n checkTabActive() {\n // Primary method: Page Visibility API\n if (this.hidden && typeof document[this.hidden] !== \"undefined\") {\n return !document[this.hidden];\n }\n \n // Fallback method: document.hasFocus()\n if (typeof document.hasFocus === \"function\") {\n return document.hasFocus();\n }\n \n // Ultimate fallback: assume active\n return true;\n }\n\n /**\n * Initialize page visibility tracking (Page Visibility API)\n * @private\n */\n initVisibilityTracking() {\n // Primary method: Page Visibility API with cross-browser support\n if (typeof document.addEventListener !== \"undefined\" && typeof document[this.hidden] !== \"undefined\") {\n document.addEventListener(this.visibilityChange, () => {\n this.isTabActive = this.checkTabActive();\n \n if (this.isTabActive) {\n this.resetUnreadCount();\n this.clearNotificationQueue();\n }\n });\n }\n\n // Fallback method: Window focus/blur events\n window.addEventListener('focus', () => {\n this.isTabActive = this.checkTabActive();\n if (this.isTabActive) {\n this.resetUnreadCount();\n }\n });\n\n window.addEventListener('blur', () => {\n this.isTabActive = this.checkTabActive();\n });\n\n // Page unload cleanup\n window.addEventListener('beforeunload', () => {\n this.clearNotificationQueue();\n });\n }\n\n /**\n * Request notification permission (BEST PRACTICE: Only call in response to user action)\n * Never call on page load!\n * @returns {Promise<boolean>} Permission granted status\n */\n async requestPermission() {\n // Secure context check\n if (!this.isSecureContext || !('Notification' in window)) {\n return false;\n }\n\n if (this.permission === 'granted') {\n return true;\n }\n\n if (this.permission === 'denied') {\n return false;\n }\n\n try {\n this.permission = await Notification.requestPermission();\n return this.permission === 'granted';\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Update page title with unread count\n * @private\n */\n updateTitle() {\n if (this.unreadCount > 0) {\n document.title = `(${this.unreadCount}) ${this.originalTitle}`;\n } else {\n document.title = this.originalTitle;\n }\n }\n\n /**\n Line truncated
|
||||
"mappings": "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 truncated
|
||||
"names": ["NotificationIntegration", "fileMessageTypes", "attempts", "start", "error", "attempts", "chunk", "fileMessageTypes", "window", "start", "webrtcManager", "start"]
|
||||
"sourcesContent": ["/**\n * Secure and Reliable Notification Manager for P2P WebRTC Chat\n * Follows best practices: OWASP, MDN, Chrome DevRel\n * \n * @version 1.0.0\n * @author SecureBit Team\n * @license MIT\n */\n\nclass SecureChatNotificationManager {\n constructor(config = {}) {\n // Safely read Notification permission (iOS Safari may not define Notification)\n this.permission = (typeof Notification !== 'undefined' && Notification && typeof Notification.permission === 'string')\n ? Notification.permission\n : 'denied';\n this.isTabActive = this.checkTabActive(); // Initialize with proper check\n this.unreadCount = 0;\n this.originalTitle = document.title;\n this.notificationQueue = [];\n this.maxQueueSize = config.maxQueueSize || 5;\n this.rateLimitMs = config.rateLimitMs || 2000; // Spam protection\n this.lastNotificationTime = 0;\n this.trustedOrigins = config.trustedOrigins || [];\n \n // Secure context flag\n this.isSecureContext = window.isSecureContext;\n \n // Cross-browser compatibility for Page Visibility API\n this.hidden = this.getHiddenProperty();\n this.visibilityChange = this.getVisibilityChangeEvent();\n \n this.initVisibilityTracking();\n this.initSecurityChecks();\n }\n\n /**\n * Initialize security checks and validation\n * @private\n */\n initSecurityChecks() {\n // Security checks are performed silently\n }\n\n /**\n * Get hidden property name for cross-browser compatibility\n * @returns {string} Hidden property name\n * @private\n */\n getHiddenProperty() {\n if (typeof document.hidden !== \"undefined\") {\n return \"hidden\";\n } else if (typeof document.msHidden !== \"undefined\") {\n return \"msHidden\";\n } else if (typeof document.webkitHidden !== \"undefined\") {\n return \"webkitHidden\";\n }\n return \"hidden\"; // fallback\n }\n\n /**\n * Get visibility change event name for cross-browser compatibility\n * @returns {string} Visibility change event name\n * @private\n */\n getVisibilityChangeEvent() {\n if (typeof document.hidden !== \"undefined\") {\n return \"visibilitychange\";\n } else if (typeof document.msHidden !== \"undefined\") {\n return \"msvisibilitychange\";\n } else if (typeof document.webkitHidden !== \"undefined\") {\n return \"webkitvisibilitychange\";\n }\n return \"visibilitychange\"; // fallback\n }\n\n /**\n * Check if tab is currently active using multiple methods\n * @returns {boolean} True if tab is active\n * @private\n */\n checkTabActive() {\n // Primary method: Page Visibility API\n if (this.hidden && typeof document[this.hidden] !== \"undefined\") {\n return !document[this.hidden];\n }\n \n // Fallback method: document.hasFocus()\n if (typeof document.hasFocus === \"function\") {\n return document.hasFocus();\n }\n \n // Ultimate fallback: assume active\n return true;\n }\n\n /**\n * Initialize page visibility tracking (Page Visibility API)\n * @private\n */\n initVisibilityTracking() {\n // Primary method: Page Visibility API with cross-browser support\n if (typeof document.addEventListener !== \"undefined\" && typeof document[this.hidden] !== \"undefined\") {\n document.addEventListener(this.visibilityChange, () => {\n this.isTabActive = this.checkTabActive();\n \n if (this.isTabActive) {\n this.resetUnreadCount();\n this.clearNotificationQueue();\n }\n });\n }\n\n // Fallback method: Window focus/blur events\n window.addEventListener('focus', () => {\n this.isTabActive = this.checkTabActive();\n if (this.isTabActive) {\n this.resetUnreadCount();\n }\n });\n\n window.addEventListener('blur', () => {\n this.isTabActive = this.checkTabActive();\n });\n\n // Page unload cleanup\n window.addEventListener('beforeunload', () => {\n this.clearNotificationQueue();\n });\n }\n\n /**\n * Request notification permission (BEST PRACTICE: Only call in response to user action)\n * Never call on page load!\n * @returns {Promise<boolean>} Permission granted status\n */\n async requestPermission() {\n // Secure context check\n if (!this.isSecureContext || !('Notification' in window)) {\n return false;\n }\n\n if (this.permission === 'granted') {\n return true;\n }\n\n if (this.permission === 'denied') {\n return false;\n }\n\n try {\n this.permission = await Notification.requestPermission();\n return this.permission === 'granted';\n } catch (error) {\n return false;\n }\n }\n\n /**\n * Update page title with unread count\n * @private\n */\n updateTitle() {\n if (this.unreadCount > 0) {\n document.title = `(${this.unreadCount}) ${this.originalTitle}`;\n } else {\n document.title = this.originalTitle;\n }\n }\n\n /**\n Line truncated
|
||||
"mappings": "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 truncated
|
||||
"names": ["NotificationIntegration", "fileMessageTypes", "attempts", "start", "error", "attempts", "randomValue", "chunk", "fileMessageTypes", "window", "start", "webrtcManager", "start"]
|
||||
}
|
||||
@@ -224,13 +224,18 @@ class EnhancedSecureCryptoUtils {
|
||||
// Generate secure password for data exchange
|
||||
static generateSecurePassword() {
|
||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+-=[]{}|;:,.<>?';
|
||||
const charCount = chars.length;
|
||||
const length = 32;
|
||||
const randomValues = new Uint32Array(length);
|
||||
crypto.getRandomValues(randomValues);
|
||||
|
||||
let password = '';
|
||||
|
||||
// Use rejection sampling to avoid bias
|
||||
for (let i = 0; i < length; i++) {
|
||||
password += chars[randomValues[i] % chars.length];
|
||||
let randomValue;
|
||||
do {
|
||||
randomValue = crypto.getRandomValues(new Uint32Array(1))[0];
|
||||
} while (randomValue >= 4294967296 - (4294967296 % charCount)); // Reject biased values
|
||||
|
||||
password += chars[randomValue % charCount];
|
||||
}
|
||||
return password;
|
||||
}
|
||||
@@ -2322,11 +2327,19 @@ class EnhancedSecureCryptoUtils {
|
||||
// Generate verification code for out-of-band authentication
|
||||
static generateVerificationCode() {
|
||||
const chars = '0123456789ABCDEF';
|
||||
const charCount = chars.length;
|
||||
let result = '';
|
||||
const values = crypto.getRandomValues(new Uint8Array(6));
|
||||
|
||||
// Use rejection sampling to avoid bias
|
||||
for (let i = 0; i < 6; i++) {
|
||||
result += chars[values[i] % chars.length];
|
||||
let randomByte;
|
||||
do {
|
||||
randomByte = crypto.getRandomValues(new Uint8Array(1))[0];
|
||||
} while (randomByte >= 256 - (256 % charCount)); // Reject biased values
|
||||
|
||||
result += chars[randomByte % charCount];
|
||||
}
|
||||
|
||||
return result.match(/.{1,2}/g).join('-');
|
||||
}
|
||||
|
||||
|
||||
@@ -404,12 +404,13 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida
|
||||
|
||||
// 3. Fake Traffic Generation
|
||||
this.fakeTrafficConfig = {
|
||||
enabled: this._config.fakeTraffic.enabled,
|
||||
minInterval: this._config.fakeTraffic.minInterval,
|
||||
maxInterval: this._config.fakeTraffic.maxInterval,
|
||||
minSize: this._config.fakeTraffic.minSize,
|
||||
maxSize: this._config.fakeTraffic.maxSize,
|
||||
patterns: this._config.fakeTraffic.patterns
|
||||
enabled: this._config.fakeTraffic?.enabled || false,
|
||||
minInterval: this._config.fakeTraffic?.minInterval || 15000,
|
||||
maxInterval: this._config.fakeTraffic?.maxInterval || 30000,
|
||||
minSize: this._config.fakeTraffic?.minSize || 64,
|
||||
maxSize: this._config.fakeTraffic?.maxSize || 1024,
|
||||
patterns: this._config.fakeTraffic?.patterns || ['heartbeat', 'status', 'ping'],
|
||||
randomDecoyIntervals: this._config.fakeTraffic?.randomDecoyIntervals || true
|
||||
};
|
||||
this.fakeTrafficTimer = null;
|
||||
this.lastFakeTraffic = 0;
|
||||
@@ -3620,7 +3621,14 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida
|
||||
|
||||
const dv = new DataView(bits);
|
||||
const n = (dv.getUint32(0) ^ dv.getUint32(4)) >>> 0;
|
||||
const sasCode = String(n % 10_000_000).padStart(7, '0');
|
||||
|
||||
// Use rejection sampling to avoid bias in SAS code generation
|
||||
let sasValue;
|
||||
do {
|
||||
sasValue = crypto.getRandomValues(new Uint32Array(1))[0];
|
||||
} while (sasValue >= 4294967296 - (4294967296 % 10_000_000));
|
||||
|
||||
const sasCode = String(sasValue % 10_000_000).padStart(7, '0');
|
||||
|
||||
|
||||
this._secureLog('info', 'SAS code computed successfully', {
|
||||
@@ -4461,22 +4469,52 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to generate unbiased random values in a range
|
||||
getUnbiasedRandomInRange(min, max) {
|
||||
const range = max - min + 1;
|
||||
|
||||
// If range is larger than 256, use multiple bytes
|
||||
if (range > 256) {
|
||||
const bytesNeeded = Math.ceil(Math.log2(range) / 8);
|
||||
const maxValue = Math.pow(256, bytesNeeded);
|
||||
const threshold = maxValue - (maxValue % range);
|
||||
|
||||
let randomValue;
|
||||
do {
|
||||
const randomBytes = crypto.getRandomValues(new Uint8Array(bytesNeeded));
|
||||
randomValue = 0;
|
||||
for (let i = 0; i < bytesNeeded; i++) {
|
||||
randomValue = (randomValue << 8) + randomBytes[i];
|
||||
}
|
||||
} while (randomValue >= threshold);
|
||||
|
||||
return (randomValue % range) + min;
|
||||
}
|
||||
|
||||
// For ranges <= 256, use single byte with rejection sampling
|
||||
let randomValue;
|
||||
do {
|
||||
randomValue = crypto.getRandomValues(new Uint8Array(1))[0];
|
||||
} while (randomValue >= 256 - (256 % range));
|
||||
return (randomValue % range) + min;
|
||||
}
|
||||
|
||||
// Generate fingerprint mask for anti-fingerprinting with enhanced randomization
|
||||
generateFingerprintMask() {
|
||||
// Enhanced randomization to prevent side-channel attacks
|
||||
const cryptoRandom = crypto.getRandomValues(new Uint8Array(128));
|
||||
|
||||
const mask = {
|
||||
timingOffset: cryptoRandom[0] % 1000 + cryptoRandom[1] % 500, // 0-1500ms
|
||||
sizeVariation: (cryptoRandom[2] % 50 + 75) / 100, // 0.75 to 1.25
|
||||
timingOffset: this.getUnbiasedRandomInRange(0, 1500), // 0-1500ms
|
||||
sizeVariation: this.getUnbiasedRandomInRange(75, 125) / 100, // 0.75 to 1.25
|
||||
noisePattern: Array.from(crypto.getRandomValues(new Uint8Array(64))), // Increased size
|
||||
headerVariations: [
|
||||
'X-Client-Version', 'X-Session-ID', 'X-Request-ID', 'X-Timestamp', 'X-Signature',
|
||||
'X-Secure', 'X-Encrypted', 'X-Protected', 'X-Safe', 'X-Anonymous', 'X-Private'
|
||||
],
|
||||
noiseIntensity: cryptoRandom[3] % 100 + 50, // 50-150%
|
||||
sizeMultiplier: (cryptoRandom[4] % 50 + 75) / 100, // 0.75-1.25
|
||||
timingVariation: cryptoRandom[5] % 1000 + 100 // 100-1100ms
|
||||
noiseIntensity: this.getUnbiasedRandomInRange(50, 150), // 50-150%
|
||||
sizeMultiplier: this.getUnbiasedRandomInRange(75, 125) / 100, // 0.75-1.25
|
||||
timingVariation: this.getUnbiasedRandomInRange(100, 1100) // 100-1100ms
|
||||
};
|
||||
return mask;
|
||||
}
|
||||
@@ -4914,8 +4952,7 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida
|
||||
|
||||
// FIX: Increase intervals to reduce load
|
||||
const nextInterval = this.fakeTrafficConfig.randomDecoyIntervals ?
|
||||
Math.random() * (this.fakeTrafficConfig.maxInterval - this.fakeTrafficConfig.minInterval) +
|
||||
this.fakeTrafficConfig.minInterval :
|
||||
this.getUnbiasedRandomInRange(this.fakeTrafficConfig.minInterval, Math.min(this.fakeTrafficConfig.maxInterval, 60000)) : // Cap at 60 seconds
|
||||
this.fakeTrafficConfig.minInterval;
|
||||
|
||||
// Minimum interval 15 seconds for stability
|
||||
@@ -4931,7 +4968,10 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida
|
||||
};
|
||||
|
||||
// Start fake traffic generation with longer initial delay
|
||||
const initialDelay = Math.random() * this.fakeTrafficConfig.maxInterval + EnhancedSecureWebRTCManager.TIMEOUTS.DECOY_INITIAL_DELAY; // Add 5 seconds minimum
|
||||
// Use a reasonable range for initial delay (5-30 seconds)
|
||||
const minDelay = EnhancedSecureWebRTCManager.TIMEOUTS.DECOY_INITIAL_DELAY;
|
||||
const maxDelay = Math.min(this.fakeTrafficConfig.maxInterval, 30000); // Cap at 30 seconds
|
||||
const initialDelay = this.getUnbiasedRandomInRange(minDelay, maxDelay);
|
||||
this.fakeTrafficTimer = setTimeout(sendFakeMessage, initialDelay);
|
||||
}
|
||||
|
||||
@@ -4943,13 +4983,10 @@ this._secureLog('info', '🔒 Enhanced Mutex system fully initialized and valida
|
||||
}
|
||||
|
||||
generateFakeMessage() {
|
||||
const pattern = this.fakeTrafficConfig.patterns[
|
||||
Math.floor(Math.random() * this.fakeTrafficConfig.patterns.length)
|
||||
];
|
||||
const patternIndex = this.getUnbiasedRandomInRange(0, this.fakeTrafficConfig.patterns.length - 1);
|
||||
const pattern = this.fakeTrafficConfig.patterns[patternIndex];
|
||||
|
||||
const size = Math.floor(Math.random() *
|
||||
(this.fakeTrafficConfig.maxSize - this.fakeTrafficConfig.minSize + 1)) +
|
||||
this.fakeTrafficConfig.minSize;
|
||||
const size = this.getUnbiasedRandomInRange(this.fakeTrafficConfig.minSize, this.fakeTrafficConfig.maxSize);
|
||||
|
||||
const fakeData = crypto.getRandomValues(new Uint8Array(size));
|
||||
|
||||
@@ -5550,7 +5587,7 @@ async processOrderedPackets() {
|
||||
|
||||
addNoise(data) {
|
||||
const dataArray = new Uint8Array(data);
|
||||
const noiseSize = Math.floor(Math.random() * 32) + 8; // 8-40 bytes
|
||||
const noiseSize = this.getUnbiasedRandomInRange(8, 40); // 8-40 bytes
|
||||
const noise = crypto.getRandomValues(new Uint8Array(noiseSize));
|
||||
|
||||
const result = new Uint8Array(dataArray.length + noiseSize);
|
||||
@@ -5595,12 +5632,12 @@ async processOrderedPackets() {
|
||||
|
||||
addRandomHeaders(data) {
|
||||
const dataArray = new Uint8Array(data);
|
||||
const headerCount = Math.floor(Math.random() * 3) + 1; // 1-3 headers
|
||||
const headerCount = this.getUnbiasedRandomInRange(1, 3); // 1-3 headers
|
||||
let totalHeaderSize = 0;
|
||||
|
||||
// Calculate total header size
|
||||
for (let i = 0; i < headerCount; i++) {
|
||||
totalHeaderSize += 4 + Math.floor(Math.random() * 16) + 4; // size + data + checksum
|
||||
totalHeaderSize += 4 + this.getUnbiasedRandomInRange(0, 15) + 4; // size + data + checksum
|
||||
}
|
||||
|
||||
const result = new Uint8Array(totalHeaderSize + dataArray.length);
|
||||
@@ -5608,10 +5645,21 @@ async processOrderedPackets() {
|
||||
|
||||
// Add random headers
|
||||
for (let i = 0; i < headerCount; i++) {
|
||||
const headerName = this.fingerprintMask.headerVariations[
|
||||
Math.floor(Math.random() * this.fingerprintMask.headerVariations.length)
|
||||
];
|
||||
const headerData = crypto.getRandomValues(new Uint8Array(Math.floor(Math.random() * 16) + 4));
|
||||
// Generate unbiased random index for header selection
|
||||
let headerIndex;
|
||||
do {
|
||||
headerIndex = crypto.getRandomValues(new Uint8Array(1))[0];
|
||||
} while (headerIndex >= 256 - (256 % this.fingerprintMask.headerVariations.length));
|
||||
|
||||
const headerName = this.fingerprintMask.headerVariations[headerIndex % this.fingerprintMask.headerVariations.length];
|
||||
|
||||
// Generate unbiased random size for header data (4-19 bytes)
|
||||
let headerSize;
|
||||
do {
|
||||
headerSize = crypto.getRandomValues(new Uint8Array(1))[0];
|
||||
} while (headerSize >= 256 - (256 % 16));
|
||||
|
||||
const headerData = crypto.getRandomValues(new Uint8Array((headerSize % 16) + 4));
|
||||
|
||||
// Header structure: [size:4][name:4][data:variable][checksum:4]
|
||||
const headerView = new DataView(result.buffer, offset);
|
||||
|
||||
Reference in new issue
Block a user