package org.bouncycastle.crypto.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;

import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.StreamCipher;
import org.bouncycastle.crypto.engines.HC128Engine;
import org.bouncycastle.crypto.engines.HC256Engine;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.util.Arrays;
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.util.test.SimpleTest;

/**
 * HC-128 and HC-256 Tests. Based on the test vectors in the official reference
 * papers, respectively:
 * 
 * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf
 * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc256_p3.pdf
 */
public class HCFamilyVecTest
    extends SimpleTest
{
    private static class PeekableLineReader extends BufferedReader
    {
        public PeekableLineReader(Reader r) throws IOException
        {
            super(r);

            peek = super.readLine();
        }

        public String peekLine()
        {
            return peek;
        }

        public String readLine() throws IOException
        {
            String tmp = peek;
            peek = super.readLine();
            return tmp;
        }

        private String peek; 
    }

    public String getName()
    {
        return "HC-128 and HC-256 (ecrypt)";
    }

    public void performTest() throws Exception
    {
        runTests(new HC128Engine(), "ecrypt_HC-128.txt");
        runTests(new HC256Engine(), "ecrypt_HC-256_128K_128IV.txt");
        runTests(new HC256Engine(), "ecrypt_HC-256_256K_128IV.txt");
        runTests(new HC256Engine(), "ecrypt_HC-256_128K_256IV.txt");
        runTests(new HC256Engine(), "ecrypt_HC-256_256K_256IV.txt");
    }

    private void runTests(StreamCipher hc, String fileName) throws IOException
    {
        Reader resource = new InputStreamReader(getClass().getResourceAsStream(fileName));
        PeekableLineReader r = new PeekableLineReader(resource);
        runAllVectors(hc, fileName, r);
    }

    private void runAllVectors(StreamCipher hc, String fileName, PeekableLineReader r)
        throws IOException
    {
        for (;;)
        {
            String line = r.readLine();
            if (line == null)
            {
                break;
            }

            line = line.trim();

            if (line.startsWith("Set "))
            {
                runVector(hc, fileName, r, dellChar(line, ':'));
            }
        }
    }

    private String dellChar(String s, char c)
    {
        StringBuffer b = new StringBuffer();

        for (int i = 0; i != s.length(); i++)
        {
            if (s.charAt(i) != c)
            {
                b.append(s.charAt(i));
            }
        }

        return b.toString();
    }

    private void runVector(StreamCipher hc, String fileName, PeekableLineReader r, String vectorName)
        throws IOException
    {
//        System.out.println(fileName + " => " + vectorName);
        String hexKey = readBlock(r);
        String hexIV = readBlock(r);

        CipherParameters cp = new KeyParameter(Hex.decode(hexKey));
        cp = new ParametersWithIV(cp, Hex.decode(hexIV));
        hc.init(true, cp);

        byte[] input = new byte[64];
        byte[] output = new byte[64];
        byte[] digest = new byte[64];
        int pos = 0;

        for (;;)
        {
            String line1 = r.peekLine().trim();
            int equalsPos = line1.indexOf('=');
            String lead = line1.substring(0, equalsPos - 1);

            String hexData = readBlock(r);
            byte[] data = Hex.decode(hexData);

            if (lead.equals("xor-digest"))
            {
                if (!Arrays.areEqual(data, digest))
                {
                    fail("Failed in " + fileName + " for test vector: " + vectorName + " at " + lead);
//                  System.out.println(fileName + " => " + vectorName + " failed at " + lead); return;
                }
                break;
            }

            int posA = lead.indexOf('[');
            int posB = lead.indexOf("..");
            int posC = lead.indexOf(']');
            int start = Integer.parseInt(lead.substring(posA + 1, posB));
            int end = Integer.parseInt(lead.substring(posB + 2, posC));

            if (start % 64 != 0 || (end - start != 63))
            {
                throw new IllegalStateException(vectorName + ": " + lead + " not on 64 byte boundaries");
            }

            while (pos < end)
            {
                hc.processBytes(input, 0, input.length, output, 0);
                xor(digest, output);
                pos += 64;
            }

            if (!Arrays.areEqual(data, output))
            {
                fail("Failed in " + fileName + " for test vector: " + vectorName + " at " + lead);
//              System.out.println(fileName + " => " + vectorName + " failed at " + lead); return;
            }
        }
    }

    private static String readBlock(PeekableLineReader r) throws IOException
    {
        String first = r.readLine().trim();
        String result = first.substring(first.lastIndexOf(' ') + 1);

        for (;;)
        {
            String peek = r.peekLine().trim();
            if (peek.length() < 1 || peek.indexOf('=') >= 0)
            {
                break;
            }
            result += r.readLine().trim();
        }

        return result;
    }

    private static void xor(byte[] digest, byte[] block)
    {
        for (int i = 0; i < digest.length; ++i)
        {
            digest[i] ^= block[i];
        }
    }

    public static void main(String[] args)
    {
        runTest(new HCFamilyVecTest());
    }
}
