commons.mathematical.js 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376
  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.commons = cryptolib.modules.commons || {};
  9. /**
  10. * @namespace commons/mathematical
  11. */
  12. cryptolib.modules.commons.mathematical = function(box) {
  13. 'use strict';
  14. box.commons = box.commons || {};
  15. /**
  16. * A module the defines mathematical groups, elements, and operations that
  17. * can be performed
  18. *
  19. * @exports commons/mathematical
  20. */
  21. box.commons.mathematical = {};
  22. var BigInteger = box.forge.jsbn.BigInteger;
  23. var exceptions;
  24. var converters;
  25. cryptolib('commons.exceptions', 'commons.utils', function(box) {
  26. exceptions = box.commons.exceptions;
  27. converters = new box.commons.utils.Converters();
  28. });
  29. /**
  30. * Given p and Zp representing 'Integers (mod p)' group, a Zp subgroup is a
  31. * group where the elements are a subset of elements from Zp.
  32. *
  33. * The order of the subgroup is q, that is the number of elements. Both Zp
  34. * and the ZpSubgroup are finite cyclic groups, it means that all elements
  35. * can be generated exponentiating a special group element called generator.
  36. *
  37. * When the p and q are related with the restriction p = 2q + 1 the subgroup
  38. * is also defined as 'Quadratic Residue'.
  39. *
  40. * @class
  41. * @param valueG
  42. * {forge.jsbn.BigInteger} The generator of the subgroup, as a
  43. * BigInteger. This value must be a group element different from
  44. * one.
  45. * @param valueP
  46. * {forge.jsbn.BigInteger} The modulus, as a BigInteger.
  47. * @param valueQ
  48. * {forge.jsbn.BigInteger} The order of the subgroup, as a
  49. * BigInteger.
  50. *
  51. * @throws CryptoLibException
  52. * if 0 < q < p restriction is not accomplished
  53. * @throws CryptoLibException
  54. * if subgroup generator is nor between 2 and p-1
  55. *
  56. */
  57. box.commons.mathematical.ZpSubgroup = function(valueG, valueP, valueQ) {
  58. if ((typeof valueG === 'undefined') || (typeof valueP === 'undefined') ||
  59. (typeof valueQ === 'undefined')) {
  60. throw new exceptions.CryptoLibException(
  61. 'The given parameters should be initialized');
  62. }
  63. if ((BigInteger.ONE.compareTo(valueG) >= 0) ||
  64. (valueP.compareTo(valueG) <= 0)) {
  65. throw new exceptions.CryptoLibException(
  66. 'The generator should be between 2 and p-1');
  67. }
  68. if ((BigInteger.ZERO.compareTo(valueQ) >= 0) ||
  69. (valueP.compareTo(valueQ) <= 0)) {
  70. throw new exceptions.CryptoLibException(
  71. 'The relationship between the values of the p and q parameters should be such that 0 < q < p');
  72. }
  73. var _p = valueP;
  74. var _q = valueQ;
  75. var generator = new box.commons.mathematical.ZpGroupElement(valueG, _p, _q);
  76. var identity =
  77. new box.commons.mathematical.ZpGroupElement(BigInteger.ONE, _p, _q);
  78. /**
  79. * @function
  80. * @returns the identity element of the group.
  81. */
  82. this.getIdentity = function() {
  83. return identity;
  84. };
  85. /**
  86. * @function
  87. * @returns the q parameter (the order of the group).
  88. */
  89. this.getQ = function() {
  90. return _q;
  91. };
  92. /**
  93. * @function
  94. * @returns the p parameter (the modulus of the group).
  95. */
  96. this.getP = function() {
  97. return _p;
  98. };
  99. /**
  100. * @function
  101. * @returns {box.commons.mathematical.ZpGroupElement} the generator
  102. * element of the group.
  103. */
  104. this.getGenerator = function() {
  105. return generator;
  106. };
  107. };
  108. box.commons.mathematical.ZpSubgroup.prototype = {
  109. /**
  110. * Checks whether a given element is a member of this MathematicalGroup.
  111. *
  112. * An element is a member of the group if:
  113. * <ul>
  114. * <li><code>element</code> has an integer value between
  115. * <code>1</code> and <code>p-1</code>:
  116. * <code>(0 < element < p)</code></li>
  117. * <li><code>element<sup>q</sup> mod p = 1</code></li>
  118. * </ul>
  119. *
  120. * @function
  121. * @param element
  122. * {ZpGroupElement} the element whose group membership should
  123. * be checked.
  124. * @returns true if the given element is member of the group, otherwise
  125. * false.
  126. */
  127. isGroupMember: function(element) {
  128. if (typeof element !== 'undefined' &&
  129. element.getP().equals(this.getP())) {
  130. var modPow = element.getElementValue().modPow(this.getQ(), this.getP());
  131. return BigInteger.ONE.equals(modPow);
  132. } else {
  133. return false;
  134. }
  135. },
  136. /**
  137. * Check if this group is equal to the received group.
  138. *
  139. * @function
  140. * @param group
  141. * {ZpSubgroup} the group which should be checked against
  142. * this group for equality.
  143. * @returns true if the given group has the same <code>q</code>, the
  144. * same <code>p</code>, and the same <code>generator</code>.
  145. */
  146. equals: function(group) {
  147. if (typeof group !== 'undefined' &&
  148. group.getGenerator().equals(this.getGenerator()) &&
  149. group.getQ().equals(this.getQ()) &&
  150. group.getP().equals(this.getP())) {
  151. return true;
  152. } else {
  153. return false;
  154. }
  155. },
  156. /**
  157. * Check if this group is a quadratic residue group, which is defined
  158. * such that p = 2q + 1.
  159. *
  160. * @function
  161. * @returns true if the given group is a quadratic residue group.
  162. */
  163. isQuadraticResidueGroup: function() {
  164. return this.getP().equals(
  165. new BigInteger('2').multiply(this.getQ()).add(BigInteger.ONE));
  166. },
  167. /**
  168. * Displays a string representation of this mathematical group JSON.
  169. * <p>
  170. * Note: in order to permit interoperability between libraries, this
  171. * representation should match the equivalent representation in Java.
  172. *
  173. * @function
  174. * @returns a string representation of this mathematical group JSON.
  175. */
  176. stringify: function() {
  177. return JSON.stringify({
  178. zpSubgroup: {
  179. p: converters.base64FromBigInteger(this.getP()),
  180. q: converters.base64FromBigInteger(this.getQ()),
  181. g: converters.base64FromBigInteger(
  182. this.getGenerator().getElementValue())
  183. }
  184. });
  185. }
  186. };
  187. /**
  188. * Class representing elements of a Zp group.
  189. *
  190. * <p>
  191. * Note: This constructor does not check whether the given value is a valid
  192. * member of the subgroup. To check subgroup membership the function
  193. * <code>zpSubgroup.isGroupMember(groupElement)</code> can be called,
  194. * however this is a computationally expensive operation.
  195. *
  196. * @class
  197. * @param value
  198. * {forge.jsbn.BigInteger} Value of the element (not null). The
  199. * value must be between <code>[1..p-1]</code>
  200. * @param groupP
  201. * {forge.jsbn.BigInteger} The p parameter, as a BigInteger.
  202. * @param groupQ
  203. * {forge.jsbn.BigInteger} The q parameter, as a BigInteger.
  204. * @throws CryptoLibException
  205. * if there are any problems with the inputs.
  206. */
  207. box.commons.mathematical.ZpGroupElement = function(value, groupP, groupQ) {
  208. if ((typeof value === 'undefined')) {
  209. throw new exceptions.CryptoLibException(
  210. 'The received value is not the expected object');
  211. }
  212. if ((BigInteger.ZERO.compareTo(value) >= 0) ||
  213. (groupP.compareTo(value) <= 0)) {
  214. throw new exceptions.CryptoLibException(
  215. 'The value of the element should be between 1 and p-1. P: ' + groupP +
  216. ', value: ' + value);
  217. }
  218. if ((BigInteger.ZERO.compareTo(groupQ) >= 0) ||
  219. (groupP.compareTo(groupQ) <= 0)) {
  220. throw new exceptions.CryptoLibException(
  221. 'The relationship between the values of the p and q parameters should hold that 0 < q < p');
  222. }
  223. var v = value;
  224. var p = groupP;
  225. var q = groupQ;
  226. /**
  227. * Performs a basic check to verify if this element belongs to the same
  228. * group as <code>element</code> by checking if the p and q parameters
  229. * of both are equal.
  230. * <p>
  231. * Note: this function does NOT perform the mathematical operation
  232. * needed to actually confirm that a value is an element of a group,
  233. * which involves modular exponentiation and is very computationally
  234. * costly. Instead, this function simply examines the p and q parameters
  235. * that are stored within both elements.
  236. *
  237. * @function
  238. * @param element
  239. * {ZpGroupElement} element to by multiplied with this
  240. * element.
  241. * @throws CryptoLibException
  242. * if the p and q parameters of the group that the received
  243. * element belongs to are not equal to the p and q
  244. * parameters of this element.
  245. */
  246. this._validateReceivedElementIsFromSameGroup = function(element) {
  247. if (typeof element === 'undefined') {
  248. throw new exceptions.CryptoLibException(
  249. 'The received value is not the expected object');
  250. }
  251. if ((!this.getP().equals(element.getP())) ||
  252. (!this.getQ().equals(element.getQ()))) {
  253. throw new exceptions.CryptoLibException(
  254. 'Operations can only be performed on group elements which are members of the same Zp subgroup');
  255. }
  256. };
  257. /**
  258. * Performs a basic check to verify if this element belongs to the same
  259. * group as <code>exponent</code> by checking if the p and q
  260. * parameters of both are equal.
  261. * <p>
  262. * Note: this function does NOT perform the mathematical operation
  263. * needed to actually confirm that an exponent belongs to a particular
  264. * group, which would involve confirming the following:
  265. * <p>
  266. * <code>0 >= exponent value <= p-1</code>
  267. *
  268. * @function
  269. * @param exponent
  270. * {Exponent} element to by multiplied with this element.
  271. * @throws CryptoLibException
  272. * if p and q parameters of the group that the received
  273. * element belongs to are not equal to the p and q
  274. * parameters of this element.
  275. */
  276. this._validateReceivedExponent = function(exponent) {
  277. if (typeof exponent === 'undefined') {
  278. throw new exceptions.CryptoLibException(
  279. 'The received value is not the expected object');
  280. }
  281. if (!this.getQ().equals(exponent.getQ())) {
  282. throw new exceptions.CryptoLibException(
  283. 'The exponent should have the same q as this Zp group element');
  284. }
  285. };
  286. /**
  287. * @function
  288. * @returns The value of this element.
  289. */
  290. this.getElementValue = function() {
  291. return v;
  292. };
  293. /**
  294. * @function
  295. * @returns The p parameter of the mathematical group to which this
  296. * element belongs.
  297. */
  298. this.getP = function() {
  299. return p;
  300. };
  301. /**
  302. * @function
  303. * @returns The q parameter of the mathematical group to which this
  304. * element belongs.
  305. */
  306. this.getQ = function() {
  307. return q;
  308. };
  309. };
  310. box.commons.mathematical.ZpGroupElement.prototype = {
  311. /**
  312. * Multiple this element by the received element. The operation is
  313. * performed mod p. Performs a basic check to confirm that this element
  314. * and the received element belong to the same group.
  315. *
  316. * @function
  317. * @param element
  318. * {ZpGroupElement} element to by multiplied with this
  319. * element.
  320. * @returns <code>(this * element) mod p</code>, as a ZpGroupElement.
  321. * @throws CryptoLibException
  322. * if the p and q parameters of the group that the received
  323. * element belongs to are not equal to the p and q
  324. * parameters of this element.
  325. */
  326. multiply: function(element) {
  327. this._validateReceivedElementIsFromSameGroup(element);
  328. var result = this.getElementValue()
  329. .multiply(element.getElementValue())
  330. .mod(this.getP());
  331. return new box.commons.mathematical.ZpGroupElement(
  332. result, this.getP(), this.getQ());
  333. },
  334. /**
  335. * Exponentiate this element to the received exponent.
  336. *
  337. * @function
  338. * @param exponent
  339. * {Exponent} the exponent used to raise the value of the
  340. * group element.
  341. * @returns <code>(this<sup>exponent</sup>) mod p</code>, as a
  342. * ZpGroupElement.
  343. * @throws CryptoLibException
  344. * if the p and q parameters of the group that the received
  345. * exponent belongs to are not equal to the p and q
  346. * parameters of this element.
  347. */
  348. exponentiate: function(exponent) {
  349. this._validateReceivedExponent(exponent);
  350. var result =
  351. this.getElementValue().modPow(exponent.getValue(), this.getP());
  352. return new box.commons.mathematical.ZpGroupElement(
  353. result, this.getP(), this.getQ());
  354. },
  355. /**
  356. * Get the inverse of this element, mod p.
  357. *
  358. * @function
  359. * @returns the inverse of this element mod p, as a ZpGroupElement.
  360. */
  361. invert: function() {
  362. var result = this.getElementValue().modInverse(this.getP());
  363. return new box.commons.mathematical.ZpGroupElement(
  364. result, this.getP(), this.getQ());
  365. },
  366. /**
  367. * Check if this element is equal to the received element.
  368. * <p>
  369. * Elements are considered equal if:
  370. * <ul>
  371. * <li>They have the same value.</li>
  372. * <li>They belong to the same group (which is confirmed here by
  373. * checking if their p and q parameters are equal).</li>
  374. * </ul>
  375. *
  376. * @function
  377. * @param element
  378. * {ZpGroupElement} the element which should be checked
  379. * against this element for equality.
  380. * @returns true if the given group element has the same <code>v</code>,
  381. * the same <code>p</code> and the same <code>q</code>.
  382. */
  383. equals: function(element) {
  384. if (typeof element !== 'undefined' &&
  385. element.getElementValue().equals(this.getElementValue()) &&
  386. element.getP().equals(this.getP()) &&
  387. element.getQ().equals(this.getQ())) {
  388. return true;
  389. } else {
  390. return false;
  391. }
  392. },
  393. /**
  394. * Displays a string representation of this Zp group element JSON.
  395. * <p>
  396. * Note: in order to permit interoperability between libraries, this
  397. * representation should match the equivalent representation in Java.
  398. *
  399. * @function
  400. * @returns a string representation of Zp group element JSON.
  401. */
  402. stringify: function() {
  403. return JSON.stringify({
  404. zpGroupElement: {
  405. p: converters.base64FromBigInteger(this.getP()),
  406. q: converters.base64FromBigInteger(this.getQ()),
  407. value: converters.base64FromBigInteger(this.getElementValue())
  408. }
  409. });
  410. }
  411. };
  412. /**
  413. * Represents an exponent for a particular mathematical group.
  414. * <p>
  415. * The value of an exponent must be within the range [0..q-1]. If the
  416. * received value is not within this range, then the value that will be
  417. * assigned to the created Exponent will be calculated as follows:
  418. * <p>
  419. * <code>value = value mod q</code>
  420. *
  421. * @class
  422. *
  423. * @param q
  424. * {forge.jsbn.BigInteger} the order of the mathematical group
  425. * for which this is an exponent.
  426. * @param exponentValue
  427. * {forge.jsbn.BigInteger} the value of the exponent.
  428. * @throws CryptoLibException
  429. * if there are any problems with the inputs.
  430. */
  431. box.commons.mathematical.Exponent = function(valueQ, exponentValue) {
  432. if (valueQ === 'undefined' || valueQ.compareTo(BigInteger.ZERO) === 0) {
  433. throw new exceptions.CryptoLibException(
  434. 'Q (the order of the group) cannot be null or zero');
  435. }
  436. var _q = valueQ;
  437. /**
  438. * Gets the value to set for this Exponent. This value has to be a
  439. * number between <code>0</code> and <code>q-1</code> (inclusive),
  440. * so if it is less than <code>0</code> or greater than
  441. * <code>q-1</code>, then <code>mod q</code> has to be applied.
  442. *
  443. * @function
  444. * @param {forge.jsbn.BigInteger}
  445. * exponentValue the value of the exponent.
  446. * @returns the value to set to this exponent.
  447. */
  448. function getExponent(exponentValue) {
  449. if ((_q.compareTo(exponentValue) > 0) &&
  450. (BigInteger.ZERO.compareTo(exponentValue) <= 0)) {
  451. return exponentValue;
  452. } else {
  453. return exponentValue.mod(_q);
  454. }
  455. }
  456. var _value = getExponent(exponentValue);
  457. /**
  458. * Checks if this exponent and the received exponent belong to the same
  459. * group.
  460. *
  461. * @function
  462. * @param exponent
  463. * {Exponent} the exponent which should be checked to see if
  464. * it belongs to the same group as this exponent.
  465. * @throws CryptoLibException
  466. * if the received exponent is undefined or does not belong
  467. * to the same group as this exponent.
  468. */
  469. this._confirmSameGroup = function(exponent) {
  470. if (typeof exponent === 'undefined') {
  471. throw new exceptions.CryptoLibException(
  472. 'The received exponent is not the expected object');
  473. }
  474. if (!_q.equals(exponent.getQ())) {
  475. throw new exceptions.CryptoLibException(
  476. 'Operations may only be performed with exponents of the same mathematical group order');
  477. }
  478. };
  479. /**
  480. * @function
  481. * @returns The numeric value of the exponent.
  482. */
  483. this.getValue = function() {
  484. return _value;
  485. };
  486. /**
  487. * @function
  488. * @returns The numeric value of the exponent.
  489. */
  490. this.getQ = function() {
  491. return _q;
  492. };
  493. };
  494. box.commons.mathematical.Exponent.prototype = {
  495. /**
  496. * Returns an Exponent whose value is:
  497. * <p>
  498. * <code>(this + exponent) mod q</code>
  499. *
  500. * @param exponent
  501. * {Exponent} the exponent to be added to this exponent.
  502. * @returns <code>(this + exponent) mod q</code>
  503. */
  504. add: function(exponent) {
  505. this._confirmSameGroup(exponent);
  506. var result = this.getValue().add(exponent.getValue()).mod(this.getQ());
  507. return new box.commons.mathematical.Exponent(this.getQ(), result);
  508. },
  509. /**
  510. * Returns an Exponent whose value is:
  511. * <p>
  512. * <code>(this - exponent) mod q</code>
  513. *
  514. * @param exponent
  515. * {Exponent} the exponent to be subtracted from this
  516. * exponent.
  517. * @returns <code>(this - exponent) mod q</code>
  518. */
  519. subtract: function(exponent) {
  520. this._confirmSameGroup(exponent);
  521. var result =
  522. this.getValue().subtract(exponent.getValue()).mod(this.getQ());
  523. return new box.commons.mathematical.Exponent(this.getQ(), result);
  524. },
  525. /**
  526. * Returns an Exponent whose value is:
  527. * <p>
  528. * <code>(this * exponent) mod q</code>
  529. *
  530. * @param exponent
  531. * {Exponent} the exponent to be multiplied with this
  532. * exponent.
  533. * @returns <code>(this * exponent) mod q</code>
  534. */
  535. multiply: function(exponent) {
  536. this._confirmSameGroup(exponent);
  537. var result =
  538. this.getValue().multiply(exponent.getValue()).mod(this.getQ());
  539. return new box.commons.mathematical.Exponent(this.getQ(), result);
  540. },
  541. /**
  542. * Returns an Exponent whose value is <code>(-this) mod q</code>
  543. *
  544. * @returns <code>(-this mod q)</code>
  545. */
  546. negate: function() {
  547. return new box.commons.mathematical.Exponent(
  548. this.getQ(), this.getValue().negate().mod(this.getQ()));
  549. },
  550. /**
  551. * Check if this exponent is equal to the received exponent.
  552. * <p>
  553. * Elements are considered equal if:
  554. * <ul>
  555. * <li>They have the same value.</li>
  556. * <li>They belong to the groups with the same order.</li>
  557. * </ul>
  558. *
  559. * @param {Exponent}
  560. * exponent the exponent to be checked against this exponent
  561. * for equality.
  562. * @returns true if the given exponent has the same <code>value</code>
  563. * and belongs to the same <code>group</code> as this
  564. * exponent.
  565. */
  566. equals: function(exponent) {
  567. if (exponent.getValue().equals(this.getValue()) &&
  568. exponent.getQ().equals(this.getQ())) {
  569. return true;
  570. } else {
  571. return false;
  572. }
  573. },
  574. /**
  575. * Displays a string representation of the exponent JSON.
  576. * <p>
  577. * Note: in order to permit interoperability between libraries, this
  578. * representation should match the equivalent representation in Java.
  579. *
  580. * @function
  581. * @returns a string representation of the exponent JSON.
  582. */
  583. stringify: function() {
  584. return JSON.stringify({
  585. exponent: {
  586. q: converters.base64FromBigInteger(this.getQ()),
  587. value: converters.base64FromBigInteger(this.getValue())
  588. }
  589. });
  590. }
  591. };
  592. /**
  593. * Provides utility functionality for working with mathematical groups.
  594. *
  595. * @class groupUtils
  596. * @memberof commons/mathematical
  597. */
  598. box.commons.mathematical.groupUtils = (function() {
  599. /**
  600. * Deserializes a Zp Subgroup string representation to a ZpSubgroup
  601. * object.
  602. *
  603. * @function
  604. * @memberof commons/mathematical.groupUtils
  605. * @param groupJson
  606. * {JSON} a JSON representation of a Zp subgroup.
  607. * @returns a new ZpSubgroup, created from the received string.
  608. */
  609. function deserializeGroup(groupJson) {
  610. var parsed = JSON.parse(groupJson);
  611. var p = converters.base64ToBigInteger(parsed.zpSubgroup.p);
  612. var q = converters.base64ToBigInteger(parsed.zpSubgroup.q);
  613. var g = converters.base64ToBigInteger(parsed.zpSubgroup.g);
  614. return new box.commons.mathematical.ZpSubgroup(g, p, q);
  615. }
  616. /**
  617. * Deserializes a Zp Subgroup element string to a ZpGroupElement object.
  618. *
  619. * @function
  620. * @memberof commons/mathematical.groupUtils
  621. * @param groupElementJson
  622. * {JSON} a JSON representation of a Zp Subgroup element
  623. * element.
  624. * @returns a new ZpGroupElement, created from the received string.
  625. */
  626. function deserializeGroupElement(groupElementJson) {
  627. var parsed = JSON.parse(groupElementJson);
  628. var value = converters.base64ToBigInteger(parsed.zpGroupElement.value);
  629. var p = converters.base64ToBigInteger(parsed.zpGroupElement.p);
  630. var q = converters.base64ToBigInteger(parsed.zpGroupElement.q);
  631. return new box.commons.mathematical.ZpGroupElement(value, p, q);
  632. }
  633. /**
  634. * Deserializes an exponent string to an Exponent object.
  635. *
  636. * @function
  637. * @memberof commons/mathematical.groupUtils
  638. * @param exponentJson
  639. * {JSON} a JSON representation of an exponent.
  640. * @returns a new Exponent, created from the received string.
  641. */
  642. function deserializeExponent(exponentJson) {
  643. var parsed = JSON.parse(exponentJson);
  644. var q = converters.base64ToBigInteger(parsed.exponent.q);
  645. var value = converters.base64ToBigInteger(parsed.exponent.value);
  646. return new box.commons.mathematical.Exponent(q, value);
  647. }
  648. /**
  649. * Compress a list of group elements.
  650. * <P>
  651. * Note: an exception will be thrown if an array is received which
  652. * contains any elements that are not elements of the mathematical
  653. * group.
  654. *
  655. * @function
  656. * @memberof commons/mathematical.groupUtils
  657. * @param group
  658. * {ZpSubgroup} the mathematical group.
  659. * @param elementsToBeCompressedArray
  660. * {object} the array of group elements to be compressed.
  661. * @returns the result of the compression process, as a group element.
  662. * @throws CryptoLibException
  663. * if there are any problems with the inputs.
  664. */
  665. function compressGroupElements(group, elementsToBeCompressedArray) {
  666. validateArray(elementsToBeCompressedArray);
  667. validateGroup(group);
  668. var elem = elementsToBeCompressedArray[0];
  669. for (var i = 1; i < elementsToBeCompressedArray.length; i++) {
  670. elem = elem.multiply(elementsToBeCompressedArray[i]);
  671. }
  672. return elem;
  673. }
  674. /**
  675. * Compress a list of exponents.
  676. * <P>
  677. * Note: an exception will be thrown if an array is received which
  678. * contains any exponents that are not exponents of the mathematical
  679. * group.
  680. *
  681. * @function
  682. * @memberof commons/mathematical.groupUtils
  683. * @param group
  684. * {ZpSubgroup} the mathematical group
  685. * @param exponentsToBeCompressedArray
  686. * {object} the array of exponents to be compressed
  687. * @returns the result of the compression process, as an exponent.
  688. * @throws CryptoLibException
  689. * if there are any problems with the inputs.
  690. */
  691. function compressExponents(group, exponentsToBeCompressedArray) {
  692. validateArray(exponentsToBeCompressedArray);
  693. validateGroup(group);
  694. validateExponents(group.getQ(), exponentsToBeCompressedArray);
  695. var elem = exponentsToBeCompressedArray[0];
  696. for (var i = 1; i < exponentsToBeCompressedArray.length; i++) {
  697. elem = elem.add(exponentsToBeCompressedArray[i]);
  698. }
  699. return elem;
  700. }
  701. /**
  702. * Builds a new array of elements from the input array, where the final
  703. * elements from the input array are compressed into a simple element.
  704. *
  705. * @function
  706. * @memberof commons/mathematical.groupUtils
  707. * @param group
  708. * {ZpSubgroup} the mathematical group that this compressor
  709. * operates on.
  710. * @param inputArray
  711. * {object} the input array of group elements.
  712. * @param numElementsRequiredInNewList
  713. * {number} the number of elements that should be in the
  714. * output array.
  715. * @returns a new array of group elements.
  716. * @throws CryptoLibException
  717. * if there are any problems with the inputs.
  718. */
  719. function buildListWithCompressedFinalElement(
  720. group, inputArray, numElementsRequiredInNewList) {
  721. validateArray(inputArray);
  722. validateGroup(group);
  723. if (numElementsRequiredInNewList < 1) {
  724. throw new exceptions.CryptoLibException(
  725. 'The number of elements in the output list must be at least 1');
  726. }
  727. var offset = numElementsRequiredInNewList - 1;
  728. var outputArray = inputArray.slice(0, offset);
  729. var lastElement = compressGroupElements(
  730. group, inputArray.slice(offset, inputArray.length));
  731. outputArray.push(lastElement);
  732. return outputArray;
  733. }
  734. /**
  735. * Builds a new array of exponents from the input array, where the final
  736. * exponents from the input array are compressed into a simple
  737. * exponents.
  738. *
  739. * @function
  740. * @memberof commons/mathematical.groupUtils
  741. * @param group
  742. * {ZpSubgroup} the mathematical group that this compressor
  743. * operates on.
  744. * @param inputArray
  745. * {object} the input array of exponents.
  746. * @param numExponentsRequiredInNewList
  747. * {number} the number of exponents that should be in the
  748. * output array.
  749. * @returns a new array of group elements.
  750. * @throws CryptoLibException
  751. * if there are any problems with the inputs.
  752. */
  753. function buildListWithCompressedFinalExponent(
  754. group, inputArray, numExponentsRequiredInNewList) {
  755. validateArray(inputArray);
  756. validateGroup(group);
  757. if (numExponentsRequiredInNewList < 1) {
  758. throw new exceptions.CryptoLibException(
  759. 'The number of exponents in the output list must be at least 1');
  760. }
  761. var offset = numExponentsRequiredInNewList - 1;
  762. var outputArray = inputArray.slice(0, offset);
  763. var lastExponent =
  764. compressExponents(group, inputArray.slice(offset, inputArray.length));
  765. outputArray.push(lastExponent);
  766. return outputArray;
  767. }
  768. /**
  769. * Given two arrays of group elements, this method produces a new list
  770. * of group elements that represents the two input lists combined.
  771. * <P>
  772. * The two arrays must only contain values that are elements of the
  773. * mathematical group that this divider operates on. If either array
  774. * contains any element that is not a group element then an exception
  775. * will be thrown.
  776. *
  777. * @function
  778. * @memberof commons/mathematical.groupUtils
  779. * @param arrayElements1
  780. * {object} an input array of Zp group elements.
  781. * @param arrayElements2
  782. * {object} an input array of Zp group elements.
  783. * @returns a new list of group elements.
  784. * @throws CryptoLibException
  785. * if there are any problems with the inputs.
  786. */
  787. function divide(arrayElements1, arrayElements2) {
  788. validateArray(arrayElements1);
  789. validateArray(arrayElements2);
  790. if (arrayElements1.length !== arrayElements2.length) {
  791. throw new exceptions.CryptoLibException(
  792. 'Both arrays should have the same length');
  793. }
  794. var newList = [];
  795. var newElement;
  796. for (var i = 0; i < arrayElements1.length; i++) {
  797. newElement = arrayElements1[i].multiply(arrayElements2[i].invert());
  798. newList.push(newElement);
  799. }
  800. return newList;
  801. }
  802. /**
  803. * Given an array of group elements and one exponent, this method
  804. * produces a new list of group elements that represents the
  805. * exponentiation of the group elements to the exponent.
  806. * <P>
  807. * The array must contain values that are elements of the mathematical
  808. * group that this exponentiation activity operates on. If the array
  809. * contains any element that is not a group element then an exception
  810. * will be thrown.
  811. *
  812. * @function
  813. * @memberof commons/mathematical.groupUtils
  814. * @param {array} arrayElements
  815. * an input array of Zp group elements.
  816. * @param {object} exponent
  817. * An Exponent.
  818. * @param {object} group
  819. * The mathematical group that all of the elements in
  820. * arrayElements belong to.
  821. * @param {boolean} validateElements An Exponent.
  822. * @return A new list of group elements.
  823. *
  824. */
  825. function exponentiateArrays(
  826. arrayElements, exponent, group, validateElements) {
  827. validateArray(arrayElements);
  828. validateExponent(exponent);
  829. validateGroup(group);
  830. // If requested, validate all elements prior to any operations.
  831. if (typeof validateElements !== 'undefined' && validateElements) {
  832. for (var j = 0; j < arrayElements.length; j++) {
  833. if (!group.isGroupMember(arrayElements[j])) {
  834. throw new exceptions.CryptoLibException(
  835. 'The element does not belong to the group');
  836. }
  837. }
  838. }
  839. var newList = [];
  840. var newElement;
  841. for (var i = 0; i < arrayElements.length; i++) {
  842. newElement = arrayElements[i].exponentiate(exponent);
  843. newList.push(newElement);
  844. }
  845. return newList;
  846. }
  847. /**
  848. * Returns a new random exponent for the received mathematical group.
  849. * <P>
  850. * The value of the created exponent will be between <code>0</code>
  851. * and q-1.
  852. *
  853. * @function
  854. * @memberof commons/mathematical.groupUtils
  855. * @param group
  856. * {ZpSubgroup} the mathematical group.
  857. * @param cryptoRandomInteger
  858. * {CryptoScytlRandomInteger} the source of randomness.
  859. * @param {boolean}
  860. * useShortExponent true if a short exponent is to be
  861. * generated. Default value is false.
  862. * @returns a new random exponent.
  863. * @throws CryptoLibException
  864. * if there are any problems with the inputs.
  865. */
  866. function generateRandomExponent(
  867. group, cryptoRandomInteger, useShortExponent) {
  868. validateGroup(group);
  869. if (typeof cryptoRandomInteger === 'undefined') {
  870. throw new exceptions.CryptoLibException(
  871. 'The given parameters should be initialized');
  872. }
  873. var _useShortExponent = true;
  874. if (!useShortExponent) {
  875. _useShortExponent = false;
  876. }
  877. var q = group.getQ();
  878. var qBitLength = q.bitLength();
  879. var randomExponentLength;
  880. if (_useShortExponent) {
  881. if (qBitLength < box.SHORT_EXPONENT_BIT_LENGTH) {
  882. throw new exceptions.CryptoLibException(
  883. 'Zp subgroup order bit length must be greater than or equal to short exponent bit length : ' +
  884. box.SHORT_EXPONENT_BIT_LENGTH + '; Found ' + qBitLength);
  885. }
  886. randomExponentLength = box.SHORT_EXPONENT_BIT_LENGTH;
  887. } else {
  888. randomExponentLength = qBitLength;
  889. }
  890. var randomExponentValue;
  891. var randomExponentFound = false;
  892. while (!randomExponentFound) {
  893. randomExponentValue =
  894. cryptoRandomInteger.nextRandomByBits(randomExponentLength);
  895. if (randomExponentValue.compareTo(q) < 0) {
  896. randomExponentFound = true;
  897. }
  898. }
  899. return new box.commons.mathematical.Exponent(q, randomExponentValue);
  900. }
  901. /**
  902. * Returns a group element symmetric key which is obtained by
  903. * exponentiating the generator of a given mathematical group to a
  904. * random exponent <code>k</code>.
  905. *
  906. * @function
  907. * @memberof commons/mathematical.groupUtils
  908. * @param group
  909. * {ZpSubgroup} the mathematical group.
  910. * @param cryptoRandomInteger
  911. * {CryptoScytlRandomInteger} the source of randomness.
  912. * @returns the secret key, as a group element.
  913. * @throws CryptoLibException
  914. * if there are any problems with the inputs.
  915. */
  916. function generateGroupElementSecretKey(group, cryptoRandomInteger) {
  917. var exponent = generateRandomExponent(group, cryptoRandomInteger);
  918. var groupElementSecretKey = group.getGenerator().exponentiate(exponent);
  919. return groupElementSecretKey;
  920. }
  921. /**
  922. * Build a ZpSubgroup from the p and g parameters.
  923. * <P>
  924. * NOTE: This method builds a particular type of mathematical group with
  925. * property that:
  926. * <P>
  927. * P = (Q * 2) + 1
  928. * <P>
  929. * This property holds for all groups generated using this method, but
  930. * this property does not hold for all mathematical groups.
  931. *
  932. * @function
  933. * @memberof commons/mathematical.groupUtils
  934. * @param p
  935. * {forge.jsbn.BigInteger} the p parameter of the group.
  936. * @param g
  937. * {forge.jsbn.BigInteger} the generator of the group.
  938. * @returns the generated ZpSubgroup.
  939. * @throws CryptoLibException
  940. * if there are any problems with the inputs.
  941. */
  942. function buildZpSubgroupFromPAndG(p, g) {
  943. validateBuildFromPAndGInputs(p, g);
  944. var q = p.subtract(BigInteger.ONE).divide(new BigInteger('2'));
  945. return new box.commons.mathematical.ZpSubgroup(g, p, q);
  946. }
  947. /**
  948. * Build a random ZpSubgroup whose p parameter will have the specified
  949. * bit length. The certainty that both p and q are both prime is
  950. * specified by certainty.
  951. * <P>
  952. * NOTE: This method builds a particular type of Zp subgroup with
  953. * property that:
  954. * <P>
  955. * p = (q * 2) + 1
  956. * <P>
  957. * This property holds for all mathematical groups generated using this
  958. * method, but this property does not hold for all mathematical groups.
  959. * <P>
  960. * Note: the minimum bit length of the p parameter that is permitted by
  961. * this method is 2. If a bit length less than 2 is requested then a
  962. * CryptoLibException will be thrown.
  963. *
  964. * @function
  965. * @memberof commons/mathematical.groupUtils
  966. * @param bitLengthOfP
  967. * {number} the bit length that the p parameter of the
  968. * generated group should be.
  969. * @param cryptoRandomInteger
  970. * {CryptoScytlRandomInteger} an instance of
  971. * CryptoRandomInteger that can be used as a source of random
  972. * integers.
  973. * @param certainty
  974. * {number} the required level of certainty that the q
  975. * parameter of the generated group is prime.
  976. * @returns the generated ZpSubgroup.
  977. * @throws CryptoLibException
  978. * if there are any problems with the inputs.
  979. */
  980. function buildRandomZpSubgroupFromLengthOfP(
  981. bitLengthOfP, cryptoRandomBytes, certainty) {
  982. validateBuildFromLengthPInputs(
  983. bitLengthOfP, cryptoRandomBytes, certainty);
  984. var p, q;
  985. var twoBI = new BigInteger('2');
  986. var randomGroupFound = false;
  987. var options = {prng: cryptoRandomBytes};
  988. var callback = function(err, num) {
  989. if (err) {
  990. throw new exceptions.CryptoLibException(
  991. 'Error while generating prime ' + err);
  992. }
  993. p = num;
  994. q = num.subtract(BigInteger.ONE).divide(twoBI);
  995. };
  996. while (!randomGroupFound) {
  997. forge.prime.generateProbablePrime(bitLengthOfP, options, callback);
  998. if (q.isProbablePrime(certainty)) {
  999. randomGroupFound = true;
  1000. }
  1001. }
  1002. var generator = findSmallestGenerator(p, q);
  1003. return new box.commons.mathematical.ZpSubgroup(generator, p, q);
  1004. }
  1005. /**
  1006. * Given an input array containing possible group members, this method
  1007. * cycles through that array, checking if each element is a group
  1008. * member. This method attempts to find the specified number of group
  1009. * members. Once that number has been found, the method will return a
  1010. * new array containing the specified number of group members.
  1011. * <p>
  1012. * If the required number of group members are not found in the input
  1013. * array then a CryptoLibException will be thrown.
  1014. *
  1015. * @function
  1016. * @memberof commons/mathematical.groupUtils
  1017. * @param possibleGroupMembersArray
  1018. * {object} an array containing possible group members.
  1019. * @param group
  1020. * {ZpSubgroup} the Zp subgroup for which the specified
  1021. * number of group members are required.
  1022. * @param numMembersRequired
  1023. * {number} the number of group members of the specified
  1024. * group that should be added to the output list.
  1025. * @returns a new array containing the specified number of group
  1026. * elements, which have been read from the input array.
  1027. * @throws CryptoLibException
  1028. * if there are any problems with the inputs.
  1029. */
  1030. function extractNumberOfGroupMembersFromListOfPossibleMembers(
  1031. possibleGroupMembersArray, group, numMembersRequired) {
  1032. validateExtractFromListInputs(
  1033. possibleGroupMembersArray, group, numMembersRequired);
  1034. var outputArray = [];
  1035. var membersFound = 0;
  1036. var candidate;
  1037. for (var i = 0; i < possibleGroupMembersArray.length; i++) {
  1038. candidate = new box.commons.mathematical.ZpGroupElement(
  1039. possibleGroupMembersArray[i], group.getP(), group.getQ());
  1040. if (group.isGroupMember(candidate)) {
  1041. outputArray.push(candidate);
  1042. membersFound++;
  1043. }
  1044. if (membersFound === numMembersRequired) {
  1045. return outputArray;
  1046. }
  1047. }
  1048. if (membersFound !== numMembersRequired) {
  1049. throw new exceptions.CryptoLibException(
  1050. 'Error - did not find the required number of group members in the given list. The required number of was ' +
  1051. numMembersRequired + ', number of members found was ' +
  1052. membersFound);
  1053. }
  1054. }
  1055. /**
  1056. * Find the smallest generator of a mathematical group.
  1057. * <p>
  1058. * Note: starts with a candidate generator value (two is the initial
  1059. * candidate generator value), and checks if the candidate generator is
  1060. * a group memeber. If that candidate is a group memeber then return
  1061. * that value, else increment the candidate by one and again check if
  1062. * the candidate is a group member. Continue this process until the
  1063. * candidate value is less than the parameter p.
  1064. *
  1065. * @function
  1066. * @memberof commons/mathematical.groupUtils
  1067. * @params p {number} the p parameter of the group.
  1068. * @params q {number} the q parameter of the group.
  1069. * @throws CryptoLibException
  1070. */
  1071. function findSmallestGenerator(p, q) {
  1072. var g = new BigInteger('2');
  1073. var generatorFound = false;
  1074. while ((!generatorFound) && (g.compareTo(p) < 0)) {
  1075. if (g.modPow(q, p).equals(BigInteger.ONE)) {
  1076. generatorFound = true;
  1077. } else {
  1078. g = g.add(BigInteger.ONE);
  1079. }
  1080. }
  1081. if (!generatorFound) {
  1082. throw new exceptions.CryptoLibException(
  1083. 'Failed to find a generator, p was: ' + p + ', q was: ' + q);
  1084. }
  1085. return g;
  1086. }
  1087. /**
  1088. * Validates a group.
  1089. *
  1090. * @function
  1091. * @memberof commons/mathematical.groupUtils
  1092. * @params group {ZpSubgroup} the group to be validated.
  1093. * @throws CryptoLibException
  1094. * if the received group is undefined.
  1095. */
  1096. function validateGroup(group) {
  1097. if (typeof group === 'undefined' || null === group) {
  1098. throw new exceptions.CryptoLibException(
  1099. 'The given group should be initialized');
  1100. }
  1101. }
  1102. function validateExponent(exponent) {
  1103. if (typeof exponent === 'undefined') {
  1104. throw new exceptions.CryptoLibException(
  1105. 'The given exponent should be initialized');
  1106. }
  1107. }
  1108. /**
  1109. * Validates that an array is initialized and non-empty.
  1110. *
  1111. * @function
  1112. * @memberof commons/mathematical.groupUtils
  1113. * @params inputArray {object} an array to be validated.
  1114. * @throws CryptoLibException
  1115. * if the received array is not initialized or is empty.
  1116. */
  1117. function validateArray(inputArray) {
  1118. if (typeof inputArray === 'undefined') {
  1119. throw new exceptions.CryptoLibException(
  1120. 'The given array should be initialized');
  1121. }
  1122. if (!(inputArray instanceof Array)) {
  1123. throw new exceptions.CryptoLibException(
  1124. 'The given array are not from the expected type');
  1125. }
  1126. if (inputArray.length < 1) {
  1127. throw new exceptions.CryptoLibException(
  1128. 'The given array cannot be empty');
  1129. }
  1130. }
  1131. /**
  1132. * Performs a very basic validation on the received inputs.
  1133. *
  1134. * @function
  1135. * @memberof commons/mathematical.groupUtils
  1136. * @params p {object} the first parameter.
  1137. * @params g {object} the second parameter.
  1138. * @throws CryptoLibException
  1139. * if either (or both) inputs are undefined.
  1140. */
  1141. function validateBuildFromPAndGInputs(p, g) {
  1142. if ((typeof p === 'undefined') || (typeof g === 'undefined')) {
  1143. throw new exceptions.CryptoLibException('p or g are incorrect');
  1144. }
  1145. }
  1146. /**
  1147. * Performs a some basic validations on the received inputs.
  1148. *
  1149. * @function
  1150. * @memberof commons/mathematical.groupUtils
  1151. * @params bitLengthOfP {number} bit length of p parameter.
  1152. * @params cryptoRandomBytes {CryptoScytlRandomBytes} a secure source of
  1153. * random bytes.
  1154. * @params certainty {number} a certainty level.
  1155. * @throws CryptoLibException
  1156. * if any of the inputs fail any of the validations.
  1157. */
  1158. function validateBuildFromLengthPInputs(
  1159. bitLengthOfP, cryptoRandomBytes, certainty) {
  1160. if (bitLengthOfP < 2) {
  1161. throw new exceptions.CryptoLibException(
  1162. 'The bit length should be higher');
  1163. }
  1164. if (typeof cryptoRandomBytes === 'undefined') {
  1165. throw new exceptions.CryptoLibException(
  1166. 'The random generator should be initialized');
  1167. }
  1168. if (certainty < box.MINIMUM_PRIME_CERTAINTY_LEVEL) {
  1169. throw new exceptions.CryptoLibException('Certainty should be higher');
  1170. }
  1171. }
  1172. /**
  1173. * Performs some basic validations on the received inputs.
  1174. *
  1175. * @function
  1176. * @memberof commons/mathematical.groupUtils
  1177. * @params inputArray {object} an array.
  1178. * @params group {ZpSubgroup} a Zp subgroup.
  1179. * @params numMembersRequired {number} an integer value.
  1180. * @throws CryptoLibException
  1181. * if any of the inputs fail any of the validations.
  1182. */
  1183. function validateExtractFromListInputs(
  1184. inputArray, group, numMembersRequired) {
  1185. validateArray(inputArray);
  1186. validateGroup(group);
  1187. if (typeof numMembersRequired === 'undefined') {
  1188. throw new exceptions.CryptoLibException(
  1189. 'The given objects should be initialized');
  1190. }
  1191. if (typeof numMembersRequired !== 'number') {
  1192. throw new exceptions.CryptoLibException(
  1193. 'The given objects are not from the expected type');
  1194. }
  1195. if (numMembersRequired < 1 || numMembersRequired > inputArray.length) {
  1196. throw new exceptions.CryptoLibException(
  1197. 'The given number of required elements cannot be higher than the number of elements of the array');
  1198. }
  1199. }
  1200. /**
  1201. * Validates that all of the exponents in the received list are
  1202. * exponents are members of the received group, by checking if the
  1203. * groups that they contain are equal.
  1204. *
  1205. * @function
  1206. * @memberof commons/mathematical.groupUtils
  1207. * @params group {ZpSubgroup} a Zp subgroup.
  1208. * @params exponents {object} a list of exponents.
  1209. */
  1210. function validateExponents(q, exponents) {
  1211. for (var i = 0; i < exponents.length; i++) {
  1212. if (!exponents[i].getQ().equals(q)) {
  1213. throw new exceptions.CryptoLibException(
  1214. 'The list of exponents contained an exponent which does not belong to the group with the same order.');
  1215. }
  1216. }
  1217. }
  1218. return {
  1219. buildZpSubgroupFromPAndG: buildZpSubgroupFromPAndG,
  1220. buildRandomZpSubgroupFromLengthOfP: buildRandomZpSubgroupFromLengthOfP,
  1221. extractNumberOfGroupMembersFromListOfPossibleMembers:
  1222. extractNumberOfGroupMembersFromListOfPossibleMembers,
  1223. generateRandomExponent: generateRandomExponent,
  1224. generateGroupElementSecretKey: generateGroupElementSecretKey,
  1225. compressGroupElements: compressGroupElements,
  1226. buildListWithCompressedFinalElement: buildListWithCompressedFinalElement,
  1227. deserializeGroup: deserializeGroup,
  1228. deserializeGroupElement: deserializeGroupElement,
  1229. deserializeExponent: deserializeExponent,
  1230. compressExponents: compressExponents,
  1231. buildListWithCompressedFinalExponent:
  1232. buildListWithCompressedFinalExponent,
  1233. divide: divide,
  1234. exponentiateArrays: exponentiateArrays
  1235. };
  1236. })();
  1237. };