package org.bouncycastle.crypto.engines;

import java.math.BigInteger;
import java.security.SecureRandom;

import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.params.CramerShoupKeyParameters;
import org.bouncycastle.crypto.params.CramerShoupPrivateKeyParameters;
import org.bouncycastle.crypto.params.CramerShoupPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.util.BigIntegers;
import org.bouncycastle.util.Strings;

/**
 * Essentially the Cramer-Shoup encryption / decryption algorithms according to
 * "A practical public key cryptosystem provably secure against adaptive chosen ciphertext attack." (Crypto 1998)
 */
public class CramerShoupCoreEngine
{
    private static final BigInteger ONE = BigInteger.valueOf(1);

    private CramerShoupKeyParameters key;
    private SecureRandom random;
    private boolean forEncryption;
    private byte[] label = null;

    /**
     * initialise the CramerShoup engine.
     *
     * @param forEncryption whether this engine should encrypt or decrypt
     * @param param         the necessary CramerShoup key parameters.
     * @param label         the label for labelled CS as {@link String}
     */
    public void init(boolean forEncryption, CipherParameters param, String label)
    {
        init(forEncryption, param);

        this.label = Strings.toUTF8ByteArray(label);
    }

    /**
     * initialise the CramerShoup engine.
     *
     * @param forEncryption whether this engine should encrypt or decrypt
     * @param param         the necessary CramerShoup key parameters.
     */
    public void init(boolean forEncryption, CipherParameters param)
    {
        SecureRandom providedRandom = null;

        if (param instanceof ParametersWithRandom)
        {
            ParametersWithRandom rParam = (ParametersWithRandom)param;

            key = (CramerShoupKeyParameters)rParam.getParameters();
            providedRandom = rParam.getRandom();
        }
        else
        {
            key = (CramerShoupKeyParameters)param;
        }

        this.random = initSecureRandom(forEncryption, providedRandom);
        this.forEncryption = forEncryption;
    }

    /**
     * Return the maximum size for an input block to this engine. For Cramer
     * Shoup this is always one byte less than the key size on encryption, and
     * the same length as the key size on decryption.
     * TODO: correct?
     * @return maximum size for an input block.
     */
    public int getInputBlockSize()
    {
        int bitSize = key.getParameters().getP().bitLength();

        if (forEncryption)
        {
            return (bitSize + 7) / 8 - 1;
        }
        else
        {
            return (bitSize + 7) / 8;
        }
    }

    /**
     * Return the maximum size for an output block to this engine. For Cramer
     * Shoup this is always one byte less than the key size on decryption, and
     * the same length as the key size on encryption.
     * TODO: correct?
     * @return maximum size for an output block.
     */
    public int getOutputBlockSize()
    {
        int bitSize = key.getParameters().getP().bitLength();

        if (forEncryption)
        {
            return (bitSize + 7) / 8;
        }
        else
        {
            return (bitSize + 7) / 8 - 1;
        }
    }

    public BigInteger convertInput(byte[] in, int inOff, int inLen)
    {
        if (inLen > (getInputBlockSize() + 1))
        {
            throw new DataLengthException("input too large for Cramer Shoup cipher.");
        }
        else if (inLen == (getInputBlockSize() + 1) && forEncryption)
        {
            throw new DataLengthException("input too large for Cramer Shoup cipher.");
        }

        byte[] block;

        if (inOff != 0 || inLen != in.length)
        {
            block = new byte[inLen];

            System.arraycopy(in, inOff, block, 0, inLen);
        }
        else
        {
            block = in;
        }

        BigInteger res = new BigInteger(1, block);
        if (res.compareTo(key.getParameters().getP()) >= 0)
        {
            throw new DataLengthException("input too large for Cramer Shoup cipher.");
        }

        return res;
    }

    public byte[] convertOutput(BigInteger result)
    {
        byte[] output = result.toByteArray();

        if (!forEncryption)
        {
            if (output[0] == 0 && output.length > getOutputBlockSize())
            { // have ended up with an extra zero byte, copy down.
                byte[] tmp = new byte[output.length - 1];

                System.arraycopy(output, 1, tmp, 0, tmp.length);

                return tmp;
            }

            if (output.length < getOutputBlockSize())
            {// have ended up with less bytes than normal, lengthen
                byte[] tmp = new byte[getOutputBlockSize()];

                System.arraycopy(output, 0, tmp, tmp.length - output.length, output.length);

                return tmp;
            }
        }
        else
        {
            if (output[0] == 0)
            { // have ended up with an extra zero byte, copy down.
                byte[] tmp = new byte[output.length - 1];

                System.arraycopy(output, 1, tmp, 0, tmp.length);

                return tmp;
            }
        }

        return output;
    }

    public CramerShoupCiphertext encryptBlock(BigInteger input)
    {

        CramerShoupCiphertext result = null;

        if (!key.isPrivate() && this.forEncryption && key instanceof CramerShoupPublicKeyParameters)
        {
            CramerShoupPublicKeyParameters pk = (CramerShoupPublicKeyParameters)key;
            BigInteger p = pk.getParameters().getP();
            BigInteger g1 = pk.getParameters().getG1();
            BigInteger g2 = pk.getParameters().getG2();

            BigInteger h = pk.getH();

            if (!isValidMessage(input, p))
            {
                return result;
            }

            BigInteger r = generateRandomElement(p, random);

            BigInteger u1, u2, v, e, a;

            u1 = g1.modPow(r, p);
            u2 = g2.modPow(r, p);
            e = h.modPow(r, p).multiply(input).mod(p);

            Digest digest = pk.getParameters().getH();
            byte[] u1Bytes = u1.toByteArray();
            digest.update(u1Bytes, 0, u1Bytes.length);
            byte[] u2Bytes = u2.toByteArray();
            digest.update(u2Bytes, 0, u2Bytes.length);
            byte[] eBytes = e.toByteArray();
            digest.update(eBytes, 0, eBytes.length);
            if (this.label != null)
            {
                byte[] lBytes = this.label;
                digest.update(lBytes, 0, lBytes.length);
            }
            byte[] out = new byte[digest.getDigestSize()];
            digest.doFinal(out, 0);
            a = new BigInteger(1, out);

            v = pk.getC().modPow(r, p).multiply(pk.getD().modPow(r.multiply(a), p)).mod(p);

            result = new CramerShoupCiphertext(u1, u2, e, v);
        }
        return result;
    }

    public BigInteger decryptBlock(CramerShoupCiphertext input)
        throws CramerShoupCiphertextException
    {

        BigInteger result = null;

        if (key.isPrivate() && !this.forEncryption && key instanceof CramerShoupPrivateKeyParameters)
        {
            CramerShoupPrivateKeyParameters sk = (CramerShoupPrivateKeyParameters)key;

            BigInteger p = sk.getParameters().getP();

            Digest digest = sk.getParameters().getH();
            byte[] u1Bytes = input.getU1().toByteArray();
            digest.update(u1Bytes, 0, u1Bytes.length);
            byte[] u2Bytes = input.getU2().toByteArray();
            digest.update(u2Bytes, 0, u2Bytes.length);
            byte[] eBytes = input.getE().toByteArray();
            digest.update(eBytes, 0, eBytes.length);
            if (this.label != null)
            {
                byte[] lBytes = this.label;
                digest.update(lBytes, 0, lBytes.length);
            }
            byte[] out = new byte[digest.getDigestSize()];
            digest.doFinal(out, 0);

            BigInteger a = new BigInteger(1, out);
            BigInteger v = input.u1.modPow(sk.getX1().add(sk.getY1().multiply(a)), p).
                multiply(input.u2.modPow(sk.getX2().add(sk.getY2().multiply(a)), p)).mod(p);

            // check correctness of ciphertext
            if (input.v.equals(v))
            {
                result = input.e.multiply(input.u1.modPow(sk.getZ(), p).modInverse(p)).mod(p);
            }
            else
            {
                throw new CramerShoupCiphertextException("Sorry, that ciphertext is not correct");
            }
        }
        return result;
    }

    private BigInteger generateRandomElement(BigInteger p, SecureRandom random)
    {
        return BigIntegers.createRandomInRange(ONE, p.subtract(ONE), random);
    }

    /**
     * just checking whether the message m is actually less than the group order p
     */
    private boolean isValidMessage(BigInteger m, BigInteger p)
    {
        return m.compareTo(p) < 0;
    }

    protected SecureRandom initSecureRandom(boolean needed, SecureRandom provided)
    {
        return !needed ? null : (provided != null) ? provided : CryptoServicesRegistrar.getSecureRandom();
    }

    /**
     * CS exception for wrong cipher-texts
     */
    public static class CramerShoupCiphertextException
        extends Exception
    {
        private static final long serialVersionUID = -6360977166495345076L;

        public CramerShoupCiphertextException(String msg)
        {
            super(msg);
        }

    }
}
