/*
 * 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.elgamal.cryptoapi.Ciphertext;
import com.scytl.cryptolib.mathematical.groups.impl.ZpGroupElement;
import com.scytl.cryptolib.proofs.proof.Proof;

/**
 * Interface which defines an API that allows a number of Zero Knowledge Proofs
 * (ZKPs) to be verified.
 * <P>
 * Note: some of the proofs that can be verified using this API have very
 * similar names. Care must be taken to ensure that the correct verify method is
 * used to verify a proof of a particular type.
 */
public interface ProofVerifierAPI {

    /**
     * Verifies a "schnorr proof".
     * 
     * @param element
     *            exponentiated element.
     * @param voterID
     *            the voter ID.
     * @param electionEventID
     *            the election event ID.
     * @param proof
     *            the proof to be verified.
     * @return true if {@code proof} is verified successfully, false otherwise.
     * @throws GeneralCryptoLibException
     *             if the exponentiated generator is null, the voter ID or
     *             election event ID is null, empty or contains only white
     *             spaces, or the Schnorr proof is null.
     */
    boolean verifySchnorrProof(ZpGroupElement element, String voterID,
            String electionEventID, Proof proof)
            throws GeneralCryptoLibException;

    /**
     * Verifies an "exponentiation proof".
     * 
     * @param exponentiatedElements
     *            the list of exponentiated elements.
     * @param baseElements
     *            the list of base elements.
     * @param proof
     *            the proof to be verified.
     * @return true if {@code proof} is verified as true, false otherwise.
     * @throws GeneralCryptoLibException
     *             if the list of exponentiated elements or base elements is
     *             null, empty or contains one or more null elements, or the
     *             exponentiation proof is null.
     */
    boolean verifyExponentiationProof(
            final List<ZpGroupElement> exponentiatedElements,
            final List<ZpGroupElement> baseElements, final Proof proof)
            throws GeneralCryptoLibException;

    /**
     * Verifies a "decryption proof".
     * 
     * @param publicKey
     *            the public key.
     * @param ciphertext
     *            the ciphertext.
     * @param plaintext
     *            the plaintext.
     * @param proof
     *            the proof to be verified.
     * @return true if {@code proof} is verified as true, false otherwise.
     * @throws GeneralCryptoLibException
     *             if the ElGamal public key or the ciphertext is null, the
     *             plaintext is null, empty or contains one or more null
     *             elements, or the decryption proof is null.
     */
    boolean verifyDecryptionProof(final ElGamalPublicKey publicKey,
            final Ciphertext ciphertext,
            final List<ZpGroupElement> plaintext, final Proof proof)
            throws GeneralCryptoLibException;

    /**
     * Verifies a "plaintext proof".
     * 
     * @param publicKey
     *            the public key.
     * @param ciphertext
     *            the ciphertext.
     * @param plaintext
     *            the plaintext.
     * @param proof
     *            the proof to be verified.
     * @return true if {@code proof} is verified successfully, false otherwise.
     * @throws GeneralCryptoLibException
     *             if the ElGamal public key or ciphertext is null, the
     *             plaintext is null, empty or contains one or more null
     *             elements, or the plaintext proof is null.
     */
    boolean verifyPlaintextProof(final ElGamalPublicKey publicKey,
            final Ciphertext ciphertext,
            final List<ZpGroupElement> plaintext, final Proof proof)
            throws GeneralCryptoLibException;

    /**
     * Verifies a "simple plaintext equality proof".
     * 
     * @param primaryCiphertext
     *            the primary ciphertext.
     * @param primaryPublicKey
     *            the primary public key.
     * @param secondaryCiphertext
     *            the secondary ciphertext.
     * @param secondaryPublicKey
     *            the secondary public key.
     * @param proof
     *            the proof to be verified.
     * @return true if {@code proof} is verified successfully, false otherwise.
     * @throws GeneralCryptoLibException
     *             if the primary ciphertext, primary ElGamal public key,
     *             secondary ciphertext, secondary ElGamal public key or simple
     *             plaintext equality proof is null.
     */
    boolean verifySimplePlaintextEqualityProof(
            final Ciphertext primaryCiphertext,
            final ElGamalPublicKey primaryPublicKey,
            final Ciphertext secondaryCiphertext,
            final ElGamalPublicKey secondaryPublicKey, Proof proof)
            throws GeneralCryptoLibException;

    /**
     * Verifies a "plaintext equality proof".
     * 
     * @param primaryCiphertext
     *            the primary ciphertext.
     * @param primaryPublicKey
     *            the primary public key.
     * @param secondaryCiphertext
     *            the secondary ciphertext.
     * @param secondaryPublicKey
     *            the secondary public key.
     * @param proof
     *            the proof to be verified.
     * @return true if {@code proof} is verified successfully, false otherwise.
     * @throws GeneralCryptoLibException
     *             if there are any problems with the inputs.
     * @deprecated since 1.31.0-alpha. Should replace this method with the
     *             method of the same name, that takes the primary and secondary
     *             ciphertext input arguments as
     *             {@link com.scytl.cryptolib.elgamal.cryptoapi.Ciphertext}
     *             objects instead of as lists of
     *             {@link com.scytl.cryptolib.mathematical.groups.impl.ZpGroupElement}
     *             objects, which is now consistent with the API for the other
     *             plaintext proofs. The method that should now be used is
     *             {@link #verifyPlaintextEqualityProof(Ciphertext, ElGamalPublicKey, Ciphertext, ElGamalPublicKey, Proof)}
     */
    @Deprecated
    boolean verifyPlaintextEqualityProof(
            final List<ZpGroupElement> primaryCiphertext,
            final ElGamalPublicKey primaryPublicKey,
            final List<ZpGroupElement> secondaryCiphertext,
            final ElGamalPublicKey secondaryPublicKey, final Proof proof)
            throws GeneralCryptoLibException;

    /**
     * Verifies a "plaintext equality proof".
     * 
     * @param primaryCiphertext
     *            the primary ciphertext.
     * @param primaryPublicKey
     *            the primary public key.
     * @param secondaryCiphertext
     *            the secondary ciphertext.
     * @param secondaryPublicKey
     *            the secondary public key.
     * @param proof
     *            the proof to be verified.
     * @return true if {@code proof} is verified successfully, false otherwise.
     * @throws GeneralCryptoLibException
     *             if the primary ciphertext, primary ElGamal public key,
     *             primary witness, secondary ciphertext, secondary ElGamal
     *             public key or plaintext equality proof is null.
     */
    boolean verifyPlaintextEqualityProof(
            final Ciphertext primaryCiphertext,
            final ElGamalPublicKey primaryPublicKey,
            final Ciphertext secondaryCiphertext,
            final ElGamalPublicKey secondaryPublicKey, final Proof proof)
            throws GeneralCryptoLibException;

    /**
     * Verifies a "plaintext exponent equality proof".
     * 
     * @param ciphertext
     *            the encrypted list of base elements.
     * @param baseElements
     *            the list of base elements.
     * @param proof
     *            the proof to be verified.
     * @return true if {@code proof} is verified successfully, false otherwise.
     * @throws GeneralCryptoLibException
     *             if the ciphertext is null, the list of base elements is null,
     *             empty or contains one or more null elements, or the plaintext
     *             exponent equality proof is null.
     */
    boolean verifyPlaintextExponentEqualityProof(
            final Ciphertext ciphertext,
            final List<ZpGroupElement> baseElements, Proof proof)
            throws GeneralCryptoLibException;

    /**
     * Verifies an "OR proof". A given proof ensures that the specified
     * ciphertext is an ElGamal encryption of one of the given group elements.
     * 
     * @param ciphertext
     *            the ciphertext
     * @param publicKey
     *            the ElGamal public key used for the encryption
     * @param elements
     *            the group elements
     * @param data
     *            the string data to be included into hash
     * @param proof
     *            the OR proof
     * @throws GeneralCryptoLibException
     *             failed to verify the OR proof.
     */
    boolean verifyORProof(Ciphertext ciphertext, ElGamalPublicKey publicKey,
            List<ZpGroupElement> elements, String data, Proof proof)
            throws GeneralCryptoLibException;
}
