From f29bbe43160cff19918a9b41e491f2def669e6a8 Mon Sep 17 00:00:00 2001 From: Kyle Spearrin Date: Sat, 15 Oct 2016 00:41:03 -0400 Subject: [PATCH] adjust password generator to use cryptographically secure RNG --- .../wwwroot/app/services/passwordService.js | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/Web/wwwroot/app/services/passwordService.js b/src/Web/wwwroot/app/services/passwordService.js index 4a67c3a1e9..54504f809b 100644 --- a/src/Web/wwwroot/app/services/passwordService.js +++ b/src/Web/wwwroot/app/services/passwordService.js @@ -97,8 +97,39 @@ angular return password; }; + // EFForg/OpenWireless + // ref https://github.com/EFForg/OpenWireless/blob/master/app/js/diceware.js function randomInt(min, max) { - return Math.floor(Math.random() * (max - min + 1)) + min; + var rval = 0; + var range = max - min; + + var bits_needed = Math.ceil(Math.log2(range)); + if (bits_needed > 53) { + throw new Exception("We cannot generate numbers larger than 53 bits."); + } + var bytes_needed = Math.ceil(bits_needed / 8); + var mask = Math.pow(2, bits_needed) - 1; + // 7776 -> (2^13 = 8192) -1 == 8191 or 0x00001111 11111111 + + // Create byte array and fill with N random numbers + var byteArray = new Uint8Array(bytes_needed); + window.crypto.getRandomValues(byteArray); + + var p = (bytes_needed - 1) * 8; + for (var i = 0; i < bytes_needed; i++) { + rval += byteArray[i] * Math.pow(2, p); + p -= 8; + } + + // Use & to apply the mask and reduce the number of recursive lookups + rval = rval & mask; + + if (rval >= range) { + // Integer out of acceptable range + return randomInt(min, max); + } + // Return an integer that falls within the range + return min + rval; } return _service;