123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- /*
- * 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 ZeroKnowledgeProof = require('./proof');
- var ZeroKnowledgeProofPreComputation = require('./pre-computation');
- var SchnorrProofHandler = require('./handlers/schnorr-proof-handler');
- var ExponentiationProofHandler =
- require('./handlers/exponentiation-proof-handler');
- var PlaintextProofHandler = require('./handlers/plaintext-proof-handler');
- var SimplePlaintextEqualityProofHandler =
- require('./handlers/simple-plaintext-equality-proof-handler');
- var PlaintextEqualityProofHandler =
- require('./handlers/plaintext-equality-proof-handler');
- var PlaintextExponentEqualityProofHandler =
- require('./handlers/plaintext-exponent-equality-proof-handler');
- var OrProofHandler = require('./handlers/or-proof-handler');
- var cryptoPolicy = require('scytl-cryptopolicy');
- var messageDigest = require('scytl-messagedigest');
- var mathematical = require('scytl-mathematical');
- var validator = require('./input-validator');
- var codec = require('scytl-codec');
- require('./array');
- module.exports = ZeroKnowledgeProofService;
- /**
- * @class ZeroKnowledgeProofService
- * @classdesc The zero-knowledge proof service API. To instantiate this object,
- * use the method {@link newService}.
- * @hideconstructor
- * @param {Object}
- * [options] An object containing optional arguments.
- * @param {Policy}
- * [options.policy=Default policy] The cryptographic policy to use.
- * @param {MessageDigestService}
- * [options.messageDigestService=Created internally] The message
- * digest service to use.
- * @param {SecureRandomService}
- * [options.secureRandomService=Created internally] The secure random
- * service to use.
- * @param {MathematicalService}
- * [options.mathematicalService=Created internally] The mathematical
- * service to use.
- */
- function ZeroKnowledgeProofService(options) {
- options = options || {};
- var policy;
- if (options.policy) {
- policy = options.policy;
- } else {
- policy = cryptoPolicy.newInstance();
- }
- var messageDigestService_;
- if (options.messageDigestService) {
- messageDigestService_ = options.messageDigestService;
- } else {
- messageDigestService_ = messageDigest.newService({policy: policy});
- }
- var secureRandomService;
- if (options.secureRandomService) {
- secureRandomService = options.secureRandomService;
- }
- var mathService_;
- if (options.mathematicalService) {
- mathService_ = options.mathematicalService;
- } else if (secureRandomService) {
- mathService_ =
- mathematical.newService({secureRandomService: secureRandomService});
- } else {
- mathService_ = mathematical.newService();
- }
- /**
- * Creates a new ZeroKnowledgeProof object from a provided zero-knowledge
- * proof of knowledge or its components.
- *
- * @function newProof
- * @memberof ZeroKnowledgeProofService
- * @param {Exponent}
- * hashOrJson The hash of the zero-knowledge proof of knowledge
- * <b>OR</b> a JSON string representation of a
- * ZeroKnowledgeProof object, compatible with its
- * <code>toJson</code> method. For the latter case, any
- * additional input arguments will be ignored.
- * @param {Exponent[]}
- * values The values of the zero-knowledge proof of knowledge.
- * @returns {ZeroKnowledgeProof} The new ZeroKnowledgeProof object.
- * @throws {Error}
- * If the input data validation fails.
- */
- this.newProof = function(hashOrJson, exponents) {
- if (typeof hashOrJson !== 'string') {
- validator.checkExponent(
- hashOrJson, 'Hash to create new ZeroKnowledgeProof object');
- validator.checkExponents(
- exponents, 'Exponents to create new ZeroKnowledgeProof object');
- return new ZeroKnowledgeProof(hashOrJson, exponents);
- } else {
- return jsonToProof(hashOrJson);
- }
- };
- /**
- * Creates a new ZeroKnowledgeProofPreComputation object from a provided
- * zero-knowledge proof of knowledge pre-computation or its components.
- *
- * @function newPreComputation
- * @memberof ZeroKnowledgeProofService
- * @param {Exponent[]}
- * exponentsOrJson The array of randomly generated exponents that
- * comprise the pre-computation <b>OR</b> a JSON string
- * representation of a ZeroKnowledgeProofPreComputation object,
- * compatible with its <code>toJson</code> method. For the
- * latter case, any additional input arguments will be ignored.
- * @param {ZpGroupElements[]}
- * phiOutputs The array of PHI function output elements that
- * comprise the pre-computation.
- * @returns {ZeroKnowledgeProofPreComputation} The new
- * ZeroKnowledgeProofPreComputation object.
- * @throws {Error}
- * If the input data validation fails.
- */
- this.newPreComputation = function(exponentsOrJson, phiOutputs) {
- if (typeof exponentsOrJson !== 'string') {
- validator.checkExponents(
- exponentsOrJson,
- 'Exponents to create new ZeroKnowledgeProofPreComputation object');
- validator.checkZpGroupElements(
- phiOutputs,
- 'PHI function output elements to create new ZeroKnowledgeProofPreComputation object');
- return new ZeroKnowledgeProofPreComputation(exponentsOrJson, phiOutputs);
- } else {
- return jsonToPreComputation(exponentsOrJson);
- }
- };
- /**
- * Creates new SchnorrProofHandler object, for generating, pre-computing and
- * verifying Schnorr zero-knowledge proofs of knowledge.
- *
- * @function newSchnorrProofHandler
- * @memberof ZeroKnowledgeProofService
- * @param {ZpSubgroup}
- * group The Zp subgroup to which all exponents and Zp group
- * elements required for the proof generation are associated or
- * belong, respectively.
- * @returns {SchnorrProofHandler} The SchnorrProofHandler object.
- * @throws {Error}
- * If the input data validation fails.
- */
- this.newSchnorrProofHandler = function(group) {
- validator.checkIsObjectWithProperties(
- group, 'Zp subgroup for Schnorr proof handler');
- return new SchnorrProofHandler(group, messageDigestService_, mathService_);
- };
- /**
- * Creates new ExponentiationProofHandler object, for generating,
- * pre-computing and verifying exponentation zero-knowledge proofs of
- * knowledge. It must be initialized with base elements before it is used.
- *
- * @function newExponentiationProofHandler
- * @memberof ZeroKnowledgeProofService
- * @param {ZpSubgroup}
- * group The Zp subgroup to which all exponents and Zp group
- * elements required for the proof generation are associated or
- * belong, respectively.
- * @returns {ExponentiationProofHandler} The ExponentiationProofHandler
- * object.
- * @throws {Error}
- * If the input data validation fails.
- */
- this.newExponentiationProofHandler = function(group) {
- validator.checkIsObjectWithProperties(
- group, 'Zp subgroup for exponentiation proof handler');
- return new ExponentiationProofHandler(
- group, messageDigestService_, mathService_);
- };
- /**
- * Creates new PlaintextProofHandler object, for generating, pre-computing
- * and verifying plaintext zero-knowledge proofs of knowledge. It must be
- * initialized with an ElGamal public key before it is used.
- *
- * @function newPlaintextProofHandler
- * @memberof ZeroKnowledgeProofService
- * @param {ZpSubgroup}
- * group The Zp subgroup to which all exponents and Zp group
- * elements required for the proof generation are associated or
- * belong, respectively.
- * @returns {PlaintextProofHandler} The PlaintextProofHandler object.
- * @throws {Error}
- * If the input data validation fails.
- */
- this.newPlaintextProofHandler = function(group) {
- validator.checkIsObjectWithProperties(
- group, 'Zp subgroup for plaintext proof handler');
- return new PlaintextProofHandler(
- group, messageDigestService_, mathService_);
- };
- /**
- * Creates new SimplePlaintextEqualityProofHandler object, for generating,
- * pre-computing and verifying simple plaintext equality zero-knowledge
- * proofs of knowledge. It must be initialized with primary and secondary
- * ElGamal public keys before it is used.
- *
- * @function newSimplePlaintextEqualityProofHandler
- * @memberof ZeroKnowledgeProofService
- * @param {ZpSubgroup}
- * group The Zp subgroup to which all exponents and Zp group
- * elements required for the proof generation are associated or
- * belong, respectively.
- * @returns {SimplePlaintextEqualityProofHandler} The
- * SimplePlaintextEqualityProofHandler object.
- * @throws {Error}
- * If the input data validation fails.
- */
- this.newSimplePlaintextEqualityProofHandler = function(group) {
- validator.checkIsObjectWithProperties(
- group, 'Zp subgroup for simple plaintext equality proof handler');
- return new SimplePlaintextEqualityProofHandler(
- group, messageDigestService_, mathService_);
- };
- /**
- * Creates new PlaintextEqualityProofHandler object, for generating,
- * pre-computing and verifying plaintext equality zero-knowledge proofs of
- * knowledge. It must be initialized with primary and secondary ElGamal
- * public keys before it is used.
- *
- * @function newPlaintextEqualityProofHandler
- * @memberof ZeroKnowledgeProofService
- * @param {ZpSubgroup}
- * group The Zp subgroup to which all exponents and Zp group
- * elements required for the proof generation are associated or
- * belong, respectively.
- * @returns {PlaintextEqualityProofHandler} The
- * PlaintextEqualityProofHandler object.
- * @throws {Error}
- * If the input data validation fails.
- */
- this.newPlaintextEqualityProofHandler = function(group) {
- validator.checkIsObjectWithProperties(
- group, 'Zp subgroup for plaintext equality proof handler');
- return new PlaintextEqualityProofHandler(
- group, messageDigestService_, mathService_);
- };
- /**
- * Creates new PlaintextExponentEqualityProofHandler object, for generating,
- * pre-computing and verifying plaintext exponent equality zero-knowledge
- * proofs of knowledge. It must be initialized with base elements before it
- * is used.
- *
- * @function newPlaintextExponentEqualityProofHandler
- * @memberof ZeroKnowledgeProofService
- * @param {ZpSubgroup}
- * group The Zp subgroup to which all exponents and Zp group
- * elements required for the proof generation are associated or
- * belong, respectively.
- * @returns {PlaintextExponentEqualityProofHandler} The
- * PlaintextExponentEqualityProofHandler object.
- * @throws {Error}
- * If the input data validation fails.
- */
- this.newPlaintextExponentEqualityProofHandler = function(group) {
- validator.checkIsObjectWithProperties(
- group, 'Zp subgroup for plaintext exponent equality proof handler');
- return new PlaintextExponentEqualityProofHandler(
- group, messageDigestService_, mathService_);
- };
- /**
- * Creates new OrProofHandler object, for generating, pre-computing and
- * verifying OR zero-knowledge proofs of knowledge. It must be initialized
- * with an ElGamal public key before it is used.
- *
- * @function newOrProofHandler
- * @memberof ZeroKnowledgeProofService
- * @param {ZpSubgroup}
- * group The Zp subgroup to which all exponents and Zp group
- * elements required for the proof generation are associated or
- * belong, respectively.
- * @returns {OrProofHandler} The OrProofHandler object.
- * @throws {Error}
- * If the input data validation fails.
- */
- this.newOrProofHandler = function(group) {
- validator.checkIsObjectWithProperties(
- group, 'Zp subgroup for OR proof handler');
- return new OrProofHandler(group, messageDigestService_, mathService_);
- };
- function jsonToProof(json) {
- validator.checkIsJsonString(
- json, 'JSON to deserialize to ZeroKnowledgeProof object');
- var parsed = JSON.parse(json).zkProof;
- var q = codec.bytesToBigInteger(codec.base64Decode(parsed.q));
- var hash = mathService_.newExponent(
- q, codec.bytesToBigInteger(codec.base64Decode(parsed.hash)));
- var values = [];
- var valuesB64 = parsed.values;
- for (var i = 0; i < valuesB64.length; i++) {
- values.push(mathService_.newExponent(
- q, codec.bytesToBigInteger(codec.base64Decode(valuesB64[i]))));
- }
- return new ZeroKnowledgeProof(hash, values);
- }
- function jsonToPreComputation(json) {
- validator.checkIsJsonString(
- json, 'JSON to deserialize to ZeroKnowledgeProofPreComputation object');
- var parsed = JSON.parse(json).preComputed;
- var p = codec.bytesToBigInteger(codec.base64Decode(parsed.p));
- var q = codec.bytesToBigInteger(codec.base64Decode(parsed.q));
- var exponentValues = parsed.exponents;
- var exponents = [];
- for (var i = 0; i < exponentValues.length; i++) {
- exponents.push(mathService_.newExponent(
- q, codec.bytesToBigInteger(codec.base64Decode(exponentValues[i]))));
- }
- var phiOutputValues = parsed.phiOutputs;
- var phiOutputs = [];
- for (var j = 0; j < phiOutputValues.length; j++) {
- phiOutputs.push(mathService_.newZpGroupElement(
- p, q,
- codec.bytesToBigInteger(codec.base64Decode(phiOutputValues[j]))));
- }
- return new ZeroKnowledgeProofPreComputation(exponents, phiOutputs);
- }
- }
|