using System;
using System.Text;

using NUnit.Framework;

using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Digests;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Encodings;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Utilities.Encoders;
using Org.BouncyCastle.Utilities.Test;

namespace Org.BouncyCastle.Crypto.Tests
{
    /**
     * standard vector test for SHA-384 from FIPS Draft 180-2.
     *
     * Note, the first two vectors are _not_ from the draft, the last three are.
     */
    [TestFixture]
    public class Sha384DigestTest
		: ITest
    {
//        static private string testVec1 = "";
        static private string resVec1 = "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b";

        static private string testVec2 = "61";
        static private string resVec2 = "54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31";

        static private string testVec3 = "616263";
        static private string resVec3 = "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7";

        static private string testVec4 = "61626364656667686263646566676869636465666768696a6465666768696a6b65666768696a6b6c666768696a6b6c6d6768696a6b6c6d6e68696a6b6c6d6e6f696a6b6c6d6e6f706a6b6c6d6e6f70716b6c6d6e6f7071726c6d6e6f707172736d6e6f70717273746e6f707172737475";
        static private string resVec4 = "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039";

        // 1 million 'a'
        static private string testVec5 = "61616161616161616161";
        static private string resVec5 = "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985";

		public string Name
        {
			get { return "SHA384"; }
        }

		public ITestResult Perform()
        {
            IDigest digest = new Sha384Digest();
            byte[] resBuf = new byte[digest.GetDigestSize()];
            string resStr;

			//
            // test 1
            //
            digest.DoFinal(resBuf, 0);

            resStr = Encoding.ASCII.GetString(Hex.Encode(resBuf));
            if (!resVec1.Equals(resStr))
            {
                return new SimpleTestResult(false,
                    "SHA-384 failing standard vector test 1"
                    + System.Environment.NewLine
                    + "    expected: " + resVec1
                    + System.Environment.NewLine
                    + "    got     : " + resStr);
            }

            //
            // test 2
            //
            byte[] bytes = Hex.Decode(testVec2);
			digest.BlockUpdate(bytes, 0, bytes.Length);

			digest.DoFinal(resBuf, 0);

			resStr = Encoding.ASCII.GetString(Hex.Encode(resBuf));
            if (!resVec2.Equals(resStr))
            {
                return new SimpleTestResult(false,
                    "SHA-384 failing standard vector test 2"
                    + System.Environment.NewLine
                    + "    expected: " + resVec2
                    + System.Environment.NewLine
                    + "    got     : " + resStr);
            }

			//
            // test 3
            //
            bytes = Hex.Decode(testVec3);

            digest.BlockUpdate(bytes, 0, bytes.Length);

            digest.DoFinal(resBuf, 0);

            resStr = Encoding.ASCII.GetString(Hex.Encode(resBuf));
            if (!resVec3.Equals(resStr))
            {
                return new SimpleTestResult(false,
                    "SHA-384 failing standard vector test 3"
                    + System.Environment.NewLine
                    + "    expected: " + resVec3
                    + System.Environment.NewLine
                    + "    got     : " + resStr);
            }

            //
            // test 4
            //
            bytes = Hex.Decode(testVec4);

            digest.BlockUpdate(bytes, 0, bytes.Length);

            digest.DoFinal(resBuf, 0);

            resStr = Encoding.ASCII.GetString(Hex.Encode(resBuf));
            if (!resVec4.Equals(resStr))
            {
                return new SimpleTestResult(false,
                    "SHA-384 failing standard vector test 4"
                    + System.Environment.NewLine
                    + "    expected: " + resVec4
                    + System.Environment.NewLine
                    + "    got     : " + resStr);
            }

            //
            // test 5
            //
            bytes = Hex.Decode(testVec4);

            digest.BlockUpdate(bytes, 0, bytes.Length/2);

            // clone the IDigest
            IDigest d = new Sha384Digest((Sha384Digest)digest);

            digest.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2);
            digest.DoFinal(resBuf, 0);

            resStr = Encoding.ASCII.GetString(Hex.Encode(resBuf));
            if (!resVec4.Equals(resStr))
            {
                return new SimpleTestResult(false,
                    "SHA384 failing standard vector test 5"
                    + System.Environment.NewLine
                    + "    expected: " + resVec4
                    + System.Environment.NewLine
                    + "    got     : " + resStr);
            }

            d.BlockUpdate(bytes, bytes.Length/2, bytes.Length - bytes.Length/2);
            d.DoFinal(resBuf, 0);

            resStr = Encoding.ASCII.GetString(Hex.Encode(resBuf));
            if (!resVec4.Equals(resStr))
            {
                return new SimpleTestResult(false,
                    "SHA384 failing standard vector test 5"
                    + System.Environment.NewLine
                    + "    expected: " + resVec4
                    + System.Environment.NewLine
                    + "    got     : " + resStr);
            }

            // test 6
            bytes = Hex.Decode(testVec5);
            for ( int i = 0; i < 100000; i++ )
            {
                digest.BlockUpdate(bytes, 0, bytes.Length);
            }
            digest.DoFinal(resBuf, 0);

            resStr = Encoding.ASCII.GetString(Hex.Encode(resBuf));
            if (!resVec5.Equals(resStr))
            {
                return new SimpleTestResult(false,
                    "SHA-384 failing standard vector test 5"
                    + System.Environment.NewLine
                    + "    expected: " + resVec5
                    + System.Environment.NewLine
                    + "    got     : " + resStr);
            }

            return new SimpleTestResult(true, Name + ": Okay");
        }

        public static void Main(
            string[] args)
        {
            ITest test = new Sha384DigestTest();
            ITestResult result = test.Perform();

			Console.WriteLine(result);
        }

		[Test]
        public void TestFunction()
        {
            string resultText = Perform().ToString();

			Assert.AreEqual(Name + ": Okay", resultText);
        }
    }
}
