this.chargingStation.stationInfo.AutomaticTransactionGenerator.minDelayBetweenTwoTransactions) * 1000;
logger.info(this.logPrefix(connectorId) + ' waiting for ' + Utils.milliSecondsToHHMMSS(wait));
await Utils.sleep(wait);
- const start = Math.random();
+ const start = Utils.secureRandom();
if (start < this.chargingStation.stationInfo.AutomaticTransactionGenerator.probabilityOfStart) {
transactionSkip = 0;
// Start transaction
}
public getRandomTagId(): string {
- const index = Math.floor(Math.random() * this.authorizedTags.length);
+ const index = Math.floor(Utils.secureRandom() * this.authorizedTags.length);
return this.authorizedTags[index];
}
const stationInfo: ChargingStationInfo = stationTemplateFromFile ?? {} as ChargingStationInfo;
if (!Utils.isEmptyArray(stationTemplateFromFile.power)) {
stationTemplateFromFile.power = stationTemplateFromFile.power as number[];
- const powerArrayRandomIndex = Math.floor(Math.random() * stationTemplateFromFile.power.length);
+ const powerArrayRandomIndex = Math.floor(Utils.secureRandom() * stationTemplateFromFile.power.length);
stationInfo.maxPower = stationTemplateFromFile.powerUnit === PowerUnits.KILO_WATT
? stationTemplateFromFile.power[powerArrayRandomIndex] * 1000
: stationTemplateFromFile.power[powerArrayRandomIndex];
indexUrl = this.index % supervisionUrls.length;
} else {
// Get a random url
- indexUrl = Math.floor(Math.random() * supervisionUrls.length);
+ indexUrl = Math.floor(Utils.secureRandom() * supervisionUrls.length);
}
return new URL(supervisionUrls[indexUrl]);
}
import Configuration from './Configuration';
import { WebSocketCloseEventStatusString } from '../types/WebSocket';
import { WorkerProcessType } from '../types/Worker';
+import crypto from 'crypto';
import { v4 as uuid } from 'uuid';
export default class Utils {
}
static getRandomFloat(max: number, min = 0): number {
- return Math.random() < 0.5 ? (1 - Math.random()) * (max - min) + min : Math.random() * (max - min) + min;
+ return (crypto.randomBytes(4).readUInt32LE() / 0xffffffff) * (max - min) + min;
}
static getRandomInt(max: number, min = 0): number {
if (min) {
- return Math.floor(Math.random() * (max - min + 1) + min);
+ return Math.floor(Utils.secureRandom() * (max - min + 1)) + min;
}
- return Math.floor(Math.random() * max + 1);
+ return Math.floor(Utils.secureRandom() * (max + 1));
}
static roundTo(numberValue: number, scale: number): number {
*/
static exponentialDelay(retryNumber = 0): number {
const delay = Math.pow(2, retryNumber) * 100;
- const randomSum = delay * 0.2 * Math.random(); // 0-20% of the delay
+ const randomSum = delay * 0.2 * Utils.secureRandom(); // 0-20% of the delay
return delay + randomSum;
}
static workerDynamicPoolInUse(): boolean {
return Configuration.getWorkerProcess() === WorkerProcessType.DYNAMIC_POOL;
}
+
+ /**
+ * Generate a cryptographically secure number in the [0, 1[ range
+ *
+ * @returns
+ */
+ static secureRandom(): number {
+ return crypto.randomBytes(4).readUInt32LE() / 0x100000000;
+ }
}