primitives.securerandom.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  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. cryptolib.modules.primitives = cryptolib.modules.primitives || {};
  9. /**
  10. * @namespace primitives/securerandom
  11. */
  12. cryptolib.modules.primitives.securerandom = function(box) {
  13. 'use strict';
  14. box.primitives = box.primitives || {};
  15. box.primitives.securerandom = {};
  16. /**
  17. * A module that holds secure random functionalities.
  18. *
  19. * @exports primitives/securerandom
  20. */
  21. box.primitives.securerandom.factory = {};
  22. var policies = {
  23. secureRandom: {provider: box.policies.primitives.secureRandom.provider}
  24. };
  25. var converters, exceptions;
  26. cryptolib('commons', function(box) {
  27. converters = new box.commons.utils.Converters();
  28. exceptions = box.commons.exceptions;
  29. });
  30. /**
  31. * A factory class for creating random generators.
  32. *
  33. * @class
  34. */
  35. box.primitives.securerandom.factory.SecureRandomFactory = function() {
  36. };
  37. box.primitives.securerandom.factory.SecureRandomFactory.prototype = {
  38. /**
  39. * Instantiates a random byte generator.
  40. *
  41. * @function
  42. * @returns {primitives/securerandom.CryptoScytlRandomBytes}
  43. */
  44. getCryptoRandomBytes: function() {
  45. try {
  46. if (policies.secureRandom.provider ===
  47. Config.primitives.secureRandom.provider.SCYTL) {
  48. return this.getCryptoScytlRandomBytes();
  49. } else {
  50. throw new exceptions.CryptoLibException(
  51. 'No suitable provider was provided.');
  52. }
  53. } catch (error) {
  54. throw new exceptions.CryptoLibException(
  55. 'A CryptoRandomBytes could not be obtained.', error);
  56. }
  57. },
  58. /**
  59. * Instantiates a Scytl random byte generator.
  60. *
  61. * @function
  62. * @returns {primitives/securerandom.CryptoScytlRandomBytes}
  63. */
  64. getCryptoScytlRandomBytes: function() {
  65. return new CryptoScytlRandomBytes();
  66. },
  67. /**
  68. * Instantiates a random integer generator.
  69. *
  70. * @function
  71. * @returns {primitives/securerandom.CryptoScytlRandomBytes}
  72. */
  73. getCryptoRandomInteger: function() {
  74. try {
  75. if (policies.secureRandom.provider ===
  76. Config.primitives.secureRandom.provider.SCYTL) {
  77. return this.getCryptoScytlRandomInteger();
  78. } else {
  79. throw new exceptions.CryptoLibException(
  80. 'No suitable provider was provided.');
  81. }
  82. } catch (error) {
  83. throw new exceptions.CryptoLibException(
  84. 'A CryptoRandomBytes could not be obtained.', error);
  85. }
  86. },
  87. /**
  88. * Instantiates a Scytl random integer generator.
  89. *
  90. * @function
  91. * @returns {primitives/securerandom.CryptoScytlRandomBytes}
  92. */
  93. getCryptoScytlRandomInteger: function() {
  94. return new CryptoScytlRandomInteger();
  95. }
  96. };
  97. var validate = function(length) {
  98. try {
  99. if (typeof length !== 'number') {
  100. throw new exceptions.CryptoLibException(
  101. 'The given length is not a number');
  102. }
  103. if (length < 1) {
  104. throw new exceptions.CryptoLibException(
  105. 'The given length should be a strictly positive integer.');
  106. }
  107. if (length > box.MAXIMUM_LENGTH_TO_GENERATE_DATA) {
  108. throw new exceptions.CryptoLibException(
  109. 'The given length should be lower than or equal to ' +
  110. box.MAXIMUM_LENGTH_TO_GENERATE_DATA);
  111. }
  112. } catch (error) {
  113. throw new exceptions.CryptoLibException(
  114. 'Random generation failed.', error);
  115. }
  116. };
  117. /**
  118. * The SCYTL Bytes Random Generator
  119. *
  120. * @class
  121. * @memberof primitives/securerandom
  122. */
  123. function CryptoScytlRandomBytes() {}
  124. CryptoScytlRandomBytes.prototype = {
  125. /**
  126. * Generates secure random bytes.
  127. *
  128. * @function
  129. * @param {number}
  130. * numBytes number of bytes to be generated..
  131. * @returns {string} secure random string.
  132. */
  133. nextRandom: function(length) {
  134. validate(length);
  135. var randomBytes = box.prng.generate(length);
  136. return randomBytes.toString();
  137. },
  138. /**
  139. * Method to be compliant with the Forge library.
  140. *
  141. * @function
  142. * @param {number}
  143. * numBytes number of bytes to be generated..
  144. * @returns {string} secure random string.
  145. */
  146. getBytesSync: function(length) {
  147. return this.nextRandom(length);
  148. }
  149. };
  150. /**
  151. * The SCYTL Integer Random Generator
  152. *
  153. * @class
  154. * @memberof primitives/securerandom
  155. */
  156. function CryptoScytlRandomInteger() {}
  157. CryptoScytlRandomInteger.prototype = {
  158. /**
  159. * Generates a secure random big integer (Forge).
  160. *
  161. * @function
  162. * @params {number} length the bit length of the random integer.
  163. * @returns {object} secure random big integer.
  164. */
  165. nextRandom: function(length) {
  166. validate(length);
  167. var n = ((new box.forge.jsbn.BigInteger('10')).pow(length))
  168. .subtract(box.forge.jsbn.BigInteger.ONE);
  169. var bitLength = n.bitLength();
  170. var numberOfBytes = bitLength / box.NUMBER_OF_BITS_PER_BYTE;
  171. numberOfBytes = Math.floor(numberOfBytes);
  172. var modBytes = bitLength % box.NUMBER_OF_BITS_PER_BYTE;
  173. if (modBytes !== 0) {
  174. numberOfBytes++;
  175. }
  176. var generatedInteger;
  177. do {
  178. var randomBytes = box.prng.generate(numberOfBytes);
  179. randomBytes = '\x00' + randomBytes;
  180. randomBytes = converters.bytesFromString(randomBytes);
  181. generatedInteger = new box.forge.jsbn.BigInteger(randomBytes);
  182. } while ((generatedInteger.compareTo(forge.jsbn.BigInteger.ZERO) <= 0) ||
  183. (generatedInteger.compareTo(n) > 0));
  184. return generatedInteger;
  185. },
  186. /**
  187. * Generates a secure random big integer according to the specified bit
  188. * length.
  189. *
  190. * @function
  191. * @params {number} bitsLength the bit length of the random integer.
  192. * @returns {object} Secure random big integer.
  193. */
  194. nextRandomByBits: function(bitsLength) {
  195. var byteLength = Math.ceil(bitsLength / box.NUMBER_OF_BITS_PER_BYTE);
  196. var modBytes = box.NUMBER_OF_BITS_PER_BYTE -
  197. (bitsLength % box.NUMBER_OF_BITS_PER_BYTE);
  198. var randomBytes = box.prng.generate(byteLength);
  199. randomBytes = '\x00' + randomBytes;
  200. randomBytes = converters.bytesFromString(randomBytes);
  201. var generatedInteger = new box.forge.jsbn.BigInteger(randomBytes);
  202. generatedInteger = generatedInteger.shiftRight(modBytes);
  203. return generatedInteger;
  204. }
  205. };
  206. };