using System;
//using System.Xml;
using System.Text;
//using System.IO;
using System.Security.Cryptography;
using SmartCard.Runtime;

namespace MyCompany.Server
{

    public class Service : MarshalByRefObject
    {
        static int RSAsize = 1024;

        #region ProtocolParameters
        //static byte[] g1;
        //static byte[] g2;
        //static byte[] g3;
        //static byte[] n;
        //static byte[] w;
        //static byte[] wi;

        static byte[] r1=new byte[128];
        static byte[] r1i = new byte[128];
        static byte[] r2 = new byte[128];
        static byte[] r2i = new byte[128];

        //static byte[] c11;
        //static byte[] c3;
        //static byte[] c22;
        //static byte[] c33;

        //static byte[] z1;
        //static byte[] z2;
        //static byte[] z1i;
        //static byte[] z2i;
        #endregion

        
        public static int length;
        

        public string Registration(string Hash,string Ri)
        {
            System.IO.StreamWriter FileRi = new System.IO.StreamWriter("D:\\Pub\\Ri.txt");
            //File.Write(Hash);
            FileRi.Write(Ri);

            System.IO.StreamWriter FileHash = new System.IO.StreamWriter("D:\\Pub\\Hash.txt");
            //File.Write(Hash);
            FileHash.Write(Hash);
            return "OK";
        }

        public byte[] Login( string PWD,string timestamp)
        {
            // Prectu si soubor s ulozenym Ri
            System.IO.StreamReader File = new System.IO.StreamReader("D:\\Pub\\Ri.txt");
            string Ri = File.ReadToEnd();
            //string Ri = filecont;
            
            // Prevedu do bytu
            byte[] byteLogin = System.Text.Encoding.UTF8.GetBytes(Ri);
            byte[] bytePWD = System.Text.Encoding.UTF8.GetBytes(PWD);
            byte[] byteTimestamp = System.Text.Encoding.UTF8.GetBytes(timestamp);

            // Provedu Ri XOR PWD
            byte[] xor = XOR(byteLogin, bytePWD);
            // Provedu (Ri XOR PWD) XOR T
            byte[] C2 = XOR(xor, byteTimestamp);
            //System.Security.Cryptography.MD5 hash;
            //MD5CryptoServiceProvider hash = new MD5CryptoServiceProvider();
            //hash.ComputeHash(C2);
            //System.Text.StringBuilder s = new System.Text.StringBuilder();
            //foreach (byte b in hash.Hash)
            //{
            //    s.Append(b.ToString().ToLower());
            //}
            //string md5hash = s.ToString();
            //string retVal = md5hash;
            //retVal.SetValue(IDiT,1);
            
            // Vratim zpet
            return C2;
            //return "True";
        }
        public byte[] Verification(string timestamp)
        {
            // Prectu si soubor s ulozenym Ri
            System.IO.StreamReader File = new System.IO.StreamReader("D:\\Pub\\Hash.txt");
            string C1 = File.ReadToEnd();
            //string Ri = filecont;

            // Prevedu do bytu
            byte[] byteC1 = System.Text.Encoding.UTF8.GetBytes(C1);
            //byte[] byteC3 = System.Text.Encoding.UTF8.GetBytes(C3);
            byte[] byteTimestamp = System.Text.Encoding.UTF8.GetBytes(timestamp);

            // Provedu Ri XOR PWD
            byte[] xor = XOR(byteC1, byteTimestamp);
            // Provedu (Ri XOR PWD) XOR T
            //byte[] C2 = XOR(xor, byteTimestamp);
            //System.Security.Cryptography.MD5 hash;
            //MD5CryptoServiceProvider hash = new MD5CryptoServiceProvider();
            //hash.ComputeHash(C2);
            //System.Text.StringBuilder s = new System.Text.StringBuilder();
            //foreach (byte b in hash.Hash)
            //{
            //    s.Append(b.ToString().ToLower());
            //}
            //string md5hash = s.ToString();
            //string retVal = md5hash;
            //retVal.SetValue(IDiT,1);

            // Vratim zpet
            return xor;
            //return "True";
        }

        public string GetRi()
        {
            System.IO.StreamReader File = new System.IO.StreamReader("D:\\Pub\\String.txt");
            string filecont = File.ReadToEnd();
            //            string Ri = filecont.Substring(32);
            return filecont;
            //byte[] byteLogin = System.Text.Encoding.UTF8.GetBytes(Ri);
            //byte[] bytePWD = System.Text.Encoding.UTF8.GetBytes(PWD);
            //byte[] xor = XOR(byteLogin, bytePWD);
            //byte[] byteTimestamp = System.Text.Encoding.UTF8.GetBytes(timestamp);
            //byte[] C2 = XOR(xor, byteTimestamp);
            
        }

        public string Registration_Hsiang(string V, string R, string hash)
        {
            System.IO.StreamWriter Hsiang_V = new System.IO.StreamWriter("D:\\Pub\\Hsiang_V.txt");
            //File.Write(Hash);
            Hsiang_V.Write(V);

            System.IO.StreamWriter Hsiang_R = new System.IO.StreamWriter("D:\\Pub\\Hsiang_R.txt");
            //File.Write(Hash);
            Hsiang_R.Write(R);

            System.IO.StreamWriter Hsiang_hash = new System.IO.StreamWriter("D:\\Pub\\Hsiang_hash.txt");
            //File.Write(Hash);
            Hsiang_hash.Write(hash);
            return "OK";
        }

        public string[] Login_Hsiang(byte[] pwdhash,string timestamp)
        {
            // Prectu si soubor s ulozenym Ri
            System.IO.StreamReader File = new System.IO.StreamReader("D:\\Pub\\Hsiang_V.txt");
            string V_2 = File.ReadToEnd();
            File.Close();
            
            File = new System.IO.StreamReader("D:\\Pub\\Hsiang_R.txt");
            string R = File.ReadToEnd();
            File.Close();

            File = new System.IO.StreamReader("D:\\Pub\\Hsiang_hash.txt");
            string hash = File.ReadToEnd();
            File.Close();
            //string Ri = filecont;

            // Prevedu do bytu
            //byte[] byteV = System.Text.Encoding.UTF8.GetBytes(V);
            byte[] byteR = System.Text.Encoding.UTF8.GetBytes(R);
            byte[] bytehash = System.Text.Encoding.UTF8.GetBytes(hash);
            //byte[] bytePWD = System.Text.Encoding.UTF8.GetBytes(PWD);
            byte[] byteTimestamp = System.Text.Encoding.UTF8.GetBytes(timestamp);

            byte[] C1 = XOR(byteR, pwdhash);
            string C1_str =System.Text.Encoding.UTF8.GetString(C1);
            string C2 = C1_str + R + timestamp;
            // Provedu Ri XOR PWD

            string[] retVal = new string[3];
            retVal.SetValue(C2, 0);
            retVal.SetValue(timestamp, 1);
            retVal.SetValue(V_2, 2);
            
            //byte[] xor = XOR(byteLogin, bytePWD);
            // Provedu (Ri XOR PWD) XOR T
            
            //byte[] C2 = XOR(xor, byteTimestamp);
            //System.Security.Cryptography.MD5 hash;
            //MD5CryptoServiceProvider hash = new MD5CryptoServiceProvider();
            //hash.ComputeHash(C2);
            //System.Text.StringBuilder s = new System.Text.StringBuilder();
            //foreach (byte b in hash.Hash)
            //{
            //    s.Append(b.ToString().ToLower());
            //}
            //string md5hash = s.ToString();
            //string retVal = md5hash;
            //retVal.SetValue(IDiT,1);

            // Vratim zpet
            return retVal;
            //return "True";
        }
        public byte[] Verification_Hsiang(byte[] pwdhash)
        {
            // Prectu si soubor s ulozenym Ri
            // Prectu si soubor s ulozenym Ri
            //System.IO.StreamReader File = new System.IO.StreamReader("D:\\Pub\\Hsiang_V.txt");
            //string V_2 = File.ReadToEnd();
            //File.Close();

            System.IO.StreamReader File = new System.IO.StreamReader("D:\\Pub\\Hsiang_R.txt");
            string R = File.ReadToEnd();
            File.Close();

            //File = new System.IO.StreamReader("D:\\Pub\\Hsiang_hash.txt");
            //string hash = File.ReadToEnd();
            //File.Close();
            //string Ri = filecont;

            // Prevedu do bytu
            //byte[] byteV = System.Text.Encoding.UTF8.GetBytes(V);
            byte[] byteR = System.Text.Encoding.UTF8.GetBytes(R);
            //byte[] bytehash = System.Text.Encoding.UTF8.GetBytes(hash);
            //byte[] bytePWD = System.Text.Encoding.UTF8.GetBytes(PWD);
            //byte[] byteTimestamp = System.Text.Encoding.UTF8.GetBytes(timestamp);

            byte[] C1 = XOR(byteR, pwdhash);
            
            

            // Vratim zpet
            return C1;
            //return "True";
        }

        public string GetRi_Hsiang()
        {
            System.IO.StreamReader File = new System.IO.StreamReader("D:\\Pub\\String.txt");
            string filecont = File.ReadToEnd();
            //            string Ri = filecont.Substring(32);
            return filecont;
            //byte[] byteLogin = System.Text.Encoding.UTF8.GetBytes(Ri);
            //byte[] bytePWD = System.Text.Encoding.UTF8.GetBytes(PWD);
            //byte[] xor = XOR(byteLogin, bytePWD);
            //byte[] byteTimestamp = System.Text.Encoding.UTF8.GetBytes(timestamp);
            //byte[] C2 = XOR(xor, byteTimestamp);

        }

        public string Registration_Improved(string ID, string A,string B, string p, string g)
        {
            System.IO.StreamWriter Fwr = new System.IO.StreamWriter("D:\\Pub\\Improved_ID.txt");
            //File.Write(Hash);
            Fwr.Write(ID);
            Fwr.Close();

            Fwr = new System.IO.StreamWriter("D:\\Pub\\Improved_A.txt");
            Fwr.Write(A.ToString());
            Fwr.Close();

            Fwr = new System.IO.StreamWriter("D:\\Pub\\Improved_B.txt");
            Fwr.Write(B.ToString());
            Fwr.Close();
            Fwr = new System.IO.StreamWriter("D:\\Pub\\Improved_p.txt");
            Fwr.Write(p.ToString());
            Fwr.Close();
            Fwr = new System.IO.StreamWriter("D:\\Pub\\Improved_g.txt");
            Fwr.Write(g.ToString());
            Fwr.Close();

            return "OK";
        }

        public string[] Login_Improved()
        {
            // Prectu si soubor s ulozenym Ri
            System.IO.StreamReader File = new System.IO.StreamReader("D:\\Pub\\Improved_ID.txt");
            string ID = File.ReadToEnd();
            File.Close();
            File = new System.IO.StreamReader("D:\\Pub\\Improved_A.txt");
            string A = File.ReadToEnd();
            File.Close();

            File = new System.IO.StreamReader("D:\\Pub\\Improved_B.txt");
            string B = File.ReadToEnd();
            File.Close();
            File = new System.IO.StreamReader("D:\\Pub\\Improved_p.txt");
            string p = File.ReadToEnd();
            File.Close();
            File = new System.IO.StreamReader("D:\\Pub\\Improved_g.txt");
            string g = File.ReadToEnd();
            File.Close();


            //BigInteger bB = new BigInteger(Convert.ToUInt32(B));
            //BigInteger bp = new BigInteger(Convert.ToUInt32(p));
            //BigInteger bg = new BigInteger(Convert.ToUInt32(g));

            //BigInteger exp = A * PWD.GetHashCode();
            //BigInteger B_2 = bg.modPow(exp, bp);


            string[] retVal = new string[5];
            retVal.SetValue(ID, 0);
            retVal.SetValue(A, 1);
            retVal.SetValue(B, 2);
            retVal.SetValue(p, 3);
            retVal.SetValue(g, 4);

            return retVal;
        }
        public byte[] Verification_Nonce(byte[] pwdhash)
        {
            // Prectu si soubor s ulozenym Ri
            // Prectu si soubor s ulozenym Ri
            //System.IO.StreamReader File = new System.IO.StreamReader("D:\\Pub\\Hsiang_V.txt");
            //string V_2 = File.ReadToEnd();
            //File.Close();

            System.IO.StreamReader File = new System.IO.StreamReader("D:\\Pub\\Hsiang_R.txt");
            string R = File.ReadToEnd();
            File.Close();

            //File = new System.IO.StreamReader("D:\\Pub\\Hsiang_hash.txt");
            //string hash = File.ReadToEnd();
            //File.Close();
            //string Ri = filecont;

            // Prevedu do bytu
            //byte[] byteV = System.Text.Encoding.UTF8.GetBytes(V);
            byte[] byteR = System.Text.Encoding.UTF8.GetBytes(R);
            //byte[] bytehash = System.Text.Encoding.UTF8.GetBytes(hash);
            //byte[] bytePWD = System.Text.Encoding.UTF8.GetBytes(PWD);
            //byte[] byteTimestamp = System.Text.Encoding.UTF8.GetBytes(timestamp);

            byte[] C1 = XOR(byteR, pwdhash);



            // Vratim zpet
            return C1;
            //return "True";
        }

        public string Registration_nova(string V, string R, string hash)
        {
            System.IO.StreamWriter Hsiang_V = new System.IO.StreamWriter("D:\\Pub\\nova_V.txt");
            //File.Write(Hash);
            Hsiang_V.Write(V);

            System.IO.StreamWriter Hsiang_R = new System.IO.StreamWriter("D:\\Pub\\nova_R.txt");
            //File.Write(Hash);
            Hsiang_R.Write(R);

            System.IO.StreamWriter Hsiang_hash = new System.IO.StreamWriter("D:\\Pub\\nova_hash.txt");
            //File.Write(Hash);
            Hsiang_hash.Write(hash);
            return "OK";
        }
        public byte[] GetR_nova( string timestamp)
        {
            System.IO.StreamReader File = new System.IO.StreamReader("D:\\Pub\\nova_R.txt");
            string R = File.ReadToEnd();
            File.Close();
            byte[] byteR = System.Text.Encoding.UTF8.GetBytes(R);
            //MD5 asdf = MD5.Create();
            //asdf.ComputeHash(byteR);
            //System.Text.StringBuilder s = new System.Text.StringBuilder();
            //foreach (byte byt in asdf.Hash)
            //{
            //    s.Append(byt.ToString("x2"));
            //}
            //string md5hash_PwdB = s.ToString();
            byte[] byteTimestamp = System.Text.Encoding.UTF8.GetBytes(timestamp);
            byte[] RxorT = XOR(byteR, byteTimestamp);
            
            return RxorT;
           
        }
        public string[] Login_nova(byte[] pwdhash, string timestamp)
        {
            // Prectu si soubor s ulozenym Ri
            System.IO.StreamReader File = new System.IO.StreamReader("D:\\Pub\\nova_V.txt");
            string V_2 = File.ReadToEnd();
            File.Close();

            File = new System.IO.StreamReader("D:\\Pub\\nova_R.txt");
            string R = File.ReadToEnd();
            File.Close();

            File = new System.IO.StreamReader("D:\\Pub\\nova_hash.txt");
            string hash = File.ReadToEnd();
            File.Close();
            //string Ri = filecont;

            // Prevedu do bytu
            //byte[] byteV = System.Text.Encoding.UTF8.GetBytes(V);
            byte[] byteR = System.Text.Encoding.UTF8.GetBytes(R);
            byte[] bytehash = System.Text.Encoding.UTF8.GetBytes(hash);
            //byte[] bytePWD = System.Text.Encoding.UTF8.GetBytes(PWD);
            byte[] byteTimestamp = System.Text.Encoding.UTF8.GetBytes(timestamp);

            byte[] C1 = XOR(byteR, pwdhash);
            string C1_str = System.Text.Encoding.UTF8.GetString(C1);
            string C2 = C1_str + R + timestamp;
            // Provedu Ri XOR PWD

            string[] retVal = new string[3];
            retVal.SetValue(C2, 0);
            retVal.SetValue(timestamp, 1);
            retVal.SetValue(V_2, 2);

            // Vratim zpet
            return retVal;
        }
        public byte[] Verification_nova(byte[] pwdhash)
        {

            System.IO.StreamReader File = new System.IO.StreamReader("D:\\Pub\\nova_R.txt");
            string R = File.ReadToEnd();
            File.Close();

            byte[] byteR = System.Text.Encoding.UTF8.GetBytes(R);

            byte[] C1 = XOR(byteR, pwdhash);
            // Vratim zpet
            return C1;
        }

        //public string Registration_Pairing(string ID, int regid)
        //{
        //    System.IO.StreamWriter Pairing_ID = new System.IO.StreamWriter("D:\\Pub\\Pairing_ID.txt");
        //    //File.Write(Hash);
        //    Pairing_ID.Write(ID);

        //    System.IO.StreamWriter Pairing_regid = new System.IO.StreamWriter("D:\\Pub\\Pairing_regid.txt");
        //    //File.Write(Hash);
        //    Pairing_regid.Write(regid.ToString());

        //    return "OK";
        //}

        //public string Login_Pairing(string ReqID)
        //{
        //    // Prectu si soubor s ulozenym Ri
        //    System.IO.StreamReader File = new System.IO.StreamReader("D:\\Pub\\Pairing_ID.txt");
        //    string ID = File.ReadToEnd();
        //    File.Close();
        //    File = new System.IO.StreamReader("D:\\Pub\\Pairing_regid.txt");
        //    string regid = File.ReadToEnd();
        //    File.Close();
        //    if (ReqID == ID)
        //    {
        //        return regid;
        //    }
        //    else
        //    {
        //        return "False";
        //    }
        //}
        
        public static byte[] XOR(byte[] a, byte[] b)
        {
            BigInteger a_big = new BigInteger(a);
            BigInteger b_big = new BigInteger(b);
            //  BigInteger m_big = new BigInteger(modulus);
            return (a_big ^ b_big).getBytes();

        }

        public static string Arr2String(byte[] input)
        {
            BigInteger BigNum = new BigInteger(input);
            return BigNum.ToString(10);
        }
        public static byte[] String2Arr(string input)
        {
            byte[] b = new byte[RSAsize / 8];
            BigInteger BigNum = new BigInteger(input, 10);
            length = BigNum.getBytes().Length;
            for (int j = 0; j < length; j++)
            {
                b[j] = BigNum.getBytes()[j];
            }
            for (int i = length; i < RSAsize / 8; i++)
            {
                b[i] = 0;
            }
            return b;
        }

        

        //public byte[] Test(byte[] input, byte[] exponent, byte[] modulus)
        //{

        //    RSAparam = TestRSA.ExportParameters(false);
        //    RSAparam.Exponent = exponent;
        //    RSAparam.Modulus = modulus;
        //    TestRSA.ImportParameters(RSAparam);
        //    return TestRSA.EncryptValue(input);
        //    //return TestRSA.ExportParameters(false);
        //}

        //public byte[] Test1(byte[]input)
        //{

        //    return TestRSA.Decrypt(input, false);
        //}

        //Inverze RSA, nepouzivane
        


        //Export RSA parametru
        //public RSAParameters RSA_export()
        //{
        //    return RSAd.ExportParameters(true);
        //}

        //Nasobeni
        

        //Ulozeni parametru
      /*  public void SetParameters(string variable, string name, bool first, bool last)
        {
            //Prida dalsi parametry do souboru
            FileStream file = new FileStream("C:/Data/TokenList.xml", FileMode.Append, FileAccess.Write);
            StreamWriter sw = new StreamWriter(file);
            string parameters = "";

            //Hlavicka otevreni
            if (first == true)
            {
                parameters += "<token id=\"" + "TokenID" + "\">\n";
            }

            //Parametry
            parameters += "\t<" + name + ">" + variable + "</" + name + ">\n";

            //Hlavicka uzavreni
            if (last == true)
            {
                parameters += "</token>\n";
            }

            //Zapsaní všech tokenù na kartu
            sw.Write(parameters);

            sw.Close();
            file.Close();
        }
        

        //Vypocet prvniho kroku
        public void FirstStep()
        {
            r1 = RandomGen(r1,80,48);
            r1i = RandomGen(r1i, 60, 68);
            r2 = RandomGen(r2, 53, 75);
            r2i = RandomGen(r2i, 32, 96);
            RSAsize = 1024;
            StreamReader sReader = new StreamReader("C:/Data/TokenList.xml");
            XmlTextReader xr = new XmlTextReader(sReader);

            while (xr.Read())
            {
                if (xr.Name == "token" && xr.HasAttributes == true)
                {

                    xr.Read();
                    g1 = Convert.FromBase64String(xr.ReadElementString("g1"));
                    g2 = Convert.FromBase64String(xr.ReadElementString("g2"));
                    g3 = Convert.FromBase64String(xr.ReadElementString("g3"));
                    n = Convert.FromBase64String(xr.ReadElementString("n"));
                    w = Convert.FromBase64String(xr.ReadElementString("w"));
                    wi = Convert.FromBase64String(xr.ReadElementString("wi"));

                    break;

                }
            }

            c11 = Multiply(Power(g1, r1, n), Power(g2, r1i, n), n);
            c3 = Power(g3, r1, n);
            c22 = Multiply(Power(g1, r2, n), Power(g2, r2i, n), n);
            c33 = Power(g3, r2, n);

        }
        
        //Vypocet odpovedi na vyzvu
        public void LastStep(byte[] e1)
        {
            RSAsize = 1024;
            z1 = ArrSubSimple(r1, Multiply(e1, w, n), n);
            z1i = ArrSubSimple(r1i, Multiply(e1, wi, n), n);
            z2 = ArrSubSimple(r2, Multiply(e1, r1, n), n);
            z2i = ArrSubSimple(r2i, Multiply(e1, r1i, n), n);
        }
        */
        //Zkouska nahodneho generatoru
        

        //Nějaké gettery na zkoušku, potřeba udělat lépe

        #region Getters
        //public byte[] Getc11()
        //{
        //    return c11;
        //}

        //public byte[] Getc22()
        //{
        //    return c22;
        //}

        //public byte[] Getc33()
        //{
        //    return c33;
        //}
        //public byte[] Getz1i()
        //{
        //    return z1i;
        //}
        //public byte[] Getz2()
        //{
        //    return z2;
        //}
        //public byte[] Getz2i()
        //{
        //    return z2i;
        //}
        //public byte[] Getc3()
        //{
        //    return c3;
        //}
        //public byte[] Getz1()
        //{
        //    return z1;
        //}
        #endregion

        #region Lukas, Schoolbook(opt), Comba(opt), Montgomery+podpora

        //public byte[] ArrMultiObecneOpt2(byte[] a, byte[] b)
        //{


        //    int x_len = a.Length;
        //    int y_len = b.Length;

        //    byte[] result = new byte[a.Length + b.Length];

        //    for (int i = a.Length - 1; i >= 0; i--)
        //    {
        //        int mcarry = 0;
        //        for (int j = b.Length - 1; j >= 0; j--)
        //        {
        //            int val = (a[i] * b[j]) +
        //                             result[i + j + 1] + mcarry;

        //            result[i + j + 1] = (byte)(val & 0xFF);
        //            mcarry = (val >> 8);
        //        }

        //        if (mcarry != 0)
        //            result[i + y_len] = (byte)mcarry;
        //    }
        //    return result;

        //}

        //public byte[] CombaOpt(byte[] a, byte[] b, int size)
        //{
        //    int ucarry;
        //    int utv = 0;
        //    byte[] result = new byte[size + size];

        //    for (int i = 0; i < size; i++)
        //    {
        //        for (int j = 0; j <= i; j++)
        //        {
        //            utv = (a[j] * b[i - j]) + utv;
        //        }
        //        result[i] = (byte)(utv & 0xFF);
        //        ucarry = (utv >> 8);
        //        utv = ucarry;
        //    }
        //    for (int i = size; i < size + size; i++)
        //    {
        //        for (int j = i - size + 1; j <= size - 1; j++)
        //        {
        //            utv = (a[j] * b[i - j]) + utv;
        //        }
        //        result[i] = (byte)(utv & 0xFF);
        //        ucarry = (utv >> 8);
        //        utv = ucarry;
        //    }

        //    return result;
        //}

        //public byte[] ArrMultiMontgomeryREV(byte[] x, byte[] y, byte[] m, int N, int mQ)
        //{
        //    int LONG_MASK = 0xFF;
        //    int BITS = 8;
        //    byte[] a = new byte[N + 1];
        //    for (int i = 0; i < N; i++)
        //    {
        //        int u = ((a[0] + (((x[i] & LONG_MASK) * (y[0] & LONG_MASK)) & LONG_MASK)) * mQ) & LONG_MASK;
        //        int xy = (x[i] & LONG_MASK) * (y[0] & LONG_MASK);
        //        int um = u * (m[0] & LONG_MASK);
        //        int temp = (a[0] & LONG_MASK) + (xy & LONG_MASK) + (um & LONG_MASK);
        //        int carry = (xy >> BITS) + (um >> BITS) + (temp >> BITS);
        //        for (int pos = 1; pos < N; pos++)
        //        {
        //            xy = (x[i] & LONG_MASK) * (y[pos] & LONG_MASK);
        //            um = u * (m[pos] & LONG_MASK);
        //            temp = (a[pos] & LONG_MASK) + (xy & LONG_MASK) + (um & LONG_MASK) + (carry & LONG_MASK);
        //            carry = (carry >> BITS) + (xy >> BITS) + (um >> BITS) + (temp >> BITS);
        //            a[pos - 1] = (byte)temp;
        //        }
        //        carry += (a[N] & LONG_MASK);
        //        a[N - 1] = (byte)carry;
        //        a[N] = (byte)(carry >> BITS);
        //    }
        //    if (UrciVetsiInt(a, m) == true)
        //    {
        //        ArrSubSimple(a, m, m);
        //    }
        //    return a;
        //}


        //public bool UrciVetsiInt(byte[] a, byte[] b)
        //{
        //    byte[] aReduced;
        //    if (a[0] == 0)
        //    {
        //        aReduced = RedukceByteArr(a);
        //    }
        //    else
        //    {
        //        aReduced = new byte[a.Length];
        //        aReduced = a;
        //    }
        //    byte[] bReduced;
        //    if (b[0] == 0)
        //    {
        //        bReduced = RedukceByteArr(b);
        //    }
        //    else
        //    {
        //        bReduced = new byte[b.Length];
        //        bReduced = b;
        //    }
        //    int delkaA = aReduced.Length;
        //    int delkaB = bReduced.Length;
        //    if (delkaA > delkaB)
        //    {
        //        return true;
        //    }
        //    else if (delkaB > delkaA)
        //    {
        //        return false;
        //    }
        //    else
        //    {
        //        for (int i = 0; i < delkaA; i++)
        //        {
        //            if (aReduced[i] > bReduced[i])
        //            {
        //                return true;
        //            }
        //            else if (aReduced[i] < bReduced[i])
        //            {
        //                return false;
        //            }
        //            if ((delkaA - 1) == i)
        //            {
        //                return true;
        //            }
        //        }
        //        return true;
        //    }
        //}

        ////Metoda pro odstranění nul ze začátku pole
        //public byte[] RedukceByteArr(byte[] a)
        //{
        //    int pocetNul = 0;
        //    byte[] aReduced;
        //    int difference = 0;
        //    if (a[0] == 0)
        //    {
        //        for (int i = 0; i < a.Length - 1; i++)
        //        {
        //            if ((i == 0 && a[0] == 0) || (a[0] == 0 && a[i] == 0))
        //            {
        //                pocetNul++;
        //            }
        //            else
        //            {
        //                break;
        //            }
        //        }
        //        aReduced = new byte[a.Length - pocetNul];
        //        difference = a.Length - aReduced.Length;
        //        for (int i = aReduced.Length - 1; i >= 0; i--)
        //        {
        //            aReduced[i] = a[i + difference];
        //        }
        //    }
        //    else
        //    {
        //        aReduced = new byte[a.Length];
        //        aReduced = a;
        //    }
        //    return aReduced;
        //}
        #endregion

        #region scitani, odcitani, deleni - na co je AddEqual?

        //public byte[] ArrAddEqual(byte[] a, byte[] b)
        //{

        //    int size = a.Length;

        //    // byte[] res = new byte[RSAsize / 8];
        //    byte[] res = new byte[size];

        //    int[] carry = new int[2];

        //    for (int i = size - 1; i >= 0; i--)
        //    {
        //        carry[(i + 1) % 2] = ((a[i] + b[i] + carry[i % 2]) > 255) ? 0x1 : 0x0;
        //        res[i] = (byte)((a[i] + b[i] + carry[i % 2]) % 256);
        //    }

        //    return res;
        //}

        //public byte[] ArrAddSimple(byte[] a, byte[] b, byte[] modulus)
        //{
        //    byte[] res = new byte[RSAsize / 8];
        //    int[] carry = new int[2];

        //    for (int i = RSAsize / 8 - 1; i >= 0; i--)
        //    {
        //        carry[(i + 1) % 2] = ((a[i] + b[i] + carry[i % 2]) > 255) ? 0x1 : 0x0;
        //        res[i] = (byte)((a[i] + b[i] + carry[i % 2]) % 256);
        //    }

        //    if (carry[1] == 1)
        //    {
        //        a = ArrSubSimple(a, modulus, modulus);
        //        res = ArrAddSimple(b, a, modulus);
        //    }

        //    return res;
        //}

        public byte[] ArrSubSimple(byte[] a, byte[] b, byte[] modulus)
        {
            byte[] res = new byte[RSAsize / 8];
            int[] carry = new int[2];


            for (int j = 0; j < RSAsize / 8; j++)
            {
                if (a[j] > b[j])
                {
                    for (int i = RSAsize / 8 - 1; i >= 0; i--)
                    {
                        carry[(i + 1) % 2] = ((a[i] - b[i] - carry[i % 2]) < 0) ? 0x1 : 0x0;
                        res[i] = (byte)((a[i] - b[i] - carry[i % 2] + 256 * carry[(i + 1) % 2]) % 256);
                    }
                    return res;
                }

                if (a[j] < b[j])
                {
                    for (int i = RSAsize / 8 - 1; i >= 0; i--)
                    {
                        carry[(i + 1) % 2] = ((modulus[i] + a[i] + carry[i % 2]) > 255) ? 0x1 : 0x0;
                        res[i] = (byte)((modulus[i] + a[i] + carry[i % 2]) % 256);
                    }

                    for (int i = RSAsize / 8 - 1; i >= 0; i--)
                    {
                        carry[(i + 1) % 2] = ((res[i] - b[i] - carry[i % 2]) < 0) ? 0x1 : 0x0;
                        res[i] = (byte)((res[i] - b[i] - carry[i % 2] + 256 * carry[(i + 1) % 2]) % 256);
                    }

                    return res;
                }

            }

            for (int i = RSAsize / 8 - 1; i >= 0; i--)
            {
                carry[(i + 1) % 2] = ((a[i] - b[i] - carry[i % 2]) < 0) ? 0x1 : 0x0;
                res[i] = (byte)((a[i] - b[i] - carry[i % 2] + 256 * carry[(i + 1) % 2]) % 256);
            }

            return res;

        }

        //public byte[] ArrHalfSimple(byte[] input, byte[] modulus)
        //{
        //    //Fix pro velke hodnoty
        //    if (input[RSAsize / 8 - 1] % 2 == 1)
        //    {
        //        byte[] res = new byte[RSAsize / 8 + 1];
        //        int[] carry = new int[2];

        //        for (int i = RSAsize / 8 - 1; i >= 0; i--)
        //        {
        //            carry[(i + 1) % 2] = ((input[i] + modulus[i] + carry[i % 2]) > 255) ? 0x1 : 0x0;
        //            res[i + 1] = (byte)((input[i] + modulus[i] + carry[i % 2]) % 256);
        //        }

        //        res[0] = (byte)carry[1];

        //        int[] carry2 = new int[2];

        //        for (int j = 0; j < RSAsize / 8 + 1; j++)
        //        {
        //            carry2[(j + 1) % 2] = (res[j] % 2) * 128;
        //            res[j] = (byte)((res[j] >> 1) + carry2[j % 2]);
        //        };

        //        for (int j = 0; j < RSAsize / 8; j++)
        //        {
        //            input[j] = res[j + 1];
        //        };

        //        return input;

        //    }

        //    //if (input[RSAsize / 8 - 1] % 2 == 1)
        //    //{
        //    //    input = ArrAddSimple(input, modulus, modulus);
        //    //}

        //    int[] carry3 = new int[2];
        //    for (int j = 0; j < RSAsize / 8; j++)
        //    {
        //        carry3[(j + 1) % 2] = (input[j] % 2) * 128;
        //        input[j] = (byte)((input[j] >> 1) + carry3[j % 2]);
        //    };

        //    return input;
        //}
        
        #endregion

    }
}

