From c37528f1b44c116d0e714194e881d94951efdef6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Fri, 17 Sep 2021 09:22:15 +0200 Subject: [PATCH] Fix and secure random number generation code MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Jérôme Benoit --- .../AutomaticTransactionGenerator.ts | 2 +- src/charging-station/ChargingStation.ts | 6 +++--- src/utils/Utils.ts | 18 ++++++++++++++---- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/charging-station/AutomaticTransactionGenerator.ts b/src/charging-station/AutomaticTransactionGenerator.ts index 963042a4..756f5b80 100644 --- a/src/charging-station/AutomaticTransactionGenerator.ts +++ b/src/charging-station/AutomaticTransactionGenerator.ts @@ -79,7 +79,7 @@ export default class AutomaticTransactionGenerator { 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 diff --git a/src/charging-station/ChargingStation.ts b/src/charging-station/ChargingStation.ts index fe2b5d8d..575d7096 100644 --- a/src/charging-station/ChargingStation.ts +++ b/src/charging-station/ChargingStation.ts @@ -85,7 +85,7 @@ export default class ChargingStation { } 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]; } @@ -453,7 +453,7 @@ export default class ChargingStation { 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]; @@ -924,7 +924,7 @@ export default class ChargingStation { 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]); } diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts index 73e5e3f9..c94d9397 100644 --- a/src/utils/Utils.ts +++ b/src/utils/Utils.ts @@ -1,6 +1,7 @@ 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 { @@ -98,14 +99,14 @@ 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 { @@ -195,7 +196,7 @@ export default class Utils { */ 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; } @@ -232,4 +233,13 @@ export default class Utils { 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; + } } -- 2.34.1