/*
 * 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.api.elgamal;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.elgamal.bean.ElGamalEncryptionParameters;
import com.scytl.cryptolib.elgamal.bean.ElGamalKeyPair;
import com.scytl.cryptolib.elgamal.bean.ElGamalPrivateKey;
import com.scytl.cryptolib.elgamal.bean.ElGamalPublicKey;
import com.scytl.cryptolib.elgamal.cryptoapi.CryptoAPIElGamalDecrypter;
import com.scytl.cryptolib.elgamal.cryptoapi.CryptoAPIElGamalEncrypter;
import com.scytl.cryptolib.elgamal.cryptoapi.CryptoAPIElGamalKeyPairGenerator;
import com.scytl.cryptolib.elgamal.cryptoapi.CryptoAPIElGamalReEncrypter;
import com.scytl.cryptolib.ffc.cryptoapi.FFCDomainParameters;

/**
 * Defines the API offered by the ElGamal service.
 */
public interface ElGamalServiceAPI {

    /**
     * Generates an {@link ElGamalEncryptionParameters}.
     * <P>
     * Instances of {@link ElGamalEncryptionParameters} can be used for
     * generating an {@link ElGamalKeyPair}.
     * 
     * @return an {@link ElGamalEncryptionParameters}.
     */
    ElGamalEncryptionParameters generateEncryptionParameters();

    /**
     * Generates an {@link ElGamalEncryptionParameters} from given
     * {@link FFCDomainParameters}.
     * <P>
     * Instances of {@link ElGamalEncryptionParameters} can be used for
     * generating an {@link ElGamalKeyPair}.
     * 
     * @param parameters
     *            the FFC domain parameters
     * @return an {@link ElGamalEncryptionParameters}
     * @throws GeneralCryptoLibException
     *             the domain parameters is null or invalid.
     */
    ElGamalEncryptionParameters generateEncryptionParameters(
            FFCDomainParameters parameters)
            throws GeneralCryptoLibException;

    /**
     * Returns a CryptoAPIElGamalKeyPairGenerator which can be used for
     * generating an ElGamalKeyPair.
     * <P>
     * Note: repeated calls to this method will return the same instance of
     * {@link CryptoAPIElGamalKeyPairGenerator}.
     * 
     * @return a CryptoAPIElGamalKeyPairGenerator.
     */
    CryptoAPIElGamalKeyPairGenerator getElGamalKeyPairGenerator();

    /**
     * Creates a {@link CryptoAPIElGamalEncrypter} that can be used for
     * encrypting data. The created CryptoAPIElGamalEncrypter will have the
     * specified public key set, and this key will always be used for encrypting
     * data using that CryptoAPIElGamalEncrypter.
     * 
     * @param publicKey
     *            the public key to be set in the created
     *            CryptoAPIElGamalEncrypter.
     * @return a newly created {@link CryptoAPIElGamalEncrypter}.
     * @throws GeneralCryptoLibException
     *             if the public key is null or if any of its elements belong to
     *             a different group.
     */
    CryptoAPIElGamalEncrypter createEncrypter(
            final ElGamalPublicKey publicKey)
            throws GeneralCryptoLibException;

    /**
     * Creates a {@link CryptoAPIElGamalDecrypter} that can be used for
     * decrypting data. The created {@link CryptoAPIElGamalDecrypter} will have
     * the specified private key set, and this key will always be used for
     * decrypting data using that CryptoAPIElGamalDecrypter.
     * 
     * @see #createEncrypter(com.scytl.cryptolib.elgamal.bean.ElGamalPublicKey)
     * @param privateKey
     *            the private key to be set in the created
     *            CryptoElGamalDecrypter.
     * @return a newly created {@link CryptoAPIElGamalDecrypter}.
     * @throws GeneralCryptoLibException
     *             if the private key is null or if any of its exponents belong
     *             to a different group.
     */
    CryptoAPIElGamalDecrypter createDecrypter(
            final ElGamalPrivateKey privateKey)
            throws GeneralCryptoLibException;

    /**
     * Creates a {@link CryptoAPIElGamalReEncrypter} that can be used for
     * re-encrypting data. The created CryptoAPIElGamalReEncrypter will have the
     * specified public key set, and this key will always be used for
     * re-encrypting data using that CryptoAPIElGamalReEncrypter.
     * 
     * @param publicKey
     *            the public key to be set in the created
     *            CryptoAPIElGamalReEncrypter.
     * @return a newly created {@link CryptoAPIElGamalReEncrypter}.
     * @throws GeneralCryptoLibException
     *             if the public key is null or if any of its elements belong to
     *             a different group.
     */
    CryptoAPIElGamalReEncrypter createReEncrypter(
            final ElGamalPublicKey publicKey)
            throws GeneralCryptoLibException;
}
