commons.mathematical.spec.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765
  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. describe('Mathematical ...', function() {
  9. 'use strict';
  10. var G_STR = '2';
  11. var P_STR = '23';
  12. var Q_STR = '11';
  13. var GROUP_ELEMENT_STR = '3';
  14. var EXPONENT_STR = '2';
  15. var EXPONENT_1_LARGE_STR =
  16. '129547331161844130899924173735104728702220700682642138851022406761777994632728337153635583150724889632689084497665212926336088840842855597736181764744122977345480665146165524664735861913761423291109155186483836806324970977794125768575887671259015293979900588616487195411477129839925141145884519189238456836206862720534398725375349481201999965487100563522135988094619173050092410477941592825803862292425503577691441721033806466916501473758812704373810862790693842410609705251142958265348495650713103821889837809522418329172422392659115758749365074645804533890934339070499112165048929164809093509978635413193830265570';
  17. var EXPONENT_2_LARGE_STR =
  18. '7533608948657130117198364792462971241599837777629317286887202126604432685322243335715285630236984093165224740099563982076007648728594011814311120331313200895892632245003875959905589367483155794698953057915454892457379023058909518440394905695255170407948701433659375513788930419544151891518689331636455316691827048845766063478445484089208223819510250476623436782404385896353292653750744111841510466992101967325081746747885221256692886521245630131046183525331085171958919416648097910028887247120874015121272894655357197879292253781160838729753609784455892951965051119314203469298666741439497193677501351952497150273389';
  19. var GROUP_ELEMENT_1_STR = '2';
  20. var GROUP_ELEMENT_2_STR = '3';
  21. var GROUP_ELEMENT_3_STR = '9';
  22. var GROUP_ELEMENT_VALUES_FOR_LARGE_ARRAY = [3, 4, 6, 8, 9, 12, 13, 16, 18];
  23. var _initialized = false;
  24. var _g;
  25. var _p;
  26. var _q;
  27. var _groupElementValue;
  28. var _exponentValue;
  29. var _zpSubgroup;
  30. var _zpSubgroupJson;
  31. var _zpSubgroupElem;
  32. var _zpSubgroupElemJson;
  33. var _exponent;
  34. var _exponentJson;
  35. var _exponent1Large;
  36. var _exponent2Large;
  37. var _groupElement1Value;
  38. var _groupElement2Value;
  39. var _groupElement3Value;
  40. var _zpGroupElementArray;
  41. var _zpGroupElementArrayLarge;
  42. beforeEach(function() {
  43. if (!_initialized) {
  44. cryptolib('commons.utils', 'commons.mathematical', function(box) {
  45. var converters = new box.commons.utils.Converters();
  46. _g = new forge.jsbn.BigInteger(G_STR);
  47. _p = new forge.jsbn.BigInteger(P_STR);
  48. _q = new forge.jsbn.BigInteger(Q_STR);
  49. _groupElementValue = new forge.jsbn.BigInteger(GROUP_ELEMENT_STR);
  50. _exponentValue = new forge.jsbn.BigInteger(EXPONENT_STR);
  51. var gB64 = converters.base64FromBigInteger(_g);
  52. var pB64 = converters.base64FromBigInteger(_p);
  53. var qB64 = converters.base64FromBigInteger(_q);
  54. var expValueB64 = converters.base64FromBigInteger(_exponentValue);
  55. var elemValueB64 = converters.base64FromBigInteger(_groupElementValue);
  56. _zpSubgroup = new box.commons.mathematical.ZpSubgroup(_g, _p, _q);
  57. _zpSubgroupJson = '{"zpSubgroup":{"p":"' + pB64 + '","q":"' + qB64 +
  58. '","g":"' + gB64 + '"}}';
  59. _zpSubgroupElem = new box.commons.mathematical.ZpGroupElement(
  60. _groupElementValue, _p, _q);
  61. _zpSubgroupElemJson = '{"zpGroupElement":{"p":"' + pB64 + '","q":"' +
  62. qB64 + '","value":"' + elemValueB64 + '"}}';
  63. _exponent = new box.commons.mathematical.Exponent(_q, _exponentValue);
  64. _exponentJson =
  65. '{"exponent":{"q":"' + qB64 + '","value":"' + expValueB64 + '"}}';
  66. var exponentValue = new box.forge.jsbn.BigInteger(EXPONENT_1_LARGE_STR);
  67. _exponent1Large =
  68. new box.commons.mathematical.Exponent(_q, exponentValue);
  69. exponentValue = new box.forge.jsbn.BigInteger(EXPONENT_2_LARGE_STR);
  70. _exponent2Large =
  71. new box.commons.mathematical.Exponent(_q, exponentValue);
  72. var groupElement;
  73. _zpGroupElementArray = [];
  74. _groupElement1Value =
  75. new box.forge.jsbn.BigInteger(GROUP_ELEMENT_1_STR);
  76. groupElement = new box.commons.mathematical.ZpGroupElement(
  77. _groupElement1Value, _p, _q);
  78. _zpGroupElementArray.push(groupElement);
  79. _groupElement2Value =
  80. new box.forge.jsbn.BigInteger(GROUP_ELEMENT_2_STR);
  81. groupElement = new box.commons.mathematical.ZpGroupElement(
  82. _groupElement2Value, _p, _q);
  83. _zpGroupElementArray.push(groupElement);
  84. _groupElement3Value =
  85. new box.forge.jsbn.BigInteger(GROUP_ELEMENT_3_STR);
  86. groupElement = new box.commons.mathematical.ZpGroupElement(
  87. _groupElement3Value, _p, _q);
  88. _zpGroupElementArray.push(groupElement);
  89. _zpGroupElementArrayLarge = [];
  90. for (var i = 0; i < GROUP_ELEMENT_VALUES_FOR_LARGE_ARRAY.length; i++) {
  91. var value = new box.forge.jsbn.BigInteger(
  92. '' + GROUP_ELEMENT_VALUES_FOR_LARGE_ARRAY[i]);
  93. groupElement =
  94. new box.commons.mathematical.ZpGroupElement(value, _p, _q);
  95. _zpGroupElementArrayLarge.push(groupElement);
  96. }
  97. });
  98. _initialized = true;
  99. }
  100. });
  101. it('should exist as a module', function() {
  102. cryptolib(function(box) {
  103. expect(box.commons.mathematical).toBeDefined();
  104. });
  105. });
  106. describe('ZpSubgroup ..', function() {
  107. it('should be defined', function() {
  108. expect(_zpSubgroup).toBeDefined();
  109. expect(_zpSubgroup.getIdentity()).toBeDefined();
  110. });
  111. it('should be properly serialized', function() {
  112. var zpSubgroupJson = _zpSubgroup.stringify();
  113. expect(zpSubgroupJson).toBe(_zpSubgroupJson);
  114. });
  115. it('should be able to check group membership', function() {
  116. cryptolib('commons.mathematical', function(box) {
  117. var zpGroupElement = new box.commons.mathematical.ZpGroupElement(
  118. box.forge.jsbn.BigInteger.ONE, _p, _q);
  119. expect(_zpSubgroup.isGroupMember(zpGroupElement)).toBeTruthy();
  120. // check membership of member with different q
  121. var q2 = new box.forge.jsbn.BigInteger('19');
  122. var p2 = new box.forge.jsbn.BigInteger('37');
  123. var zpSubgroup2 = new box.commons.mathematical.ZpSubgroup(_g, p2, q2);
  124. var zpGroupElement2 = new box.commons.mathematical.ZpGroupElement(
  125. box.forge.jsbn.BigInteger.ONE, zpSubgroup2.getP(),
  126. zpSubgroup2.getQ());
  127. expect(!_zpSubgroup.isGroupMember(zpGroupElement2)).toBeTruthy();
  128. // check membership of member with positive value but not within the set
  129. zpGroupElement = new box.commons.mathematical.ZpGroupElement(
  130. new box.forge.jsbn.BigInteger('5'), _p, _q);
  131. expect(!_zpSubgroup.isGroupMember(zpGroupElement)).toBeTruthy();
  132. // throw error when the given element is incorrect
  133. var wrongElement;
  134. expect(!_zpSubgroup.isGroupMember(wrongElement)).toBeTruthy();
  135. });
  136. });
  137. it('should be able to compare with other groups', function() {
  138. cryptolib('commons.mathematical', function(box) {
  139. var zpSubgroup2 = new box.commons.mathematical.ZpSubgroup(_g, _p, _q);
  140. var q2 = new box.forge.jsbn.BigInteger('19');
  141. var p2 = new box.forge.jsbn.BigInteger('37');
  142. var zpSubgroup3 = new box.commons.mathematical.ZpSubgroup(_g, p2, q2);
  143. expect(_zpSubgroup.equals(zpSubgroup2)).toBeTruthy();
  144. expect(!_zpSubgroup.equals(zpSubgroup3)).toBeTruthy();
  145. });
  146. });
  147. });
  148. describe('ZpGroupElement ..', function() {
  149. it('should be defined', function() {
  150. expect(_zpSubgroupElem).toBeDefined();
  151. expect(_zpSubgroupElem.getElementValue().equals(_groupElementValue))
  152. .toBeTruthy();
  153. });
  154. it('should be properly serialized', function() {
  155. var zpGroupElementJson = _zpSubgroupElem.stringify();
  156. expect(zpGroupElementJson).toBe(_zpSubgroupElemJson);
  157. });
  158. it('should be able to multiply', function() {
  159. cryptolib('commons.mathematical', function(box) {
  160. var value = new box.forge.jsbn.BigInteger('2');
  161. var zpGroupElement2 =
  162. new box.commons.mathematical.ZpGroupElement(value, _p, _q);
  163. var zpSubgroupResult = _zpSubgroupElem.multiply(zpGroupElement2);
  164. expect(zpSubgroupResult).toBeDefined();
  165. expect(zpSubgroupResult.getElementValue().equals(
  166. new box.forge.jsbn.BigInteger('6')))
  167. .toBeTruthy();
  168. });
  169. });
  170. it('should be able to exponentiate', function() {
  171. cryptolib('commons.mathematical', function(box) {
  172. var value = new box.forge.jsbn.BigInteger('2');
  173. var zpGroupElement2 = new box.commons.mathematical.Exponent(_q, value);
  174. var zpSubgroupResult = _zpSubgroupElem.exponentiate(zpGroupElement2);
  175. expect(zpSubgroupResult).toBeDefined();
  176. expect(zpSubgroupResult.getElementValue().equals(
  177. new box.forge.jsbn.BigInteger('9')))
  178. .toBeTruthy();
  179. });
  180. });
  181. it('should be able to invert', function() {
  182. cryptolib(function(box) {
  183. var zpSubgroupResult = _zpSubgroupElem.invert();
  184. expect(zpSubgroupResult).toBeDefined();
  185. expect(zpSubgroupResult.getElementValue().equals(
  186. new box.forge.jsbn.BigInteger('8')))
  187. .toBeTruthy();
  188. });
  189. });
  190. });
  191. describe('Exponent ..', function() {
  192. it('should be defined', function() {
  193. expect(_exponent).toBeDefined();
  194. expect(_exponent.getValue().equals(_exponentValue)).toBeTruthy();
  195. });
  196. it('should be properly serialized', function() {
  197. var exponentJson = _exponent.stringify();
  198. expect(exponentJson).toBe(_exponentJson);
  199. });
  200. it('should be able to add another exponent', function() {
  201. cryptolib('commons.mathematical', function(box) {
  202. var value = new box.forge.jsbn.BigInteger('3');
  203. var exponent2 = new box.commons.mathematical.Exponent(_q, value);
  204. var exponentResult = _exponent.add(exponent2);
  205. expect(exponentResult).toBeDefined();
  206. expect(exponentResult.getValue().equals(
  207. new box.forge.jsbn.BigInteger('5')))
  208. .toBeTruthy();
  209. });
  210. });
  211. it('should be able to subtract another exponent', function() {
  212. cryptolib('commons.mathematical', function(box) {
  213. var value = new box.forge.jsbn.BigInteger('5');
  214. var exponent2 = new box.commons.mathematical.Exponent(_q, value);
  215. var exponentResult = exponent2.subtract(_exponent);
  216. expect(exponentResult).toBeDefined();
  217. expect(exponentResult.getValue().equals(
  218. new box.forge.jsbn.BigInteger('3')))
  219. .toBeTruthy();
  220. });
  221. });
  222. it('should be able to multiply another exponent', function() {
  223. cryptolib('commons.mathematical', function(box) {
  224. var value = new box.forge.jsbn.BigInteger('3');
  225. var exponent2 = new box.commons.mathematical.Exponent(_q, value);
  226. var exponentResult = _exponent.multiply(exponent2);
  227. expect(exponentResult).toBeDefined();
  228. expect(exponentResult.getValue().toString())
  229. .toEqual('' + _exponent.getValue() * exponent2.getValue() % _q);
  230. });
  231. });
  232. it('should be able to multiply exponents with large values', function() {
  233. var exponentResult = _exponent1Large.multiply(_exponent2Large);
  234. expect(exponentResult).toBeDefined();
  235. });
  236. it('should be able to negate an exponent', function() {
  237. cryptolib(function(box) {
  238. var exponentResult = _exponent.negate();
  239. expect(exponentResult).toBeDefined();
  240. expect(exponentResult.getValue().equals(
  241. new box.forge.jsbn.BigInteger('9')))
  242. .toBeTruthy();
  243. });
  244. });
  245. it('should throw error when multiplying an exponent with a different q parameter',
  246. function() {
  247. cryptolib('commons.mathematical', function(box) {
  248. var exponent2 = new box.commons.mathematical.Exponent(
  249. new forge.jsbn.BigInteger('89'), _exponentValue);
  250. expect(function() {
  251. _exponent.multiply(exponent2);
  252. }).toThrow();
  253. });
  254. });
  255. it('should throw error when multiplying an exponent which is undefined',
  256. function() {
  257. expect(function() {
  258. _exponent.multiply(undefined);
  259. }).toThrow();
  260. });
  261. it('should throw error when multiplying an exponent which is null',
  262. function() {
  263. expect(function() {
  264. _exponent.multiply(null);
  265. }).toThrow();
  266. });
  267. });
  268. describe('groupUtils ..', function() {
  269. it('should be able to deserialize a ZpSubgroup', function() {
  270. cryptolib('commons.mathematical', function(box) {
  271. var zpSubgroupFromJson =
  272. box.commons.mathematical.groupUtils.deserializeGroup(
  273. _zpSubgroupJson);
  274. expect(zpSubgroupFromJson).toBeDefined();
  275. expect(zpSubgroupFromJson.getP()).toEqual(_p);
  276. expect(zpSubgroupFromJson.getQ()).toEqual(_q);
  277. expect(zpSubgroupFromJson.getGenerator().getElementValue()).toEqual(_g);
  278. });
  279. });
  280. it('should be able to deserialize a ZpGroupElement', function() {
  281. cryptolib('commons.mathematical', function(box) {
  282. var zpGroupElementFromJson =
  283. box.commons.mathematical.groupUtils.deserializeGroupElement(
  284. _zpSubgroupElemJson);
  285. expect(zpGroupElementFromJson).toBeDefined();
  286. expect(zpGroupElementFromJson.equals(_zpSubgroupElem)).toBeTruthy();
  287. });
  288. });
  289. it('should be able to deserialize an Exponent', function() {
  290. cryptolib('commons.mathematical', function(box) {
  291. var exponentFromJson =
  292. box.commons.mathematical.groupUtils.deserializeExponent(
  293. _exponentJson);
  294. expect(exponentFromJson).toBeDefined();
  295. expect(exponentFromJson.equals(_exponent)).toBeTruthy();
  296. });
  297. });
  298. it('should be able to compress group elements', function() {
  299. cryptolib('commons.mathematical', function(box) {
  300. var compressedElement =
  301. box.commons.mathematical.groupUtils.compressGroupElements(
  302. _zpSubgroup, _zpGroupElementArray);
  303. expect(compressedElement).toBeDefined();
  304. expect(compressedElement.getElementValue().equals(
  305. new forge.jsbn.BigInteger('8')))
  306. .toBeTruthy();
  307. compressedElement =
  308. box.commons.mathematical.groupUtils.compressGroupElements(
  309. _zpSubgroup, _zpGroupElementArrayLarge);
  310. expect(compressedElement).toBeDefined();
  311. expect(compressedElement.getElementValue().equals(
  312. new forge.jsbn.BigInteger('12')))
  313. .toBeTruthy();
  314. expect(function() {
  315. var zpSubgroupNOTDEFINED;
  316. box.commons.mathematical.groupUtils.compressGroupElements(
  317. zpSubgroupNOTDEFINED, _zpGroupElementArrayLarge);
  318. }).toThrow();
  319. });
  320. });
  321. it('should be able to build an array by compressing the final element',
  322. function() {
  323. cryptolib('commons.mathematical', function(box) {
  324. var requiredLength = 4;
  325. var compressedArray =
  326. box.commons.mathematical.groupUtils
  327. .buildListWithCompressedFinalElement(
  328. _zpSubgroup, _zpGroupElementArrayLarge, requiredLength);
  329. expect(compressedArray.length).toBe(requiredLength);
  330. var expectedCompressedArray = [];
  331. var expectedCompressedArrayValues = [3, 4, 6, 4];
  332. for (var i = 0; i < expectedCompressedArrayValues.length; i++) {
  333. var value = new box.forge.jsbn.BigInteger(
  334. '' + expectedCompressedArrayValues[i]);
  335. var groupElement =
  336. new box.commons.mathematical.ZpGroupElement(value, _p, _q);
  337. expectedCompressedArray.push(groupElement);
  338. }
  339. var equals = true;
  340. for (var j = 0; j < compressedArray.length; j++) {
  341. if (!compressedArray[j].equals(expectedCompressedArray[j])) {
  342. equals = false;
  343. }
  344. }
  345. expect(equals).toBeTruthy();
  346. expect(function() {
  347. var zpSubgroupNOTDEFINED;
  348. box.commons.mathematical.groupUtils
  349. .buildListWithCompressedFinalElement(
  350. zpSubgroupNOTDEFINED, _zpGroupElementArrayLarge,
  351. requiredLength);
  352. }).toThrow();
  353. });
  354. });
  355. it('should be able to build an array by compressing the final exponent',
  356. function() {
  357. cryptolib('commons.mathematical', function(box) {
  358. var requiredLength = 4;
  359. var value;
  360. var exponent;
  361. var exponentValues = [1, 2, 3, 4, 6, 8, 9, 12, 13, 16, 18];
  362. var exponentArray = [];
  363. for (var i = 0; i < exponentValues.length; i++) {
  364. value = new box.forge.jsbn.BigInteger('' + exponentValues[i]);
  365. exponent = new box.commons.mathematical.Exponent(_q, value);
  366. exponentArray.push(exponent);
  367. }
  368. var compressedArray =
  369. box.commons.mathematical.groupUtils
  370. .buildListWithCompressedFinalExponent(
  371. _zpSubgroup, exponentArray, requiredLength);
  372. expect(compressedArray.length).toBe(requiredLength);
  373. var expectedCompressedArray = [];
  374. var expectedCompressedArrayValues = [1, 2, 3, 9];
  375. for (var j = 0; j < expectedCompressedArrayValues.length; j++) {
  376. value = new box.forge.jsbn.BigInteger(
  377. '' + expectedCompressedArrayValues[j]);
  378. exponent = new box.commons.mathematical.Exponent(_q, value);
  379. expectedCompressedArray.push(exponent);
  380. }
  381. var equals = true;
  382. for (var k = 0; k < compressedArray.length; k++) {
  383. if (!compressedArray[k].equals(expectedCompressedArray[k])) {
  384. equals = false;
  385. }
  386. }
  387. expect(equals).toBeTruthy();
  388. });
  389. });
  390. it('should be able to generate a random Exponent', function() {
  391. cryptolib(
  392. 'commons.mathematical', 'primitives.securerandom', function(box) {
  393. var zpSubgroup =
  394. box.commons.mathematical.groupUtils.buildZpSubgroupFromPAndG(
  395. _p, _g);
  396. var secureRandomFactory =
  397. new box.primitives.securerandom.factory.SecureRandomFactory();
  398. var cryptoRandomInteger =
  399. secureRandomFactory.getCryptoRandomInteger();
  400. var randomExponent =
  401. box.commons.mathematical.groupUtils.generateRandomExponent(
  402. zpSubgroup, cryptoRandomInteger);
  403. expect(randomExponent).toBeDefined();
  404. expect(function() {
  405. var zpSubgroupNOTDEFINED;
  406. box.commons.mathematical.groupUtils.generateRandomExponent(
  407. zpSubgroupNOTDEFINED, cryptoRandomInteger);
  408. }).toThrow();
  409. expect(function() {
  410. box.commons.mathematical.groupUtils.generateRandomExponent(
  411. 1, cryptoRandomInteger);
  412. }).toThrow();
  413. });
  414. });
  415. it('should be able to generate a group element symmetric key', function() {
  416. cryptolib(
  417. 'commons.mathematical', 'primitives.securerandom', function(box) {
  418. var zpSubgroup =
  419. box.commons.mathematical.groupUtils.buildZpSubgroupFromPAndG(
  420. _p, _g);
  421. var secureRandomFactory =
  422. new box.primitives.securerandom.factory.SecureRandomFactory();
  423. var cryptoRandomInteger =
  424. secureRandomFactory.getCryptoRandomInteger();
  425. for (var i = 0; i < 100; i++) {
  426. var groupElementSymmetricKey =
  427. box.commons.mathematical.groupUtils
  428. .generateGroupElementSecretKey(
  429. zpSubgroup, cryptoRandomInteger);
  430. expect(groupElementSymmetricKey).toBeDefined();
  431. expect(zpSubgroup.isGroupMember(groupElementSymmetricKey))
  432. .toBeTruthy();
  433. }
  434. });
  435. });
  436. it('should be able to build a ZpSubgroup, given a p parameter and a generator',
  437. function() {
  438. cryptolib('commons.mathematical', function(box) {
  439. var zpSubgroup =
  440. new box.commons.mathematical.groupUtils.buildZpSubgroupFromPAndG(
  441. _p, _g);
  442. expect(zpSubgroup).toBeDefined();
  443. var undefinedP;
  444. var undefinedGenerator;
  445. expect(function() {
  446. box.commons.mathematical.groupUtils.buildZpSubgroupFromPAndG(
  447. undefinedP, undefinedGenerator);
  448. }).toThrow();
  449. expect(function() {
  450. box.commons.mathematical.groupUtils.buildZpSubgroupFromPAndG(1, 2);
  451. }).toThrow();
  452. });
  453. });
  454. it('should be able to build a random ZpSubgroup, given a p parameter length',
  455. function() {
  456. cryptolib(
  457. 'commons.mathematical', 'primitives.securerandom', function(box) {
  458. var secureRandomFactory = new box.primitives.securerandom.factory
  459. .SecureRandomFactory();
  460. var cryptoRandomBytes =
  461. secureRandomFactory.getCryptoRandomBytes();
  462. var bitLengthOfP = 16;
  463. var certainty = box.MINIMUM_PRIME_CERTAINTY_LEVEL;
  464. var zpSubgroup =
  465. new box.commons.mathematical.groupUtils
  466. .buildRandomZpSubgroupFromLengthOfP(
  467. bitLengthOfP, cryptoRandomBytes, certainty);
  468. expect(zpSubgroup).toBeDefined();
  469. });
  470. });
  471. it('should be able to extract the number of group members from a list of possible members',
  472. function() {
  473. cryptolib('commons.mathematical', function(box) {
  474. var possibleGroupMembersArray = [];
  475. for (var i = 0; i < GROUP_ELEMENT_VALUES_FOR_LARGE_ARRAY.length;
  476. i++) {
  477. possibleGroupMembersArray.push(new box.forge.jsbn.BigInteger(
  478. '' + GROUP_ELEMENT_VALUES_FOR_LARGE_ARRAY[i]));
  479. }
  480. var numMembersRequired =
  481. GROUP_ELEMENT_VALUES_FOR_LARGE_ARRAY.length - 2;
  482. var extractedGroupMembersArray =
  483. new box.commons.mathematical.groupUtils
  484. .extractNumberOfGroupMembersFromListOfPossibleMembers(
  485. possibleGroupMembersArray, _zpSubgroup,
  486. numMembersRequired);
  487. expect(extractedGroupMembersArray).toBeDefined();
  488. expect(extractedGroupMembersArray.length).toBe(numMembersRequired);
  489. // throw an error when more members are required than are available.
  490. var excessNumMembersRequired =
  491. GROUP_ELEMENT_VALUES_FOR_LARGE_ARRAY.length + 1;
  492. expect(function() {
  493. box.commons.mathematical.groupUtils
  494. .extractNumberOfGroupMembersFromListOfPossibleMembers(
  495. possibleGroupMembersArray, _zpSubgroup,
  496. excessNumMembersRequired);
  497. }).toThrow();
  498. // throw an error when arguments are undefined
  499. expect(function() {
  500. box.commons.mathematical.groupUtils
  501. .extractNumberOfGroupMembersFromListOfPossibleMembers(
  502. undefined, undefined, undefined);
  503. }).toThrow();
  504. // throw an error when array is empty
  505. expect(function() {
  506. box.commons.mathematical.groupUtils
  507. .extractNumberOfGroupMembersFromListOfPossibleMembers(
  508. [], _zpSubgroup, numMembersRequired);
  509. }).toThrow();
  510. // throw an error when the given array is not an array
  511. expect(function() {
  512. box.commons.mathematical.groupUtils
  513. .extractNumberOfGroupMembersFromListOfPossibleMembers(
  514. 1, _zpSubgroup, numMembersRequired);
  515. }).toThrow();
  516. });
  517. });
  518. it('should be able to divide two group element arrays', function() {
  519. cryptolib('commons.mathematical', function(box) {
  520. var value;
  521. var groupElement;
  522. var zpGroupElementsArray = [];
  523. value = new box.forge.jsbn.BigInteger('1');
  524. groupElement =
  525. new box.commons.mathematical.ZpGroupElement(value, _p, _q);
  526. zpGroupElementsArray.push(groupElement);
  527. value = new box.forge.jsbn.BigInteger('2');
  528. groupElement =
  529. new box.commons.mathematical.ZpGroupElement(value, _p, _q);
  530. zpGroupElementsArray.push(groupElement);
  531. value = new box.forge.jsbn.BigInteger('16');
  532. groupElement =
  533. new box.commons.mathematical.ZpGroupElement(value, _p, _q);
  534. zpGroupElementsArray.push(groupElement);
  535. var dividedElementsArray =
  536. new box.commons.mathematical.groupUtils.divide(
  537. _zpGroupElementArray, zpGroupElementsArray, _zpSubgroup);
  538. expect(dividedElementsArray).toBeDefined();
  539. });
  540. });
  541. it('should be able to exponentiate a group element array', function() {
  542. cryptolib('commons.mathematical', function(box) {
  543. var exponentiatedElementArray =
  544. new box.commons.mathematical.groupUtils.exponentiateArrays(
  545. _zpGroupElementArray, _exponent, _zpSubgroup);
  546. expect(exponentiatedElementArray).toBeDefined();
  547. expect(exponentiatedElementArray.length)
  548. .toEqual(_zpGroupElementArray.length);
  549. expect(exponentiatedElementArray[0].getElementValue().toString())
  550. .toEqual('' + (Math.pow(_groupElement1Value, _exponentValue) % _p));
  551. expect(exponentiatedElementArray[1].getElementValue().toString())
  552. .toEqual('' + (Math.pow(_groupElement2Value, _exponentValue) % _p));
  553. expect(exponentiatedElementArray[2].getElementValue().toString())
  554. .toEqual('' + (Math.pow(_groupElement3Value, _exponentValue) % _p));
  555. expect(exponentiatedElementArray[0].getP()).toEqual(_p);
  556. expect(exponentiatedElementArray[1].getP()).toEqual(_p);
  557. expect(exponentiatedElementArray[2].getP()).toEqual(_p);
  558. expect(exponentiatedElementArray[0].getQ()).toEqual(_q);
  559. expect(exponentiatedElementArray[1].getQ()).toEqual(_q);
  560. expect(exponentiatedElementArray[2].getQ()).toEqual(_q);
  561. });
  562. });
  563. it('should honor the validation flag', function() {
  564. cryptolib('commons.mathematical', function(box) {
  565. var zpGroupElementArray = [];
  566. for (var i = 1; i < GROUP_ELEMENT_VALUES_FOR_LARGE_ARRAY.length; i++) {
  567. var numberString = GROUP_ELEMENT_VALUES_FOR_LARGE_ARRAY[i].toString();
  568. var value = new box.forge.jsbn.BigInteger(numberString);
  569. var groupElement =
  570. new box.commons.mathematical.ZpGroupElement(value, _p, _q);
  571. zpGroupElementArray.push(groupElement);
  572. }
  573. // Ensure group membership is not tested with no flag.
  574. var spy = spyOn(_zpSubgroup, 'isGroupMember');
  575. box.commons.mathematical.groupUtils.exponentiateArrays(
  576. zpGroupElementArray, _exponent, _zpSubgroup);
  577. expect(spy).toHaveBeenCalledTimes(0);
  578. // Ensure group membership is not tested with a false flag.
  579. box.commons.mathematical.groupUtils.exponentiateArrays(
  580. zpGroupElementArray, _exponent, _zpSubgroup, false);
  581. expect(spy).toHaveBeenCalledTimes(0);
  582. // The function should crash, as the array contains elements that do not
  583. // belong to the group.
  584. expect(function() {
  585. box.commons.mathematical.groupUtils.exponentiateArrays(
  586. zpGroupElementArray, _exponent, _zpSubgroup, true);
  587. }).toThrow();
  588. });
  589. });
  590. describe(
  591. 'Exponentiation of a ZpGroupElement array should throw an error ',
  592. function() {
  593. it(' when the base element is not from the current group',
  594. function() {
  595. cryptolib('commons.mathematical', function(box) {
  596. var value = new box.forge.jsbn.BigInteger('19');
  597. var groupElement =
  598. new box.commons.mathematical.ZpGroupElement(value, _p, _q);
  599. var zpGroupElementArray = [];
  600. zpGroupElementArray.push(groupElement);
  601. expect(function() {
  602. box.commons.mathematical.groupUtils.exponentiateArrays(
  603. zpGroupElementArray, _exponent, _zpSubgroup, true);
  604. }).toThrow();
  605. });
  606. });
  607. it('when the ZpGroupElement array is undefined', function() {
  608. cryptolib('commons.mathematical', function(box) {
  609. expect(function() {
  610. box.commons.mathematical.groupUtils.exponentiateArrays(
  611. undefined, _exponent, _zpSubgroup);
  612. }).toThrow();
  613. });
  614. });
  615. it('when the ZpGroupElement array is empty', function() {
  616. cryptolib('commons.mathematical', function(box) {
  617. expect(function() {
  618. box.commons.mathematical.groupUtils.exponentiateArrays(
  619. [], _exponent, _zpSubgroup);
  620. }).toThrow();
  621. });
  622. });
  623. it('when the Exponent is undefined', function() {
  624. cryptolib('commons.mathematical', function(box) {
  625. expect(function() {
  626. box.commons.mathematical.groupUtils.exponentiateArrays(
  627. _zpGroupElementArray, undefined, _zpSubgroup);
  628. }).toThrow();
  629. });
  630. });
  631. it('when the Exponent is null', function() {
  632. cryptolib('commons.mathematical', function(box) {
  633. expect(function() {
  634. box.commons.mathematical.groupUtils.exponentiateArrays(
  635. _zpGroupElementArray, null, _zpSubgroup);
  636. }).toThrow();
  637. });
  638. });
  639. it('when the ZpSubgroup is undefined', function() {
  640. cryptolib('commons.mathematical', function(box) {
  641. expect(function() {
  642. box.commons.mathematical.groupUtils.exponentiateArrays(
  643. _zpGroupElementArray, _exponent, undefined);
  644. }).toThrow();
  645. });
  646. });
  647. it('when the ZpSubgroup is null', function() {
  648. cryptolib('commons.mathematical', function(box) {
  649. expect(function() {
  650. box.commons.mathematical.groupUtils.exponentiateArrays(
  651. _zpGroupElementArray, _exponent, null);
  652. }).toThrow();
  653. });
  654. });
  655. });
  656. });
  657. });