package org.bouncycastle.jce.provider.test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.Key;
import java.security.Security;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;

import org.bouncycastle.crypto.io.InvalidCipherTextIOException;
import org.bouncycastle.jcajce.io.CipherInputStream;
import org.bouncycastle.jcajce.io.CipherOutputStream;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.test.SimpleTest;

public class CipherStreamTest2
    extends SimpleTest
{
    private int streamSize;

    public String getName()
    {
        return "CipherStreamTest2";
    }

    private void testModes(String algo, String[] transforms, boolean authenticated)
        throws Exception
    {
        Key key = generateKey(algo);
        for (int i = 0; i != transforms.length; i++)
        {
            String transform = transforms[i];
            String cipherName = algo + transform;

            boolean cts = transform.indexOf("CTS") > -1;
            if (cts && streamSize < Cipher.getInstance(cipherName, "BC").getBlockSize())
            {
                continue;
            }
            testWriteRead(cipherName, key, authenticated, true, false);
            testWriteRead(cipherName, key, authenticated, true, true);
            testWriteRead(cipherName, key, authenticated, false, false);
            testWriteRead(cipherName, key, authenticated, false, true);
            testReadWrite(cipherName, key, authenticated, true, false);
            testReadWrite(cipherName, key, authenticated, true, true);
            testReadWrite(cipherName, key, authenticated, false, false);
            testReadWrite(cipherName, key, authenticated, false, true);

            if (!cts)
            {
                testWriteReadEmpty(cipherName, key, authenticated, true, false);
                testWriteReadEmpty(cipherName, key, authenticated, true, true);
                testWriteReadEmpty(cipherName, key, authenticated, false, false);
                testWriteReadEmpty(cipherName, key, authenticated, false, true);
            }

            if (authenticated)
            {
                testTamperedRead(cipherName, key, true, true);
                testTamperedRead(cipherName, key, true, false);
                testTruncatedRead(cipherName, key, true, true);
                testTruncatedRead(cipherName, key, true, false);
                testTamperedWrite(cipherName, key, true, true);
                testTamperedWrite(cipherName, key, true, false);
            }
        }
    }

    private InputStream createInputStream(byte[] data, Cipher cipher, boolean useBc)
    {
        ByteArrayInputStream bytes = new ByteArrayInputStream(data);
        // cast required for earlier JDK
        return useBc ? (InputStream)new CipherInputStream(bytes, cipher) : (InputStream)new javax.crypto.CipherInputStream(bytes, cipher);
    }

    private OutputStream createOutputStream(ByteArrayOutputStream bytes, Cipher cipher, boolean useBc)
    {
        // cast required for earlier JDK
        return useBc ? (OutputStream)new CipherOutputStream(bytes, cipher) : (OutputStream)new javax.crypto.CipherOutputStream(bytes, cipher);
    }

    /**
     * Test tampering of ciphertext followed by read from decrypting CipherInputStream
     */
    private void testTamperedRead(String name, Key key, boolean authenticated, boolean useBc)
        throws Exception
    {
        Cipher encrypt = Cipher.getInstance(name, "BC");
        Cipher decrypt = Cipher.getInstance(name, "BC");
        encrypt.init(Cipher.ENCRYPT_MODE, key);
        if (encrypt.getIV() != null)
        {
            decrypt.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(encrypt.getIV()));
        }
        else
        {
            decrypt.init(Cipher.DECRYPT_MODE, key);
        }

        byte[] ciphertext = encrypt.doFinal(new byte[streamSize]);

        // Tamper
        ciphertext[0] += 1;

        InputStream input = createInputStream(ciphertext, decrypt, useBc);
        try
        {
            while (input.read() >= 0)
            {
            }
            fail("Expected invalid ciphertext after tamper and read : " + name, authenticated, useBc);
        }
        catch (InvalidCipherTextIOException e)
        {
            // Expected
        }
        catch (IOException e)       //     cause will be AEADBadTagException
        {
            // Expected
        }
        try
        {
            input.close();
        }
        catch (Exception e)
        {
            fail("Unexpected exception : " + name, e, authenticated, useBc);
        }
    }

    /**
     * Test truncation of ciphertext to make tag calculation impossible, followed by read from
     * decrypting CipherInputStream
     */
    private void testTruncatedRead(String name, Key key, boolean authenticated, boolean useBc)
        throws Exception
    {
        Cipher encrypt = Cipher.getInstance(name, "BC");
        Cipher decrypt = Cipher.getInstance(name, "BC");
        encrypt.init(Cipher.ENCRYPT_MODE, key);
        if (encrypt.getIV() != null)
        {
            decrypt.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(encrypt.getIV()));
        }
        else
        {
            decrypt.init(Cipher.DECRYPT_MODE, key);
        }

        byte[] ciphertext = encrypt.doFinal(new byte[streamSize]);

        // Truncate to just smaller than complete tag
        byte[] truncated = new byte[ciphertext.length - streamSize - 1];
        System.arraycopy(ciphertext, 0, truncated, 0, truncated.length);

        // Tamper
        ciphertext[0] += 1;

        InputStream input = createInputStream(truncated, decrypt, useBc);
        while (true)
        {
            int read = 0;
            try
            {
                read = input.read();
            }
            catch (InvalidCipherTextIOException e)
            {
                // Expected
                break;
            }
            catch (IOException e)
            {
                // Expected from JDK 1.7 on
                break;
            }
            catch (Exception e)
            {
                fail("Unexpected exception : " + name, e, authenticated, useBc);
                break;
            }
            if (read < 0)
            {
                fail("Expected invalid ciphertext after truncate and read : " + name, authenticated, useBc);
                break;
            }
        }
        try
        {
            input.close();
        }
        catch (Exception e)
        {
            fail("Unexpected exception : " + name, e, authenticated, useBc);
        }
    }

    /**
     * Test tampering of ciphertext followed by write to decrypting CipherOutputStream
     */
    private void testTamperedWrite(String name, Key key, boolean authenticated, boolean useBc)
        throws Exception
    {
        Cipher encrypt = Cipher.getInstance(name, "BC");
        Cipher decrypt = Cipher.getInstance(name, "BC");
        encrypt.init(Cipher.ENCRYPT_MODE, key);
        if (encrypt.getIV() != null)
        {
            decrypt.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(encrypt.getIV()));
        }
        else
        {
            decrypt.init(Cipher.DECRYPT_MODE, key);
        }

        byte[] ciphertext = encrypt.doFinal(new byte[streamSize]);

        // Tamper
        ciphertext[0] += 1;

        ByteArrayOutputStream plaintext = new ByteArrayOutputStream();
        OutputStream output = createOutputStream(plaintext, decrypt, useBc);

        for (int i = 0; i < ciphertext.length; i++)
        {
            output.write(ciphertext[i]);
        }
        try
        {
            output.close();
            fail("Expected invalid ciphertext after tamper and write : " + name, authenticated, useBc);
        }
        catch (InvalidCipherTextIOException e)
        {
            // Expected
        }
    }

    /**
     * Test CipherOutputStream in ENCRYPT_MODE, CipherInputStream in DECRYPT_MODE
     */
    private void testWriteRead(String name, Key key, boolean authenticated, boolean useBc, boolean blocks)
        throws Exception
    {
        byte[] data = new byte[streamSize];
        for (int i = 0; i < data.length; i++)
        {
            data[i] = (byte)(i % 255);
        }

        testWriteRead(name, key, authenticated, useBc, blocks, data);
    }

    /**
     * Test CipherOutputStream in ENCRYPT_MODE, CipherInputStream in DECRYPT_MODE
     */
    private void testWriteReadEmpty(String name, Key key, boolean authenticated, boolean useBc, boolean blocks)
        throws Exception
    {
        byte[] data = new byte[0];

        testWriteRead(name, key, authenticated, useBc, blocks, data);
    }

    private void testWriteRead(String name, Key key, boolean authenticated, boolean useBc, boolean blocks, byte[] data)
    {
        ByteArrayOutputStream bOut = new ByteArrayOutputStream();

        try
        {
            Cipher encrypt = Cipher.getInstance(name, "BC");
            Cipher decrypt = Cipher.getInstance(name, "BC");
            encrypt.init(Cipher.ENCRYPT_MODE, key);
            if (encrypt.getIV() != null)
            {
                decrypt.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(encrypt.getIV()));
            }
            else
            {
                decrypt.init(Cipher.DECRYPT_MODE, key);
            }

            OutputStream cOut = createOutputStream(bOut, encrypt, useBc);
            if (blocks)
            {
                int chunkSize = Math.max(1, data.length / 8);
                for (int i = 0; i < data.length; i += chunkSize)
                {
                    cOut.write(data, i, Math.min(chunkSize, data.length - i));
                }
            }
            else
            {
                for (int i = 0; i < data.length; i++)
                {
                    cOut.write(data[i]);
                }
            }
            cOut.close();

            byte[] cipherText = bOut.toByteArray();
            bOut.reset();
            InputStream cIn = createInputStream(cipherText, decrypt, useBc);

            if (blocks)
            {
                byte[] block = new byte[encrypt.getBlockSize() + 1];
                int c;
                while ((c = cIn.read(block)) >= 0)
                {
                    bOut.write(block, 0, c);
                }
            }
            else
            {
                int c;
                while ((c = cIn.read()) >= 0)
                {
                    bOut.write(c);
                }

            }
            cIn.close();

        }
        catch (Exception e)
        {
            fail("Unexpected exception " + name, e, authenticated, useBc);
        }

        byte[] decrypted = bOut.toByteArray();
        if (!Arrays.areEqual(data, decrypted))
        {
            fail("Failed - decrypted data doesn't match: " + name, authenticated, useBc);
        }
    }

    protected void fail(String message, boolean authenticated, boolean bc)
    {
        if (bc || !authenticated)
        {
            super.fail(message);
        }
        else
        {
            // javax.crypto.CipherInputStream/CipherOutputStream
            // are broken wrt handling AEAD failures
            // System.err.println("Broken JCE Streams: " + message);
        }
    }

    protected void fail(String message, Throwable throwable, boolean authenticated, boolean bc)
    {
        if (bc || !authenticated)
        {
            super.fail(message, throwable);
        }
        else
        {
            // javax.crypto.CipherInputStream/CipherOutputStream
            // are broken wrt handling AEAD failures
            //System.err.println("Broken JCE Streams: " + message + " : " + throwable);
            throwable.printStackTrace();
        }
    }

    /**
     * Test CipherInputStream in ENCRYPT_MODE, CipherOutputStream in DECRYPT_MODE
     */
    private void testReadWrite(String name, Key key, boolean authenticated, boolean useBc, boolean blocks)
        throws Exception
    {
        String lCode = "ABCDEFGHIJKLMNOPQRSTU";

        ByteArrayOutputStream bOut = new ByteArrayOutputStream();

        try
        {
            Cipher in = Cipher.getInstance(name, "BC");
            Cipher out = Cipher.getInstance(name, "BC");
            in.init(Cipher.ENCRYPT_MODE, key);
            if (in.getIV() != null)
            {
                out.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(in.getIV()));
            }
            else
            {
                out.init(Cipher.DECRYPT_MODE, key);
            }

            InputStream cIn = createInputStream(lCode.getBytes(), in, useBc);
            OutputStream cOut = createOutputStream(bOut, out, useBc);

            if (blocks)
            {
                byte[] block = new byte[in.getBlockSize() + 1];
                int c;
                while ((c = cIn.read(block)) >= 0)
                {
                    cOut.write(block, 0, c);
                }
            }
            else
            {
                int c;
                while ((c = cIn.read()) >= 0)
                {
                    cOut.write(c);
                }
            }

            cIn.close();

            cOut.flush();
            cOut.close();

        }
        catch (Exception e)
        {
            fail("Unexpected exception " + name, e, authenticated, useBc);
        }

        String res = new String(bOut.toByteArray());
        if (!res.equals(lCode))
        {
            fail("Failed - decrypted data doesn't match: " + name, authenticated, useBc);
        }
    }

    private static Key generateKey(String name)
        throws Exception
    {
        KeyGenerator kGen;

        if (name.indexOf('/') < 0)
        {
            kGen = KeyGenerator.getInstance(name, "BC");
        }
        else
        {
            kGen = KeyGenerator.getInstance(name.substring(0, name.indexOf('/')), "BC");
        }
        return kGen.generateKey();
    }

    public void performTest()
        throws Exception
    {
        int[] testSizes = new int[]{0, 1, 7, 8, 9, 15, 16, 17, 1023, 1024, 1025, 2047, 2048, 2049, 4095, 4096, 4097};
        for (int i = 0; i < testSizes.length; i++)
        {
            this.streamSize = testSizes[i];
            performTests();
        }
    }

    private void performTests()
        throws Exception
    {
        final String[] blockCiphers64 = new String[]{"BLOWFISH", "DES", "DESEDE", "TEA", "CAST5", "RC2", "XTEA"};

        for (int i = 0; i != blockCiphers64.length; i++)
        {
            testModes(blockCiphers64[i], new String[]{
                "/ECB/PKCS5Padding",
                "/CBC/PKCS5Padding",
                "/OFB/NoPadding",
                "/CFB/NoPadding",
                "/CTS/NoPadding",}, false);
            testModes(blockCiphers64[i], new String[]{"/EAX/NoPadding"}, true);
        }

        final String[] blockCiphers128 = new String[]{
            "AES",
            "NOEKEON",
            "Twofish",
            "CAST6",
            "SEED",
            "Serpent",
            "RC6",
            "CAMELLIA"};

        for (int i = 0; i != blockCiphers128.length; i++)
        {
            testModes(blockCiphers128[i], new String[]{
                "/ECB/PKCS5Padding",
                "/CBC/PKCS5Padding",
                "/OFB/NoPadding",
                "/CFB/NoPadding",
                "/CTS/NoPadding",
                "/CTR/NoPadding",
                "/SIC/NoPadding"}, false);
            testModes(blockCiphers128[i], new String[]{"/CCM/NoPadding", "/EAX/NoPadding", "/GCM/NoPadding", "/OCB/NoPadding"}, true);
        }

        final String[] streamCiphers = new String[]{
            "ARC4",
            "SALSA20",
            "XSalsa20",
            "ChaCha",
            "ChaCha7539",
            "Grainv1",
            "Grain128",
            "HC128",
            "HC256"};

        for (int i = 0; i != streamCiphers.length; i++)
        {
            testModes(streamCiphers[i], new String[]{""}, false);
        }
    }

    public static void main(String[] args)
    {
        Security.addProvider(new BouncyCastleProvider());
        runTest(new CipherStreamTest2());
    }

}
