using System;
using System.Diagnostics;
using System.IO;
using CryptoSysAPI;

// Some tests using the CryptoSysAPI .NET interface.

/* 
 **************************** COPYRIGHT NOTICE ****************************
 * Copyright (C) 2005-6 DI Management Services Pty Limited. 
 * All rights reserved. <www.di-mgt.com.au> <www.cryptosys.net>
 *   $Id: TestAPIcsharp.cs $
 *   Last updated:
 *   $Date: 2006-07-21 09:50:00 $
 *   $Version: 3.2.0 $
 ************************* END OF COPYRIGHT NOTICE ************************
 */

namespace TestAPIcsharp
{
    /// <summary>
    /// Test examples for CryptoSysAPI interface
    /// </summary>
    class TestAPIcsharp
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            string s;
            string okhex;
            string filename;
            string keyStr, ivStr, saltHex;
            string plain, cipher;
            byte [] arrPlain;
            byte [] arrCipher;
            byte [] arrKey;
            byte [] arrIV;
            byte[] b;
            byte[] salt;
            byte[] arrPwd;
            byte[] arrOk;
            int n, i;
            char ch;
            bool tf;
            string excontent;
            string fnameData;
            string fnameEnc;
            string fnameCheck;
            byte[] a1000;

            //****************
            // GENERAL TESTS *
            //****************
            Console.WriteLine("GENERAL FUNCTIONS:");
            n = General.Version();
            Console.WriteLine("Version={0}", n);

            n = General.PowerUpTests();
            Console.WriteLine("PowerUpTests={0}", n);
            
            s = General.CompileTime();
            Console.WriteLine("CompileTime={0}", s);

            s = General.ModuleName();
            Console.WriteLine("ModuleName={0}", s);

            ch = General.LicenceType();
            Console.WriteLine("LicenceType={0}", ch);

            //*******************************
            // HEXADECIMAL CONVERSION TESTS *
            //*******************************
            Console.WriteLine("CONVERSION TESTS:");
            b = Cnv.FromHex("deadbeef");
            s = Cnv.ToHex(b);
            Console.WriteLine("ToHex={0}", s);
            b = Cnv.FromHex(s);
            Console.WriteLine("In base64='{0}'", Convert.ToBase64String(b));
            s = Cnv.StringFromHex("616263");
            Console.WriteLine("0x616263='{0}'", s);

            //**********************
            // ERROR LOOKUP TESTS *
            //**********************
            Console.WriteLine("ERROR CODES:");
            for (i = 0; i < 10000; i++)
            {
                s = General.ErrorLookup(i);
                if (!s.Equals(String.Empty))
                    Console.WriteLine("Error {0}={1}", i, s);
            }

            //****************************
            // BLOWFISH ENCRYPTION TESTS *
            //****************************
            Console.WriteLine("TESTING BLOWFISH:");
            keyStr = "FEDCBA9876543210";
            plain = "0123456789ABCDEF";
            cipher = "0ACEAB0FC6A0A28D";
            // Encrypt in ECB mode using hex strings
            s = Blowfish.Encrypt(plain, keyStr, Mode.ECB, null);
            Console.WriteLine("KY={0}",keyStr);
            Console.WriteLine("PT={0}",plain);
            Console.WriteLine("CT={0}",s);
            Console.WriteLine("OK={0}",cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Blowfish.Encrypt failed");
            // Decrypt
            s = Blowfish.Decrypt(cipher, keyStr, Mode.ECB, null);
            Console.WriteLine("P'={0}",s);
            Console.WriteLine("OK={0}",plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Blowfish.Decrypt failed");

            // Ditto using byte arrays
            arrPlain = Cnv.FromHex(plain);
            arrCipher = Cnv.FromHex(cipher);
            arrKey = Cnv.FromHex(keyStr);
            b = Blowfish.Encrypt(arrPlain, arrKey, Mode.ECB, null);
            Console.WriteLine("CT={0}",Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(b), cipher, true)==0, "Blowfish.Encrypt failed");
            b = Blowfish.Decrypt(arrCipher, arrKey, Mode.ECB, null);
            Console.WriteLine("P'={0}",Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(b), plain, true)==0, "Blowfish.Decrypt failed");

            // Encrypt in CBC mode using hex strings
            keyStr = "0123456789ABCDEFF0E1D2C3B4A59687";
            ivStr = "FEDCBA9876543210";
            plain = "37363534333231204E6F77206973207468652074696D6520666F722000000000";
            cipher = "6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC";
            s = Blowfish.Encrypt(plain, keyStr, Mode.CBC, ivStr);
            Console.WriteLine("KY={0}",keyStr);
            Console.WriteLine("IV={0}",ivStr);
            Console.WriteLine("PT={0}",plain);
            Console.WriteLine("CT={0}",s);
            Console.WriteLine("OK={0}",cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Blowfish.Encrypt (CBC) failed");
            // Decrypt
            s = Blowfish.Decrypt(cipher, keyStr, Mode.CBC, ivStr);
            Console.WriteLine("P'={0}",s);
            Console.WriteLine("OK={0}",plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Blowfish.Decrypt (CBC) failed");

            // Ditto using byte arrays
            arrPlain = Cnv.FromHex(plain);
            arrCipher = Cnv.FromHex(cipher);
            arrKey = Cnv.FromHex(keyStr);
            arrIV = Cnv.FromHex(ivStr);
            b = Blowfish.Encrypt(arrPlain, arrKey, Mode.CBC, arrIV);
            Console.WriteLine("CT={0}",Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(b), cipher, true)==0, "Blowfish.Encrypt (CBC) failed");
            b = Blowfish.Decrypt(arrCipher, arrKey, Mode.CBC, arrIV);
            Console.WriteLine("P'={0}",Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(b), plain, true)==0, "Blowfish.Decrypt (CBC) failed");

            // And again using base64 strings
            keyStr = "ASNFZ4mrze/w4dLDtKWWhw==";
            ivStr = "/ty6mHZUMhA=";
            plain = "NzY1NDMyMSBOb3cgaXMgdGhlIHRpbWUgZm9yIAAAAAA=";
            cipher = "a3e01jAG3uYFsVbidAOXk1jeuecVRhbZWfFlK9X/ksw=";
            s = Blowfish.Encrypt(plain, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
            Console.WriteLine("KY={0}",keyStr);
            Console.WriteLine("IV={0}",ivStr);
            Console.WriteLine("PT={0}",plain);
            Console.WriteLine("CT={0}",s);
            Console.WriteLine("OK={0}",cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Blowfish.Encrypt (CBC-base64) failed");
            // Decrypt
            s = Blowfish.Decrypt(cipher, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
            Console.WriteLine("P'={0}",s);
            Console.WriteLine("OK={0}",plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Blowfish.Decrypt (CBC-base64) failed");

            // Pad some data ready for encryption - first in hex format
            okhex = "ffffff";
            s = okhex;
            plain = Blowfish.Pad(s);
            Console.WriteLine("Blowfish.Pad('{0}')='{1}'", s, plain);
            Debug.Assert((plain.Length % (Blowfish.BlockSize * 2)) == 0, "Blowfish.Pad(hex) failed");
            // and remove it
            s = Blowfish.Unpad(plain);
            Console.WriteLine("Blowfish.Unpad('{0}')='{1}'", plain, s);
            Debug.Assert(s == okhex, "Blowfish.Unpad(hex) failed");
            // again padding an empty string
            okhex = "";
            s = okhex;
            plain = Blowfish.Pad(s);
            Console.WriteLine("Blowfish.Pad('{0}')='{1}'", s, plain);
            Debug.Assert((plain.Length % (Blowfish.BlockSize * 2)) == 0, "Blowfish.Pad(hex) failed");
            // and remove it
            s = Blowfish.Unpad(plain);
            Console.WriteLine("Blowfish.Unpad('{0}')='{1}'", plain, s);
            Debug.Assert(s == okhex, "Blowfish.Unpad(hex) failed");
            // Pad using bytes
            arrOk = Cnv.FromHex("ffffffffffffffff");
            b = arrOk;
            arrPlain = Blowfish.Pad(b);
            Console.WriteLine("Blowfish.Pad(0x{0})=0x{1}", Cnv.ToHex(b), Cnv.ToHex(arrPlain));
            Debug.Assert((arrPlain.Length % Blowfish.BlockSize) == 0, "Blowfish.Pad(bytes) failed");
            b = Blowfish.Unpad(arrPlain);
            Console.WriteLine("Blowfish.Unpad(0x{0})=0x{1}", Cnv.ToHex(arrPlain), Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(b), Cnv.ToHex(arrOk)) == 0, "Blowfish.Unpad(bytes) failed");

            // Now use Init-Update-Final
            keyStr = "FEDCBA9876543210";
            ivStr = "0123456789abcdef";
            // Instantiate a new encryption object
            Blowfish oBlf = Blowfish.Instance();
            // Setup to encrypt in CBC mode
            n = oBlf.InitEncrypt(keyStr, Mode.CBC, ivStr);
            Console.WriteLine("Initialize returns {0}", n);
            Debug.Assert(oBlf.ErrCode == 0, "Blowfish.Initialize failed");

            plain = "0101010101010101";
            cipher = "46733BCD9C72C5E3";
            s = oBlf.Update(plain);
            Console.WriteLine("PT1={0}", plain);
            Console.WriteLine("CT1={0}", s);
            Console.WriteLine("OK1={0}", cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Blowfish.Update failed");
            // Line 2 using bytes
            plain = "0202020202020202";
            cipher = "F434DA62B6869A06";
            b = Cnv.FromHex(plain);
            b = oBlf.Update(b);
            s = Cnv.ToHex(b);
            Console.WriteLine("PT2={0}", plain);
            Console.WriteLine("CT2={0}", s);
            Console.WriteLine("OK2={0}", cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Blowfish.Update failed");
            // Lines 3 and 4 together using hex and a longer input
            plain = "03030303030303030404040404040404";
            cipher = "2AE6DFE458559138DEEBF97D6F83A5F3";
            s = oBlf.Update(plain);
            Console.WriteLine("PT3={0}", plain);
            Console.WriteLine("CT3={0}", s);
            Console.WriteLine("OK3={0}", cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Blowfish.Update failed");

            // Create a second object this time to decrypt
            // NB You can only have one Instance at a time in the same thread
            // So this just overwrites the previous one as a test
            // TODO: perhaps return an error here to emphasise the point?
            Blowfish oBlf2 = Blowfish.Instance();
            n = oBlf2.InitDecrypt(keyStr, Mode.CBC, ivStr);
            Console.WriteLine("Initialize returns {0}", n);
            Debug.Assert(oBlf2.ErrCode == 0, "Blowfish.Init failed");

            plain = "0101010101010101";
            cipher = "46733BCD9C72C5E3";
            s = oBlf2.Update(cipher);
            Console.WriteLine("CT1={0}", cipher);
            Console.WriteLine("PT1={0}", s);
            Console.WriteLine("OK1={0}", plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Blowfish.Update failed");
            // Line 2 using bytes
            plain = "0202020202020202";
            cipher = "F434DA62B6869A06";
            b = Cnv.FromHex(cipher);
            b = oBlf2.Update(b);
            s = Cnv.ToHex(b);
            Console.WriteLine("CT2={0}", cipher);
            Console.WriteLine("PT2={0}", s);
            Console.WriteLine("OK2={0}", plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Blowfish.Update failed");
            // Lines 3 and 4 using hex
            plain = "03030303030303030404040404040404";
            cipher = "2AE6DFE458559138DEEBF97D6F83A5F3";
            s = oBlf2.Update(cipher);
            Console.WriteLine("CT3={0}", cipher);
            Console.WriteLine("PT3={0}", s);
            Console.WriteLine("OK3={0}", plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Blowfish.Update failed");

            // Experiment with object methods
            s = oBlf.ToString();
            Console.WriteLine("oBlf.ToString()={0}", s);
            Type ty = oBlf.GetType();
            Console.WriteLine("oBlf.GetType()={0}", ty);
            n = oBlf.GetHashCode();
            Console.WriteLine("oBlf.GetHashCode()={0}", n);
            n = oBlf2.GetHashCode();
            Console.WriteLine("oBlf2.GetHashCode()={0}", n);
            
            // Make sure keys are disposed of
            oBlf.Dispose();
            oBlf2.Dispose();
            Console.WriteLine("Blf Objects disposed of.");

            // Create a test text file
            excontent = "This is some sample content.";
            fnameData = "excontent.txt";
            MakeATextFile(fnameData, excontent);

            // Encrypt a file
            keyStr = "fedcba9876543210";
            fnameEnc = "excontent.blf.enc.dat";
            okhex = "D45B1B15FA7960E34D67F6366B5ECDD91E941467F21F5BE34A1F5A5158A8569C";
            n = Blowfish.FileEncrypt(fnameEnc, fnameData, keyStr, Mode.ECB, null);
            if (0 == n)
                Console.WriteLine("Blowfish.File created encrypted file '{0}'", fnameEnc);
            else
                Console.WriteLine("Blowfish.File returned error code {0}", n);
            Debug.Assert(0 == n, "Blowfish.File failed.");

            // Check we got what we should
            b = ReadABinaryFile(fnameEnc);
            Console.WriteLine("CT={0}", Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(b), okhex, true)==0, "Blowfish.FileEncrypt failed");

            // Decrypt it using byte format of key instead of hex
            fnameCheck = "excontent.blf.chk.txt";
            b = Cnv.FromHex(keyStr);
            n = Blowfish.FileDecrypt(fnameCheck, fnameEnc, b, Mode.ECB, null);
            if (0 == n)
            {
                Console.WriteLine("Blowfish.File decrypted to file '{0}'", fnameCheck);
                // Show contents of file
                s = ReadATextFile(fnameCheck);
                Debug.Assert(String.Compare(s, excontent)==0, "Decrypted file data does not match");
            }
            else
                Console.WriteLine("Blowfish.File returned error code {0}", n);
            Debug.Assert(0 == n, "Blowfish.File failed.");


            //***************************
            // DES ENCRYPTION TESTS *
            //***************************
            Console.WriteLine("TESTING DES:");
            keyStr = "0123456789abcdef";
            plain = "4e6f772069732074";
            cipher = "3fa40e8a984d4815";
            // Encrypt in ECB mode using hex strings
            s = Des.Encrypt(plain, keyStr, Mode.ECB, null);
            Console.WriteLine("KY={0}",keyStr);
            Console.WriteLine("PT={0}",plain);
            Console.WriteLine("CT={0}",s);
            Console.WriteLine("OK={0}",cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Des.HexECB failed");
            // Decrypt
            s = Des.Decrypt(cipher, keyStr, Mode.ECB, null);
            Console.WriteLine("P'={0}",s);
            Console.WriteLine("OK={0}",plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Des.HexECB failed");

            // Ditto using byte arrays
            arrPlain = Cnv.FromHex(plain);
            arrCipher = Cnv.FromHex(cipher);
            arrKey = Cnv.FromHex(keyStr);
            b = Des.Encrypt(arrPlain, arrKey, Mode.ECB, null);
            Console.WriteLine("CT={0}",Cnv.ToHex(b));
            b = Des.Decrypt(arrCipher, arrKey, Mode.ECB, null);
            Console.WriteLine("P'={0}",Cnv.ToHex(b));

            // Encrypt in CBC mode using hex strings
            keyStr = "0123456789abcdef";
            ivStr = "1234567890abcdef";
            plain = "4e6f77206973207468652074696d6520666f7220616c6c20";
            cipher = "e5c7cdde872bf27c43e934008c389c0f683788499a7c05f6";
            s = Des.Encrypt(plain, keyStr, Mode.CBC, ivStr);
            Console.WriteLine("KY={0}",keyStr);
            Console.WriteLine("IV={0}",ivStr);
            Console.WriteLine("PT={0}",plain);
            Console.WriteLine("CT={0}",s);
            Console.WriteLine("OK={0}",cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Des.Encrypt{Hex,CBC} failed");
            // Decrypt
            s = Des.Decrypt(cipher, keyStr, Mode.CBC, ivStr);
            Console.WriteLine("P'={0}",s);
            Console.WriteLine("OK={0}",plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Des.Decrypt{Hex,CBC} failed");

            // Ditto using byte arrays
            arrPlain = Cnv.FromHex(plain);
            arrCipher = Cnv.FromHex(cipher);
            arrKey = Cnv.FromHex(keyStr);
            arrIV = Cnv.FromHex(ivStr);
            b = Des.Encrypt(arrPlain, arrKey, Mode.CBC, arrIV);
            Console.WriteLine("CT={0}",Cnv.ToHex(b));
            b = Des.Decrypt(arrCipher, arrKey, Mode.CBC, arrIV);
            Console.WriteLine("P'={0}",Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(arrPlain), Cnv.ToHex(b))==0, "Des.BytesCBC failed");

            // And again using base64 strings
            keyStr = "ASNFZ4mrze8=";
            ivStr = "EjRWeJCrze8=";
            plain = "Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwg";
            cipher = "5cfN3ocr8nxD6TQAjDicD2g3iEmafAX2";
            s = Des.Encrypt(plain, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
            Console.WriteLine("KY={0}",keyStr);
            Console.WriteLine("IV={0}",ivStr);
            Console.WriteLine("PT={0}",plain);
            Console.WriteLine("CT={0}",s);
            Console.WriteLine("OK={0}",cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Des.Encrypt{base64,CBC} failed");
            // Decrypt
            s = Des.Decrypt(cipher, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
            Console.WriteLine("P'={0}",s);
            Console.WriteLine("OK={0}",plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Des.Decrypt{base64,CBC} failed");

            // Pad some data ready for encryption - first in hex format
            okhex = "ffffff";
            s = okhex;
            plain = Des.Pad(s);
            Console.WriteLine("Des.Pad('{0}')='{1}'", s, plain);
            Debug.Assert((plain.Length % (Des.BlockSize * 2)) == 0, "Des.Pad(hex) failed");
            // and remove it
            s = Des.Unpad(plain);
            Console.WriteLine("Des.Unpad('{0}')='{1}'", plain, s);
            Debug.Assert(s == okhex, "Des.Unpad(hex) failed");
            // Pad using bytes
            arrOk = Cnv.FromHex("ffffffffffffffff");
            b = arrOk;
            arrPlain = Des.Pad(b);
            Console.WriteLine("Des.Pad(0x{0})=0x{1}", Cnv.ToHex(b), Cnv.ToHex(arrPlain));
            Debug.Assert((arrPlain.Length % Des.BlockSize) == 0, "Des.Pad(bytes) failed");
            b = Des.Unpad(arrPlain);
            Console.WriteLine("Des.Unpad(0x{0})=0x{1}", Cnv.ToHex(arrPlain), Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(b), Cnv.ToHex(arrOk)) == 0, "Des.Unpad(bytes) failed");

            // Now use Init-Update-Final
            keyStr = "0123456789abcdef";
            ivStr = "1234567890abcdef";
            // Instantiate a new encryption object
            Des oDes = Des.Instance();
            n = oDes.InitEncrypt(keyStr, Mode.CBC, ivStr);
            Console.WriteLine("Initialize returns {0}", n);
            Debug.Assert(oDes.ErrCode == 0, "Des.Initialize failed");

            plain = "4e6f772069732074";
            cipher = "E5C7CDDE872BF27C";
            s = oDes.Update(plain);
            Console.WriteLine("PT1={0}", plain);
            Console.WriteLine("CT1={0}", s);
            Console.WriteLine("OK1={0}", cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Des.Update failed");
            // Line 2 using bytes
            plain = "68652074696d6520";
            cipher = "43E934008C389C0F";
            b = Cnv.FromHex(plain);
            b = oDes.Update(b);
            s = Cnv.ToHex(b);
            Console.WriteLine("PT2={0}", plain);
            Console.WriteLine("CT2={0}", s);
            Console.WriteLine("OK2={0}", cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Des.Update failed");
            // Line 3 using hex
            plain = "666f7220616c6c20";
            cipher = "683788499A7C05F6";
            s = oDes.Update(plain);
            Console.WriteLine("PT3={0}", plain);
            Console.WriteLine("CT3={0}", s);
            Console.WriteLine("OK3={0}", cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Des.Update failed");

            n = oDes.InitDecrypt(keyStr, Mode.CBC, ivStr);
            Console.WriteLine("Initialize returns {0}", n);
            Debug.Assert(oDes.ErrCode == 0, "Des.Initialize failed");

            plain = "4e6f772069732074";
            cipher = "E5C7CDDE872BF27C";
            s = oDes.Update(cipher);
            Console.WriteLine("CT1={0}", cipher);
            Console.WriteLine("PT1={0}", s);
            Console.WriteLine("OK1={0}", plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Des.Update failed");
            // Line 2 using bytes
            plain = "68652074696d6520";
            cipher = "43E934008C389C0F";
            b = Cnv.FromHex(cipher);
            b = oDes.Update(b);
            s = Cnv.ToHex(b);
            Console.WriteLine("CT2={0}", cipher);
            Console.WriteLine("PT2={0}", s);
            Console.WriteLine("OK2={0}", plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Des.Update failed");
            // Line 3 using hex
            plain = "666f7220616c6c20";
            cipher = "683788499A7C05F6";
            s = oDes.Update(cipher);
            Console.WriteLine("CT3={0}", cipher);
            Console.WriteLine("PT3={0}", s);
            Console.WriteLine("OK3={0}", plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Des.Update failed");

            // Make sure keys are disposed of
            oDes.Dispose();
            Console.WriteLine("Des Object disposed of.");

            // Create a test text file
            excontent = "This is some sample content.";
            fnameData = "excontent.txt";
            MakeATextFile(fnameData, excontent);

            // Encrypt a file
            keyStr = "fedcba9876543210";
            fnameEnc = "excontent.des.enc.dat";
            okhex = "84D1604C0A33D9335F7EDB5C7ABE73F86B9C87F0639D45F2C8172C8AA976B247";
            n = Des.FileEncrypt(fnameEnc, fnameData, keyStr, Mode.ECB, null);
            if (0 == n)
                Console.WriteLine("Des.File created encrypted file '{0}'", fnameEnc);
            else
                Console.WriteLine("Des.File returned error code {0}", n);
            Debug.Assert(0 == n, "Des.File failed.");

            // Check we got what we should
            b = ReadABinaryFile(fnameEnc);
            Console.WriteLine("CT={0}", Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(b), okhex, true)==0, "Des.FileEncrypt failed");

            // Decrypt it using byte format of key instead of hex
            fnameCheck = "excontent.des.chk.txt";
            b = Cnv.FromHex(keyStr);
            n = Des.FileDecrypt(fnameCheck, fnameEnc, b, Mode.ECB, null);
            if (0 == n)
            {
                Console.WriteLine("Des.File decrypted to file '{0}'", fnameCheck);
                // Show contents of file
                s = ReadATextFile(fnameCheck);
                Debug.Assert(String.Compare(s, excontent)==0, "Decrypted file data does not match");
            }
            else
                Console.WriteLine("Des.File returned error code {0}", n);
            Debug.Assert(0 == n, "Des.File failed.");


            //*****************************************************
            // TDEA (Triple DES, 3DES, DES-EDE3) ENCRYPTION TESTS *
            //*****************************************************
            Console.WriteLine("TESTING TRIPLE DES:");
            keyStr = "010101010101010101010101010101010101010101010101";
            plain = "8000000000000000";
            cipher = "95F8A5E5DD31D900";
            // Encrypt in ECB mode using hex strings
            s = Tdea.Encrypt(plain, keyStr, Mode.ECB, null);
            Console.WriteLine("KY={0}",keyStr);
            Console.WriteLine("PT={0}",plain);
            Console.WriteLine("CT={0}",s);
            Console.WriteLine("OK={0}",cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Tdea.HexECB failed");
            // Decrypt
            s = Tdea.Decrypt(cipher, keyStr, Mode.ECB, null);
            Console.WriteLine("P'={0}",s);
            Console.WriteLine("OK={0}",plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Tdea.HexECB failed");

            // Ditto using byte arrays
            arrPlain = Cnv.FromHex(plain);
            arrCipher = Cnv.FromHex(cipher);
            arrKey = Cnv.FromHex(keyStr);
            b = Tdea.Encrypt(arrPlain, arrKey, Mode.ECB, null);
            Console.WriteLine("CT={0}",Cnv.ToHex(b));
            b = Tdea.Decrypt(arrCipher, arrKey, Mode.ECB, null);
            Console.WriteLine("P'={0}",Cnv.ToHex(b));

            // Encrypt in CBC mode using hex strings
            keyStr = "737C791F25EAD0E04629254352F7DC6291E5CB26917ADA32";
            ivStr = "B36B6BFB6231084E";
            plain = "5468697320736F6D652073616D706520636F6E74656E742E0808080808080808";
            cipher = "d76fd1178fbd02f84231f5c1d2a2f74a4159482964f675248254223daf9af8e4";
            s = Tdea.Encrypt(plain, keyStr, Mode.CBC, ivStr);
            Console.WriteLine("KY={0}",keyStr);
            Console.WriteLine("IV={0}",ivStr);
            Console.WriteLine("PT={0}",plain);
            Console.WriteLine("CT={0}",s);
            Console.WriteLine("OK={0}",cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Tdea.Encrypt{Hex,CBC} failed");
            // Decrypt
            s = Tdea.Decrypt(cipher, keyStr, Mode.CBC, ivStr);
            Console.WriteLine("P'={0}",s);
            Console.WriteLine("OK={0}",plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Tdea.Decrypt{Hex,CBC} failed");

            // Ditto using byte arrays
            arrPlain = Cnv.FromHex(plain);
            arrCipher = Cnv.FromHex(cipher);
            arrKey = Cnv.FromHex(keyStr);
            arrIV = Cnv.FromHex(ivStr);
            b = Tdea.Encrypt(arrPlain, arrKey, Mode.CBC, arrIV);
            Console.WriteLine("CT={0}",Cnv.ToHex(b));
            b = Tdea.Decrypt(arrCipher, arrKey, Mode.CBC, arrIV);
            Console.WriteLine("P'={0}",Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(arrPlain), Cnv.ToHex(b))==0, "Tdea.BytesCBC failed");

            // ditto using base64 data
            keyStr = "c3x5HyXq0OBGKSVDUvfcYpHlyyaRetoy";
            ivStr = "s2tr+2IxCE4=";
            plain = "VGhpcyBzb21lIHNhbXBlIGNvbnRlbnQuCAgICAgICAg=";
            cipher = "12/RF4+9AvhCMfXB0qL3SkFZSClk9nUkglQiPa+a+OQ=";
            s = Tdea.Encrypt(plain, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
            Console.WriteLine("KY={0}",keyStr);
            Console.WriteLine("IV={0}",ivStr);
            Console.WriteLine("PT={0}",plain);
            Console.WriteLine("CT={0}",s);
            Console.WriteLine("OK={0}",cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Tdea.Encrypt{Base64,CBC} failed");
            // Decrypt
            s = Tdea.Decrypt(cipher, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
            Console.WriteLine("P'={0}",s);
            Console.WriteLine("OK={0}",plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Tdea.Decrypt{Base64,CBC} failed");

            // Pad some data ready for encryption - first in hex format
            okhex = "ffffff";
            s = okhex;
            plain = Tdea.Pad(s);
            Console.WriteLine("Tdea.Pad('{0}')='{1}'", s, plain);
            Debug.Assert((plain.Length % (Tdea.BlockSize * 2)) == 0, "Tdea.Pad(hex) failed");
            // and remove it
            s = Tdea.Unpad(plain);
            Console.WriteLine("Tdea.Unpad('{0}')='{1}'", plain, s);
            Debug.Assert(s == okhex, "Tdea.Unpad(hex) failed");
            // Pad using bytes
            arrOk = Cnv.FromHex("ffffffffffffffff");
            b = arrOk;
            arrPlain = Tdea.Pad(b);
            Console.WriteLine("Tdea.Pad(0x{0})=0x{1}", Cnv.ToHex(b), Cnv.ToHex(arrPlain));
            Debug.Assert((arrPlain.Length % Tdea.BlockSize) == 0, "Tdea.Pad(bytes) failed");
            b = Tdea.Unpad(arrPlain);
            Console.WriteLine("Tdea.Unpad(0x{0})=0x{1}", Cnv.ToHex(arrPlain), Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(b), Cnv.ToHex(arrOk)) == 0, "Tdea.Unpad(bytes) failed");

            // Now use Init-Update-Final
            keyStr = "0123456789abcdeffedcba987654321089abcdef01234567";
            ivStr = "1234567890abcdef";
            // Instantiate a new encryption object
            Tdea oTdea = Tdea.Instance();
            n = oTdea.InitEncrypt(keyStr, Mode.CBC, ivStr);
            Console.WriteLine("Initialize returns {0}", n);
            Debug.Assert(oTdea.ErrCode == 0, "Tdea.Initialize failed");

            plain = "4e6f772069732074";
            cipher = "204011f986e35647";
            s = oTdea.Update(plain);
            Console.WriteLine("PT1={0}", plain);
            Console.WriteLine("CT1={0}", s);
            Console.WriteLine("OK1={0}", cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Tdea.Update failed");
            // Line 2 using bytes
            plain = "68652074696d6520";
            cipher = "199e47af391620c5";
            b = Cnv.FromHex(plain);
            b = oTdea.Update(b);
            s = Cnv.ToHex(b);
            Console.WriteLine("PT2={0}", plain);
            Console.WriteLine("CT2={0}", s);
            Console.WriteLine("OK2={0}", cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Tdea.Update failed");
            // Line 3 using hex
            plain = "666f7220616c6c20";
            cipher = "bb9a5bcfc86db0bb";
            s = oTdea.Update(plain);
            Console.WriteLine("PT3={0}", plain);
            Console.WriteLine("CT3={0}", s);
            Console.WriteLine("OK3={0}", cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Tdea.Update failed");

            // Now decrypt
            n = oTdea.InitDecrypt(keyStr, Mode.CBC, ivStr);
            Console.WriteLine("Initialize returns {0}", n);
            Debug.Assert(oTdea.ErrCode == 0, "Tdea.Initialize failed");

            plain = "4e6f772069732074";
            cipher = "204011f986e35647";
            s = oTdea.Update(cipher);
            Console.WriteLine("CT1={0}", cipher);
            Console.WriteLine("PT1={0}", s);
            Console.WriteLine("OK1={0}", plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Tdea.Update failed");
            // Line 2 using bytes
            plain = "68652074696d6520";
            cipher = "199e47af391620c5";
            b = Cnv.FromHex(cipher);
            b = oTdea.Update(b);
            s = Cnv.ToHex(b);
            Console.WriteLine("CT2={0}", cipher);
            Console.WriteLine("PT2={0}", s);
            Console.WriteLine("OK2={0}", plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Tdea.Update failed");
            // Line 3 using hex
            plain = "666f7220616c6c20";
            cipher = "bb9a5bcfc86db0bb";
            s = oTdea.Update(cipher);
            Console.WriteLine("CT3={0}", cipher);
            Console.WriteLine("PT3={0}", s);
            Console.WriteLine("OK3={0}", plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Tdea.Update failed");

            // Make sure keys are disposed of
            oTdea.Dispose();
            Console.WriteLine("Tdea Object disposed of.");

            // Create a test text file
            excontent = "This is some sample content.";
            fnameData = "excontent.txt";
            MakeATextFile(fnameData, excontent);

            // Encrypt a file
            keyStr = "fedcba98765432100123456789abcdeffedcba9876543210";
            fnameEnc = "excontent.tdea.enc.dat";
            okhex = "DD1E1FA430AE6BE1D3B83245F7A5B17C4BF03688238778E95F2CCD05AF1A8F44";
            n = Tdea.FileEncrypt(fnameEnc, fnameData, keyStr, Mode.ECB, null);
            if (0 == n)
                Console.WriteLine("Tdea.File created encrypted file '{0}'", fnameEnc);
            else
                Console.WriteLine("Tdea.File returned error code {0}", n);
            Debug.Assert(0 == n, "Tdea.File failed.");

            // Check we got what we should
            b = ReadABinaryFile(fnameEnc);
            Console.WriteLine("CT={0}", Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(b), okhex, true)==0, "Tdea.FileEncrypt failed");

            // Decrypt it using byte format of key instead of hex
            fnameCheck = "excontent.tdea.chk.txt";
            b = Cnv.FromHex(keyStr);
            n = Tdea.FileDecrypt(fnameCheck, fnameEnc, b, Mode.ECB, null);
            if (0 == n)
            {
                Console.WriteLine("Tdea.File decrypted to file '{0}'", fnameCheck);
                // Show contents of file
                s = ReadATextFile(fnameCheck);
                Debug.Assert(String.Compare(s, excontent)==0, "Decrypted file data does not match");
            }
            else
                Console.WriteLine("Tdea.File returned error code {0}", n);
            Debug.Assert(0 == n, "Tdea.File failed.");


            //***************************
            // AES-128 ENCRYPTION TESTS *
            //***************************
            Console.WriteLine("TESTING AES-128:");
            keyStr = "000102030405060708090a0b0c0d0e0f";
            plain = "00112233445566778899aabbccddeeff";
            cipher = "69c4e0d86a7b0430d8cdb78070b4c55a";
            // Encrypt in ECB mode using hex strings
            s = Aes128.Encrypt(plain, keyStr, Mode.ECB, null);
            Console.WriteLine("KY={0}",keyStr);
            Console.WriteLine("PT={0}",plain);
            Console.WriteLine("CT={0}",s);
            Console.WriteLine("OK={0}",cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Aes128.HexECB failed");
            // Decrypt
            s = Aes128.Decrypt(cipher, keyStr, Mode.ECB, null);
            Console.WriteLine("P'={0}",s);
            Console.WriteLine("OK={0}",plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Aes128.HexECB failed");

            // Ditto using byte arrays
            arrPlain = Cnv.FromHex(plain);
            arrCipher = Cnv.FromHex(cipher);
            arrKey = Cnv.FromHex(keyStr);
            b = Aes128.Encrypt(arrPlain, arrKey, Mode.ECB, null);
            Console.WriteLine("CT={0}",Cnv.ToHex(b));
            b = Aes128.Decrypt(arrCipher, arrKey, Mode.ECB, null);
            Console.WriteLine("P'={0}",Cnv.ToHex(b));

            // Encrypt in CBC mode using hex strings
            keyStr = "56e47a38c5598974bc46903dba290349";
            ivStr = "8ce82eefbea0da3c44699ed7db51b7d9";
            plain = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
                + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
                + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
                + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf";
            cipher = "c30e32ffedc0774e6aff6af0869f71aa"
                + "0f3af07a9a31a9c684db207eb0ef8e4e"
                + "35907aa632c3ffdf868bb7b29d3d46ad"
                + "83ce9f9a102ee99d49a53e87f4c3da55";
            s = Aes128.Encrypt(plain, keyStr, Mode.CBC, ivStr);
            Console.WriteLine("KY={0}",keyStr);
            Console.WriteLine("IV={0}",ivStr);
            Console.WriteLine("PT={0}",plain);
            Console.WriteLine("CT={0}",s);
            Console.WriteLine("OK={0}",cipher);
            // Decrypt
            s = Aes128.Decrypt(cipher, keyStr, Mode.CBC, ivStr);
            Console.WriteLine("P'={0}",s);
            Console.WriteLine("OK={0}",plain);

            // Ditto using byte arrays
            arrPlain = Cnv.FromHex(plain);
            arrCipher = Cnv.FromHex(cipher);
            arrKey = Cnv.FromHex(keyStr);
            arrIV = Cnv.FromHex(ivStr);
            b = Aes128.Encrypt(arrPlain, arrKey, Mode.CBC, arrIV);
            Console.WriteLine("CT={0}",Cnv.ToHex(b));
            b = Aes128.Decrypt(arrCipher, arrKey, Mode.CBC, arrIV);
            Console.WriteLine("P'={0}",Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(arrPlain), Cnv.ToHex(b))==0, "Aes128.BytesCBC failed");

            // Ditto using base64 strings
            keyStr = "VuR6OMVZiXS8RpA9uikDSQ==";
            ivStr = "jOgu776g2jxEaZ7X21G32Q==";
            plain = "oKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vr/"
                + "AwcLDxMXGx8jJysvMzc7P0NHS09TV1tfY2drb3N3e3w==";
            cipher = "ww4y/+3Ad05q/2rwhp9xqg868HqaManGhNsgfrDvjk"
                + "41kHqmMsP/34aLt7KdPUatg86fmhAu6Z1JpT6H9MPaVQ==";
            s = Aes128.Encrypt(plain, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
            Console.WriteLine("KY={0}",keyStr);
            Console.WriteLine("IV={0}",ivStr);
            Console.WriteLine("PT={0}",plain);
            Console.WriteLine("CT={0}",s);
            Console.WriteLine("OK={0}",cipher);
            // Decrypt
            s = Aes128.Decrypt(cipher, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
            Console.WriteLine("P'={0}",s);
            Console.WriteLine("OK={0}",plain);

            // Pad some data ready for encryption - first in hex format
            okhex = "ffffff";
            s = okhex;
            plain = Aes128.Pad(s);
            Console.WriteLine("Aes128.Pad('{0}')='{1}'", s, plain);
            Debug.Assert((plain.Length % (Aes128.BlockSize * 2)) == 0, "Aes128.Pad(hex) failed");
            // and remove it
            s = Aes128.Unpad(plain);
            Console.WriteLine("Aes128.Unpad('{0}')='{1}'", plain, s);
            Debug.Assert(s == okhex, "Aes128.Unpad(hex) failed");
            // again padding an empty string
            okhex = "";
            s = okhex;
            plain = Aes128.Pad(s);
            Console.WriteLine("Aes128.Pad('{0}')='{1}'", s, plain);
            Debug.Assert((plain.Length % (Aes128.BlockSize * 2)) == 0, "Aes128.Pad(hex) failed");
            // and remove it
            s = Aes128.Unpad(plain);
            Console.WriteLine("Aes128.Unpad('{0}')='{1}'", plain, s);
            Debug.Assert(s == okhex, "Aes128.Unpad(hex) failed");
            // Pad using bytes
            arrOk = Cnv.FromHex("ffffffffffffffff");
            b = arrOk;
            arrPlain = Aes128.Pad(b);
            Console.WriteLine("Aes128.Pad(0x{0})=0x{1}", Cnv.ToHex(b), Cnv.ToHex(arrPlain));
            Debug.Assert((arrPlain.Length % Aes128.BlockSize) == 0, "Aes128.Pad(bytes) failed");
            b = Aes128.Unpad(arrPlain);
            Console.WriteLine("Aes128.Unpad(0x{0})=0x{1}", Cnv.ToHex(arrPlain), Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(b), Cnv.ToHex(arrOk)) == 0, "Aes128.Unpad(bytes) failed");

            // Now use Init-Update-Final
            keyStr = "56e47a38c5598974bc46903dba290349";
            ivStr = "8ce82eefbea0da3c44699ed7db51b7d9";
            // Instantiate a new encryption object
            Aes128 oAes128 = Aes128.Instance();
            n = oAes128.InitEncrypt(keyStr, Mode.CBC, ivStr);
            Console.WriteLine("Initialize returns {0}", n);
            Debug.Assert(oAes128.ErrCode == 0, "Aes128.Initialize failed");

            plain = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf";
            cipher = "c30e32ffedc0774e6aff6af0869f71aa";
            s = oAes128.Update(plain);
            Console.WriteLine("PT1={0}", plain);
            Console.WriteLine("CT1={0}", s);
            Console.WriteLine("OK1={0}", cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Aes128.Update failed");
            // Line 2 using bytes
            plain = "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf";
            cipher = "0f3af07a9a31a9c684db207eb0ef8e4e";
            b = Cnv.FromHex(plain);
            b = oAes128.Update(b);
            s = Cnv.ToHex(b);
            Console.WriteLine("PT2={0}", plain);
            Console.WriteLine("CT2={0}", s);
            Console.WriteLine("OK2={0}", cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Aes128.Update failed");
            // Lines 3 and 4 using hex
            plain = "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf";
            cipher = "35907aa632c3ffdf868bb7b29d3d46ad83ce9f9a102ee99d49a53e87f4c3da55";
            s = oAes128.Update(plain);
            Console.WriteLine("PT3={0}", plain);
            Console.WriteLine("CT3={0}", s);
            Console.WriteLine("OK3={0}", cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Aes128.Update failed");

            // Now decrypt using the same object
            n = oAes128.InitDecrypt(keyStr, Mode.CBC, ivStr);
            Console.WriteLine("Initialize returns {0}", n);
            Debug.Assert(oAes128.ErrCode == 0, "Aes128.Initialize failed");

            plain = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf";
            cipher = "c30e32ffedc0774e6aff6af0869f71aa";
            s = oAes128.Update(cipher);
            Console.WriteLine("CT1={0}", cipher);
            Console.WriteLine("PT1={0}", s);
            Console.WriteLine("OK1={0}", plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Aes128.Update failed");
            // Line 2 using bytes
            plain = "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf";
            cipher = "0f3af07a9a31a9c684db207eb0ef8e4e";
            b = Cnv.FromHex(cipher);
            b = oAes128.Update(b);
            s = Cnv.ToHex(b);
            Console.WriteLine("CT2={0}", cipher);
            Console.WriteLine("PT2={0}", s);
            Console.WriteLine("OK2={0}", plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Aes128.Update failed");
            // Lines 3 and 4 using hex
            plain = "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf";
            cipher = "35907aa632c3ffdf868bb7b29d3d46ad83ce9f9a102ee99d49a53e87f4c3da55";
            s = oAes128.Update(cipher);
            Console.WriteLine("CT3={0}", cipher);
            Console.WriteLine("PT3={0}", s);
            Console.WriteLine("OK3={0}", plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Aes128.Update failed");

            // Make sure keys are disposed of
            oAes128.Dispose();
            Console.WriteLine("AES128 Objects disposed of.");

            // Create a test text file
            excontent = "This is some sample content.";
            fnameData = "excontent.txt";
            MakeATextFile(fnameData, excontent);

            // Encrypt a file
            keyStr = "fedcba98765432100123456789abcdef";
            fnameEnc = "excontent.aes128.enc.dat";
            okhex = "DBBACBCC97FBFBE869079864B5077245FA9FD96992CFFF3F4387BD0ABC04EBCA";
            n = Aes128.FileEncrypt(fnameEnc, fnameData, keyStr, Mode.ECB, null);
            if (0 == n)
                Console.WriteLine("Aes128.File created encrypted file '{0}'", fnameEnc);
            else
                Console.WriteLine("Aes128.File returned error code {0}", n);
            Debug.Assert(0 == n, "Aes128.File failed.");

            // Check we got what we should
            b = ReadABinaryFile(fnameEnc);
            Console.WriteLine("CT={0}", Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(b), okhex, true)==0, "Aes128.FileEncrypt failed");

            // Decrypt it using byte format of key instead of hex
            fnameCheck = "excontent.aes128.chk.txt";
            b = Cnv.FromHex(keyStr);
            n = Aes128.FileDecrypt(fnameCheck, fnameEnc, b, Mode.ECB, null);
            if (0 == n)
            {
                Console.WriteLine("Aes128.File decrypted to file '{0}'", fnameCheck);
                // Show contents of file
                s = ReadATextFile(fnameCheck);
                Debug.Assert(String.Compare(s, excontent)==0, "Decrypted file data does not match");
            }
            else
                Console.WriteLine("Aes128.File returned error code {0}", n);
            Debug.Assert(0 == n, "Aes128.File failed.");
            

            //***************************
            // AES-192 ENCRYPTION TESTS *
            //***************************
            Console.WriteLine("TESTING AES-192:");
            keyStr = "000102030405060708090a0b0c0d0e0f1011121314151617";
            plain = "00112233445566778899aabbccddeeff";
            cipher = "dda97ca4864cdfe06eaf70a0ec0d7191";
            // Encrypt in ECB mode using hex strings
            s = Aes192.Encrypt(plain, keyStr, Mode.ECB, null);
            Console.WriteLine("KY={0}",keyStr);
            Console.WriteLine("PT={0}",plain);
            Console.WriteLine("CT={0}",s);
            Console.WriteLine("OK={0}",cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Aes192.HexECB failed");
            // Decrypt
            s = Aes192.Decrypt(cipher, keyStr, Mode.ECB, null);
            Console.WriteLine("P'={0}",s);
            Console.WriteLine("OK={0}",plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Aes192.HexECB failed");

            // Ditto using byte arrays
            arrPlain = Cnv.FromHex(plain);
            arrCipher = Cnv.FromHex(cipher);
            arrKey = Cnv.FromHex(keyStr);
            b = Aes192.Encrypt(arrPlain, arrKey, Mode.ECB, null);
            Console.WriteLine("CT={0}",Cnv.ToHex(b));
            b = Aes192.Decrypt(arrCipher, arrKey, Mode.ECB, null);
            Console.WriteLine("P'={0}",Cnv.ToHex(b));

            // Encrypt in CBC mode using hex strings
            keyStr = "56e47a38c5598974bc46903dba29034906a9214036b8a15b";
            ivStr = "8ce82eefbea0da3c44699ed7db51b7d9";
            plain = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
                + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
                + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
                + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf";
            cipher = "738237036dfdde9dda3374fa182600c5"
                + "38d9187a0299725d0a7fdbe844d77578"
                + "1539e401b5597cbbfa836efd22d998d2"
                + "1605d8df340622417b911467b5e51a12";
            s = Aes192.Encrypt(plain, keyStr, Mode.CBC, ivStr);
            Console.WriteLine("KY={0}",keyStr);
            Console.WriteLine("IV={0}",ivStr);
            Console.WriteLine("PT={0}",plain);
            Console.WriteLine("CT={0}",s);
            Console.WriteLine("OK={0}",cipher);
            // Decrypt
            s = Aes192.Decrypt(cipher, keyStr, Mode.CBC, ivStr);
            Console.WriteLine("P'={0}",s);
            Console.WriteLine("OK={0}",plain);

            // Ditto using byte arrays
            arrPlain = Cnv.FromHex(plain);
            arrCipher = Cnv.FromHex(cipher);
            arrKey = Cnv.FromHex(keyStr);
            arrIV = Cnv.FromHex(ivStr);
            b = Aes192.Encrypt(arrPlain, arrKey, Mode.CBC, arrIV);
            Console.WriteLine("CT={0}",Cnv.ToHex(b));
            b = Aes192.Decrypt(arrCipher, arrKey, Mode.CBC, arrIV);
            Console.WriteLine("P'={0}",Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(arrPlain), Cnv.ToHex(b))==0, "Aes192.BytesCBC failed");

            // Ditto using base64 strings
            keyStr = "VuR6OMVZiXS8RpA9uikDSQapIUA2uKFb";
            ivStr = "jOgu776g2jxEaZ7X21G32Q==";
            plain = "oKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vr/"
                + "AwcLDxMXGx8jJysvMzc7P0NHS09TV1tfY2drb3N3e3w==";
            cipher = "c4I3A2393p3aM3T6GCYAxTjZGHoCmXJdCn/b6"
                + "ETXdXgVOeQBtVl8u/qDbv0i2ZjSFgXY3zQGIkF7kRRnteUaEg==";
            s = Aes192.Encrypt(plain, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
            Console.WriteLine("KY={0}",keyStr);
            Console.WriteLine("IV={0}",ivStr);
            Console.WriteLine("PT={0}",plain);
            Console.WriteLine("CT={0}",s);
            Console.WriteLine("OK={0}",cipher);
            // Decrypt
            s = Aes192.Decrypt(cipher, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
            Console.WriteLine("P'={0}",s);
            Console.WriteLine("OK={0}",plain);

            // Pad some data ready for encryption - first in hex format
            okhex = "ffffff";
            s = okhex;
            plain = Aes192.Pad(s);
            Console.WriteLine("Aes192.Pad('{0}')='{1}'", s, plain);
            Debug.Assert((plain.Length % (Aes192.BlockSize * 2)) == 0, "Aes192.Pad(hex) failed");
            // and remove it
            s = Aes192.Unpad(plain);
            Console.WriteLine("Aes192.Unpad('{0}')='{1}'", plain, s);
            Debug.Assert(s == okhex, "Aes192.Unpad(hex) failed");
            // Pad using bytes
            arrOk = Cnv.FromHex("ffffffffffffffff");
            b = arrOk;
            arrPlain = Aes192.Pad(b);
            Console.WriteLine("Aes192.Pad(0x{0})=0x{1}", Cnv.ToHex(b), Cnv.ToHex(arrPlain));
            Debug.Assert((arrPlain.Length % Aes192.BlockSize) == 0, "Aes192.Pad(bytes) failed");
            b = Aes192.Unpad(arrPlain);
            Console.WriteLine("Aes192.Unpad(0x{0})=0x{1}", Cnv.ToHex(arrPlain), Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(b), Cnv.ToHex(arrOk)) == 0, "Aes192.Unpad(bytes) failed");

            // Now use Init-Update-Final
            keyStr = "56e47a38c5598974bc46903dba29034906a9214036b8a15b";
            ivStr = "8ce82eefbea0da3c44699ed7db51b7d9";
            // Instantiate a new encryption object
            Aes192 oAes192 = Aes192.Instance();
            n = oAes192.InitEncrypt(keyStr, Mode.CBC, ivStr);
            Console.WriteLine("Initialize returns {0}", n);
            Debug.Assert(oAes192.ErrCode == 0, "Aes192.Initialize failed");

            plain = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf";
            cipher = "738237036dfdde9dda3374fa182600c5";
            s = oAes192.Update(plain);
            Console.WriteLine("PT1={0}", plain);
            Console.WriteLine("CT1={0}", s);
            Console.WriteLine("OK1={0}", cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Aes192.Update failed");
            // Line 2 using bytes
            plain = "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf";
            cipher = "38d9187a0299725d0a7fdbe844d77578";
            b = Cnv.FromHex(plain);
            b = oAes192.Update(b);
            s = Cnv.ToHex(b);
            Console.WriteLine("PT2={0}", plain);
            Console.WriteLine("CT2={0}", s);
            Console.WriteLine("OK2={0}", cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Aes192.Update failed");
            // Lines 3 and 4 using hex
            plain  = "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf";
            cipher = "1539e401b5597cbbfa836efd22d998d21605d8df340622417b911467b5e51a12";
            s = oAes192.Update(plain);
            Console.WriteLine("PT3={0}", plain);
            Console.WriteLine("CT3={0}", s);
            Console.WriteLine("OK3={0}", cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Aes192.Update failed");

            n = oAes192.InitDecrypt(keyStr, Mode.CBC, ivStr);
            Console.WriteLine("Initialize returns {0}", n);
            Debug.Assert(oAes192.ErrCode == 0, "Aes192.Initialize failed");

            plain = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf";
            cipher = "738237036dfdde9dda3374fa182600c5";
            s = oAes192.Update(cipher);
            Console.WriteLine("CT1={0}", cipher);
            Console.WriteLine("PT1={0}", s);
            Console.WriteLine("OK1={0}", plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Aes192.Update failed");
            // Line 2 using bytes
            plain = "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf";
            cipher = "38d9187a0299725d0a7fdbe844d77578";
            b = Cnv.FromHex(cipher);
            b = oAes192.Update(b);
            s = Cnv.ToHex(b);
            Console.WriteLine("CT2={0}", cipher);
            Console.WriteLine("PT2={0}", s);
            Console.WriteLine("OK2={0}", plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Aes192.Update failed");
            // Lines 3 and 4 using hex
            plain = "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf";
            cipher = "1539e401b5597cbbfa836efd22d998d21605d8df340622417b911467b5e51a12";
            s = oAes192.Update(cipher);
            Console.WriteLine("CT3={0}", cipher);
            Console.WriteLine("PT3={0}", s);
            Console.WriteLine("OK3={0}", plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Aes192.Update failed");

            // Make sure keys are disposed of
            oAes192.Dispose();
            Console.WriteLine("AES192 Objects disposed of.");

            // Create a test text file
            excontent = "This is some sample content.";
            fnameData = "excontent.txt";
            MakeATextFile(fnameData, excontent);

            // Encrypt a file
            keyStr = "fedcba98765432100123456789abcdeffedcba9876543210";
            fnameEnc = "excontent.aes192.enc.dat";
            okhex = "37C94F74ADDC362FA16B2A16DE40B583296A25DB83136E2CD669351EFE61A6C0";
            n = Aes192.FileEncrypt(fnameEnc, fnameData, keyStr, Mode.ECB, null);
            if (0 == n)
                Console.WriteLine("Aes192.File created encrypted file '{0}'", fnameEnc);
            else
                Console.WriteLine("Aes192.File returned error code {0}", n);
            Debug.Assert(0 == n, "Aes192.File failed.");

            // Check we got what we should
            b = ReadABinaryFile(fnameEnc);
            Console.WriteLine("CT={0}", Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(b), okhex, true)==0, "Aes192.FileEncrypt failed");

            // Decrypt it using byte format of key instead of hex
            fnameCheck = "excontent.aes192.chk.txt";
            b = Cnv.FromHex(keyStr);
            n = Aes192.FileDecrypt(fnameCheck, fnameEnc, b, Mode.ECB, null);
            if (0 == n)
            {
                Console.WriteLine("Aes192.File decrypted to file '{0}'", fnameCheck);
                // Show contents of file
                s = ReadATextFile(fnameCheck);
                Debug.Assert(String.Compare(s, excontent)==0, "Decrypted file data does not match");
            }
            else
                Console.WriteLine("Aes192.File returned error code {0}", n);
            Debug.Assert(0 == n, "Aes192.File failed.");

            //***************************
            // AES-256 ENCRYPTION TESTS *
            //***************************
            Console.WriteLine("TESTING AES-256:");
            keyStr = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
            plain = "00112233445566778899aabbccddeeff";
            cipher = "8EA2B7CA516745BFEAFC49904B496089";
            // Encrypt in ECB mode using hex strings
            s = Aes256.Encrypt(plain, keyStr, Mode.ECB, null);
            Console.WriteLine("KY={0}",keyStr);
            Console.WriteLine("PT={0}",plain);
            Console.WriteLine("CT={0}",s);
            Console.WriteLine("OK={0}",cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Aes256.HexECB failed");
            // Decrypt
            s = Aes256.Decrypt(cipher, keyStr, Mode.ECB, null);
            Console.WriteLine("P'={0}",s);
            Console.WriteLine("OK={0}",plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Aes256.HexECB failed");

            // Ditto using byte arrays
            arrPlain = Cnv.FromHex(plain);
            arrCipher = Cnv.FromHex(cipher);
            arrKey = Cnv.FromHex(keyStr);
            b = Aes256.Encrypt(arrPlain, arrKey, Mode.ECB, null);
            Console.WriteLine("CT={0}",Cnv.ToHex(b));
            b = Aes256.Decrypt(arrCipher, arrKey, Mode.ECB, null);
            Console.WriteLine("P'={0}",Cnv.ToHex(b));

            // Encrypt in CBC mode using hex strings
            keyStr = "56e47a38c5598974bc46903dba29034906a9214036b8a15b512e03d534120006";
            ivStr = "8ce82eefbea0da3c44699ed7db51b7d9";
            plain = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
                + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
                + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
                + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf";
            cipher = "28409A2982BD2CF7CE343A7D43F6927F"
                + "DB9EC532BBA569EEC92E57A209C4FDBA"
                + "59ADBA05A5C854694DDC9F7991C01634"
                + "E72BEB4FE0236CB3B119A463891E346F";
            s = Aes256.Encrypt(plain, keyStr, Mode.CBC, ivStr);
            Console.WriteLine("KY={0}",keyStr);
            Console.WriteLine("IV={0}",ivStr);
            Console.WriteLine("PT={0}",plain);
            Console.WriteLine("CT={0}",s);
            Console.WriteLine("OK={0}",cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Aes256.Encrypt{Hex,CBC} failed");
            // Decrypt
            s = Aes256.Decrypt(cipher, keyStr, Mode.CBC, ivStr);
            Console.WriteLine("P'={0}",s);
            Console.WriteLine("OK={0}",plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Aes256.Decrypt{Hex,CBC} failed");

            // Ditto using byte arrays
            arrPlain = Cnv.FromHex(plain);
            arrCipher = Cnv.FromHex(cipher);
            arrKey = Cnv.FromHex(keyStr);
            arrIV = Cnv.FromHex(ivStr);
            b = Aes256.Encrypt(arrPlain, arrKey, Mode.CBC, arrIV);
            Console.WriteLine("CT={0}",Cnv.ToHex(b));
            b = Aes256.Decrypt(arrCipher, arrKey, Mode.CBC, arrIV);
            Console.WriteLine("P'={0}",Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(arrPlain), Cnv.ToHex(b))==0, "Aes256.BytesCBC failed");

            // Ditto using base64 strings
            keyStr = "VuR6OMVZiXS8RpA9uikDSQapIUA2uKFbUS4D1TQSAAY=";
            ivStr = "jOgu776g2jxEaZ7X21G32Q==";
            plain = "oKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vr/"
                + "AwcLDxMXGx8jJysvMzc7P0NHS09TV1tfY2drb3N3e3w==";
            cipher = "KECaKYK9LPfONDp9Q/aSf9uexTK7pWnuyS5XognE/"
                + "bpZrboFpchUaU3cn3mRwBY05yvrT+AjbLOxGaRjiR40bw==";
            s = Aes256.Encrypt(plain, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
            Console.WriteLine("KY={0}",keyStr);
            Console.WriteLine("IV={0}",ivStr);
            Console.WriteLine("PT={0}",plain);
            Console.WriteLine("CT={0}",s);
            Console.WriteLine("OK={0}",cipher);
            // Decrypt
            s = Aes256.Decrypt(cipher, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
            Console.WriteLine("P'={0}",s);
            Console.WriteLine("OK={0}",plain);

            // Pad some data ready for encryption - first in hex format
            okhex = "ffffff";
            s = okhex;
            plain = Aes256.Pad(s);
            Console.WriteLine("Aes256.Pad('{0}')='{1}'", s, plain);
            Debug.Assert((plain.Length % (Aes256.BlockSize * 2)) == 0, "Aes256.Pad(hex) failed");
            // and remove it
            s = Aes256.Unpad(plain);
            Console.WriteLine("Aes256.Unpad('{0}')='{1}'", plain, s);
            Debug.Assert(s == okhex, "Aes256.Unpad(hex) failed");
            // Pad using bytes
            arrOk = Cnv.FromHex("ffffffffffffffff");
            b = arrOk;
            arrPlain = Aes256.Pad(b);
            Console.WriteLine("Aes256.Pad(0x{0})=0x{1}", Cnv.ToHex(b), Cnv.ToHex(arrPlain));
            Debug.Assert((arrPlain.Length % Aes256.BlockSize) == 0, "Aes256.Pad(bytes) failed");
            b = Aes256.Unpad(arrPlain);
            Console.WriteLine("Aes256.Unpad(0x{0})=0x{1}", Cnv.ToHex(arrPlain), Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(b), Cnv.ToHex(arrOk)) == 0, "Aes256.Unpad(bytes) failed");

            // Now use Init-Update-Final
            keyStr = "56e47a38c5598974bc46903dba29034906a9214036b8a15b512e03d534120006";
            ivStr = "8ce82eefbea0da3c44699ed7db51b7d9";
            // Instantiate a new encryption object
            Aes256 oAes256 = Aes256.Instance();
            n = oAes256.InitEncrypt(keyStr, Mode.CBC, ivStr);
            Console.WriteLine("Initialize returns {0}", n);
            Debug.Assert(oAes256.ErrCode == 0, "Aes256.Initialize failed");

            plain = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf";
            cipher = "28409A2982BD2CF7CE343A7D43F6927F";
            s = oAes256.Update(plain);
            Console.WriteLine("PT1={0}", plain);
            Console.WriteLine("CT1={0}", s);
            Console.WriteLine("OK1={0}", cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Aes256.Update failed");
            // Line 2 using bytes
            plain = "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf";
            cipher = "DB9EC532BBA569EEC92E57A209C4FDBA";
            b = Cnv.FromHex(plain);
            b = oAes256.Update(b);
            s = Cnv.ToHex(b);
            Console.WriteLine("PT2={0}", plain);
            Console.WriteLine("CT2={0}", s);
            Console.WriteLine("OK2={0}", cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Aes256.Update failed");
            // Lines 3 and 4 using hex
            plain = "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf";
            cipher = "59ADBA05A5C854694DDC9F7991C01634E72BEB4FE0236CB3B119A463891E346F";
            s = oAes256.Update(plain);
            Console.WriteLine("PT3={0}", plain);
            Console.WriteLine("CT3={0}", s);
            Console.WriteLine("OK3={0}", cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Aes256.Update failed");

            n = oAes256.InitDecrypt(keyStr, Mode.CBC, ivStr);
            Console.WriteLine("Initialize returns {0}", n);
            Debug.Assert(oAes256.ErrCode == 0, "Aes256.Initialize failed");

            plain = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf";
            cipher = "28409A2982BD2CF7CE343A7D43F6927F";
            s = oAes256.Update(cipher);
            Console.WriteLine("CT1={0}", cipher);
            Console.WriteLine("PT1={0}", s);
            Console.WriteLine("OK1={0}", plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Aes256.Update failed");
            // Line 2 using bytes
            plain = "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf";
            cipher = "DB9EC532BBA569EEC92E57A209C4FDBA";
            b = Cnv.FromHex(cipher);
            b = oAes256.Update(b);
            s = Cnv.ToHex(b);
            Console.WriteLine("CT2={0}", cipher);
            Console.WriteLine("PT2={0}", s);
            Console.WriteLine("OK2={0}", plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Aes256.Update failed");
            // Lines 3 and 4 using hex
            plain = "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf";
            cipher = "59ADBA05A5C854694DDC9F7991C01634E72BEB4FE0236CB3B119A463891E346F";
            s = oAes256.Update(cipher);
            Console.WriteLine("CT3={0}", cipher);
            Console.WriteLine("PT3={0}", s);
            Console.WriteLine("OK3={0}", plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Aes256.Update failed");

            // Make sure keys are disposed of
            oAes256.Dispose();
            Console.WriteLine("AES256 Objects disposed of.");

            // Create a test text file
            excontent = "This is some sample content.";
            fnameData = "excontent.txt";
            MakeATextFile(fnameData, excontent);

            // Encrypt a file
            keyStr = "fedcba98765432100123456789abcdeffedcba98765432100123456789abcdef";
            fnameEnc = "excontent.aes256.enc.dat";
            okhex = "7F94B5E5A76B747B9778FD20D033E804790E633D34F78C9194F799DD967996C4";
            n = Aes256.FileEncrypt(fnameEnc, fnameData, keyStr, Mode.ECB, null);
            if (0 == n)
                Console.WriteLine("Aes256.File created encrypted file '{0}'", fnameEnc);
            else
                Console.WriteLine("Aes256.File returned error code {0}", n);
            Debug.Assert(0 == n, "Aes256.File failed.");

            // Check we got what we should
            b = ReadABinaryFile(fnameEnc);
            Console.WriteLine("CT={0}", Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(b), okhex, true)==0, "Aes256.FileEncrypt failed");

            // Decrypt it using byte format of key instead of hex
            fnameCheck = "excontent.aes256.chk.txt";
            b = Cnv.FromHex(keyStr);
            n = Aes256.FileDecrypt(fnameCheck, fnameEnc, b, Mode.ECB, null);
            if (0 == n)
            {
                Console.WriteLine("Aes256.File decrypted to file '{0}'", fnameCheck);
                // Show contents of file
                s = ReadATextFile(fnameCheck);
                Debug.Assert(String.Compare(s, excontent)==0, "Decrypted file data does not match");
            }
            else
                Console.WriteLine("Aes256.File returned error code {0}", n);
            Debug.Assert(0 == n, "Aes256.File failed.");

            
            //***********************
            // PC1 ENCRYPTION TESTS *
            //***********************
            Console.WriteLine("TESTING PC1 (RC4):");
            keyStr = "0123456789abcdef";
            plain = "0123456789abcdef";
            cipher = "75b7878099e0c596";
            // convert to byte arrays
            arrKey = Cnv.FromHex(keyStr);
            arrPlain = Cnv.FromHex(plain);
            arrCipher = Cnv.FromHex(cipher);
            // encrypt
            b = Pc1.Encrypt(arrPlain, arrKey);
            Console.WriteLine("PC1:");
            Console.WriteLine("KY={0}", Cnv.ToHex(arrKey));
            Console.WriteLine("PT={0}", Cnv.ToHex(arrPlain));
            s = Cnv.ToHex(b);
            Console.WriteLine("CT={0}", s);
            Console.WriteLine("OK={0}", cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Pc1.Encrypt failed");
            // decrypt by encrypting again
            b = Pc1.Encrypt(b, arrKey);
            s = Cnv.ToHex(b);
            Console.WriteLine("P'={0}", s);
            Console.WriteLine("OK={0}", plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Pc1.Encrypt(2) failed");

            // Again using data directly in hex format
            keyStr = "ef012345";
            plain = "00000000000000000000";
            cipher = "d6a141a7ec3c38dfbd61";
            s = Pc1.Encrypt(plain, keyStr);
            Console.WriteLine("PC1:");
            Console.WriteLine("KY={0}", keyStr);
            Console.WriteLine("PT={0}", plain);
            Console.WriteLine("CT={0}", s);
            Console.WriteLine("OK={0}", cipher);
            Debug.Assert(String.Compare(s, cipher, true)==0, "Pc1.Encrypt(Hex) failed");
            // decrypt by encrypting again
            s = Pc1.Encrypt(s, keyStr);
            Console.WriteLine("P'={0}", s);
            Console.WriteLine("OK={0}", plain);
            Debug.Assert(String.Compare(s, plain, true)==0, "Pc1.Encrypt(Hex, 2) failed");

            // Create a test text file
            excontent = "This is some sample content.";
            fnameData = "excontent.txt";
            MakeATextFile(fnameData, excontent);

            // Encrypt a file
            keyStr = "fedcba98765432100123456789abcdeffedcba98765432100123456789abcdef";
            fnameEnc = "excontent.pc1.enc.dat";
            okhex = "E61C8126AC8B830C32E5ECF1862BCD70778C42B7C130310206151AB1";
            b = Cnv.FromHex(keyStr);
            n = Pc1.File(fnameEnc, fnameData, b);
            if (0 == n)
                Console.WriteLine("Pc1.File created encrypted file '{0}'", fnameEnc);
            else
                Console.WriteLine("Pc1.File returned error code {0}", n);
            Debug.Assert(0 == n, "Pc1.File failed.");

            // Check we got what we should
            b = ReadABinaryFile(fnameEnc);
            Console.WriteLine("CT={0}", Cnv.ToHex(b));
            Debug.Assert(String.Compare(Cnv.ToHex(b), okhex, true)==0, "Pc1.FileEncrypt failed");

            // Decrypt it by encrypting again
            fnameCheck = "excontent.pc1.chk.txt";
            b = Cnv.FromHex(keyStr);
            n = Pc1.File(fnameCheck, fnameEnc, b);
            if (0 == n)
            {
                Console.WriteLine("Pc1.File decrypted to file '{0}'", fnameCheck);
                // Show contents of file
                s = ReadATextFile(fnameCheck);
                Debug.Assert(String.Compare(s, excontent)==0, "Decrypted file data does not match");
            }
            else
                Console.WriteLine("Pc1.File returned error code {0}", n);
            Debug.Assert(0 == n, "Pc1.File failed.");

            
            //**************************
            // SHA-1 HASH DIGEST TESTS *
            //**************************
            Console.WriteLine("TESTING SHA-1:");
            // Ansi string input
            s = Sha1.HexHash("abc");
            Console.WriteLine("Sha1('abc')={0}", s);
            // Correct answers from FIPS-180-2
            okhex = "a9993e364706816aba3e25717850c26c9cd0d89d";
            Debug.Assert(String.Compare(okhex, s, true)==0, "Sha1('abc') failed");

            // byte data input, hex output
            b = new byte[3] {0x61, 0x62, 0x63};
            s = Sha1.HexHash(b);
            Console.WriteLine("Sha1('abc')={0}", s);

            // byte data input, byte output
            b = Sha1.BytesHash(b);
            Console.WriteLine("Sha1('abc')={0}", Cnv.ToHex(b));

            // file input
            fnameData = "abc.txt";
            MakeATextFile(fnameData, "abc");
            s = Sha1.FileHexHash(fnameData);
            Console.WriteLine("Sha1('abc')={0}", s);

            // Get digest of core DLL file
            // See http://www.cryptosys.net/integrity.html
            fnameData = General.ModuleName();
            s = Sha1.FileHexHash(fnameData);
            Console.WriteLine("Sha1(DLL module)={0}", s);

            // Instantiate a new object
            Sha1 oSha1 = Sha1.Instance();
            tf = oSha1.Init();
            Console.WriteLine("oSha1.Init returned {0}", tf);
            Debug.Assert(tf, "Sha1.Init failed");

            n = oSha1.AddData("a");
            n = oSha1.AddData("bc");
            s = oSha1.HexDigest();
            Console.WriteLine("Sha1('abc')={0}", s);

            // Compute SHA1(one million repetitions of 'a')
            oSha1.Init();
            a1000 = new byte[1000];
            for (i = 0; i < 1000; i++)
                a1000[i] = 0x61;    // 'a' in ascii form
            for (i = 0; i < 1000; i++)
            {
                n = oSha1.AddData(a1000);
                Debug.Assert(0 == n, "Sha1.Adddata failed");
            }
            s = oSha1.HexDigest();
            Console.WriteLine("Sha1(1M x 'a')={0}", s);
            okhex = "34aa973cd4c4daa4f61eeb2bdbad27316534016f";
            Debug.Assert(String.Compare(okhex, s, true)==0, "Sha1(1M x 'a') failed");

            //****************************
            // SHA-256 HASH DIGEST TESTS *
            //****************************
            Console.WriteLine("TESTING SHA-256:");
            // Ansi string input
            s = Sha256.HexHash("abc");
            Console.WriteLine("Sha256('abc')={0}", s);
            // Correct answers from FIPS-180-2
            okhex = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
            Debug.Assert(String.Compare(okhex, s, true)==0, "Sha256('abc') failed");

            // byte data input, hex output
            b = new byte[3] {0x61, 0x62, 0x63};
            s = Sha256.HexHash(b);
            Console.WriteLine("Sha256('abc')={0}", s);

            // byte data input, byte output
            b = Sha256.BytesHash(b);
            Console.WriteLine("Sha256('abc')={0}", Cnv.ToHex(b));

            // file input
            fnameData = "abc.txt";
            MakeATextFile(fnameData, "abc");
            s = Sha256.FileHexHash(fnameData);
            Console.WriteLine("Sha256('abc')={0}", s);

            // Get digest of core DLL file
            // See http://www.cryptosys.net/integrity.html
            fnameData = General.ModuleName();
            s = Sha256.FileHexHash(fnameData);
            Console.WriteLine("Sha256(DLL module)={0}", s);

            // Instantiate a new object
            Sha256 oSha256 = Sha256.Instance();
            tf = oSha256.Init();
            Console.WriteLine("oSha256.Init returned {0}", tf);
            Debug.Assert(tf, "Sha256.Init failed");

            n = oSha256.AddData("a");
            n = oSha256.AddData("bc");
            s = oSha256.HexDigest();
            Console.WriteLine("Sha256('abc')={0}", s);

            // Compute SHA256(one million repetitions of 'a')
            oSha256.Init();
            a1000 = new byte[1000];
            for (i = 0; i < 1000; i++)
                a1000[i] = 0x61;    // 'a' in ascii form
            for (i = 0; i < 1000; i++)
            {
                n = oSha256.AddData(a1000);
                Debug.Assert(0 == n, "Sha256.Adddata failed");
            }
            s = oSha256.HexDigest();
            Console.WriteLine("Sha256(1M x 'a')={0}", s);
            okhex = "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0";
            Debug.Assert(String.Compare(okhex, s, true)==0, "Sha256(1M x 'a') failed");


            //************************
            // MD5 HASH DIGEST TESTS *
            //************************
            Console.WriteLine("TESTING MD5:");
            // Ansi string input
            s = Md5.HexHash("abc");
            Console.WriteLine("Md5('abc')={0}", s);
            // Correct answers from RFC 1321
            okhex = "900150983cd24fb0d6963f7d28e17f72";
            Debug.Assert(String.Compare(okhex, s, true)==0, "Md5('abc') failed");

            // byte data input, hex output
            b = new byte[3] {0x61, 0x62, 0x63};
            s = Md5.HexHash(b);
            Console.WriteLine("Md5('abc')={0}", s);

            // byte data input, byte output
            b = Md5.BytesHash(b);
            Console.WriteLine("Md5('abc')={0}", Cnv.ToHex(b));

            // file input
            fnameData = "abc.txt";
            MakeATextFile(fnameData, "abc");
            s = Md5.FileHexHash(fnameData);
            Console.WriteLine("Md5('abc')={0}", s);

            // Get digest of core DLL file
            // See http://www.cryptosys.net/integrity.html
            fnameData = General.ModuleName();
            s = Md5.FileHexHash(fnameData);
            Console.WriteLine("Md5(DLL module)={0}", s);

            // Instantiate a new object
            Md5 oMd5 = Md5.Instance();
            tf = oMd5.Init();
            Console.WriteLine("oMd5.Init returned {0}", tf);
            Debug.Assert(tf, "Md5.Init failed");

            n = oMd5.AddData("a");
            n = oMd5.AddData("bc");
            s = oMd5.HexDigest();
            Console.WriteLine("Md5('abc')={0}", s);

            // Compute MD5(one million repetitions of 'a')
            oMd5.Init();
            a1000 = new byte[1000];
            for (i = 0; i < 1000; i++)
                a1000[i] = 0x61;    // 'a' in ascii form
            for (i = 0; i < 1000; i++)
            {
                n = oMd5.AddData(a1000);
                Debug.Assert(0 == n, "Md5.Adddata failed");
            }
            s = oMd5.HexDigest();
            Console.WriteLine("Md5(1M x 'a')={0}", s);
            okhex = "7707d6ae4e027c70eea2a935c2296f21";
            Debug.Assert(String.Compare(okhex, s, true)==0, "Md5(1M x 'a') failed");

            
            //**************
            // PBKDF2 TESTS *
            //**************
            Console.WriteLine("TESTING PBKDF2...");
            // convert password string to bytes
            arrPwd = System.Text.Encoding.Default.GetBytes("password");
            // make a salt
            salt = new byte[] {0x78, 0x57, 0x8e, 0x5a, 0x5d, 0x63, 0xcb, 0x06};
            // create a 24-byte (192-bit) key
            n = 24;
            arrKey = Pbe.Kdf2(n, arrPwd, salt, 2048);
            Debug.Assert(arrKey.Length > 0, "ERROR with Pbe.Kdf2");
            Console.WriteLine("Key({0})={1}", n * 8, Cnv.ToHex(arrKey));
            // and again for a 64-byte (512-bit) key
            n = 64;
            arrKey = Pbe.Kdf2(n, arrPwd, salt, 2048);
            Debug.Assert(arrKey.Length > 0, "ERROR with Pbe.Kdf2");
            Console.WriteLine("Key({0})={1}", n * 8, Cnv.ToHex(arrKey));
            // Same example using hex format
            saltHex = "78578e5a5d63cb06";
            n = 24;
            keyStr = Pbe.Kdf2(n, "password", saltHex, 2048);
            Debug.Assert(keyStr.Length > 0, "ERROR with PbeKdf2/Hex");
            Console.WriteLine("Key({0})={1}", n * 8, keyStr);

            //*************************
            // ZLIB COMPRESSION TESTS *
            //*************************
            Console.WriteLine("TESTING ZLIB COMPRESSION...");
            // Some sample text to compress
            excontent = "hello, hello, hello. This is a 'hello world' message for the world, repeat, for the world.";
            // Convert to bytes
            b = System.Text.Encoding.Default.GetBytes(excontent);
            // Remember uncompressed len for later
            n = b.Length;
            // Compress
            b = Zlib.Deflate(b);
            Debug.Assert(b.Length > 0, "ERROR with Zlib.Deflate");
            Console.WriteLine("Compressed {0} to {1} bytes", n, b.Length);
            Console.WriteLine("DEFL={0}", Cnv.ToHex(b));

            // Now inflate back (note we need the original uncompressed length here)
            b = Zlib.Inflate(b, n);
            Debug.Assert(b.Length > 0, "ERROR with Zlib.Deflate");
            s = System.Text.ASCIIEncoding.Default.GetString(b);
            Console.WriteLine("INFL={0}", s);

            //**********************
            // RANDOM NUMBER TESTS *
            //**********************
            Console.WriteLine("SOME RANDOM NUMBERS...");
            for (i = 0; i < 3; i++)
            {
                s = Rng.NonceHex(8);
                Console.WriteLine("NonceHex={0}", s);
            }
            for (i = 0; i < 3; i++)
            {
                s = Rng.KeyHex(24,"");
                Console.WriteLine("KeyHex={0}", s);
            }
            for (i = 0; i < 3; i++)
            {
                b = Rng.KeyBytes(16, "");
                Console.WriteLine("KeyBytes={0}", Cnv.ToHex(b));
            }
            for (i = 0; i < 3; i++)
            {
                b = Rng.NonceBytes(8);
                Console.WriteLine("NonceBytes={0}", Cnv.ToHex(b));
            }
            for (i = 0; i < 3; i++)
            {
                n = Rng.Number(100,200);
                Console.WriteLine("Rng.Number(100,200)={0}", n);
            }

            filename = "Fips140.txt";
            n = Rng.Test(filename);
            if (0 == n)
                Console.WriteLine("Rng.Test OK. Created file {0}", filename);
            else
                Console.WriteLine("Rng.Test ERROR> Returned error code {0}", n);
            Debug.Assert(0 == n, "Rng.Test Failed");

            //******************
            // WIPE DATA TESTS *
            //******************
            Console.WriteLine("TESTING WIPE DATA...");
            // Create a test text file
            excontent = "This is some very secret data.";
            fnameData= "todelete.txt";
            MakeATextFile(fnameData, excontent);
            tf = Wipe.File(fnameData);
            Console.WriteLine("Wipe.File returns {0}", tf);
            Debug.Assert(tf , "ERROR with Wipe.File");

            // Copy the string into a byte array
            b = System.Text.Encoding.Default.GetBytes(excontent);
            // Wipe the byte data
            Console.WriteLine("Before={0}", Cnv.ToHex(b));
            tf = Wipe.Data(b);
            Console.WriteLine("Wipe.Data returns {0}", tf);
            Console.WriteLine("After ={0}", Cnv.ToHex(b));
            Debug.Assert(tf , "ERROR with Wipe.Data");

            // Copy to a StringBuilder (we can't wipe a plain string)
            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            sb.Append(excontent);
            Console.WriteLine("Before=[{0}]", sb.ToString());
            tf = Wipe.String(sb);
            Console.WriteLine("Wipe.String returns {0}", tf);
            Console.WriteLine("After =[{0}]", sb.ToString());
            Debug.Assert(tf , "ERROR with Wipe.String");

            //************
            // CRC TESTS *
            //************
            Console.WriteLine("TESTING CRC CHECKSUMS...");
            // Create a test text file
            excontent = "hello world\r\n";
            fnameData= "hello.txt";
            MakeATextFile(fnameData, excontent);
            n = Crc.File(fnameData);
            Console.WriteLine("CRC32('{0}')={1:x}", fnameData, n);

            s = "123456789";
            n = Crc.Data(s);
            Console.WriteLine("CRC32('{0}')={1:x}", s, n);

            // Convert to bytes
            b = System.Text.Encoding.Default.GetBytes(s);
            n = Crc.Data(b);
            Console.WriteLine("CRC32(0x{0})={1:x}", Cnv.ToHex(b), n);

            //*****************
            // MODULE DETAILS *
            //*****************
            Console.WriteLine("MODULE DETAILS:");
            s = General.ModuleName();
            Console.WriteLine("ModuleName={0}", s);
            n = Crc.File(s);
            Console.WriteLine("CRC32(Module)={0:X}", n);
            s = General.CompileTime();
            Console.WriteLine("CompileTime={0}", s);
            ch = General.LicenceType();
            Console.WriteLine("LicenceType={0}", ch);
            n = General.Version();
            Console.WriteLine("Version={0}", n);

            Console.WriteLine("ALL TESTS COMPLETED.");

        }

        //*****************
        // FILE UTILITIES *
        //*****************
        static bool MakeATextFile(string fileName, string data)
        {
            FileStream fs;
            StreamWriter sw;
            // Create a test text file
            fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
            sw = new StreamWriter(fs);
            sw.Write(data);
            sw.Close();
            fs.Close();
            return true;
        }

        static string ReadATextFile(string fileName)
        {
            string s = String.Empty;
            FileInfo finfo = new FileInfo(fileName);
            if (finfo.Exists)
            {
                FileStream fsi = finfo.OpenRead();
                StreamReader sr = new StreamReader(fsi);
                s = sr.ReadToEnd();
                Console.WriteLine(s);
                sr.Close();
                fsi.Close();
            }
            Debug.Assert(finfo.Exists, "File '" + fileName + "' does not exist.");
            return s;
        }

        static byte[] ReadABinaryFile(string fileName)
        {
            byte[] b = new byte[0];
            FileInfo finfo = new FileInfo(fileName);
            if (finfo.Exists)
            {
                FileStream fsi = finfo.OpenRead();
                BinaryReader br = new BinaryReader(fsi);
                int count = (int)fsi.Length;
                b = br.ReadBytes(count);
                br.Close();
                fsi.Close();
            }
            Debug.Assert(finfo.Exists, "File '" + fileName + "' does not exist.");
            return b;
        }
    }
}