/* * 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'; /** * Input data validation utility for this module. Only intended for internal * use. */ module.exports = { /** * Checks if a value is defined. * * @function checkIsDefined * @private * @param {Object} * value The value to check. * @param {string} * label The error message label for the value. * @throws {TypeError} * If the value is undefined. */ checkIsDefined: function(value, label) { if (typeof value === 'undefined') { throw new TypeError(label + ' is undefined.'); } }, /** * Checks if a value is not null. * * @function checkIsNotNull * @private * @param {Object} * value The value to check. * @param {string} * label The error message label for the value. * @throws {TypeError} * If the value is null. */ checkIsNotNull: function(value, label) { if (value === null) { throw new TypeError(label + ' is null.'); } }, /** * Checks if a value is defined and not null. * * @function checkIsDefinedAndNotNull * @private * @param {Object} * value The value to check. * @param {string} * label The error message label for the value. * @throws {TypeError} * If the value is not defined or it is null. */ checkIsDefinedAndNotNull: function(value, label) { this.checkIsDefined(value, label); this.checkIsNotNull(value, label); }, /** * Checks if a value is of an expected type. * * @function checkIsType * @private * @param {Object} * value The value to check. * @param {string} * type The expected type of the value. * @param {string} * label The error message label for the value. * @throws {TypeError} * If the value is not of the expected type. */ checkIsType: function(value, type, label) { var typeFound = typeof value; if (typeFound !== type) { throw new TypeError( 'Expected ' + label + ' to have type \'' + type + '\' ; Found: \'' + typeFound + '\''); } }, /** * Checks if a value is an instance of an Object. * * @function checkIsInstanceOf * @private * @param {Object} * value The value to check. * @param {Object} * obj The Object to check against. * @param {string} * objName The Object name, for error handling purposes. * @param {string} * label The error message label for the value. * @throws {TypeError} * If the object is undefined, null, or it is not an instance of * the Object. */ checkIsInstanceOf: function(value, obj, objName, label) { this.checkIsDefinedAndNotNull(value, label); if (!(value instanceof obj)) { throw new TypeError(label + ' is not an instance of Object ' + objName); } }, /** * Checks if a value is an object. * * @function checkIsObject * @private * @param {Object} * value The value to check. * @param {string} * label The error message label for the value. * @throws {TypeError} * If the value is not an object. */ checkIsObject: function(value, label) { if (typeof value !== 'object') { throw new TypeError(label + ' is not an object.'); } }, /** * Checks if a value is an object and has properties. * * @function checkIsObjectWithProperties * @private * @param {Object} * value The value to check. * @param {string} * label The error message label for the value. * @throws {TypeError} * If the value is not an object or it has no properties. */ checkIsObjectWithProperties: function(value, label) { this.checkIsDefinedAndNotNull(value, label); this.checkIsObject(value, label); if (!Object.getOwnPropertyNames(value).length) { throw new TypeError(label + ' does not have any properties.'); } }, /** * Checks if a value is an Array object. * * @function checkIsArray * @private * @param {Array} * array The value to check. * @param {string} * label The error message label for the value. * @throws {TypeError} * If the value is not an Array object. */ checkIsArray: function(value, label) { this.checkIsDefinedAndNotNull(value, 'Array of ' + label); if (value.constructor !== Array) { throw new TypeError('Array of ' + label + ' is not of type Array.'); } }, /** * Checks if a value is a non-empty string. * * @function checkIsNonEmptyString * @private * @param {string} * value The value to check. * @param {string} * label The error message label for the value. * @throws {TypeError} * If the value is not a non-empty string. */ checkIsNonEmptyString: function(value, label) { this.checkIsType(value, 'string', label); if (value.length === 0) { throw new TypeError(label + ' is empty.'); } }, /** * Checks if a value is a non-empty Array object. * * @function checkIsNonEmptyArray * @private * @param {Array} * array The value to check. * @param {string} * label The error message label for the value. * @throws {TypeError} * If the value is not a non-empty Array object. */ checkIsNonEmptyArray: function(value, label) { this.checkIsArray(value, label); if (value.length < 1) { throw new TypeError('Array of ' + label + ' is empty.'); } }, /** * Checks if a value is an array of strings. * * @function checkIsStringArray * @private * @param {string[]} * value The value to check. * @param {string} * label The error message label for the value. * @throws {TypeError} * If value is not an array of strings. */ checkIsStringArray: function(value, label) { this.checkIsNonEmptyArray(value, label); for (var i = 0; i < value.length; i++) { this.checkIsType(value[i], 'string', 'Element ' + i + ' of ' + label); } }, /** * Checks if a value is a valid JSON object. * * @function checkIsJsonObject * @private * @param {Object} * value The value to check. * @param {string} * label The error message label for the value. * @throws {TypeError} * If the value is a valid JSON object. */ checkIsJsonObject: function(value, label) { try { JSON.parse(value); } catch (error) { throw new TypeError(label + ' is not a valid JSON object.'); } }, /** * Checks if a value is a valid JSON string. * * @function checkIsJsonString * @private * @param {Object} * value The value to check. * @param {string} * label The error message label for the value. * @throws {TypeError} * If the value is a valid JSON string. */ checkIsJsonString: function(value, label) { this.checkIsNonEmptyString(value, label); this.checkIsJsonObject(value, label); }, /** * Checks the validity of a ZpGroupElement object. * * @function checkZpGroupElement * @private * @param {ZpGroupElement} * element The object to check. * @param {string} * label The error message label for the object. * @param {Zpsubgroup} * [group] Optional parameter pertaining to a Zp subgroup. If * this option is provided, the modulus and order of the element * will be checked against those of the group. * @throws {TypeError} * If the value is not a valid ZpGroupElement object. */ checkZpGroupElement: function(element, label, group) { this.checkIsObjectWithProperties(element, label); if (typeof group !== 'undefined') { var groupP = group.p; var groupQ = group.q; var elementP = element.p; if (!elementP.equals(groupP)) { throw new TypeError( 'Expected modulus p of ' + label + ' to equal modulus of Zp subgroup provided as input: ' + groupP + ' ; Found: ' + elementP); } var elementQ = element.q; if (!elementQ.equals(groupQ)) { throw new TypeError( 'Expected order q of ' + label + ' to equal order of Zp subgroup provided as input: ' + groupQ + ' ; Found: ' + elementQ); } } }, /** * Checks the validity of an Exponent object. * * @function checkExponent * @private * @param {Exponent} * exponent The object to check. * @param {string} * label The error message label for the object. * @param {Zpsubgroup} * [q] Optional parameter pertaining to a Zp subgroup order. If * this option is provided, the order of the exponent will be * checked against that order. * @throws {TypeError} * If the value is not a valid Exponent value. */ checkExponent: function(exponent, label, q) { this.checkIsObjectWithProperties(exponent, label); if (typeof q !== 'undefined') { var exponentQ = exponent.q; if (!exponentQ.equals(q)) { throw new TypeError( 'Expected order q of ' + label + ' to equal order of Zp subgroup provided as input: ' + q + ' ; Found: ' + exponentQ); } } }, /** * Checks the validity of an array of ZpGroupElement objects. * * @function checkZpGroupElements * @private * @param {ZpGroupElement[]} * elements The array to check. * @param {string} * label The error message label for the array. * @param {Zpsubgroup} * [group] Optional parameter pertaining to a Zp subgroup. If * this option is provided, the modulus and order of each element * will be checked against those of the group. * @throws {TypeError} * If the array of ZpGroupElement objects is not valid. */ checkZpGroupElements: function(elements, label, group) { this.checkIsNonEmptyArray(elements, label); for (var i = 0; i < elements.length; i++) { this.checkZpGroupElement( elements[i], 'element ' + i + ' of ' + label, group); } }, /** * Checks the validity of an array of Exponent objects. * * @function checkExponents * @private * @param {Exponent[]} * exponents The array to check. * @param {string} * label The error message label for the array. * @param {Zpsubgroup} * [q] Optional parameter pertaining to a Zp subgroup order. If * this option is provided, the order of the exponent will be * checked against that order. * @throws {TypeError} * If the array of Exponent objects is not valid. */ checkExponents: function(exponents, label, q) { this.checkIsNonEmptyArray(exponents, label); for (var i = 0; i < exponents.length; i++) { this.checkExponent(exponents[i], 'exponent ' + i + ' of ' + label, q); } }, /** * Checks the validity of an ElGamalPublicKey object. * * @function checkElGamalPublicKey * @private * @param {ElGamalPublicKey} * publicKey The object to check. * @param {string} * label The error message label for the object. * @param {Zpsubgroup} * [group] Optional parameter pertaining to a Zp subgroup. If * this option is provided, the modulus and order of the public * key will be checked against those of the group. * @throws {TypeError} * If the ElGamalPublicKey object is not valid. */ checkElGamalPublicKey: function(publicKey, label, group) { this.checkIsObjectWithProperties(publicKey, label); if (typeof group !== 'undefined') { var groupP = group.p; var groupQ = group.q; var publicKeyP = publicKey.group.p; if (!publicKeyP.equals(groupP)) { throw new TypeError( 'Expected modulus p of ' + label + ' to equal modulus of Zp subgroup provided as input: ' + groupP + ' ; Found: ' + publicKeyP); } var publicKeyQ = publicKey.group.q; if (!publicKeyQ.equals(groupQ)) { throw new TypeError( 'Expected order q of ' + label + ' to equal order of Zp subgroup provided as input: ' + groupQ + ' ; Found: ' + publicKeyQ); } } }, /** * Checks the validity of an ElGamalPrivateKey object. * * @function checkElGamalPrivateKey * @private * @param {ElGamalPrivateKey} * privateKey The object to check. * @param {string} * label The error message label for the object. * @param {Zpsubgroup} * [group] Optional parameter pertaining to a Zp subgroup. If * this option is provided, the order of the private key will be * checked against that of the group. * @throws {TypeError} * If the ElGamalPrivateKey object is not valid. */ checkElGamalPrivateKey: function(privateKey, label, group) { this.checkIsObjectWithProperties(privateKey, label); if (typeof group !== 'undefined') { var groupQ = group.q; var privateKeyQ = privateKey.group.q; if (!privateKeyQ.equals(groupQ)) { throw new TypeError( 'Expected order q of ' + label + ' to equal order of Zp subgroup provided as input: ' + groupQ + ' ; Found: ' + privateKeyQ); } } }, /** * Checks the validity of an ElGamalEncryptedElements object. * * @function checkElGamalEncryptedElements * @private * @param {ElGamalEncryptedElements} * encryptedElements The object to check. * @param {string} * label The error message label for the object. * @param {Zpsubgroup} * [group] Optional parameter pertaining to a Zp subgroup. If * this option is provided, the modulus and order of the value's * secret and ElGamal encrypted elements will be checked against * those of the group. * @throws {TypeError} * If the ElGamalEncryptedElements object is not valid. */ checkElGamalEncryptedElements: function(encryptedElements, label, group) { this.checkIsObjectWithProperties(encryptedElements, label); if (typeof group !== 'undefined') { var groupP = group.p; var groupQ = group.q; var gamma = encryptedElements.gamma; var gammaP = gamma.p; if (!gammaP.equals(groupP)) { throw new TypeError( 'Expected modulus p of gamma element of ' + label + ' to equal modulus of Zp subgroup provided as input: ' + groupP + ' ; Found: ' + gammaP); } var gammaQ = gamma.q; if (!gammaQ.equals(groupQ)) { throw new TypeError( 'Expected order q of gamma element of ' + label + ' to equal order of Zp subgroup provided as input: ' + groupQ + ' ; Found: ' + gammaQ); } } var secret = encryptedElements.secret; if (typeof secret !== 'undefined') { this.checkExponent(secret, group); } } };