Slowtime MCP Server
by bmorphism
Verified
import { randomBytes } from 'crypto';
/**
* Time fuzzing utilities to prevent timing attacks and add randomness to intervals
*/
export class TimeFuzz {
// Constants for fuzzing ranges (in milliseconds)
private static readonly MIN_FUZZ = 100; // Minimum fuzz amount
private static readonly MAX_FUZZ = 5000; // Maximum fuzz amount
private static readonly DEFAULT_ENTROPY_BYTES = 4; // Number of bytes to use for entropy
/**
* Generate cryptographically secure random number within a range
*/
private static getSecureRandom(min: number, max: number): number {
// Get 4 bytes of randomness
const rand = randomBytes(this.DEFAULT_ENTROPY_BYTES);
// Convert to 32-bit unsigned integer
const num = rand.readUInt32BE(0);
// Scale to our range
return min + (num % (max - min));
}
/**
* Add random fuzzing to a time duration
* Returns the fuzzed duration in milliseconds
*/
static fuzzDuration(durationMs: number): number {
// Generate random fuzz amount
const fuzzAmount = this.getSecureRandom(this.MIN_FUZZ, this.MAX_FUZZ);
// 50% chance to add or subtract the fuzz
const addFuzz = (randomBytes(1)[0] & 1) === 1;
if (addFuzz) {
return durationMs + fuzzAmount;
} else {
// Don't let duration go below minimum fuzz amount
return Math.max(this.MIN_FUZZ, durationMs - fuzzAmount);
}
}
/**
* Compare two time values in constant time to prevent timing attacks
*/
static timingSafeEqual(a: number, b: number): boolean {
// Convert numbers to buffers for constant-time comparison
const aBuf = Buffer.alloc(8);
const bBuf = Buffer.alloc(8);
aBuf.writeBigInt64BE(BigInt(a));
bBuf.writeBigInt64BE(BigInt(b));
// Use crypto's timing safe comparison
try {
return require('crypto').timingSafeEqual(aBuf, bBuf);
} catch {
// Fallback constant-time comparison if crypto not available
let result = 0;
for (let i = 0; i < aBuf.length; i++) {
result |= aBuf[i] ^ bBuf[i];
}
return result === 0;
}
}
/**
* Generate a random delay between min and max milliseconds
*/
static async randomDelay(minMs: number = this.MIN_FUZZ, maxMs: number = this.MAX_FUZZ): Promise<void> {
const delay = this.getSecureRandom(minMs, maxMs);
return new Promise(resolve => setTimeout(resolve, delay));
}
/**
* Add jitter to a timestamp to prevent timing correlation
*/
static addJitter(timestamp: number): number {
const jitterMs = this.getSecureRandom(-this.MAX_FUZZ, this.MAX_FUZZ);
return timestamp + jitterMs;
}
}