zp-subgroup.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  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 ZpGroupElement = require('./zp-group-element');
  11. var validator = require('./input-validator');
  12. var codec = require('scytl-codec');
  13. var forge = require('node-forge');
  14. module.exports = ZpSubgroup;
  15. var BigInteger = forge.jsbn.BigInteger;
  16. /**
  17. * Encapsulates a Zp subgroup. To instantiate this object, use the method {@link
  18. * MathematicalService.newZpSubgroup}.
  19. * <p>
  20. * Given a prime <code>p</code>, the Zp group is defined as the set of all
  21. * <code>Integers (mod p)</code>. A Zp subgroup is a subset of the Zp group,
  22. * of order <code>q</code>, defined as a set of <code>Primes (mod p)</code>.
  23. * <p>
  24. * Both the Zp group and the Zp subgroup are finite cyclic groups, which means
  25. * that all of their elements can be generated by exponentiating a special Zp
  26. * group element called the <code>generator</code>.
  27. * <p>
  28. * When the modulus <code>p</code> and the order <code>q</code> are related
  29. * by the restriction, <code>p = 2q + 1</code>, then the Zp subgroup can also
  30. * be referred to as a quadratic residue group.
  31. *
  32. * @class ZpSubgroup
  33. * @property {forge.jsbn.BigInteger} p The modulus of the Zp subgroup.
  34. * @property {forge.jsbn.BigInteger} q The order of the Zp subgroup.
  35. * @property {ZpGroupElement} generator The generator element of the Zp
  36. * subgroup.
  37. * @property {ZpGroupElement} identity The identity element of the Zp subgroup.
  38. */
  39. function ZpSubgroup(p, q, g) {
  40. this.p = p;
  41. this.q = q;
  42. this.generator = new ZpGroupElement(p, q, g);
  43. this.identity = new ZpGroupElement(p, q, BigInteger.ONE);
  44. Object.freeze(this);
  45. }
  46. ZpSubgroup.prototype = {
  47. /**
  48. * Checks whether a Zp group element provided as input is a member of this
  49. * Zp subgroup.
  50. *
  51. * An element is a member of the Zp subgroup if its value satisfies the
  52. * following conditions:
  53. * <ul>
  54. * <li><code>0 < value < p</code></li>
  55. * <li><code>value<sup>q</sup> mod p = 1</code></li>
  56. * </ul>
  57. *
  58. * @function isGroupMember
  59. * @memberof ZpSubgroup
  60. * @param {ZpGroupElement}
  61. * element The Zp group element whose group membership is to be
  62. * checked.
  63. * @returns {boolean} <code>true</code> if the element provided as input
  64. * is a member of the subgroup, <code>false</false> otherwise.
  65. * @throws {Error}
  66. * If the input data validation fails.
  67. */
  68. isGroupMember: function(element) {
  69. checkZpGroupElement(
  70. element, 'Zp group element to check for group membership');
  71. if (element.p.equals(this.p)) {
  72. return element.value.modPow(this.q, this.p).equals(BigInteger.ONE);
  73. } else {
  74. return false;
  75. }
  76. },
  77. /**
  78. * Checks if this Zp subgroup is equal to the Zp subgroup provided as input.
  79. *
  80. * @function equals
  81. * @memberof ZpSubgroup
  82. * @param {ZpSubgroup}
  83. * group The Zp subgroup to compare with this Zp subgroup.
  84. * @returns {boolean} True if the equality holds, false otherwise.
  85. * @throws {Error}
  86. * If the input data validation fails.
  87. */
  88. equals: function(group) {
  89. validator.checkIsInstanceOf(
  90. group, ZpSubgroup, 'ZpSubgroup',
  91. 'Zp subgroup to compare with this Zp subgroup');
  92. if (group.p.equals(this.p) && group.q.equals(this.q) &&
  93. group.generator.equals(this.generator)) {
  94. return true;
  95. } else {
  96. return false;
  97. }
  98. },
  99. /**
  100. * Check whether this Zp subgroup is a quadratic residue group, which is
  101. * defined such that <code>p = 2q + 1</code>.
  102. *
  103. * @function isQuadraticResidueGroup
  104. * @memberof ZpSubgroup
  105. * @returns {boolean} <code>true</code> if the given group is a quadratic
  106. * residue group, <code>false</code> otherwise.
  107. */
  108. isQuadraticResidueGroup: function() {
  109. return this.p.equals(
  110. new BigInteger('2').multiply(this.q).add(BigInteger.ONE));
  111. },
  112. /**
  113. * Serializes this object into a JSON string representation.
  114. * <p>
  115. * <b>IMPORTANT:</b> This serialization must be exactly the same as the
  116. * corresponding serialization in the library <code>cryptoLib</code>,
  117. * implemented in Java, since the two libraries are expected to communicate
  118. * with each other via these serializations.
  119. *
  120. * @function toJson
  121. * @memberof ZpSubgroup
  122. * @returns {string} The JSON string representation of this object.
  123. */
  124. toJson: function() {
  125. return JSON.stringify({
  126. zpSubgroup: {
  127. p: codec.base64Encode(this.p),
  128. q: codec.base64Encode(this.q),
  129. g: codec.base64Encode(this.generator.value)
  130. }
  131. });
  132. }
  133. };
  134. function checkZpGroupElement(element, label) {
  135. validator.checkZpGroupElement(element, label);
  136. validator.checkIsInstanceOf(element, ZpGroupElement, 'ZpGroupElement', label);
  137. }