/*
 * 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
 */
package com.scytl.cryptolib.proofs.cryptoapi;

import java.util.List;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.elgamal.bean.ElGamalPublicKey;
import com.scytl.cryptolib.mathematical.groups.impl.ZpGroupElement;
import com.scytl.cryptolib.proofs.bean.ProofPreComputedValues;

/**
 * Interface that allows for the pre-computation of values needed to generate a
 * zero knowledge proof. Since the pre-computation process is independent of the
 * user data and since it dominates the generation times, performing this
 * process ahead of time can result in considerable savings in time.
 */
public interface ProofPreComputerAPI {

    /**
     * Pre-computes the values needed to generate a Schnorr zero knowledge
     * proof.
     * 
     * @return the proof pre-computed values.
     * @throws GeneralCryptoLibException
     *             if the pre-computation process fails.
     */
    ProofPreComputedValues preComputeSchnorrProof()
            throws GeneralCryptoLibException;

    /**
     * Pre-computes the values needed to generate an exponentiation zero
     * knowledge proof.
     * 
     * @param baseElements
     *            the list of base elements used for the exponentiation.
     * @return the proof pre-computed values.
     * @throws GeneralCryptoLibException
     *             if the list of base elements is null, empty or contains one
     *             or more null elements, or if the pre-computation process
     *             fails.
     */
    ProofPreComputedValues preComputeExponentiationProof(
            final List<ZpGroupElement> baseElements)
            throws GeneralCryptoLibException;

    /**
     * Pre-computes the values needed to generate a decryption zero knowledge
     * proof.
     * 
     * @param privateKeyLength
     *            the number of exponents in the ElGamal private key used for
     *            decryption.
     * @param gamma
     *            the pre-computed gamma element used for ElGamal encryption.
     * @return the proof pre-computed values.
     * @throws GeneralCryptoLibException
     *             if the ElGamal public key or ciphertext gamma element is
     *             null, or if the pre-computation process fails.
     */
    ProofPreComputedValues preComputeDecryptionProof(
            final int privateKeyLength, final ZpGroupElement gamma)
            throws GeneralCryptoLibException;

    /**
     * Pre-computes the values needed to generate a plaintext zero knowledge
     * proof.
     * 
     * @param publicKey
     *            the ElGamal public key used to encrypt the plaintext.
     * @return the proof pre-computed values.
     * @throws GeneralCryptoLibException
     *             if the ElGamal public key is null, or if the pre-computation
     *             process fails.
     */
    ProofPreComputedValues preComputePlaintextProof(
            final ElGamalPublicKey publicKey)
            throws GeneralCryptoLibException;

    /**
     * Pre-computes the values needed to generate a simple plaintext equality
     * zero knowledge proof.
     * 
     * @param primaryPublicKey
     *            the ElGamal public key used to encrypt the primary plaintext.
     * @param secondaryPublicKey
     *            the ElGamal public key used to encrypt the secondary
     *            plaintext.
     * @return the proof pre-computed values.
     * @throws GeneralCryptoLibException
     *             if the primary or secondary ElGamal public key is null, or if
     *             the pre-computation process fails.
     */
    ProofPreComputedValues preComputeSimplePlaintextEqualityProof(
            final ElGamalPublicKey primaryPublicKey,
            final ElGamalPublicKey secondaryPublicKey)
            throws GeneralCryptoLibException;

    /**
     * Pre-computes the values needed to generate a plaintext equality zero
     * knowledge proof.
     * 
     * @param primaryPublicKey
     *            the ElGamal public key used to encrypt the primary plaintext.
     * @param secondaryPublicKey
     *            the ElGamal public key used to encrypt the secondary
     *            plaintext.
     * @return the proof pre-computed values.
     * @throws GeneralCryptoLibException
     *             if the primary or secondary ElGamal public key is null, or if
     *             the pre-computation process fails.
     */
    ProofPreComputedValues preComputePlaintextEqualityProof(
            final ElGamalPublicKey primaryPublicKey,
            final ElGamalPublicKey secondaryPublicKey)
            throws GeneralCryptoLibException;

    /**
     * Pre-computes the values needed to generate a plaintext exponent equality
     * zero knowledge proof.
     * 
     * @param baseElements
     *            the list of base elements.
     * @return the proof pre-computed values.
     * @throws GeneralCryptoLibException
     *             the list of base elements is null, empty or contains one or
     *             more null elements, or if the pre-computation process fails.
     */
    ProofPreComputedValues preComputePlaintextExponentEqualityProof(
            final List<ZpGroupElement> baseElements)
            throws GeneralCryptoLibException;

    /**
     * Pre-computes the values needed to generate an OR proof.
     * 
     * @param publicKey
     *            the public key
     * @param elementCount
     *            the number of elements
     * @return the proof pre-computed values.
     * @throws GeneralCryptoLibException
     *             failed to pre-compute the values.
     */
    ProofPreComputedValues preComputeORProof(ElGamalPublicKey publicKey,
            int elementCount) throws GeneralCryptoLibException;
}
