service.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  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 ZpSubgroup = require('./zp-subgroup');
  11. var ZpGroupElement = require('./zp-group-element');
  12. var Exponent = require('./exponent');
  13. var MathematicalArrayCompressor = require('./array-compressor');
  14. var MathematicalRandomGenerator = require('./random-generator');
  15. var MathematicalGroupHandler = require('./group-handler');
  16. var secureRandom = require('scytl-securerandom');
  17. var validator = require('./input-validator');
  18. var codec = require('scytl-codec');
  19. var forge = require('node-forge');
  20. var BigInteger = forge.jsbn.BigInteger;
  21. module.exports = MathematicalService;
  22. /**
  23. * @class MathematicalService
  24. * @classdesc The mathematical service API. To instantiate this object, use the
  25. * method {@link newService}.
  26. * @hideconstructor
  27. * @param {Object}
  28. * [options] An object containing optional arguments.
  29. * @param {SecureRandomService}
  30. * [options.secureRandomService=Created internally] The secure random
  31. * service to use.
  32. */
  33. function MathematicalService(options) {
  34. options = options || {};
  35. var secureRandomService;
  36. if (options.secureRandomService) {
  37. secureRandomService = options.secureRandomService;
  38. } else {
  39. secureRandomService = secureRandom.newService();
  40. }
  41. /**
  42. * Creates a new MathematicalRandomGenerator object for generating random
  43. * mathematical objects.
  44. *
  45. * @function newRandomGenerator
  46. * @memberof MathematicalService
  47. * @returns {MathematicalRandomGenerator} The new
  48. * MathematicalRandomGenerator object.
  49. */
  50. this.newRandomGenerator = function() {
  51. return new MathematicalRandomGenerator(secureRandomService);
  52. };
  53. }
  54. MathematicalService.prototype = {
  55. /**
  56. * Creates a new ZpSubgroup object, which encapsulates a Zp subgroup.
  57. *
  58. * @function newZpSubgroup
  59. * @memberof MathematicalService
  60. * @param {forge.jsbn.BigInteger|string}
  61. * pOrJson The modulus of the Zp subgroup <b>OR</b> a JSON
  62. * string representation of a ZpSubgroup object, compatible with
  63. * its <code>toJson</code> method. For the latter case, any
  64. * additional input arguments will be ignored.
  65. * @param {forge.jsbn.BigInteger}
  66. * q The order of the Zp subgroup. It must be within the range
  67. * <code>[1, p-1]</code>.
  68. * @param {forge.jsbn.BigInteger}
  69. * g The generator of the Zp subgroup. It must be within the
  70. * range <code>[2, p-1]</code>.
  71. * @returns {ZpSubgroup} The new ZpSubgroup object.
  72. * @throws {Error}
  73. * If the input data validation fails.
  74. */
  75. newZpSubgroup: function(pOrJson, q, g) {
  76. if (typeof pOrJson !== 'string') {
  77. validator.checkZpSubgroupModulus(
  78. pOrJson, 'Modulus p to create new ZpSubgroup object');
  79. validator.checkZpSubgroupOrder(
  80. q, 'Order q to create new ZpSubgroup object', pOrJson);
  81. validator.checkZpSubgroupGenerator(
  82. g, 'Generator to create new ZpSubgroup object', pOrJson);
  83. return new ZpSubgroup(pOrJson, q, g);
  84. } else {
  85. return jsonToZpSubgroup(pOrJson);
  86. }
  87. },
  88. /**
  89. * Creates a new ZpGroupElement object, which encapsulates a Zp group
  90. * element.
  91. *
  92. * @function newZpGroupElement
  93. * @memberof MathematicalService
  94. * @param {forge.jsbn.BigInteger|string}
  95. * pOrJson The modulus of the Zp subgroup to which the Zp group
  96. * element belongs <b>OR</b> a JSON string representation of a
  97. * ZpGroupElement object, compatible with its <code>toJson</code>
  98. * method. For the latter case, any additional input arguments
  99. * will be ignored.
  100. * @param {forge.jsbn.BigInteger}
  101. * q The order of the Zp subgroup to which the Zp group element
  102. * belongs. It must be within the range <code>[1, p-1]</code>.
  103. * @param {forge.jsbn.BigInteger}
  104. * value The value of the Zp group element. It must be within the
  105. * range <code>[1, p-1]</code>.
  106. * @returns {ZpGroupElement} The new ZpGroupElement object.
  107. * @throws {Error}
  108. * If the input data validation fails.
  109. */
  110. newZpGroupElement: function(pOrJson, q, value) {
  111. if (typeof pOrJson !== 'string') {
  112. validator.checkZpSubgroupModulus(
  113. pOrJson, 'Modulus p to create new ZpGroupElement object');
  114. validator.checkZpSubgroupOrder(
  115. q, 'Order q to create new ZpGroupElement object', pOrJson);
  116. validator.checkZpGroupElementValue(
  117. value, 'Value to create new ZpGroupElement object', pOrJson);
  118. return new ZpGroupElement(pOrJson, q, value);
  119. } else {
  120. return jsonToZpGroupElement(pOrJson);
  121. }
  122. },
  123. /**
  124. * Creates a new Exponent object, which encapsulates an exponent.
  125. *
  126. * @function newExponent
  127. * @memberof MathematicalService
  128. * @param {forge.jsbn.BigInteger|string}
  129. * qOrJson The order of the Zp subgroup to which the exponent is
  130. * associated <b>OR</b> a JSON string representation of an
  131. * Exponent object, compatible with its <code>toJson</code>
  132. * method. For the latter case, any additional input arguments
  133. * will be ignored.
  134. * @param {forge.jsbn.BigInteger}
  135. * value The value of the exponent. If this value is greater than
  136. * or equal to <code>q</code> it will be adjusted to be less
  137. * then <code>q</code>, via the <code>mod(q)</code>
  138. * operation.
  139. * @returns {Exponent} The new Exponent object.
  140. * @throws {Error}
  141. * If the input data validation fails.
  142. */
  143. newExponent: function(qOrJson, value) {
  144. if (typeof qOrJson !== 'string') {
  145. validator.checkZpSubgroupOrder(
  146. qOrJson, 'Order q to create new Exponent object');
  147. validator.checkExponentValue(
  148. value, 'Value to create new Exponent object');
  149. return new Exponent(qOrJson, value);
  150. } else {
  151. return jsonToExponent(qOrJson);
  152. }
  153. },
  154. /**
  155. * Creates a new quadratic residue Zp subgroup from the modulus
  156. * <code>p</code> and <code>generator</code> provided as input.
  157. * <p>
  158. * <b>NOTE</b>: This method creates a particular type of Zp subgroup, with
  159. * the following property:
  160. * <p>
  161. * <code>p = 2q + 1</code>
  162. *
  163. * @function newQuadraticResidueGroup
  164. * @memberof MathematicalService
  165. * @param {forge.jsbn.BigInteger}
  166. * p The modulus of the quadratic residue group.
  167. * @param {forge.jsbn.BigInteger}
  168. * g The generator of the quadratic residue group.
  169. * @returns {ZpSubgroup} The quadratic residue group.
  170. * @throws {Error}
  171. * If the input validation fails.
  172. */
  173. newQuadraticResidueGroup: function(p, g) {
  174. validator.checkZpSubgroupModulus(
  175. p, 'Modulus p for quadratic residue group generation');
  176. validator.checkZpSubgroupGenerator(
  177. g, 'Generator for quadratic residue group generation', p);
  178. var q = p.subtract(BigInteger.ONE).divide(new BigInteger('2'));
  179. return new ZpSubgroup(p, q, g);
  180. },
  181. /**
  182. * Creates a new MathematicalArrayCompressor object for reducing the size of
  183. * arrays containing mathematical objects.
  184. *
  185. * @function newArrayCompressor
  186. * @memberof MathematicalService
  187. * @returns {MathematicalArrayCompressor} The new
  188. * MathematicalArrayCompressor object.
  189. */
  190. newArrayCompressor: function() {
  191. return new MathematicalArrayCompressor();
  192. },
  193. /**
  194. * Creates a new MathematicalGroupHandler object for performing operations
  195. * involving mathematical groups.
  196. *
  197. * @function newGroupHandler
  198. * @memberof MathematicalService
  199. * @returns {MathematicalGroupHandler} The new MathematicalGroupHandler
  200. * object.
  201. */
  202. newGroupHandler: function() {
  203. return new MathematicalGroupHandler();
  204. }
  205. };
  206. function jsonToZpSubgroup(json) {
  207. validator.checkIsJsonString(
  208. json, 'JSON string representation of ZpSubgroup object');
  209. var parsed = JSON.parse(json);
  210. var p = codec.bytesToBigInteger(codec.base64Decode(parsed.zpSubgroup.p));
  211. var q = codec.bytesToBigInteger(codec.base64Decode(parsed.zpSubgroup.q));
  212. var g = codec.bytesToBigInteger(codec.base64Decode(parsed.zpSubgroup.g));
  213. return new ZpSubgroup(p, q, g);
  214. }
  215. function jsonToZpGroupElement(json) {
  216. validator.checkIsJsonString(
  217. json, 'JSON string representation of ZpGroupElement object');
  218. var parsed = JSON.parse(json);
  219. var p = codec.bytesToBigInteger(codec.base64Decode(parsed.zpGroupElement.p));
  220. var q = codec.bytesToBigInteger(codec.base64Decode(parsed.zpGroupElement.q));
  221. var value =
  222. codec.bytesToBigInteger(codec.base64Decode(parsed.zpGroupElement.value));
  223. return new ZpGroupElement(p, q, value);
  224. }
  225. function jsonToExponent(json) {
  226. validator.checkIsJsonString(
  227. json, 'JSON string representation of Exponent object');
  228. var parsed = JSON.parse(json);
  229. var q = codec.bytesToBigInteger(codec.base64Decode(parsed.exponent.q));
  230. var value =
  231. codec.bytesToBigInteger(codec.base64Decode(parsed.exponent.value));
  232. return new Exponent(q, value);
  233. }