/* * 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 Exponent = require('./exponent'); var validator = require('./input-validator'); var codec = require('scytl-codec'); module.exports = ZpGroupElement; /** * @class ZpGroupElement * @classdesc Encapsulates a Zp group element. To instantiate this object, use * the method {@link MathematicalService.newZpGroupElement}. * @property {forge.jsbn.BigInteger} p The modulus of the Zp subgroup to which * this Zp group element belongs. * @property {forge.jsbn.BigInteger} q The order of the Zp subgroup to which * this Zp group element belongs. * @property {forge.jsbn.BigInteger} value The value of this Zp group element. */ function ZpGroupElement(p, q, value) { this.p = p; this.q = q; this.value = value; Object.freeze(this); } ZpGroupElement.prototype = { /** * Multiplies this Zp group element by the Zp group element provided as * input, using the formula: *

* (this * element) mod p * * @function multiply * @memberof ZpGroupElement * @param {ZpGroupElement} * element The element to be multiplied with this element. * @returns {ZpGroupElement} The result of the multiplication operation. * @throws {Error} * If the input data validation fails. */ multiply: function(element) { checkZpGroupElement( element, 'Zp group element to multiply with this Zp group element', this.p, this.q); var newValue = this.value.multiply(element.value).mod(this.p); return new ZpGroupElement(this.p, this.q, newValue); }, /** * Exponentiates this Zp group element with the exponent provided as input, * using the formula: *

* (thisexponent) mod p * * @function exponentiate * @memberof ZpGroupElement * @param {Exponent} * exponent The exponent to use in the exponentiation. * @returns {ZpGroupElement} The result of the exponentiation operation. * @throws {Error} * If the input data validation fails. */ exponentiate: function(exponent) { checkExponent( exponent, 'exponent with which to exponentiate this Zp group element', this.q); var newValue = this.value.modPow(exponent.value, this.p); return new ZpGroupElement(this.p, this.q, newValue); }, /** * Calculates the inverse of this Zp group element, using the formula: *

* (this-1) mod p * * @function invert * @memberof ZpGroupElement * @returns {ZpGroupElement} The result of the inverse operation. */ invert: function() { var newValue = this.value.modInverse(this.p); return new ZpGroupElement(this.p, this.q, newValue); }, /** * Checks if this Zp group element is equal to the Zp group element provided * as input. *

* Elements are considered equal if: *

* * @function equals * @memberof ZpGroupElement * @param {ZpGroupElement} * element The Zp group element to compare with this Zp group * element. * @returns {boolean} True if the equality holds, false otherwise. * @throws {Error} * If the input data validation fails. */ equals: function(element) { validator.checkZpGroupElement( element, 'Zp group element to compare with this Zp group element'); if (element.p.equals(this.p) && element.q.equals(this.q) && element.value.equals(this.value)) { return true; } else { return false; } }, /** * 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 ZpGroupElement * @returns {string} The JSON string representation of this object. */ toJson: function() { return JSON.stringify({ zpGroupElement: { p: codec.base64Encode(this.p), q: codec.base64Encode(this.q), value: codec.base64Encode(this.value) } }); } }; function checkZpGroupElement(element, label, p, q) { validator.checkZpGroupElement(element, label); validator.checkIsInstanceOf(element, ZpGroupElement, 'ZpGroupElement', label); var pFound = element.p; if (!pFound.equals(p)) { throw new Error( 'Expected ' + label + ' to belong to Zp subgroup with modulus p: ' + p + ' ; Found p: ' + pFound); } var qFound = element.q; if (!qFound.equals(q)) { throw new Error( 'Expected ' + label + ' to belong to Zp subgroup of order q: ' + q + ' ; Found q: ' + qFound); } } function checkExponent(exponent, label, q) { validator.checkExponent(exponent, label, q); validator.checkIsInstanceOf(exponent, Exponent, 'Exponent', label); }