
using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using SmartCard.Runtime.Remoting.Channels.APDU;
using System.IO;
using System.Xml;
using System.Collections;
using MyCompany.Client;
using MyCompany.Server;
using MyCompany.Client.EncryptionSink;
using System.Security.Cryptography;




namespace MyCompany.Client
{


    public class ClientApp
    {
        static int RSAsize = 2048;
        public static int a_length;
        public static int length;
        public static int b_length;
        public static int m_length;

        public int getA_length()
        {
            return a_length * 8;
        }
        public int getB_length()
        {
            return b_length * 8;
        }
        public int getM_length()
        {
            return m_length * 8;
        }
        public static string Info;
        public string GetInfo()
        {
            return Info;
        }
        #region Pamet
        public static string Memory;
        public string GetMemory()
        {

            //Inicializace komunikace s kartou
            //Inicializace();

            //long memory = getService().getMemory();
            //Inicializace parametru pro RSA funkci na kartě

            //Vrati postupne vystup, modulus. Pro prevod z pole bytu se pouziva fce Arr2Str
            return Memory;
        }
        #endregion

        #region AES, DES
        public string Key_DES(int keysize)
        {
            Inicializace();
            byte[] encrypted = getService().DES_NovyKlic(keysize);
            return Arr2String(encrypted);
        }
        public string IV_DES()
        {
            Inicializace();
            byte[] encrypted = getService().DES_NovyIV();
            return Arr2String(encrypted);
        }
        public string Key_AES(int keysize)
        {
            Inicializace();
            byte[] encrypted = getService().AES_NovyKlic(keysize);
            return Arr2String(encrypted);
        }
        public string IV_AES()
        {
            Inicializace();
            byte[] encrypted = getService().AES_NovyIV();
            return Arr2String(encrypted);
        }
        public string Enc_DES(string input, string e, string modulus)
        {
            int ModSize = (int)Math.Ceiling((double)String2ArrBig(modulus).Length * 8 / 128) * 128;
            //Inicializace komunikace s kartou
            Inicializace();

            getService().SetRSAsize(ModSize);
            RSAsize = ModSize;

            //Inicializace parametru pro RSA funkci na kartě
            byte[] exp = String2ArrBig(e);

            //byte[] exp = String2ArrReverse(e);
            //Array.Reverse(exp);
            byte[] mod = String2ArrReverse(modulus);
            m_length = length;
            Array.Reverse(mod);

            byte[] plain = String2ArrReverse2(input);
            a_length = length;
            Array.Reverse(plain);

            //Ziska zasifrovanou hodnotu jako pole bytu    
            System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();
            long startMemory = currentProcess.WorkingSet64;
            DateTime startTime = DateTime.Now;
            byte[] encrypted = getService().Enc_DES(plain, exp, mod);
            DateTime stopTime = DateTime.Now;
            Memory = currentProcess.WorkingSet64.ToString();
            TimeSpan duration = stopTime - startTime;
            string strsec = duration.TotalMilliseconds.ToString();
            //long memory = stopMemory;
            //Ukonceni spojeni s kartou
            UkonciSpojeni();
            Info = "\r\ncas:" + strsec + " ms" + "\r\n" + "delky parametru: a= " + a_length * 8 + " bits,  b= " + b_length * 8 + " bits,  mod= " + m_length * 8 + " bits \r\n" + "\r\n" + "Pamet: " + Memory + "b";
            //Vrati postupne vytsup, modulus. Pro prevod z pole bytu se pouziva fce Arr2Str
            return Arr2String(encrypted);
        }
        public string Dec_DES(string input, string e, string modulus)
        {
            int ModSize = (int)Math.Ceiling((double)String2ArrBig(modulus).Length * 8 / 128) * 128;
            //Inicializace komunikace s kartou
            Inicializace();

            getService().SetRSAsize(ModSize);
            RSAsize = ModSize;

            //Inicializace parametru pro RSA funkci na kartě
            byte[] exp = String2ArrBig(e);

            //byte[] exp = String2ArrReverse(e);
            //Array.Reverse(exp);
            byte[] mod = String2ArrReverse(modulus);
            m_length = length;
            Array.Reverse(mod);

            byte[] plain = String2ArrReverse2(input);
            a_length = length;
            Array.Reverse(plain);

            //Ziska zasifrovanou hodnotu jako pole bytu    
            System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();
            long startMemory = currentProcess.WorkingSet64;
            DateTime startTime = DateTime.Now;
            byte[] encrypted = getService().Dec_DES(plain, exp, mod);
            DateTime stopTime = DateTime.Now;
            long stopMemory = currentProcess.WorkingSet64;
            Memory = currentProcess.WorkingSet64.ToString();
            TimeSpan duration = stopTime - startTime;
            string strsec = duration.TotalMilliseconds.ToString();
            long memory = stopMemory;
            //Ukonceni spojeni s kartou
            UkonciSpojeni();
            Info = "\r\ncas:" + strsec + " ms" + "\r\n" + "delky parametru: a= " + a_length * 8 + " bits,  b= " + b_length * 8 + " bits,  mod= " + m_length * 8 + " bits \r\n" + "\r\n" + "Pamet: " + Memory + "b";
            //Vrati postupne vytsup, modulus. Pro prevod z pole bytu se pouziva fce Arr2Str
            return Arr2String(encrypted);
        }
        public string Enc_AES(string input, string e, string modulus)
        {
            int ModSize = (int)Math.Ceiling((double)String2ArrBig(modulus).Length * 8 / 128) * 128;
            //Inicializace komunikace s kartou
            Inicializace();

            getService().SetRSAsize(ModSize);
            RSAsize = ModSize;

            //Inicializace parametru pro RSA funkci na kartě
            byte[] exp = String2ArrBig(e);

            //byte[] exp = String2ArrReverse(e);
            //Array.Reverse(exp);

            byte[] mod = String2ArrReverse(modulus);
            m_length = length;
            Array.Reverse(mod);

            byte[] plain = String2ArrReverse2(input);
            a_length = length;
            Array.Reverse(plain);

            //Ziska zasifrovanou hodnotu jako pole bytu    
            System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();
            long startMemory = currentProcess.WorkingSet64;
            DateTime startTime = DateTime.Now;
            //byte[] encrypted = getService().Enc_AES(System.Text.Encoding.UTF8.GetBytes(input.PadRight(8, ' ')), exp, System.Text.Encoding.UTF8.GetBytes(modulus));
            byte[] encrypted = getService().Enc_AES(plain, exp, mod);
            DateTime stopTime = DateTime.Now;
            long stopMemory = currentProcess.WorkingSet64;
            Memory = currentProcess.WorkingSet64.ToString();
            TimeSpan duration = stopTime - startTime;
            string strsec = duration.TotalMilliseconds.ToString();
            long memory = stopMemory;
            //Ukonceni spojeni s kartou
            UkonciSpojeni();

            //Vrati postupne vytsup, modulus. Pro prevod z pole bytu se pouziva fce Arr2Str
            //string ret = System.Text.Encoding.UTF8.GetString(encrypted);
            Info = "\r\ncas:" + strsec + " ms" + "\r\n" + "delky parametru: a= " + a_length * 8 + " bits,  b= " + b_length * 8 + " bits,  mod= " + m_length * 8 + " bits \r\n" + "\r\n" + "Pamet: " + Memory + "b";
            return Arr2String(encrypted);
        }
        public string Dec_AES(string input, string e, string modulus)
        {
            int ModSize = (int)Math.Ceiling((double)String2ArrBig(modulus).Length * 8 / 128) * 128;
            //Inicializace komunikace s kartou
            Inicializace();

            getService().SetRSAsize(ModSize);
            RSAsize = ModSize;

            //Inicializace parametru pro RSA funkci na kartě
            byte[] exp = String2ArrBig(e);

            //byte[] exp = String2ArrReverse(e);
            //Array.Reverse(exp);

            byte[] mod = String2ArrReverse(modulus);
            m_length = length;
            Array.Reverse(mod);

            byte[] plain = String2ArrReverse2(input);
            a_length = length;
            Array.Reverse(plain);

            //Ziska zasifrovanou hodnotu jako pole bytu    
            System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();
            long startMemory = currentProcess.WorkingSet64;
            DateTime startTime = DateTime.Now;
            byte[] encrypted = getService().Dec_AES(plain, exp, mod);
            //byte[] encrypted = getService().Dec_AES(System.Text.Encoding.Unicode.GetBytes(input), exp, mod);
            //byte[] encrypted = getService().Dec_AES(System.Text.Encoding.UTF8.GetBytes(input), exp, mod);
            DateTime stopTime = DateTime.Now;
            long stopMemory = currentProcess.WorkingSet64;
            Memory = currentProcess.WorkingSet64.ToString();
            TimeSpan duration = stopTime - startTime;
            string strsec = duration.TotalMilliseconds.ToString();
            long memory = stopMemory;
            //Ukonceni spojeni s kartou
            UkonciSpojeni();
            Info = "\r\ncas:" + strsec + " ms" + "\r\n" + "delky parametru: a= " + a_length * 8 + " bits,  b= " + b_length * 8 + " bits,  mod= " + m_length * 8 + " bits \r\n" + "\r\n" + "Pamet: " + Memory + "b";
            //Vrati postupne vytsup, modulus. Pro prevod z pole bytu se pouziva fce Arr2Str
            return Arr2String(encrypted);
        }
        #endregion

        #region Kod pro komunikaci s kartou

        private const string URL = "apdu://selfdiscover/EncryptionSinkService.uri";
        private Service cardServer;                                     //definice nové služby
        private APDUClientChannel channel = new APDUClientChannel();    //definice nového komunikaèního kanálu (channel)

        //metoda pro nastaveni promìnne service
        private void setService(Service cardServer)
        {
            this.cardServer = cardServer;
        }
        //metoda pro získáni hodnoty z promìnne service
        private Service getService()
        {
            return this.cardServer;
        }
        //metoda pro nastavení promìnne channel
        private void setChannel(APDUClientChannel channel)
        {
            this.channel = channel;
        }
        //metoda pro získáni hodnoty z promìnne channel
        private APDUClientChannel getChannel()
        {
            return this.channel;
        }

        public static void Main()
        {
        }

        //----------------------------------------------------------------------------
        //Metoda sloužící k ustanovení komunikaèního kanálu a registraci dané služby
        //---------------------------------------------------------------------------- 
        private void Inicializace()
        {

            //Nastavení pøipojení ke službì "EncryptionSinkClient" na kartì
            setChannel(new APDUClientChannel());

            //Registrace komunikaèního kanálu
            ChannelServices.RegisterChannel(getChannel(), false);

            //Nastavíme požadovanou službu (nacházející se na pøislušné URL adrese)
            setService((Service)Activator.GetObject(typeof(Service), URL));
        }

        //----------------------------------------------------------------------------
        //Metoda sloužící ke zrušní komunikaèního kanálu
        //---------------------------------------------------------------------------- 
        private void UkonciSpojeni()
        {
            ChannelServices.UnregisterChannel(getChannel());
        }

        //----------------------------------------------------------------------------
        //Metoda pro odesílání vybraných parametrù na kartu (jen 1x)
        //----------------------------------------------------------------------------

        #endregion

        #region Pristup ke scitani, nasobeni, mocneni (RSA)

        public string FastAdd(string a, string b, string modulus)
        {
            int ModSize = (int)Math.Ceiling((double)String2ArrBig(modulus).Length * 8 / 128) * 128;
            //Inicializace komunikace s kartou
            Inicializace();
            getService().SetRSAsize(ModSize);
            RSAsize = ModSize;

            //Inicializace parametru pro RSA funkci na kartě
            byte[] a_byte = String2ArrReverse(a);
            Array.Reverse(a_byte);
            byte[] b_byte = String2ArrReverse(b);
            Array.Reverse(b_byte);
            byte[] modulus_byte = String2ArrReverse(modulus);
            Array.Reverse(modulus_byte);

            //Ziska zasifrovanou hodnotu jako pole bytu            
            byte[] encrypted = ArrAddSimple(a_byte, b_byte, modulus_byte);

            //Ukonceni spojeni s kartou
            UkonciSpojeni();

            //Vrati postupne vystup, modulus. Pro prevod z pole bytu se pouziva fce Arr2Str
            return "a + b:\r\n" + Arr2String(encrypted);
        }

        public string FastPower(string input, string e, string modulus)
        {
            int ModSize = (int) Math.Ceiling((double) String2ArrBig(modulus).Length * 8 / 128) * 128;
            //Inicializace komunikace s kartou
            Inicializace();

            getService().SetRSAsize(ModSize);
            RSAsize = ModSize;

            //Inicializace parametru pro RSA funkci na kartě
            byte[] exp = String2ArrBig(e);

            //byte[] exp = String2ArrReverse(e);
            //Array.Reverse(exp);
            byte[] mod = String2ArrReverse(modulus);
            m_length = length;
            Array.Reverse(mod);
           
            byte[] plain = String2ArrReverse(input);
            a_length = length;
            Array.Reverse(plain);

            //Ziska zasifrovanou hodnotu jako pole bytu    
            System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();
            long startMemory = currentProcess.WorkingSet64;
            DateTime startTime = DateTime.Now;
            byte[] encrypted = getService().Power(plain, exp, mod);
            DateTime stopTime = DateTime.Now;
            long stopMemory = currentProcess.WorkingSet64;
            
            Memory = currentProcess.WorkingSet64.ToString();
            TimeSpan duration = stopTime - startTime;
            string strsec = duration.TotalMilliseconds.ToString();
            long memory = stopMemory;
            //Ukonceni spojeni s kartou
            UkonciSpojeni();
            Info = "\r\ncas:" + strsec + " ms" + "\r\n" + "delky parametru: a= " + a_length * 8 + " bits,  b= " + b_length * 8 + " bits,  mod= " + m_length * 8 + " bits \r\n" + "\r\n" + "Pamet: " + Memory + "b";
            //Vrati postupne vytsup, modulus. Pro prevod z pole bytu se pouziva fce Arr2Str
            return Arr2String(encrypted);
        }
        public string FastDePower(string input, string e, string modulus)
        {
            int ModSize = (int)Math.Ceiling((double)String2ArrBig(modulus).Length * 8 / 128) * 128;
            //Inicializace komunikace s kartou
            Inicializace();

            getService().SetRSAsize(ModSize);
            RSAsize = ModSize;

            //Inicializace parametru pro RSA funkci na kartě
            byte[] exp = String2ArrBig(e);

            //byte[] exp = String2ArrReverse(e);
            //Array.Reverse(exp);
            byte[] mod = String2ArrReverse(modulus);
            m_length = length;
            Array.Reverse(mod);

            byte[] plain = String2ArrReverse(input);
            a_length = length;
            Array.Reverse(plain);

            //Ziska zasifrovanou hodnotu jako pole bytu    
            System.Diagnostics.Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();
            long startMemory = currentProcess.WorkingSet64;
            DateTime startTime = DateTime.Now;
            byte[] encrypted = getService().DePower(plain, exp, mod);
            DateTime stopTime = DateTime.Now;
            long stopMemory = currentProcess.WorkingSet64;
            Memory = currentProcess.WorkingSet64.ToString();
            TimeSpan duration = stopTime - startTime;
            string strsec = duration.TotalMilliseconds.ToString();
            long memory = stopMemory;
            //Ukonceni spojeni s kartou
            UkonciSpojeni();
            Info = "\r\ncas:" + strsec + " ms" + "\r\n" + "delky parametru: a= " + a_length * 8 + " bits,  b= " + b_length * 8 + " bits,  mod= " + m_length * 8 + " bits \r\n" + "\r\n" + "Pamet: " + Memory + "b";
            //Vrati postupne vytsup, modulus. Pro prevod z pole bytu se pouziva fce Arr2Str
            return Arr2String(encrypted);
        }

        //public string Test(string input, string e, string modulus)
        //{
        //    //Inicializace komunikace s kartou
        //    Inicializace();

        //    //Inicializace parametru pro RSA funkci na kartě
        //    //RSAsize = 1024;
        //    byte[] exp = String2ArrReverse(e);
        //    Array.Reverse(exp);
        //    byte[] plain = String2ArrReverse(input);
        //    Array.Reverse(plain);
        //    //RSAsize = 2048;
        //    byte[] mod = String2ArrReverse(modulus);
        //    Array.Reverse(mod);
            
        //    //Ziska zasifrovanou hodnotu jako pole bytu            

        //    byte[] exponent = String2ArrBig(e);

            
        //    byte[] encrypted = getService().Test(plain, exponent, mod);

        //    RSAParameters tt = new RSAParameters();
        //    //   tt= getService().Test(plain, exponent,mod);
        //    //byte[] decrypted = getService().Test1(encrypted);


        //    //Ukonceni spojeni s kartou
        //    UkonciSpojeni();

        //    //Vrati postupne vytsup, modulus. Pro prevod z pole bytu se pouziva fce Arr2Str
        //    return "a^b:\r\n" + Arr2String(encrypted) + "\r\n" + "\r\n" + "delky parametru: a= " + a_length * 8 + " bits,  b= " + b_length * 8 + " bits,  mod= " + m_length * 8 + " bits \r\n" + "\r\n";
        //}

        public string FastMulti(string a, string b, string modulus, int iterace)
        {
            int ModSize = (int)Math.Ceiling((double)String2ArrBig(modulus).Length * 8 / 128) * 128;
            //Inicializace komunikace s kartou
            Inicializace();
            getService().SetRSAsize(ModSize);
            RSAsize = ModSize;

            //Inicializace parametru RSA
            byte[] a_byte = String2ArrReverse(a);
            a_length = length;
            Array.Reverse(a_byte);
            byte[] mod_byte = String2ArrReverse(modulus);
            m_length = length;
            Array.Reverse(mod_byte);
            byte[] b_byte = String2ArrReverse(b);
            b_length = length;
            Array.Reverse(b_byte);

            //Vypocte soucin na karte
            DateTime startTime = DateTime.Now;
            byte[] res = getService().Multiply(a_byte, b_byte, mod_byte);

            DateTime stopTime = DateTime.Now;
            TimeSpan duration = stopTime - startTime;
            string strsec = duration.TotalMilliseconds.ToString();
      

            //Ukonceni spojeni s kartou
            UkonciSpojeni();

            //Vypocet kontrolni hodnoty pomoci bigint
            byte[] res2 = Overeni(a_byte, b_byte, mod_byte);

            //Vrati postupne kryptogra, pouzite parametry RSA a desifrovanou hodnotu. Pro prevod z pole bytu se pouziva fce Arr2Str
            return "a x b:\r\n" + Arr2String(res) + "\r\n cas:" + strsec + " ms" + "\r\n" + "a x b (overeni):\r\n" + Arr2String(res2) + "\r\n" + "\r\n" + "delky parametru: a= " + a_length * 8 + " bits,  b= " + b_length * 8 + " bits,  mod= " + m_length * 8 + " bits \r\n" + "\r\n";
        }

        #endregion

        #region Protokol
        /*
        public void SetParameters()
        {
            //Prevod na String_base
            byte[] g1_byte = String2ArrReverse("2");
            Array.Reverse(g1_byte);
            string g1 = Convert.ToBase64String(g1_byte);

            byte[] g2_byte = String2ArrReverse("10025007711078970032722090924244823753518831265230832543972867812291534909295533755784650421637319882038517189154959272472749590988012213990204130949813293249939236148700631387232858769975421549398744560469069000199468677597593376010508357296484445672716792583456375686616540719444064846258831817642426068745");
            Array.Reverse(g2_byte);
            string g2 = Convert.ToBase64String(g2_byte);

            byte[] g3_byte = String2ArrReverse("3");
            Array.Reverse(g3_byte);
            string g3 = Convert.ToBase64String(g3_byte);

            byte[] n_byte = String2ArrReverse("103591779951956805685632667169764966971843035782519723980331864628213384015286756577861374192939798068409838383020702453300877398991771740795239376052097400553904378258514562638386783011842776923138046086547225696091469644597607554280447576816953516080944301013048157225911981589658664069265537468062555103289");
            Array.Reverse(n_byte);
            string n = Convert.ToBase64String(n_byte);

            byte[] w_byte = String2ArrReverse("1430738032943714738611547866729946237171926281834");
            Array.Reverse(w_byte);
            string w = Convert.ToBase64String(w_byte);

            byte[] wi_byte = String2ArrReverse("103591779951956805685632667169764966971843035782519723980331864628213384015286756577861374192939793383017056439603956430012616534351521140493957559829686699653858220014228482371156807862929291067680419706900390384262530445866376374692484620429009640233312656002550765621627282070462962686741769388798566542662");
            Array.Reverse(wi_byte);
            string wi = Convert.ToBase64String(wi_byte);
            //Inicializace komunikace s kartou
            Inicializace();

            //Test nahrani parametru
            getService().SetParameters(g1, "g1", true, false);
            getService().SetParameters(g2, "g2", false, false);
            getService().SetParameters(g3, "g3", false, false);
            getService().SetParameters(n, "n", false, false);
            getService().SetParameters(w, "w", false, false);
            getService().SetParameters(wi, "wi", false, true);


            //Ukonceni spojeni s kartou
            UkonciSpojeni();
        }
        
        public string RunProtocol()
        {
            byte[] g1_byte = String2ArrReverse("2");
            Array.Reverse(g1_byte);
            string g1 = Convert.ToBase64String(g1_byte);

            byte[] g2_byte = String2ArrReverse("10025007711078970032722090924244823753518831265230832543972867812291534909295533755784650421637319882038517189154959272472749590988012213990204130949813293249939236148700631387232858769975421549398744560469069000199468677597593376010508357296484445672716792583456375686616540719444064846258831817642426068745");
            Array.Reverse(g2_byte);
            string g2 = Convert.ToBase64String(g2_byte);
            byte[] n_byte = String2ArrReverse("103591779951956805685632667169764966971843035782519723980331864628213384015286756577861374192939798068409838383020702453300877398991771740795239376052097400553904378258514562638386783011842776923138046086547225696091469644597607554280447576816953516080944301013048157225911981589658664069265537468062555103289");
            Array.Reverse(n_byte);
            string n = Convert.ToBase64String(n_byte);

            //Inicializace komunikace s kartou
            Inicializace();
            byte[] r1 = String2ArrReverse("1058390237766549893870159222418659010830370154257530759414454613904048164902889234527964999069018657662946711075539");
            Array.Reverse(r1);
            byte[] r1i = String2ArrReverse("2471771760604946311944243905017210604129956002333813852872490707507528194383334396085233675685864951240347238511403583049738135841356415428983639197457584301529434");
            Array.Reverse(r1i);
            byte[] r2 = String2ArrReverse("1903504862866753128964086478881045909024927425063443777180083878088011395140893434541704099110133039878893506905932182913421997133159676012397498930887174069688974529540303424943035");
            Array.Reverse(r2);
            byte[] r2i = String2ArrReverse("3832597006221243113691114298484896729873483213992727081137902827189271452259148193729468874396405666316662048488415414063337513378212537609179357686605951493623864530401732398718104608396870886363449493338729494058172016646678859");
            Array.Reverse(r2i);
            byte[] e1_byte = String2ArrReverse("727255329137909630536094653999912989262169168985");
            Array.Reverse(e1_byte);
            string e1 = Convert.ToBase64String(e1_byte);

            //Ziskani odezvy
            getService().FirstStep();
            getService().LastStep(e1_byte);
            byte[] c11 = getService().Getc11();
            byte[] c22 = getService().Getc22();
            byte[] c3 = getService().Getc3();
            byte[] c33 = getService().Getc33();
            byte[] z1 = getService().Getz1();
            byte[] z1i = getService().Getz1i();
            byte[] z2 = getService().Getz2();
            byte[] z2i = getService().Getz2i();

            string tmp = "c11: " + Arr2String(c11) + "\r\n \r\n" + "c22: " + Arr2String(c22) + "\r\n \r\n" + "c3: " + Arr2String(c3) + "\r\n \r\n" + "\r\n \r\n" + "c22: " + Arr2String(c22) + "\r\n \r\n" + "c33: " + Arr2String(c33) + "\r\n \r\n" + "z1: " + Arr2String(z1) + "\r\n \r\n" + "z1i: " + Arr2String(z1i) + "\r\n \r\n" + "z2: " + Arr2String(z2) + "\r\n \r\n" + "z2i: " + Arr2String(z2i); 
            //Ukonceni spojeni s kartou
            UkonciSpojeni();
            return tmp;
        }
        
        */

        #endregion

        #region Pomocne metody pro vypocet (+,*), pouze pro ladeni

        public static 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;
        }

        // Scitani pro libovolne cisla, rychlejsi pro mensi cisla nez velikost modula

        public static byte[] ArrAddObecne(byte[] a, byte[] b)
        {
            int size;
            byte carry = 0;
            if (a.Length > b.Length)
            {
                size = a.Length;
            }
            else
            {
                size = b.Length;
            }
            byte[] res = new byte[size];
            for (int i = res.Length - 1; i >= 0; i--)
            {
                res[i] = Convert.ToByte((a[i] + b[i] + carry) % 256);
                if ((a[i] + b[i] + carry) > 255)
                {
                    carry = 1;
                }
                else carry = 0;
            }
            return res;
        }

        /// <summary>
        /// Obecne nasobeni v modulu, zde pro odladeni
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="modulus"></param>
        /// <returns></returns>
        public static byte[] ArrMultiSimple(byte[] a, byte[] b)
        {
            byte[] result = new byte[RSAsize / 8];

            for (int i = RSAsize / 8; i >= 0; i--)
            {

                int mcarry = 0;

                for (int j = RSAsize / 8; 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 + RSAsize / 8] = (byte)mcarry;
            }
            return result;

        }

        /// <summary>
        /// tato fce nasobení je použita na karte, metoda schoolbook asi 800 ms
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static byte[] ArrMultiObecne(byte[] a, byte[] b)
        {
            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 + b.Length] = (byte)mcarry;
            }
            return result;

        }

        //asi 300 ms
        public static byte[] ArrMultiObecneOpt(byte[] a, byte[] b)
        {

            byte[] x_red = RedukceByteArr(a);
            byte[] y_red = RedukceByteArr(b);
            int x_len = x_red.Length;
            int y_len = y_red.Length;

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

            for (int i = a.Length - 1; i >= a.Length - x_len - 1; i--)
            {
                int mcarry = 0;
                for (int j = b.Length - 1; j >= b.Length - y_len - 1; 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;

        }

        //jeste rychlejsi kdy redukce nebude na karte ale na pc- asi 100 ms
        public static 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 static byte[] ArrSubSimple(byte[] a, byte[] b, byte[] modulus)
        {
            int alen = a.Length;
            int blen = b.Length;
            int size = blen;
            if (alen > blen)
                size = RSAsize / 8;

            byte[] res = new byte[size];
            int[] carry = new int[2];

            for (int j = 0; j < size; j++)
            {
                if (a[j] > b[j])
                {
                    for (int i = size - 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 = size - 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 = size - 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 = size - 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 static byte[] ArrHalfSimple(byte[] input, byte[] modulus)
        {
            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];

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

                return input;
    
            }

            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

        #region Simple (schoolbook)

        public string VypoctiSoucin(string a, string b, string modulus, int iterace)
        {
            //Inicializace komunikace s kartou
            bool sw = false;
            Inicializace();

            //Inicializace parametru RSA
            byte[] a_byte = String2ArrReverse(a);
            a_length = length;

            //korektura pro prenos pokud jsou a b stejne dlouha jako RSAsize
            if (a_length * 8 == RSAsize)
            {
                RSAsize = RSAsize + 8;
                sw = true;
            }
            a_byte = String2ArrReverse(a);

            Array.Reverse(a_byte);
            byte[] mod_byte = String2ArrReverse(modulus);
            m_length = length;
            Array.Reverse(mod_byte);
            byte[] b_byte = String2ArrReverse(b);
            b_length = length;
            Array.Reverse(b_byte);

       //     a_byte = RedukceByteArr(a_byte);
        //    b_byte = RedukceByteArr(b_byte);

            //Vypocte soucin na karte
            DateTime startTime = DateTime.Now;
         //   byte[] res = getService().ArrMultiObecneOpt2(a_byte, b_byte);
          
    
            byte[] res = getService().ArrSubSimple(a_byte, b_byte,mod_byte);
          //  byte[] res = getService().ArrHalfSimple(a_byte, mod_byte);
           // byte[] res = getService().ArrAddEqual(a_byte, b_byte);

            DateTime stopTime = DateTime.Now;
            TimeSpan duration = stopTime - startTime;
            string strsec = duration.TotalMilliseconds.ToString();
      
            res = Modulo(res, mod_byte);


            //Ukonceni spojeni s kartou
            UkonciSpojeni();

            // Vypocet kontrolni hodnoty pomoci bigint
            //pro součet
            if (sw == true)
                RSAsize = RSAsize - 8;
            //pro součin
           // byte[] res2 = Overeni(a_byte, b_byte, mod_byte);
            byte[] res2 = Overeni2(a_byte, b_byte);
          //  res2 = Modulo(res2, mod_byte);

            //Vrati postupne kryptogra, pouzite parametry RSA a desifrovanou hodnotu. Pro prevod z pole bytu se pouziva fce Arr2Str
            return "a * b:\r\n" + Arr2String(res) + "\r\n cas:" +strsec+" ms"+ "\r\n"+  "a * b (overeni):\r\n" + Arr2String(res2) + "\r\n" + "\r\n" + "delky parametru: a= " + a_length * 8 + " bits,  b= " + b_length * 8 + " bits,  mod= " + m_length * 8 + " bits \r\n" + "\r\n";

        }
        #endregion

        #region Montgomery

        //tato je funkcni
        public string VypoctiSoucinMont1(string a, string b, string modulus, int iterace)
        {
            //Inicializace komunikace s kartou
            Inicializace();

            //testovaci menezes
            //   a = "5792";

            //    b = "1229";
            //    modulus = "72639";
            int baze = 256;
            //Inicializace parametru RSA
            byte[] a_byte = String2ArrReverse(a);
            a_length = length;
            // Array.Reverse(a_byte);

            byte[] mod_byte = String2ArrReverse(modulus);
            m_length = length;
            Array.Reverse(mod_byte);

            //zjistit delku n
            int N = RedukceByteArr(mod_byte).Length - 1;


            // nachystani mQ = -m^1 mod b.

            BigInteger mod = new BigInteger(mod_byte);
            //masku mam 255 256 uz je prenos 
            mod = ((baze - mod).modInverse(baze));
            //protoze je minus tak odecte od modula

            int mQ = Convert.ToInt32(mod.ToString()); ;//mod.IntValue();

            byte[] b_byte = String2ArrReverse(b);
            b_length = length;
            // Array.Reverse(b_byte);

            Array.Reverse(mod_byte);
            //Vypocte soucin na karte
            DateTime startTime = DateTime.Now;
            byte[] res = getService().ArrMultiMontgomeryREV(a_byte, b_byte, mod_byte, N, mQ);
            //  byte[] res = ArrMultiMontgomeryREV(a_byte, b_byte, mod_byte, N, mQ);
            DateTime stopTime = DateTime.Now;
            TimeSpan duration = stopTime - startTime;
            string strsec = duration.TotalMilliseconds.ToString();
      
            // x * y * R^-1 mod m. je nyni res
            // proto vynasobime R coz je R = b^n with gcd(m, b) = 1
            // n je delka modula 
            //b je vpocetni baze ci radix
            // double pom = Math.Pow(256.0, Convert.ToDouble(N));
            Array.Reverse(mod_byte);
            BigInteger pom = new BigInteger(baze);

            BigInteger modulo = new BigInteger(mod_byte);
            pom = pom.modPow(N, modulo);
            //  pom=pom ^ N;

            string p = pom.ToString();

            byte[] soucinitel = String2ArrReverse(p);
            Array.Reverse(soucinitel);
            Array.Reverse(res);

            res = ArrMultiObecneOpt2(soucinitel, res);
            //projedeme pres modulo
            res = Modulo(res, mod_byte);
            Array.Reverse(res);


            //Ukonceni spojeni s kartou
            UkonciSpojeni();

            Array.Reverse(a_byte);
            Array.Reverse(b_byte);
            //pro součin
            byte[] res2 = Overeni(a_byte, b_byte, mod_byte);

            //Vrati postupne kryptogra, pouzite parametry RSA a desifrovanou hodnotu. Pro prevod z pole bytu se pouziva fce Arr2Str
            return "Montgomery a * b:\r\n" + Arr2String(res) + "\r\n casIN: " +strsec +" ms" +"\r\n" + "a * b (overeni):\r\n" + Arr2String(res2) + "\r\n" + "delky parametru: a= " + a_length * 8 + " bits,  b= " + b_length * 8 + " bits,  mod= " + m_length * 8 + " bits \r\n" + "\r\n" + "\r\n";

        }

        // Montgomery multiplication
        public static byte[] ArrMultiMontgomeryREV(byte[] x, byte[] y, byte[] m, int N, int mQ)
        {

            //int LONG_MASK = 0xFF; //255
            int LONG_MASK = 255;
            int BITS = 8;

            byte[] a = new byte[N + 1];
            // for (int i = 0; i < N; i++)
            // {
            //     a[i] = 0;
            // }


            // int Y_0 = y[konst - 1] & LONG_MASK;
            // 2. For i from (n - 1) to 0  do the following:
            for (int i = 0; i < N; i++)
            //   for (int i = 0; i < n; i++)
            {
                // 2.1 u_i = (a[0] + x[i] * y[0]) * mQ mod b.

                int u = ((a[0] + (((x[i] & LONG_MASK) * (y[0] & LONG_MASK)) & LONG_MASK)) * mQ) & LONG_MASK;
                // int u = ((a[0] + ((x_i * Y_0) & LONG_MASK)) * mQ) & LONG_MASK;


                // 2.2 A = (A + x[i] * y + u_i * m) / b.

                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);
                // pos´=1
                // for (int pos = 0; pos < n - 1; pos++)
                //smycka pro vypočty xi*y a ui*m
                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;
                }
                //celkový přenos do dalši i-te iterace, pro přiklad davam na pevno
                //a[0], dle me tohle je nej
                carry += (a[N] & LONG_MASK);
                //a[1]
                a[N - 1] = (byte)carry;
                a[N] = (byte)(carry >> BITS);

            }

            // 3. If A >= m then A = A - m
            if (UrciVetsiInt(a, m) == true)
            {
                ArrSubSimple(a, m, m);

            }

            // 4. Return (A). abychom dostali a*b mod m tak je treba jeste nasobit R=b^n tj n delka modula, b je baze, a projet modulem 
            //  System.Array.Copy(a, 1, a, 0, N);
            return a;
        }



        /// <summary>
        /// porovna dve cisla a vrati true pokud prvni je vetsi
        /// </summary>
        /// <param name="a">prvni pole</param>
        /// <param name="b">druhe pole</param>
        /// <returns>true pokud je prvni vetsi</returns>
        public static 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 static 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;
                    }
                }
                //+1 kvuli prenosu u nasobeni
                aReduced = new byte[a.Length - pocetNul + 1];
                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;
        }

        public static byte[] VyrovnaniByteArr(byte[] a, int len)
        {
            int pocetB = a.Length;
            byte[] aVyr = new byte[len];

            for (int i = 0; i < len - pocetB; i++)
            {
                aVyr[i] = 0;
            }
            int j = 0;
            for (int i = len - pocetB; i < len; i++)
            {
                aVyr[i] = a[j];
                j++;
            }


            return aVyr;
        }

        #endregion

        #region Comba

        public string VypoctiSoucinComba(string a, string b, string modulus, int iterace)
        {
            //Inicializace komunikace s kartou
            Inicializace();
            //Inicializace parametru RSA
            byte[] a_byte = String2ArrReverse(a);
            a_length = length;
            Array.Reverse(a_byte);

            byte[] mod_byte = String2ArrReverse(modulus);
            m_length = length;


            byte[] b_byte = String2ArrReverse(b);
            b_length = length;
            Array.Reverse(b_byte);

            byte[] ar_byte = RedukceByteArr(a_byte);
            byte[] br_byte = RedukceByteArr(b_byte);
            int m1 = ar_byte.Length;
            int m2 = br_byte.Length;
            int m = m2;
            if (m1 > m2)
                m = m1;

            //Vypocte soucin na karte
            Array.Reverse(a_byte);
            Array.Reverse(b_byte);

            DateTime startTime = DateTime.Now;

            byte[] res = getService().CombaOpt(a_byte, b_byte, m );

            DateTime stopTime = DateTime.Now;
            TimeSpan duration = stopTime - startTime;
            string strsec = duration.TotalMilliseconds.ToString();
      

            Array.Reverse(mod_byte);
            Array.Reverse(res);

            res = Modulo(res, mod_byte);
            //Array.Reverse(res);

            //Ukonceni spojeni s kartou
            UkonciSpojeni();

            Array.Reverse(a_byte);
            Array.Reverse(b_byte);
            //pro součin
            byte[] res2 = Overeni(a_byte, b_byte, mod_byte);

            //Vrati postupne kryptogra, pouzite parametry RSA a desifrovanou hodnotu. Pro prevod z pole bytu se pouziva fce Arr2Str
            return "Comba a * b:\r\n" + Arr2String(res) + "\r\n cas: " +strsec+" ms"+ "\r\n" + "a * b (overeni):\r\n" + Arr2String(res2) + "\r\n" + "delky parametru: a= " + a_length * 8 + " bits,  b= " + b_length * 8 + " bits,  mod= " + m_length * 8 + " bits \r\n" + "\r\n" + "\r\n";

        }

        //pro ladeni 
        public static 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;
        }


        #endregion

        #region podpurne fce + - /2 prevodyByteStr a overovaci metody

        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 static byte[] String2ArrReverse2(string input)
        {
            byte[] b = new byte[RSAsize / 8];
            
            BigInteger BigNum = new BigInteger(input, 10);
            byte[] temp = BigNum.getBytes();
            length = temp.Length;
            b = new byte[length];

            Array.Reverse(temp);

            for (int j = 0; j < length; j++)
            {
                b[j] = temp[j];
            }
            //for (int i = length; i < RSAsize / 8; i++)
            //{
            //    b[i] = 0;
            //}

            return b;
        }
        //public static byte[] TranslateToBytes()

        public static byte[] String2ArrReverse(string input)
        {
            byte[] b = new byte[RSAsize / 8];
            //b = new byte[272];
            BigInteger BigNum = new BigInteger(input, 10);
            byte[] temp = BigNum.getBytes();
            length = temp.Length;

            Array.Reverse(temp);

            for (int j = 0; j < length; j++)
            {
                b[j] = temp[j];
            }
            for (int i = length; i < RSAsize / 8; i++)
            {
                b[i] = 0;
            }

            return b;
        }
        public static byte[] String2ArrBig(string input)
        {
            BigInteger BigNum = new BigInteger(input, 10);
            return BigNum.getBytes();
        }
        public static byte[] Modulo(byte[] a, byte[] modulus)
        {

            BigInteger a_big = new BigInteger(a);
            BigInteger m_big = new BigInteger(modulus);
            a_big = a_big % m_big;
            return a_big.getBytes();
        }
        public static byte[] Overeni(byte[] a, byte[] b, byte[] modulus)
        {

            BigInteger a_big = new BigInteger(a);
            BigInteger b_big = new BigInteger(b);
            BigInteger m_big = new BigInteger(modulus);
            return ((a_big * b_big) % m_big).getBytes();

        }
        public static byte[] Overeni2(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 byte[] Overeni3(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 bool Overeni3(byte[] g1, byte[] g2, byte[] c2, byte[] c22,byte[] z2, byte[] z22, byte[] e, byte[] n)
        {

            return false;
        }

        #endregion

        #region Debugovaci metody
        public string GetRandom()
        {
            //Inicializace komunikace s kartou
            Inicializace();


            //Ziskani odezvy
            byte[] rnd = new byte[128];
            string tmp = "Random: " + Arr2String(getService().RandomGen(rnd,64,64));
            //Ukonceni spojeni s kartou
            UkonciSpojeni();
            return tmp;
        }

        #region RSA test tunelu jen pro optimalizaci, nema jinak zde ve tříde uplatneni

        //private static RSACryptoServiceProvider RSAd = new RSACryptoServiceProvider(RSAsize);
        //public static RSAParameters RSAparam = new RSAParameters();

        ////Import parametrů RSA
        //public static void RSA_import(byte[] e, byte[] modulus)
        //{
        //    RSAparam = RSAd.ExportParameters(true);
        //    RSAparam.Exponent = e;
        //    RSAparam.Modulus = modulus;
        //    RSAd.ImportParameters(RSAparam);
        //}

        //public static byte[] Power(byte[] baze, byte[] exponent, byte[] modulus)
        //{
        //   // RSAparam = RSAd.ExportParameters(true);
        //    RSAparam.Exponent = exponent;
        //    RSAparam.Modulus = modulus;
        //    RSAd.ImportParameters(RSAparam);

        //    return RSAd.EncryptValue(baze);
        //}

        ////Inverze RSA, nepouzivane
        //public static byte[] RSA_Decrypt(byte[] input)
        //{
        //    byte[] foo = RSAd.DecryptValue(input);
        //    return foo;
        //}

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

        ////Nasobeni
        //public byte[] Multiply(byte[] a_byte, byte[] b_byte, byte[] mod_byte, int iterace)
        //{
        //    Inicializace();
        //    byte[] aMULTb = new byte[RSAsize / 8];
        //    byte[] two = new byte[RSAsize / 8];
        //    two[RSAsize / 8 - 1] = 2;

        //    for (int i = 0; i < iterace; i++)
        //    {
        //        aMULTb = getService().ArrSubSimple(getService().ArrSubSimple(getService().Power(ArrAddSimple(a_byte, b_byte, mod_byte), two, mod_byte), getService().Power(a_byte, two, mod_byte), mod_byte), getService().Power(b_byte, two, mod_byte), mod_byte);
        //    }
        //    //UkonciSpojeni();
        //    //aMULTb = ArrSubSimple(aMULTb,mod_byte,mod_byte);


        //    //return ArrHalfSimple(aMULTb, mod_byte);
        //    return getService().Multiply(a_byte,b_byte,mod_byte,1);
        //}

        #endregion



        #endregion

        #region Kandidati na smazani


        //public static 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 static int[] String2ArrInt(string input)
        //{
        //    int[] b = new int[RSAsize / 8];

        //    for (int j = 0; j < 1; j++)
        //    {
        //        b[j] = Convert.ToInt32(input);

        //    }
        //    return b;
        //}




        ////jen muj test
        //public string VypoctiSoucet(string a, string b, string modulus, int iterace)
        //{
        //    //Inicializace komunikace s kartou
        //    //     Inicializace();

        //    //Inicializace parametru RSA
        //    byte[] a_byte = String2ArrReverse(a);
        //    a_length = length;
        //    Array.Reverse(a_byte);
        //    byte[] mod_byte = String2ArrReverse(modulus);
        //    m_length = length;
        //    Array.Reverse(mod_byte);
        //    byte[] b_byte = String2ArrReverse(b);
        //    b_length = length;
        //    Array.Reverse(b_byte);

        //    // a_byte = RedukceByteArr(a_byte);
        //    // b_byte = RedukceByteArr(b_byte);

        //    // byte[] a_vyr = VyrovnaniByteArr(a_byte, 128);
        //    //Vypocte soucet na karte
        //    byte[] res = ArrAddEqual(a_byte, b_byte);
        //    //  byte[] res = getService().ArrAddEqual(a_byte, b_byte);
        //    // byte[] res = ArrSubSimple(a_byte, b_byte,mod_byte);
        //    //   byte[] res = ArrHalfSimple(a_byte, mod_byte);

        //    res = Modulo(res, mod_byte);

        //    //Ziska parametry z karty
        //    //      RSAParameters RSAused = new RSAParameters();
        //    //      RSAused = getService().RSA_export();

        //    //Ukonceni spojeni s kartou
        //    //       UkonciSpojeni();

        //    // Vypocet kontrolni hodnoty pomoci bigint
        //    //pro součet
        //    byte[] res2 = Overeni2(a_byte, b_byte);

        //    //Vrati postupne kryptogra, pouzite parametry RSA a desifrovanou hodnotu. Pro prevod z pole bytu se pouziva fce Arr2Str
        //    return "a + b:\r\n" + Arr2String(res) + "\r\n" + "\r\n" + "a + b (overeni):\r\n" + Arr2String(res2) + "\r\n" + "\r\n" + "delky parametru: a= " + a_length * 8 + " bits,  b= " + b_length * 8 + " bits,  mod= " + m_length * 8 + " bits \r\n" + "\r\n";

        //}

        //public string VypoctiSoucin(string a, string b, string modulus, int iterace)
        //{
        //    //Inicializace komunikace s kartou
        //    Inicializace();

        //    //Inicializace parametru RSA
        //    byte[] a_byte = String2ArrReverse(a);
        //    a_length = length;
        //    Array.Reverse(a_byte);
        //    byte[] mod_byte = String2ArrReverse(modulus);
        //    m_length = length;
        //    Array.Reverse(mod_byte);
        //    byte[] b_byte = String2ArrReverse(b);
        //    b_length = length;
        //    Array.Reverse(b_byte);

        //    a_byte = RedukceByteArr(a_byte);
        //    b_byte = RedukceByteArr(b_byte);

        //    //Vypocte soucin na karte
        //    // byte[] res = getService().ArrMultiObecne(a_byte, b_byte);
        //    //   byte[] res = getService().ArrMultiObecneOpt(a_byte, b_byte);
        //    byte[] res = getService().ArrMultiObecneOpt2(a_byte, b_byte);
        //    //Vypocte soucin test
        //    // byte[] res = ArrMultiObecne(a_byte, b_byte);
        //    // byte[] res = ArrMultiSimple(a_byte, b_byte);

        //    res = Modulo(res, mod_byte);

        //    //Ziska parametry z karty
        //    //      RSAParameters RSAused = new RSAParameters();
        //    //      RSAused = getService().RSA_export();

        //    //Ukonceni spojeni s kartou
        //    UkonciSpojeni();

        //    // Vypocet kontrolni hodnoty pomoci bigint
        //    //pro součet

        //    //pro součin
        //    byte[] res2 = Overeni(a_byte, b_byte, mod_byte);

        //    //Vrati postupne kryptogra, pouzite parametry RSA a desifrovanou hodnotu. Pro prevod z pole bytu se pouziva fce Arr2Str
        //    return "a * b:\r\n" + Arr2String(res) + "\r\n" + "\r\n" + "a * b (overeni):\r\n" + Arr2String(res2) + "\r\n" + "\r\n" + "delky parametru: a= " + a_length * 8 + " bits,  b= " + b_length * 8 + " bits,  mod= " + m_length * 8 + " bits \r\n" + "\r\n";

        //}





        #endregion
    }



}

