/*
 * 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
 */
cryptolib.modules.proofs = cryptolib.modules.proofs || {};

/**
 * Allows several cryptographic proofs to be generated and verified.
 * <P>
 */
cryptolib.modules.proofs.service = function(box) {
  'use strict';

  box.proofs = box.proofs || {};
  box.proofs.service = {};

  var proofsFactory;

  var f = function(box) {
    proofsFactory = new box.proofs.ProofsFactory();
  };

  f.policies = {
    proofs: {
      messagedigest: {
        algorithm: box.policies.proofs.messagedigest.algorithm,
        provider: box.policies.proofs.messagedigest.provider
      },
      secureRandom: {provider: box.policies.proofs.secureRandom.provider},
      charset: box.policies.proofs.charset
    },
    primitives: {
      secureRandom: {provider: box.policies.primitives.secureRandom.provider}
    }
  };

  cryptolib(
      'proofs.implementation', 'primitives.securerandom', 'commons.exceptions',
      'commons.mathematical', f);

  /**
   * Creates a Schnorr proof.
   *
   * @param voterID
   *            The voter ID. This should be a string.
   * @param electionID
   *            The election event ID. This should be a string.
   * @param exponentiatedElement
   *            The exponentiated element. This should be an element of the
   *            received group.
   * @param witness
   *            The witness. This should be an Exponent of the received group.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallbackOrPreComputedValues
   *            Progress callback function or pre-computed values (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval, if the previous
   *            parameter is a progressCallback function (optional).
   *
   * @returns The Schnorr proof.
   */
  box.proofs.service.createSchnorrProof = function(
      voterID, electionID, exponentiatedElement, witness, group,
      progressCallbackOrPreComputedValues, progressPercentMinCheckInterval) {

    var proofGenerator =
        proofsFactory.createSchnorrProofGenerator(voterID, electionID, group);

    if (!progressCallbackOrPreComputedValues) {
      return proofGenerator.generate(exponentiatedElement, witness);
    } else if (isPreComputedValues(progressCallbackOrPreComputedValues)) {
      var preComputedValues = progressCallbackOrPreComputedValues;
      return proofGenerator.generate(
          exponentiatedElement, witness, preComputedValues);
    } else {
      var progressCallback = progressCallbackOrPreComputedValues;
      return proofGenerator
          .initProgressMeter(progressCallback, progressPercentMinCheckInterval)
          .generate(exponentiatedElement, witness);
    }
  };

  /**
   * Creates an exponentiation proof.
   *
   * @param exponentiatedElements
   *            The exponentiated elements. These should consist of the
   *            following base elements, exponentiated with the specified
   *            exponent.
   * @param baseElements
   *            The base elements used for the exponentiations. These should
   *            correspond to elements of the specified group.
   * @param exponent
   *            The exponent for which this proof is to be generated. It
   *            should be an exponent of the specified group.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallbackOrPreComputedValues
   *            Progress callback function or pre-computed values (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval, if the previous
   *            parameter is a progressCallback function (optional).
   *
   * @returns The exponentiation proof.
   */
  box.proofs.service.createExponentiationProof = function(
      exponentiatedElements, baseElements, exponent, group,
      progressCallbackOrPreComputedValues, progressPercentMinCheckInterval) {

    var proofGenerator =
        proofsFactory.createExponentiationProofGenerator(baseElements, group);

    if (!progressCallbackOrPreComputedValues) {
      return proofGenerator.generate(exponentiatedElements, exponent);
    } else if (isPreComputedValues(progressCallbackOrPreComputedValues)) {
      var preComputedValues = progressCallbackOrPreComputedValues;
      return proofGenerator.generate(
          exponentiatedElements, exponent, preComputedValues);
    } else {
      var progressCallback = progressCallbackOrPreComputedValues;
      return proofGenerator
          .initProgressMeter(progressCallback, progressPercentMinCheckInterval)
          .generate(exponentiatedElements, exponent);
    }
  };

  /**
   * Creates a plaintext proof.
   *
   * @param publicKey
   *            The primary public key. This should be an ElGamal public key.
   * @param ciphertext
   *            The ciphertext. This should be the output from ElGamal
   *            encryption.
   * @param plaintext
   *            The plaintext. This should be an array of elements of the
   *            received group.
   * @param witness
   *            The witness. This should be an Exponent of the received group.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallbackOrPreComputedValues
   *            Progress callback function or pre-computed values (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval, if the previous
   *            parameter is a progressCallback function (optional).
   *
   * @returns The plaintext proof.
   */
  box.proofs.service.createPlaintextProof = function(
      publicKey, ciphertext, plaintext, witness, group,
      progressCallbackOrPreComputedValues, progressPercentMinCheckInterval) {

    var proofGenerator =
        proofsFactory.createPlaintextProofGenerator(publicKey, group);

    if (!progressCallbackOrPreComputedValues) {
      return proofGenerator.generate(ciphertext, plaintext, witness);
    } else if (isPreComputedValues(progressCallbackOrPreComputedValues)) {
      var preComputedValues = progressCallbackOrPreComputedValues;
      return proofGenerator.generate(
          ciphertext, plaintext, witness, preComputedValues);
    } else {
      var progressCallback = progressCallbackOrPreComputedValues;
      return proofGenerator
          .initProgressMeter(progressCallback, progressPercentMinCheckInterval)
          .generate(ciphertext, plaintext, witness);
    }
  };

  /**
   * Creates a simple plaintext equality Proof.
   *
   * @param primaryCiphertext
   *            The primary ciphertext. This should be the output from ElGamal
   *            encryption.
   * @param primaryPublicKey
   *            The primary public key. This should be an ElGamal public key.
   * @param witness
   *            The witness of the proof. This should be an Exponent of the
   *            received group.
   * @param secondaryCiphertext
   *            The secondary ciphertext. This should be the output from
   *            ElGamal encryption.
   * @param secondaryPublicKey
   *            The secondary public key. This should be an ElGamal public
   *            key.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallbackOrPreComputedValues
   *            Progress callback function or pre-computed values (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval, if the previous
   *            parameter is a progressCallback function (optional).
   *
   * @returns The simple plaintext equality proof.
   */
  box.proofs.service.createSimplePlaintextEqualityProof = function(
      primaryCiphertext, primaryPublicKey, witness, secondaryCiphertext,
      secondaryPublicKey, group, progressCallbackOrPreComputedValues,
      progressPercentMinCheckInterval) {

    var proofGenerator =
        proofsFactory.createSimplePlaintextEqualityProofGenerator(
            primaryPublicKey, secondaryPublicKey, group);

    if (!progressCallbackOrPreComputedValues) {
      return proofGenerator.generate(
          primaryCiphertext, secondaryCiphertext, witness);
    } else if (isPreComputedValues(progressCallbackOrPreComputedValues)) {
      var preComputedValues = progressCallbackOrPreComputedValues;
      return proofGenerator.generate(
          primaryCiphertext, secondaryCiphertext, witness, preComputedValues);
    } else {
      var progressCallback = progressCallbackOrPreComputedValues;
      return proofGenerator
          .initProgressMeter(progressCallback, progressPercentMinCheckInterval)
          .generate(primaryCiphertext, secondaryCiphertext, witness);
    }
  };

  /**
   * Creates a plaintext equality proof.
   *
   * @param primaryCiphertext
   *            The primary ciphertext. This should be the output from ElGamal
   *            encryption.
   * @param primaryPublicKey
   *            The primary public key. This should be an ElGamal public key.
   * @param primaryWitness
   *            The primary witness of the proof. This should be an Exponent
   *            of the received group.
   * @param secondaryCiphertext
   *            The secondary ciphertext. This should be the output from
   *            ElGamal encryption.
   * @param secondaryPublicKey
   *            The secondary public key. This should be an ElGamal public
   *            key.
   * @param secondaryWitness
   *            The secondary witness of the proof. This should be an Exponent
   *            of the received group.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallbackOrPreComputedValues
   *            Progress callback function or pre-computed values (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval, if the previous
   *            parameter is a progressCallback function (optional).
   *
   * @returns The plaintext equality proof.
   */
  box.proofs.service.createPlaintextEqualityProof = function(
      primaryCiphertext, primaryPublicKey, primaryWitness, secondaryCiphertext,
      secondaryPublicKey, secondaryWitness, group,
      progressCallbackOrPreComputedValues, progressPercentMinCheckInterval) {

    var proofGenerator = proofsFactory.createPlaintextEqualityProofGenerator(
        primaryPublicKey, secondaryPublicKey, group);

    if (!progressCallbackOrPreComputedValues) {
      return proofGenerator.generate(
          primaryCiphertext, primaryWitness, secondaryCiphertext,
          secondaryWitness);
    } else if (isPreComputedValues(progressCallbackOrPreComputedValues)) {
      var preComputedValues = progressCallbackOrPreComputedValues;
      return proofGenerator.generate(
          primaryCiphertext, primaryWitness, secondaryCiphertext,
          secondaryWitness, preComputedValues);
    } else {
      var progressCallback = progressCallbackOrPreComputedValues;
      return proofGenerator
          .initProgressMeter(progressCallback, progressPercentMinCheckInterval)
          .generate(
              primaryCiphertext, primaryWitness, secondaryCiphertext,
              secondaryWitness);
    }
  };

  /**
   * Creates a plaintext exponent equality proof.
   *
   * @param ciphertext
   *            The ciphertext. This should be the output from ElGamal
   *            encryption.
   * @param plaintext
   *            The plaintext. It should be an array of members of the
   *            received group.
   * @param primaryWitness
   *            The primary witness. This should be an Exponent of the
   *            received group.
   * @param secondaryWitness
   *            The secondary witness. This should be an Exponent of the
   *            received group.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallbackOrPreComputedValues
   *            Progress callback function or pre-computed values (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval, if the previous
   *            parameter is a progressCallback function (optional).
   *
   * @returns The plaintext exponent equality proof.
   */
  box.proofs.service.createPlaintextExponentEqualityProof = function(
      ciphertext, plaintext, primaryWitness, secondaryWitness, group,
      progressCallbackOrPreComputedValues, progressPercentMinCheckInterval) {

    var proofGenerator =
        proofsFactory.createPlaintextExponentEqualityProofGenerator(
            plaintext, group);

    if (!progressCallbackOrPreComputedValues) {
      return proofGenerator.generate(
          ciphertext, primaryWitness, secondaryWitness);
    } else if (isPreComputedValues(progressCallbackOrPreComputedValues)) {
      var preComputedValues = progressCallbackOrPreComputedValues;
      return proofGenerator.generate(
          ciphertext, primaryWitness, secondaryWitness, preComputedValues);
    } else {
      var progressCallback = progressCallbackOrPreComputedValues;
      return proofGenerator
          .initProgressMeter(progressCallback, progressPercentMinCheckInterval)
          .generate(ciphertext, primaryWitness, secondaryWitness);
    }
  };

  /**
   * Creates an OR-proof.
   *
   * @param publicKey
   *            The public key. This should be an ElGamal public key.
   * @param ciphertext
   *            The ciphertext of the mathematical group element that was
   *            encrypted. This should be the output from ElGamal encryption.
   * @param witness
   *            The witness used to generate the ciphertext. This should be an
   *            Exponent of the received group.
   * @param elements
   *            The mathematical group elements, one of which was encrypted.
   *            This should be an array of elements of the received group.
   * @param index
   *            The index of the mathematical group element that was
   *            encrypted. This should be an integer.
   * @param data
   *            Any extra data to use for the proof generation. This should be
   *            a String. NOTE: If this parameter is null, then data will be set
   *            to empty string.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallbackOrPreComputedValues
   *            Progress callback function or pre-computed values (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval, if the previous
   *            parameter is a progressCallback function (optional).
   *
   * @returns The OR-proof.
   */
  box.proofs.service.createORProof = function(
      publicKey, ciphertext, witness, elements, index, data, group,
      progressCallbackOrPreComputedValues, progressPercentMinCheckInterval) {

    var proofGenerator =
        proofsFactory.createORProofGenerator(publicKey, elements.length, group);

    if (!progressCallbackOrPreComputedValues) {
      return proofGenerator.generate(
          ciphertext, witness, elements, index, data);
    } else if (isPreComputedValues(progressCallbackOrPreComputedValues)) {
      var preComputedValues = progressCallbackOrPreComputedValues;
      return proofGenerator.generate(
          ciphertext, witness, elements, index, data, preComputedValues);
    } else {
      var progressCallback = progressCallbackOrPreComputedValues;
      return proofGenerator
          .initProgressMeter(progressCallback, progressPercentMinCheckInterval)
          .generate(ciphertext, witness, elements, index, data);
    }
  };

  /**
   * Verifies a Schnorr proof.
   *
   * @param exponentiatedElement
   *            The exponentiated element. This should be an element of the
   *            specified group.
   * @param voterID
   *            The voter IS. This should be a string.
   * @param electionID
   *            The election event ID. This should be a string.
   * @param proof
   *            The proof that is to be verified.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallback
   *            Progress callback function (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval (optional).
   *
   * @returns true if the Schnorr Proof can be verified, false otherwise.
   */
  box.proofs.service.verifySchnorrProof = function(
      element, voterID, electionEventID, proof, group, progressCallback,
      progressPercentMinCheckInterval) {

    return proofsFactory
        .createSchnorrProofVerifier(
            element, voterID, electionEventID, proof, group)
        .initProgressMeter(progressCallback, progressPercentMinCheckInterval)
        .verify();
  };

  /**
   * Verifies an exponentiation proof.
   *
   * @param exponentiatedElements
   *            The exponentiated elements. These should consist of the
   *            following base elements, exponentiated with the specified
   *            exponent.
   * @param baseElements
   *            The base elements used for the exponentiations. These should
   *            correspond to elements of the specified group.
   * @param proof
   *            The proof that is to be verified.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallback
   *            Progress callback function (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval (optional).
   *
   * @returns true if the exponentiation proof can be verified, false
   *          otherwise.
   */
  box.proofs.service.verifyExponentiationProof = function(
      exponentiatedElements, baseElements, proof, group, progressCallback,
      progressPercentMinCheckInterval) {

    return proofsFactory
        .createExponentiationProofVerifier(
            exponentiatedElements, baseElements, proof, group)
        .initProgressMeter(progressCallback, progressPercentMinCheckInterval)
        .verify();
  };

  /**
   * Verifies a plaintext proof.
   *
   * @param publicKey
   *            The primary public key. This should be an ElGamal public key.
   * @param ciphertext
   *            The ciphertext. This should be the output from ElGamal
   *            encryption.
   * @param plaintext
   *            The plaintext. This should be an array of elements of the
   *            received group.
   * @param proof
   *            The proof that is to be verified.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallback
   *            Progress callback function (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval (optional).
   * @returns true if the plaintext proof can be verified, false otherwise.
   */
  box.proofs.service.verifyPlaintextProof = function(
      publicKey, ciphertext, plaintext, proof, group, progressCallback,
      progressPercentMinCheckInterval) {

    return proofsFactory.createPlaintextProofVerifier(publicKey, group)
        .initProgressMeter(progressCallback, progressPercentMinCheckInterval)
        .verify(ciphertext, plaintext, proof);
  };

  /**
   * Verifies a simple plaintext equality proof.
   *
   * @param primaryCiphertext
   *            The primary ciphertext. This should be the output from ElGamal
   *            encryption.
   * @param primaryPublicKey
   *            The primary public key. This should be an ElGamal public key.
   * @param secondaryCiphertext
   *            The secondary ciphertext. This should be the output from
   *            ElGamal encryption.
   * @param secondaryPublicKey
   *            The secondary public key. This should be an ElGamal public
   *            key.
   * @param proof
   *            The proof that is to be verified.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallback
   *            Progress callback function (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval (optional).
   *
   * @returns true if the simple plaintext equality proof can be verified,
   *          false otherwise.
   */
  box.proofs.service.verifySimplePlaintextEqualityProof = function(
      primaryCiphertext, primaryPublicKey, secondaryCiphertext,
      secondaryPublicKey, proof, group, progressCallback,
      progressPercentMinCheckInterval) {

    return proofsFactory
        .createSimplePlaintextEqualityProofVerifier(
            primaryCiphertext, primaryPublicKey, secondaryCiphertext,
            secondaryPublicKey, proof, group)
        .initProgressMeter(progressCallback, progressPercentMinCheckInterval)
        .verify();
  };

  /**
   * Verifies a plaintext equality proof.
   *
   * @param primaryCiphertext
   *            The primary ciphertext. This should be the output from ElGamal
   *            encryption.
   * @param primaryPublicKey
   *            The primary public key. This should be an ElGamal public key.
   * @param secondaryCiphertext
   *            The secondary ciphertext. This should be the output from
   *            ElGamal encryption.
   * @param secondaryPublicKey
   *            The secondary public key. This should be an ElGamal public
   *            key.
   * @param proof
   *            The proof that is to be verified.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallback
   *            Progress callback function (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval (optional).
   *
   * @returns true if the plaintext equality proof can be verified, false
   *          otherwise.
   */
  box.proofs.service.verifyPlaintextEqualityProof = function(
      primaryCiphertext, primaryPublicKey, secondaryCiphertext,
      secondaryPublicKey, proof, group, progressCallback,
      progressPercentMinCheckInterval) {

    return proofsFactory
        .createPlaintextEqualityProofVerifier(
            primaryCiphertext, primaryPublicKey, secondaryCiphertext,
            secondaryPublicKey, proof, group)
        .initProgressMeter(progressCallback, progressPercentMinCheckInterval)
        .verify();
  };

  /**
   * Verifies a plaintext exponent equality proof.
   *
   * @param ciphertext
   *            The ciphertext. This should be the output from ElGamal
   *            encryption.
   * @param baseElements
   *            The array of base elements. All of these elements should be
   *            members of the received group.
   * @param witness1
   *            The primary witness. This should be an Exponent.
   * @param witness2
   *            The secondary witness. This should be an Exponent.
   * @param proof
   *            The proof that is to be verified.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallback
   *            Progress callback function (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval (optional).
   *
   * @returns true if the plaintext exponent equality proof can be verified,
   *          false otherwise.
   */
  box.proofs.service.verifyPlaintextExponentEqualityProof = function(
      ciphertext, baseElements, proof, group, progressCallback,
      progressPercentMinCheckInterval) {

    return proofsFactory
        .createPlaintextExponentEqualityProofVerifier(
            ciphertext, baseElements, proof, group)
        .initProgressMeter(progressCallback, progressPercentMinCheckInterval)
        .verify();
  };

  /**
   * Verifies an OR-proof.
   *
   * @param publicKey
   *            The public key. This should be an ElGamal public key.
   * @param ciphertext
   *            The ciphertext of the mathematical group element that was
   *            encrypted. This should be the output from ElGamal encryption.
   * @param elements
   *            The mathematical group elements, one of which was encrypted.
   *            This should be an array of elements of the received group.
   * @param data
   *            Any extra data used for the proof generation. This should be a
   *            String. NOTE: If this parameter is null, then data will be set
   *            to empty string.
   * @param proof
   *            The proof that is to be verified.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallback
   *            Progress callback function (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval (optional).
   * @returns true if the OR-proof can be verified, false otherwise.
   */
  box.proofs.service.verifyORProof = function(
      publicKey, ciphertext, elements, data, proof, group, progressCallback,
      progressPercentMinCheckInterval) {

    return proofsFactory
        .createORProofVerifier(publicKey, elements.length, group)
        .initProgressMeter(progressCallback, progressPercentMinCheckInterval)
        .verify(ciphertext, elements, data, proof);
  };

  /**
   * Pre-computes a Schnorr proof. IMPORTANT: The same pre-computed values
   * must not be used twice.
   *
   * @param voterID
   *            The voter ID. This should be a string.
   * @param electionID
   *            The election event ID. This should be a string.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallback
   *            Progress callback function or pre-computed values (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval, if the previous
   *            parameter is a progressCallback function (optional).
   *
   * @returns The Schnorr proof pre-computed values.
   */
  box.proofs.service.preComputeSchnorrProof = function(
      voterID, electionID, group, progressCallbackOrPreComputedValues,
      progressPercentMinCheckInterval) {

    return proofsFactory.createSchnorrProofGenerator(voterID, electionID, group)
        .initProgressMeter(
            progressCallbackOrPreComputedValues,
            progressPercentMinCheckInterval)
        .preCompute();
  };

  /**
   * Pre-computes an exponentiation proof. IMPORTANT: The same pre-computed
   * values must not be used twice.
   *
   * @param baseElements
   *            The base elements used for the exponentiations. These should
   *            correspond to elements of the specified group.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallback
   *            Progress callback function or pre-computed values (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval, if the previous
   *            parameter is a progressCallback function (optional).
   *
   * @returns The exponentiation proof pre-computed values.
   */
  box.proofs.service.preComputeExponentiationProof = function(
      baseElements, group, progressCallbackOrPreComputedValues,
      progressPercentMinCheckInterval) {

    return proofsFactory.createExponentiationProofGenerator(baseElements, group)
        .initProgressMeter(
            progressCallbackOrPreComputedValues,
            progressPercentMinCheckInterval)
        .preCompute();
  };

  /**
   * Pre-computes a plaintext proof. IMPORTANT: The same pre-computed values
   * must not be used twice.
   *
   * @param publicKey
   *            The primary public key. This should be an ElGamal public key.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallback
   *            Progress callback function or pre-computed values (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval, if the previous
   *            parameter is a progressCallback function (optional).
   *
   * @returns The plaintext proof pre-computed values.
   */
  box.proofs.service.preComputePlaintextProof = function(
      publicKey, group, progressCallbackOrPreComputedValues,
      progressPercentMinCheckInterval) {

    return proofsFactory.createPlaintextProofGenerator(publicKey, group)
        .initProgressMeter(
            progressCallbackOrPreComputedValues,
            progressPercentMinCheckInterval)
        .preCompute();
  };

  /**
   * Pre-computes values for a simple plaintext equality proof. IMPORTANT: The
   * same pre-computed values must not be used twice.
   *
   * @param primaryPublicKey
   *            The primary public key. This should be an ElGamal public key.
   * @param secondaryPublicKey
   *            The secondary public key. This should be an ElGamal public
   *            key.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallback
   *            Progress callback function or pre-computed values (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval, if the previous
   *            parameter is a progressCallback function (optional).
   *
   * @returns The simple plaintext equality proof pre-computed values.
   */
  box.proofs.service.preComputeSimplePlaintextEqualityProof = function(
      primaryPublicKey, secondaryPublicKey, group,
      progressCallbackOrPreComputedValues, progressPercentMinCheckInterval) {

    return proofsFactory
        .createSimplePlaintextEqualityProofGenerator(
            primaryPublicKey, secondaryPublicKey, group)
        .initProgressMeter(
            progressCallbackOrPreComputedValues,
            progressPercentMinCheckInterval)
        .preCompute();
  };

  /**
   * Pre-computes values for a plaintext equality proof. IMPORTANT: The same
   * pre-computed values must not be used twice.
   *
   * @param primaryPublicKey
   *            The primary public key. This should be an ElGamal public key.
   * @param secondaryPublicKey
   *            The secondary public key. This should be an ElGamal public
   *            key.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallback
   *            Progress callback function or pre-computed values (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval, if the previous
   *            parameter is a progressCallback function (optional).
   *
   * @returns The plaintext equality proof pre-computed values.
   */
  box.proofs.service.preComputePlaintextEqualityProof = function(
      primaryPublicKey, secondaryPublicKey, group,
      progressCallbackOrPreComputedValues, progressPercentMinCheckInterval) {

    return proofsFactory
        .createPlaintextEqualityProofGenerator(
            primaryPublicKey, secondaryPublicKey, group)
        .initProgressMeter(
            progressCallbackOrPreComputedValues,
            progressPercentMinCheckInterval)
        .preCompute();
  };

  /**
   * Returns pre-computed values for a plaintext exponent equality proof.
   * IMPORTANT: The same pre-computed values must not be used twice.
   *
   * @param plaintext
   *            The plaintext. It should be an array of members of the
   *            received group.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallback
   *            Progress callback function or pre-computed values (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval, if the previous
   *            parameter is a progressCallback function (optional).
   *
   * @returns The plaintext exponent equality proof pre-computed values.
   */
  box.proofs.service.preComputePlaintextExponentEqualityProof = function(
      plaintext, group, progressCallbackOrPreComputedValues,
      progressPercentMinCheckInterval) {

    return proofsFactory
        .createPlaintextExponentEqualityProofGenerator(plaintext, group)
        .initProgressMeter(
            progressCallbackOrPreComputedValues,
            progressPercentMinCheckInterval)
        .preCompute();
  };

  /**
   * Pre-computes an OR-proof. IMPORTANT: The same pre-computed values must
   * not be used twice.
   *
   * @param publicKey
   *            The public key. This should be an ElGamal public key.
   * @param numElements
   *            The number of elements belonging to the received mathematical
   *            group that will be used for the proof, one of which will be
   *            encrypted.
   * @param group
   *            The mathematical group. This should be a Zp subgroup.
   * @param progressCallback
   *            Progress callback function or pre-computed values (optional).
   * @param progressPercentMinCheckInterval
   *            Progress percentage minimum check interval, if the previous
   *            parameter is a progressCallback function (optional).
   *
   * @returns The OR-proof pre-computed values.
   */
  box.proofs.service.preComputeORProof = function(
      publicKey, numElements, group, progressCallbackOrPreComputedValues,
      progressPercentMinCheckInterval) {

    return proofsFactory.createORProofGenerator(publicKey, numElements, group)
        .initProgressMeter(
            progressCallbackOrPreComputedValues,
            progressPercentMinCheckInterval)
        .preCompute();
  };

  /**
   * Utility method that checks if the argument is instance of type
   * ProofPreComputedValues.
   *
   * @param values
   *            argument to check.
   * @returns {boolean} true if values is instance of ProofPreComputedValues.
   */
  function isPreComputedValues(values) {
    return !!(values) && values.className === 'ProofPreComputedValues';
  }
};
