123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- /*
- * 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 ZpSubgroup = require('./zp-subgroup');
- var Exponent = require('./exponent');
- var MathematicalGroupHandler = require('./group-handler');
- var constants = require('./constants');
- var validator = require('./input-validator');
- var forge = require('node-forge');
- var BigInteger = forge.jsbn.BigInteger;
- module.exports = MathematicalRandomGenerator;
- /**
- * @class MathematicalRandomGenerator
- * @classdesc The mathematical random generator API. To instantiate this object,
- * use the method {@link MathematicalService.newRandomGenerator}.
- * @hideconstructor
- * @param {SeureRandomService}
- * secureRandomService The secure random service to use.
- */
- function MathematicalRandomGenerator(secureRandomService) {
- var randomGenerator_ = secureRandomService.newRandomGenerator();
- var mathGroupHandler_ = new MathematicalGroupHandler();
- /**
- * Generates a random Zp group element belonging to the Zp subgroup provided
- * as input.
- *
- * @function nextZpGroupElement
- * @memberof MathematicalRandomGenerator
- * @param {ZpSubgroup}
- * group The Zp subgroup to which the Zp group element belongs.
- * @param {Object}
- * [options] An object containing optional arguments.
- * @param {SecureRandomGenerator}
- * [options.secureRandomGenerator=Internal generator used] The
- * secure random generator to use.
- * @param {boolean}
- * [options.useShortExponent=false] If <code>true</code>, then
- * a short exponent is to be generated for the exponentiation
- * used to generate the Zp group element.
- * @returns {ZpGroupElement} The generated Zp group element.
- * @throws {Error}
- * If the input validation fails.
- */
- this.nextZpGroupElement = function(group, options) {
- validator.checkIsInstanceOf(
- group, ZpSubgroup, 'ZpSubgroup',
- 'Zp subgroup to which randomly generated element is to belong');
- var exponent = this.nextExponent(group, options);
- return group.generator.exponentiate(exponent);
- };
- /**
- * Generates a random exponent associated with the Zp subgroup provided as
- * input. The value of the exponent will be within the range <code>[0,
- * q-1]</code>.
- *
- * @function nextExponent
- * @memberof MathematicalRandomGenerator
- * @param {ZpSubgroup}
- * group The Zp subgroup to which the exponent is to be
- * associated.
- * @param {Object}
- * [options] An object containing optional arguments.
- * @param {SecureRandomGenerator}
- * [options.secureRandomGenerator=Internal generator is used] The
- * secure random generator to use.
- * @param {boolean}
- * [options.useShortExponent=false] If <code>true</code>, then
- * a short exponent is to be generated.
- * @returns {Exponent} The generated exponent.
- * @throws {Error}
- * If the input validation fails.
- */
- this.nextExponent = function(group, options) {
- validator.checkIsInstanceOf(
- group, ZpSubgroup, 'ZpSubgroup',
- 'Zp subgroup to which randomly generated exponent is to be associated');
- options = options || {};
- var randomGenerator = options.secureRandomGenerator || randomGenerator_;
- validator.checkIsObjectWithProperties(
- randomGenerator,
- 'Random BigInteger generator for random exponent generation');
- var useShortExponent = options.useShortExponent || false;
- var q = group.q;
- var qBitLength = q.bitLength();
- var randomExponentBitLength;
- if (useShortExponent) {
- if (qBitLength < constants.SHORT_EXPONENT_BIT_LENGTH) {
- throw new Error(
- 'Zp subgroup order bit length must be greater than or equal to short exponent bit length : ' +
- constants.SHORT_EXPONENT_BIT_LENGTH + '; Found ' + qBitLength);
- }
- randomExponentBitLength = constants.SHORT_EXPONENT_BIT_LENGTH;
- } else {
- randomExponentBitLength = qBitLength;
- }
- var randomExponentValue;
- var randomExponentFound = false;
- while (!randomExponentFound) {
- randomExponentValue =
- randomGenerator.nextBigInteger(randomExponentBitLength);
- if (randomExponentValue.compareTo(q) < 0) {
- randomExponentFound = true;
- }
- }
- return new Exponent(q, randomExponentValue);
- };
- /**
- * Generates a random quadratic residue Zp subgroup, that has the specified
- * bit length for its modulus <code>p</code> and the specified certainty
- * of having its modulus and the order <code>q</code> being prime.
- * <p>
- * This method generates a Zp subgroup that satisfies the condition:
- * <p>
- * <code>p =
- * (q * 2) + 1</code>
- * <p>
- * <b>Note:</b> The minimum bit length of the modulus <code>p</code> that
- * is permitted by this method is 2. If a bit length less than 2 is
- * requested, then an Error will be thrown.
- *
- * @function nextQuadraticResidueGroup
- * @memberof MathematicalRandomGenerator
- * @param {number}
- * pBitLength The modulus bit length of the Zp subgroup to
- * generate.
- * @param {number}
- * certainty The level of certainty that the order <code>q</code>
- * of the generated group is prime.
- * @param {Object}
- * [options] An object containing optional arguments.
- * @param {SecureRandomGenerator}
- * [options.secureRandomGenerator=Internal generator used] The
- * secure random generator to use.
- * @returns {ZpSubgroup} The generated quadratic residue group.
- * @throws {Error}
- * If the input validation fails.
- */
- this.nextQuadraticResidueGroup = function(pBitLength, certainty, options) {
- checkQrGroupGenerationData(pBitLength, certainty);
- options = options || {};
- var randomGenerator = options.secureRandomGenerator || randomGenerator_;
- validator.checkIsObjectWithProperties(
- randomGenerator,
- 'Random bytes generator for random quadratic residue Zp subgroup generation');
- var p, q;
- var randomGroupFound = false;
- var primeOptions = {prng: randomGenerator};
- var callback = function(err, num) {
- if (err) {
- throw new Error('Error while generating prime number; ' + err);
- }
- p = num;
- q = num.subtract(BigInteger.ONE).divide(new BigInteger('2'));
- };
- while (!randomGroupFound) {
- forge.prime.generateProbablePrime(pBitLength, primeOptions, callback);
- if (q.isProbablePrime(certainty)) {
- randomGroupFound = true;
- }
- }
- var g = mathGroupHandler_.findMinGenerator(p, q);
- return new ZpSubgroup(p, q, g);
- };
- function checkQrGroupGenerationData(pBitLength, certainty) {
- validator.checkIsPositiveNumber(pBitLength);
- validator.checkIsPositiveNumber(certainty);
- if (pBitLength < 2) {
- throw new Error(
- 'Bit length: ' + pBitLength +
- ' of modulus p provided as input for generating quadratic residue group is less than minimum required value of 2.');
- }
- if (certainty < constants.MINIMUM_PRIME_CERTAINTY_LEVEL) {
- throw new Error(
- 'Certainty level: ' + certainty +
- ' provided as input for generating quadratic residue group is less than minimum required value of ' +
- constants.MINIMUM_PRIME_CERTAINTY_LEVEL);
- }
- }
- }
|