Skip to content

Commit 49e5a05

Browse files
committed
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
1 parent 9d03724 commit 49e5a05

File tree

4 files changed

+173
-63
lines changed

4 files changed

+173
-63
lines changed

dist/app-boot.js

Lines changed: 75 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -903,12 +903,15 @@ var EnhancedSecureCryptoUtils = class _EnhancedSecureCryptoUtils {
903903
// Generate secure password for data exchange
904904
static generateSecurePassword() {
905905
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+-=[]{}|;:,.<>?";
906+
const charCount = chars.length;
906907
const length = 32;
907-
const randomValues = new Uint32Array(length);
908-
crypto.getRandomValues(randomValues);
909908
let password = "";
910909
for (let i = 0; i < length; i++) {
911-
password += chars[randomValues[i] % chars.length];
910+
let randomValue;
911+
do {
912+
randomValue = crypto.getRandomValues(new Uint32Array(1))[0];
913+
} while (randomValue >= 4294967296 - 4294967296 % charCount);
914+
password += chars[randomValue % charCount];
912915
}
913916
return password;
914917
}
@@ -2591,10 +2594,14 @@ var EnhancedSecureCryptoUtils = class _EnhancedSecureCryptoUtils {
25912594
// Generate verification code for out-of-band authentication
25922595
static generateVerificationCode() {
25932596
const chars = "0123456789ABCDEF";
2597+
const charCount = chars.length;
25942598
let result = "";
2595-
const values = crypto.getRandomValues(new Uint8Array(6));
25962599
for (let i = 0; i < 6; i++) {
2597-
result += chars[values[i] % chars.length];
2600+
let randomByte;
2601+
do {
2602+
randomByte = crypto.getRandomValues(new Uint8Array(1))[0];
2603+
} while (randomByte >= 256 - 256 % charCount);
2604+
result += chars[randomByte % charCount];
25982605
}
25992606
return result.match(/.{1,2}/g).join("-");
26002607
}
@@ -4875,12 +4882,13 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager {
48754882
preserveMessageSize: this._config.packetPadding.preserveMessageSize
48764883
};
48774884
this.fakeTrafficConfig = {
4878-
enabled: this._config.fakeTraffic.enabled,
4879-
minInterval: this._config.fakeTraffic.minInterval,
4880-
maxInterval: this._config.fakeTraffic.maxInterval,
4881-
minSize: this._config.fakeTraffic.minSize,
4882-
maxSize: this._config.fakeTraffic.maxSize,
4883-
patterns: this._config.fakeTraffic.patterns
4885+
enabled: this._config.fakeTraffic?.enabled || false,
4886+
minInterval: this._config.fakeTraffic?.minInterval || 15e3,
4887+
maxInterval: this._config.fakeTraffic?.maxInterval || 3e4,
4888+
minSize: this._config.fakeTraffic?.minSize || 64,
4889+
maxSize: this._config.fakeTraffic?.maxSize || 1024,
4890+
patterns: this._config.fakeTraffic?.patterns || ["heartbeat", "status", "ping"],
4891+
randomDecoyIntervals: this._config.fakeTraffic?.randomDecoyIntervals || true
48844892
};
48854893
this.fakeTrafficTimer = null;
48864894
this.lastFakeTraffic = 0;
@@ -7447,7 +7455,11 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager {
74477455
);
74487456
const dv = new DataView(bits);
74497457
const n = (dv.getUint32(0) ^ dv.getUint32(4)) >>> 0;
7450-
const sasCode = String(n % 1e7).padStart(7, "0");
7458+
let sasValue;
7459+
do {
7460+
sasValue = crypto.getRandomValues(new Uint32Array(1))[0];
7461+
} while (sasValue >= 4294967296 - 4294967296 % 1e7);
7462+
const sasCode = String(sasValue % 1e7).padStart(7, "0");
74517463
this._secureLog("info", "SAS code computed successfully", {
74527464
localFP: localFP.substring(0, 16) + "...",
74537465
remoteFP: remoteFP.substring(0, 16) + "...",
@@ -8121,13 +8133,36 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager {
81218133
this._secureLog("error", "\u274C Failed to initialize enhanced security", { errorType: error.constructor.name });
81228134
}
81238135
}
8136+
// Helper function to generate unbiased random values in a range
8137+
getUnbiasedRandomInRange(min, max) {
8138+
const range = max - min + 1;
8139+
if (range > 256) {
8140+
const bytesNeeded = Math.ceil(Math.log2(range) / 8);
8141+
const maxValue = Math.pow(256, bytesNeeded);
8142+
const threshold = maxValue - maxValue % range;
8143+
let randomValue2;
8144+
do {
8145+
const randomBytes = crypto.getRandomValues(new Uint8Array(bytesNeeded));
8146+
randomValue2 = 0;
8147+
for (let i = 0; i < bytesNeeded; i++) {
8148+
randomValue2 = (randomValue2 << 8) + randomBytes[i];
8149+
}
8150+
} while (randomValue2 >= threshold);
8151+
return randomValue2 % range + min;
8152+
}
8153+
let randomValue;
8154+
do {
8155+
randomValue = crypto.getRandomValues(new Uint8Array(1))[0];
8156+
} while (randomValue >= 256 - 256 % range);
8157+
return randomValue % range + min;
8158+
}
81248159
// Generate fingerprint mask for anti-fingerprinting with enhanced randomization
81258160
generateFingerprintMask() {
81268161
const cryptoRandom = crypto.getRandomValues(new Uint8Array(128));
81278162
const mask = {
8128-
timingOffset: cryptoRandom[0] % 1e3 + cryptoRandom[1] % 500,
8163+
timingOffset: this.getUnbiasedRandomInRange(0, 1500),
81298164
// 0-1500ms
8130-
sizeVariation: (cryptoRandom[2] % 50 + 75) / 100,
8165+
sizeVariation: this.getUnbiasedRandomInRange(75, 125) / 100,
81318166
// 0.75 to 1.25
81328167
noisePattern: Array.from(crypto.getRandomValues(new Uint8Array(64))),
81338168
// Increased size
@@ -8144,11 +8179,11 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager {
81448179
"X-Anonymous",
81458180
"X-Private"
81468181
],
8147-
noiseIntensity: cryptoRandom[3] % 100 + 50,
8182+
noiseIntensity: this.getUnbiasedRandomInRange(50, 150),
81488183
// 50-150%
8149-
sizeMultiplier: (cryptoRandom[4] % 50 + 75) / 100,
8184+
sizeMultiplier: this.getUnbiasedRandomInRange(75, 125) / 100,
81508185
// 0.75-1.25
8151-
timingVariation: cryptoRandom[5] % 1e3 + 100
8186+
timingVariation: this.getUnbiasedRandomInRange(100, 1100)
81528187
// 100-1100ms
81538188
};
81548189
return mask;
@@ -8478,7 +8513,10 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager {
84788513
try {
84798514
const fakeMessage = this.generateFakeMessage();
84808515
await this.sendFakeMessage(fakeMessage);
8481-
const nextInterval = this.fakeTrafficConfig.randomDecoyIntervals ? Math.random() * (this.fakeTrafficConfig.maxInterval - this.fakeTrafficConfig.minInterval) + this.fakeTrafficConfig.minInterval : this.fakeTrafficConfig.minInterval;
8516+
const nextInterval = this.fakeTrafficConfig.randomDecoyIntervals ? this.getUnbiasedRandomInRange(this.fakeTrafficConfig.minInterval, Math.min(this.fakeTrafficConfig.maxInterval, 6e4)) : (
8517+
// Cap at 60 seconds
8518+
this.fakeTrafficConfig.minInterval
8519+
);
84828520
const safeInterval = Math.max(nextInterval, _EnhancedSecureWebRTCManager.TIMEOUTS.FAKE_TRAFFIC_MIN_INTERVAL);
84838521
this.fakeTrafficTimer = setTimeout(sendFakeMessage, safeInterval);
84848522
} catch (error) {
@@ -8488,7 +8526,9 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager {
84888526
this.stopFakeTrafficGeneration();
84898527
}
84908528
};
8491-
const initialDelay = Math.random() * this.fakeTrafficConfig.maxInterval + _EnhancedSecureWebRTCManager.TIMEOUTS.DECOY_INITIAL_DELAY;
8529+
const minDelay = _EnhancedSecureWebRTCManager.TIMEOUTS.DECOY_INITIAL_DELAY;
8530+
const maxDelay = Math.min(this.fakeTrafficConfig.maxInterval, 3e4);
8531+
const initialDelay = this.getUnbiasedRandomInRange(minDelay, maxDelay);
84928532
this.fakeTrafficTimer = setTimeout(sendFakeMessage, initialDelay);
84938533
}
84948534
stopFakeTrafficGeneration() {
@@ -8498,8 +8538,9 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager {
84988538
}
84998539
}
85008540
generateFakeMessage() {
8501-
const pattern = this.fakeTrafficConfig.patterns[Math.floor(Math.random() * this.fakeTrafficConfig.patterns.length)];
8502-
const size = Math.floor(Math.random() * (this.fakeTrafficConfig.maxSize - this.fakeTrafficConfig.minSize + 1)) + this.fakeTrafficConfig.minSize;
8541+
const patternIndex = this.getUnbiasedRandomInRange(0, this.fakeTrafficConfig.patterns.length - 1);
8542+
const pattern = this.fakeTrafficConfig.patterns[patternIndex];
8543+
const size = this.getUnbiasedRandomInRange(this.fakeTrafficConfig.minSize, this.fakeTrafficConfig.maxSize);
85038544
const fakeData = crypto.getRandomValues(new Uint8Array(size));
85048545
return {
85058546
type: _EnhancedSecureWebRTCManager.MESSAGE_TYPES.FAKE,
@@ -8961,7 +9002,7 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager {
89619002
}
89629003
addNoise(data) {
89639004
const dataArray = new Uint8Array(data);
8964-
const noiseSize = Math.floor(Math.random() * 32) + 8;
9005+
const noiseSize = this.getUnbiasedRandomInRange(8, 40);
89659006
const noise = crypto.getRandomValues(new Uint8Array(noiseSize));
89669007
const result = new Uint8Array(dataArray.length + noiseSize);
89679008
result.set(dataArray, 0);
@@ -8994,16 +9035,24 @@ var EnhancedSecureWebRTCManager = class _EnhancedSecureWebRTCManager {
89949035
}
89959036
addRandomHeaders(data) {
89969037
const dataArray = new Uint8Array(data);
8997-
const headerCount = Math.floor(Math.random() * 3) + 1;
9038+
const headerCount = this.getUnbiasedRandomInRange(1, 3);
89989039
let totalHeaderSize = 0;
89999040
for (let i = 0; i < headerCount; i++) {
9000-
totalHeaderSize += 4 + Math.floor(Math.random() * 16) + 4;
9041+
totalHeaderSize += 4 + this.getUnbiasedRandomInRange(0, 15) + 4;
90019042
}
90029043
const result = new Uint8Array(totalHeaderSize + dataArray.length);
90039044
let offset = 0;
90049045
for (let i = 0; i < headerCount; i++) {
9005-
const headerName = this.fingerprintMask.headerVariations[Math.floor(Math.random() * this.fingerprintMask.headerVariations.length)];
9006-
const headerData = crypto.getRandomValues(new Uint8Array(Math.floor(Math.random() * 16) + 4));
9046+
let headerIndex;
9047+
do {
9048+
headerIndex = crypto.getRandomValues(new Uint8Array(1))[0];
9049+
} while (headerIndex >= 256 - 256 % this.fingerprintMask.headerVariations.length);
9050+
const headerName = this.fingerprintMask.headerVariations[headerIndex % this.fingerprintMask.headerVariations.length];
9051+
let headerSize;
9052+
do {
9053+
headerSize = crypto.getRandomValues(new Uint8Array(1))[0];
9054+
} while (headerSize >= 256 - 256 % 16);
9055+
const headerData = crypto.getRandomValues(new Uint8Array(headerSize % 16 + 4));
90079056
const headerView = new DataView(result.buffer, offset);
90089057
headerView.setUint32(0, headerData.length + 8, false);
90099058
headerView.setUint32(4, this.hashString(headerName), false);

dist/app-boot.js.map

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/crypto/EnhancedSecureCryptoUtils.js

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -224,13 +224,18 @@ class EnhancedSecureCryptoUtils {
224224
// Generate secure password for data exchange
225225
static generateSecurePassword() {
226226
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()_+-=[]{}|;:,.<>?';
227+
const charCount = chars.length;
227228
const length = 32;
228-
const randomValues = new Uint32Array(length);
229-
crypto.getRandomValues(randomValues);
230-
231229
let password = '';
230+
231+
// Use rejection sampling to avoid bias
232232
for (let i = 0; i < length; i++) {
233-
password += chars[randomValues[i] % chars.length];
233+
let randomValue;
234+
do {
235+
randomValue = crypto.getRandomValues(new Uint32Array(1))[0];
236+
} while (randomValue >= 4294967296 - (4294967296 % charCount)); // Reject biased values
237+
238+
password += chars[randomValue % charCount];
234239
}
235240
return password;
236241
}
@@ -2322,11 +2327,19 @@ class EnhancedSecureCryptoUtils {
23222327
// Generate verification code for out-of-band authentication
23232328
static generateVerificationCode() {
23242329
const chars = '0123456789ABCDEF';
2330+
const charCount = chars.length;
23252331
let result = '';
2326-
const values = crypto.getRandomValues(new Uint8Array(6));
2332+
2333+
// Use rejection sampling to avoid bias
23272334
for (let i = 0; i < 6; i++) {
2328-
result += chars[values[i] % chars.length];
2335+
let randomByte;
2336+
do {
2337+
randomByte = crypto.getRandomValues(new Uint8Array(1))[0];
2338+
} while (randomByte >= 256 - (256 % charCount)); // Reject biased values
2339+
2340+
result += chars[randomByte % charCount];
23292341
}
2342+
23302343
return result.match(/.{1,2}/g).join('-');
23312344
}
23322345

0 commit comments

Comments
 (0)