/* * Copyright 2018 Scytl Secure Electronic Voting SA * * All rights reserved * * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package */ /* jshint node:true */ 'use strict'; var ZpGroupElement = require('./zp-group-element'); var validator = require('./input-validator'); var codec = require('scytl-codec'); var forge = require('node-forge'); module.exports = ZpSubgroup; var BigInteger = forge.jsbn.BigInteger; /** * Encapsulates a Zp subgroup. To instantiate this object, use the method {@link * MathematicalService.newZpSubgroup}. *

* Given a prime p, the Zp group is defined as the set of all * Integers (mod p). A Zp subgroup is a subset of the Zp group, * of order q, defined as a set of Primes (mod p). *

* Both the Zp group and the Zp subgroup are finite cyclic groups, which means * that all of their elements can be generated by exponentiating a special Zp * group element called the generator. *

* When the modulus p and the order q are related * by the restriction, p = 2q + 1, then the Zp subgroup can also * be referred to as a quadratic residue group. * * @class ZpSubgroup * @property {forge.jsbn.BigInteger} p The modulus of the Zp subgroup. * @property {forge.jsbn.BigInteger} q The order of the Zp subgroup. * @property {ZpGroupElement} generator The generator element of the Zp * subgroup. * @property {ZpGroupElement} identity The identity element of the Zp subgroup. */ function ZpSubgroup(p, q, g) { this.p = p; this.q = q; this.generator = new ZpGroupElement(p, q, g); this.identity = new ZpGroupElement(p, q, BigInteger.ONE); Object.freeze(this); } ZpSubgroup.prototype = { /** * Checks whether a Zp group element provided as input is a member of this * Zp subgroup. * * An element is a member of the Zp subgroup if its value satisfies the * following conditions: *

* * @function isGroupMember * @memberof ZpSubgroup * @param {ZpGroupElement} * element The Zp group element whose group membership is to be * checked. * @returns {boolean} true if the element provided as input * is a member of the subgroup, false otherwise. * @throws {Error} * If the input data validation fails. */ isGroupMember: function(element) { checkZpGroupElement( element, 'Zp group element to check for group membership'); if (element.p.equals(this.p)) { return element.value.modPow(this.q, this.p).equals(BigInteger.ONE); } else { return false; } }, /** * Checks if this Zp subgroup is equal to the Zp subgroup provided as input. * * @function equals * @memberof ZpSubgroup * @param {ZpSubgroup} * group The Zp subgroup to compare with this Zp subgroup. * @returns {boolean} True if the equality holds, false otherwise. * @throws {Error} * If the input data validation fails. */ equals: function(group) { validator.checkIsInstanceOf( group, ZpSubgroup, 'ZpSubgroup', 'Zp subgroup to compare with this Zp subgroup'); if (group.p.equals(this.p) && group.q.equals(this.q) && group.generator.equals(this.generator)) { return true; } else { return false; } }, /** * Check whether this Zp subgroup is a quadratic residue group, which is * defined such that p = 2q + 1. * * @function isQuadraticResidueGroup * @memberof ZpSubgroup * @returns {boolean} true if the given group is a quadratic * residue group, false otherwise. */ isQuadraticResidueGroup: function() { return this.p.equals( new BigInteger('2').multiply(this.q).add(BigInteger.ONE)); }, /** * Serializes this object into a JSON string representation. *

* IMPORTANT: This serialization must be exactly the same as the * corresponding serialization in the library cryptoLib, * implemented in Java, since the two libraries are expected to communicate * with each other via these serializations. * * @function toJson * @memberof ZpSubgroup * @returns {string} The JSON string representation of this object. */ toJson: function() { return JSON.stringify({ zpSubgroup: { p: codec.base64Encode(this.p), q: codec.base64Encode(this.q), g: codec.base64Encode(this.generator.value) } }); } }; function checkZpGroupElement(element, label) { validator.checkZpGroupElement(element, label); validator.checkIsInstanceOf(element, ZpGroupElement, 'ZpGroupElement', label); }