/* * Copyright 2018 Scytl Secure Electronic Voting SA * * All rights reserved * * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package */ /* jshint node:true */ 'use strict'; var Tools = require('./tools'); var validator = require('./input-validator'); var codec = require('scytl-codec'); var forge = require('node-forge'); module.exports = Prng; /** * @class Prng * @classdesc A pseudo-random number generator that generates data, based on a * hash of the entropy that has been collected by various available * sources. This object is created and managed internally by the * secure random service. * @private * @param entropyHash * {Uint8Array} The hash of the collected entropy. */ function Prng(entropyHash) { var tools_ = new Tools(); var key_ = ''; var counter_ = 0; /** * Generates some random bytes, using the gathered entropy data. * * @function nextBytes * @private * @param {number} * numBytes The number of bytes to generate. * @return {Uint8Array} The random bytes. */ this.nextBytes = function(numBytes) { validator.checkIsPositiveNumber( numBytes, 'Number of random bytes to generate'); var keyAux; if (key_ === null || key_ === '') { reseed(); } // Buffer in which to store the random bytes. var b = forge.util.createBuffer(); var limitReach = 1; while (b.length() < numBytes) { b.putBytes(tools_.cipher(key_, counter_)); counter_++; if (b.length >= (limitReach * Math.pow(2, 20))) { keyAux = key_; key_ = ''; for (var i = 0; i < 2; i++) { key_ += tools_.cipher(keyAux, counter_); counter_++; } limitReach++; } } // Do it twice to ensure a key with 256 bits. keyAux = key_; key_ = ''; for (var j = 0; j < 2; j++) { key_ += tools_.cipher(keyAux, counter_); counter_++; } return codec.binaryDecode(b.getBytes(numBytes)); }; function reseed() { var digester = tools_.getReseedDigester(); digester.start(); digester.update(codec.hexEncode(entropyHash)); digester.update(key_); key_ = codec.hexEncode(codec.binaryDecode(digester.digest().getBytes())); counter_++; } }