/* * 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: *
* 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);
}