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

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.elgamal.bean.ElGamalComputationsValues;
import com.scytl.cryptolib.elgamal.bean.ElGamalEncrypterValues;

/**
 * Defines the methods supported by a CryptoAPIElGamalReEncrypter.
 * <P>
 * The methods specified in this interface allow data to be re-encrypted using
 * an implementation of the ElGamal cryptosystem.
 * <P>
 * As well as permitting the re-encryption of data, this interface also
 * specifies methods for performing pre-computations. Pre-computations is an
 * optional process that may be performed (at any time) before re-encrypting
 * data, that allows part of the numerical computations to be performed
 * "ahead of time". In fact, pre-computations may be performed before the data
 * that will be re-encrypted is known.
 * <P>
 * The output from the pre-computations process may then be passed as an input
 * to an re-encryption process, along with the actual data to re-encrypt.
 * <P>
 * Due to the fact that pre-computation is optional, methods which don't require
 * pre-computation values, and methods which do require pre-computation values
 * are provided.
 */
public interface CryptoAPIElGamalReEncrypter {

    /**
     * Re-encrypt the received ciphertext.
     * <P>
     * The encrypted message parameter will be a list of group elements,
     * encapsulated within an {@link ElGamalComputationsValues} object.
     * <P>
     * The length of the received ciphertext (number of group elements contained
     * within it) must be equal to, or less than, the length of the public key
     * of this re-encrypter. If this condition is not met, then an exception
     * will be thrown.
     * 
     * @param ciphertext
     *            the encrypted message to be re-encrypted.
     * @return the re-encrypted messages and the random exponent that was
     *         generated during the re-encryption process, encapsulated within
     *         an {@link ElGamalEncrypterValues} object.
     * @throws GeneralCryptoLibException
     *             if the ciphertext is invalid.
     */
    ElGamalEncrypterValues reEncryptGroupElements(
            ElGamalComputationsValues ciphertext)
            throws GeneralCryptoLibException;

    /**
     * Re-encrypt the received ciphertext, and use the received pre-computed
     * values.
     * <P>
     * The encrypted message parameter will be a list of group elements,
     * encapsulated within an {@link ElGamalComputationsValues} object.
     * <P>
     * The length of the received ciphertext (number of group elements contained
     * within it) must be equal to, or less than, the length of the public key
     * of this re-encrypter. If this condition is not met, then an exception
     * will be thrown.
     * <P>
     * The {@code preComputationValues} object expected by this method is the
     * result of the method {@link #preCompute} having being previously
     * executed. Therefore, this method should only be called if the
     * {@link #preCompute} method has already been executed.
     * 
     * @param ciphertext
     *            the encrypted message to be re-encrypted.
     * @param preComputationValues
     *            the result of performing pre-computation. This object
     *            encapsulates a random exponent, a gamma value and a set of phi
     *            values (sometimes known as 'prePhi values' and they are the
     *            result of pre-computation).
     * @return the re-encrypted messages and the random exponent that was
     *         generated during the re-encryption process, encapsulated within
     *         an {@link ElGamalEncrypterValues} object.
     * @throws GeneralCryptoLibException
     *             if the ciphertext or the pre-computed values are invalid.
     */
    ElGamalEncrypterValues reEncryptGroupElements(
            ElGamalComputationsValues ciphertext,
            ElGamalEncrypterValues preComputationValues)
            throws GeneralCryptoLibException;

    /**
     * Returns output of performing pre-computation calculations.
     * <P>
     * The output of this method, which is an {@link ElGamalEncrypterValues},
     * can later be passed along with some ciphertext to one of the 'reEncrypt'
     * methods of this interface, in order to obtain the re-encryption of this
     * ciphertext.
     * 
     * @return the result of pre-computation, encapsulated in an
     *         {@link ElGamalEncrypterValues} object.
     * @throws GeneralCryptoLibException
     *             if the pre-computation process fails.
     */
    ElGamalEncrypterValues preCompute() throws GeneralCryptoLibException;
}
