package org.bouncycastle.crypto.kems;

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

import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DerivationFunction;
import org.bouncycastle.crypto.KeyEncapsulation;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.KDFParameters;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECMultiplier;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.math.ec.FixedPointCombMultiplier;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.BigIntegers;

/**
 * The ECIES Key Encapsulation Mechanism (ECIES-KEM) from ISO 18033-2.
 */
public class ECIESKeyEncapsulation
    implements KeyEncapsulation
{
    private static final BigInteger ONE = BigInteger.valueOf(1);

    private DerivationFunction kdf;
    private SecureRandom rnd;
    private ECKeyParameters key;
    private boolean CofactorMode;
    private boolean OldCofactorMode;
    private boolean SingleHashMode;

    /**
     * Set up the ECIES-KEM.
     *
     * @param kdf the key derivation function to be used.
     * @param rnd the random source for the session key.
     */
    public ECIESKeyEncapsulation(
        DerivationFunction kdf,
        SecureRandom rnd)
    {
        this.kdf = kdf;
        this.rnd = rnd;
        this.CofactorMode = false;
        this.OldCofactorMode = false;
        this.SingleHashMode = false;
    }

    /**
     * Set up the ECIES-KEM.
     *
     * @param kdf             the key derivation function to be used.
     * @param rnd             the random source for the session key.
     * @param cofactorMode    if true use the new cofactor ECDH.
     * @param oldCofactorMode if true use the old cofactor ECDH.
     * @param singleHashMode  if true use single hash mode.
     */
    public ECIESKeyEncapsulation(
        DerivationFunction kdf,
        SecureRandom rnd,
        boolean cofactorMode,
        boolean oldCofactorMode,
        boolean singleHashMode)
    {
        this.kdf = kdf;
        this.rnd = rnd;

        // If both cofactorMode and oldCofactorMode are set to true
        // then the implementation will use the new cofactor ECDH 
        this.CofactorMode = cofactorMode;
        this.OldCofactorMode = oldCofactorMode;
        this.SingleHashMode = singleHashMode;
    }

    /**
     * Initialise the ECIES-KEM.
     *
     * @param key the recipient's public (for encryption) or private (for decryption) key.
     */
    public void init(CipherParameters key)
        throws IllegalArgumentException
    {
        if (!(key instanceof ECKeyParameters))
        {
            throw new IllegalArgumentException("EC key required");
        }
        else
        {
            this.key = (ECKeyParameters)key;
        }
    }

    /**
     * Generate and encapsulate a random session key.
     *
     * @param out    the output buffer for the encapsulated key.
     * @param outOff the offset for the output buffer.
     * @param keyLen the length of the session key.
     * @return the random session key.
     */
    public CipherParameters encrypt(byte[] out, int outOff, int keyLen)
        throws IllegalArgumentException
    {
        if (!(key instanceof ECPublicKeyParameters))
        {
            throw new IllegalArgumentException("Public key required for encryption");
        }

        ECPublicKeyParameters ecPubKey = (ECPublicKeyParameters)key;
        ECDomainParameters ecParams = ecPubKey.getParameters();
        ECCurve curve = ecParams.getCurve();
        BigInteger n = ecParams.getN();
        BigInteger h = ecParams.getH();

        // Generate the ephemeral key pair    
        BigInteger r = BigIntegers.createRandomInRange(ONE, n, rnd);

        // Compute the static-ephemeral key agreement
        BigInteger rPrime = CofactorMode ? r.multiply(h).mod(n) : r;

        ECMultiplier basePointMultiplier = createBasePointMultiplier();

        ECPoint[] ghTilde = new ECPoint[]{ 
            basePointMultiplier.multiply(ecParams.getG(), r),
            ecPubKey.getQ().multiply(rPrime)
        };

        // NOTE: More efficient than normalizing each individually
        curve.normalizeAll(ghTilde);

        ECPoint gTilde = ghTilde[0], hTilde = ghTilde[1];

        // Encode the ephemeral public key
        byte[] C = gTilde.getEncoded(false);
        System.arraycopy(C, 0, out, outOff, C.length);

        // Encode the shared secret value
        byte[] PEH = hTilde.getAffineXCoord().getEncoded();

        return deriveKey(keyLen, C, PEH);
    }

    /**
     * Generate and encapsulate a random session key.
     *
     * @param out    the output buffer for the encapsulated key.
     * @param keyLen the length of the session key.
     * @return the random session key.
     */
    public CipherParameters encrypt(byte[] out, int keyLen)
    {
        return encrypt(out, 0, keyLen);
    }

    /**
     * Decrypt an encapsulated session key.
     *
     * @param in     the input buffer for the encapsulated key.
     * @param inOff  the offset for the input buffer.
     * @param inLen  the length of the encapsulated key.
     * @param keyLen the length of the session key.
     * @return the session key.
     */
    public CipherParameters decrypt(byte[] in, int inOff, int inLen, int keyLen)
        throws IllegalArgumentException
    {
        if (!(key instanceof ECPrivateKeyParameters))
        {
            throw new IllegalArgumentException("Private key required for encryption");
        }

        ECPrivateKeyParameters ecPrivKey = (ECPrivateKeyParameters)key;
        ECDomainParameters ecParams = ecPrivKey.getParameters();
        ECCurve curve = ecParams.getCurve();
        BigInteger n = ecParams.getN();
        BigInteger h = ecParams.getH();

        // Decode the ephemeral public key
        byte[] C = new byte[inLen];
        System.arraycopy(in, inOff, C, 0, inLen);

        // NOTE: Decoded points are already normalized (i.e in affine form)
        ECPoint gTilde = curve.decodePoint(C);

        // Compute the static-ephemeral key agreement
        ECPoint gHat = gTilde;
        if ((CofactorMode) || (OldCofactorMode))
        {
            gHat = gHat.multiply(h);
        }

        BigInteger xHat = ecPrivKey.getD();
        if (CofactorMode)
        {
            xHat = xHat.multiply(h.modInverse(n)).mod(n);
        }

        ECPoint hTilde = gHat.multiply(xHat).normalize();

        // Encode the shared secret value
        byte[] PEH = hTilde.getAffineXCoord().getEncoded();

        return deriveKey(keyLen, C, PEH);
    }

    /**
     * Decrypt an encapsulated session key.
     *
     * @param in     the input buffer for the encapsulated key.
     * @param keyLen the length of the session key.
     * @return the session key.
     */
    public CipherParameters decrypt(byte[] in, int keyLen)
    {
        return decrypt(in, 0, in.length, keyLen);
    }

    protected ECMultiplier createBasePointMultiplier()
    {
        return new FixedPointCombMultiplier();
    }

    protected KeyParameter deriveKey(int keyLen, byte[] C, byte[] PEH)
    {
        byte[] kdfInput = PEH;
        if (!SingleHashMode)
        {
            kdfInput = Arrays.concatenate(C, PEH);
            Arrays.fill(PEH, (byte)0);
        }

        try
        {
            // Initialise the KDF
            kdf.init(new KDFParameters(kdfInput, null));
    
            // Generate the secret key
            byte[] K = new byte[keyLen];
            kdf.generateBytes(K, 0, K.length);

            // Return the ciphertext
            return new KeyParameter(K);
        }
        finally
        {
            Arrays.fill(kdfInput, (byte)0);
        }
    }
}
