service.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /*
  2. * Copyright 2018 Scytl Secure Electronic Voting SA
  3. *
  4. * All rights reserved
  5. *
  6. * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
  7. */
  8. /* jshint node:true */
  9. 'use strict';
  10. var SecureRandomGenerator = require('./generator');
  11. var PrivateKeyCollector = require('./entropy/collectors/privatekey');
  12. var EntropyManager = require('./entropy/manager');
  13. var Prng = require('./prng');
  14. var constants = require('./constants');
  15. module.exports = SecureRandomService;
  16. /**
  17. * @class SecureRandomService
  18. * @classdesc The secure random service API. To instantiate this object, use the
  19. * method {@link newService}.
  20. * @hideconstructor
  21. * @param {Object}
  22. * [options] An object containing optional arguments.
  23. * @param {Uint8Array}
  24. * [options.prngSeed=Internally generated] The seed to initialize the
  25. * PRNG.
  26. * @param {number}
  27. * [options.maxEntropyCounter=256] The amount of entropy to
  28. * accumulate before stopping collectors. It must be a positive
  29. * number.
  30. * @param {number}
  31. * [options.hashUpdaterInterval=1000] The interval (in milliseconds)
  32. * at which entropy data is to be hashed. It must be a positive
  33. * number.
  34. * @param {Object}
  35. * [options.windowObject=Built-in window object] The
  36. * <code>window</code> object provided to the collectors.
  37. * @param {Object}
  38. * [options.cryptoApi=Built-in cryptographic library] The
  39. * cryptographic library supplied to the WebKit collector (if the
  40. * latter is being used).
  41. * @param {Object}
  42. * [options.privateKeyData=Not used] The private key collector data.
  43. * @param {string}
  44. * options.privateKeyData.privateKey The private key, in PEM format.
  45. * @param {number}
  46. * options.privateKeyData.pinEntropy The PIN entropy of the private
  47. * key. It must be a positive number.
  48. * @param {boolean}
  49. * [options.noDefaultCollectors=false] If <code>true</code>, no
  50. * default entropy collectors are to be used.
  51. */
  52. function SecureRandomService(options) {
  53. ////////////////////////////////// PRIVATE //////////////////////////////////
  54. var prng_;
  55. var entropyManager_;
  56. function init(options) {
  57. options = options || {};
  58. if (options.prngSeed) {
  59. prng_ = new Prng(options.prngSeed);
  60. }
  61. entropyManager_ = new EntropyManager(options);
  62. if (options.privateKeyData) {
  63. var privateKey = options.privateKeyData.privateKey;
  64. var pinEntropy = options.privateKeyData.pinEntropy;
  65. entropyManager_.addCollector(new PrivateKeyCollector(
  66. entropyManager_.collectEntropy, privateKey, pinEntropy));
  67. }
  68. entropyManager_.startCollectors();
  69. entropyManager_.stopCollectors();
  70. }
  71. function getPrng() {
  72. if (!prng_) {
  73. prng_ = new Prng(entropyManager_.getEntropyHash());
  74. }
  75. return prng_;
  76. }
  77. /////////////////////////////////// PUBLIC ///////////////////////////////////
  78. /**
  79. * Creates a new SecureRandomGenerator object, that uses the PRNG of this
  80. * service. This object can be used for all supported types of random
  81. * generation.
  82. *
  83. * @function newRandomGenerator
  84. * @memberof SecureRandomService
  85. * @param {Object}
  86. * [options] An object containing optional arguments.
  87. * @param {number}
  88. * [options.maxNumBytes=512] The maximum number of bytes that can
  89. * randomly generated per method call.
  90. * @param {number}
  91. * [options.maxNumDigits=512] The maximum number of BigInteger
  92. * digits that can randomly generated per method call.
  93. * @returns {SecureRandomGenerator} The new SecureRandomGenerator object.
  94. */
  95. this.newRandomGenerator = function(options) {
  96. return new SecureRandomGenerator(getPrng(), options);
  97. };
  98. /**
  99. * Generates a random seed that can be used to initialize the PRNG of a new
  100. * SecureRandomService object.
  101. *
  102. * @function nextSeed
  103. * @memberof SecureRandomService
  104. * @param {number}
  105. * [numBytes=32] The number of bytes in the seed.
  106. * @returns {Uint8Array} The random seed.
  107. */
  108. this.nextSeed = function(numBytes) {
  109. numBytes = numBytes || constants.SECURE_RANDOM_DEFAULT_NUM_SEED_BYTES;
  110. return getPrng().nextBytes(numBytes);
  111. };
  112. /**
  113. * Manually starts the entropy collection. This method has no effect if
  114. * entropy is already being collected.
  115. *
  116. * @function startEntropyCollection
  117. * @memberof SecureRandomService
  118. * @param {Function}
  119. * [callback=No callback] A callback function that will be
  120. * executed if the maximum amount of entropy required is
  121. * collected.
  122. */
  123. this.startEntropyCollection = function(callback) {
  124. entropyManager_.startCollectors(callback);
  125. };
  126. /**
  127. * Manually stops the entropy collection and resets the PRNG with the
  128. * collected entropy.
  129. *
  130. * @function stopEntropyCollection
  131. * @memberof SecureRandomService
  132. * @returns {boolean} <code>true</code> if the maximum amount of entropy
  133. * required has been collected, <code>false</code> otherwise.
  134. */
  135. this.stopEntropyCollection = function() {
  136. var maxEntropyCollected = entropyManager_.stopCollectors();
  137. prng_ = new Prng(entropyManager_.getEntropyHash());
  138. return maxEntropyCollected;
  139. };
  140. /**
  141. * Retrieves the amount of entropy collected, as a percentage of the maximum
  142. * amount of entropy required.
  143. *
  144. * @function getEntropyPercentage
  145. * @memberof SecureRandomService
  146. * @returns {number} The percentage of entropy collected.
  147. */
  148. this.getEntropyPercentage = function() {
  149. return entropyManager_.getEntropyPercentage();
  150. };
  151. //////////////////////////////// CONSTRUCTOR ////////////////////////////////
  152. // Initialize the object.
  153. init(options);
  154. }