using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using Emil.GMP;

namespace Verifier
{
    class Verify
    {
        //pro ověřování podpisu (inicializace v rsa_import)
        static private RSAParameters RSAinfo_import;
        static private UnicodeEncoding Unicode;

        static public bool init_RSA_OK = false;

        static private RSACryptoServiceProvider RSA_import;

        //----------------------------------------------------------------------------
        // Metoda sloužící pro generování náhodného čísla
        //----------------------------------------------------------------------------
        public int[] generujE(string q)
        {
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            byte[] cislo = new byte[32];

            rng.GetBytes(cislo);
            int result = BitConverter.ToInt32(cislo, 0);

            //Hodnota o kterou se bude celková délka generovaného čísla lišit od
            //   původní hodnoty 'q'
            int decr = new Random(result).Next(0, q.Length / 3);

            string genEString = "";

            while (genEString.Length < q.Length)
            {
                genEString += (new Random(result).Next()).ToString();
                rng.GetBytes(cislo);
                result = BitConverter.ToInt32(cislo, 0);
            }

            //Upravení velikosti náhodného čísla na požadovanou velikost
            if (genEString.Length >= q.Length)
            {
                int pom = genEString.Length - (genEString.Length - q.Length + 1) - decr;
                genEString = genEString.Substring(0, pom);
            }

            //Převedení generované hodnoty na int[]
            int[] genEInt = new int[genEString.Length];
            for (int i = 0; i <= genEString.Length - 1; i++)
            {
                genEInt[i] = genEString[i] - '0';
            }

            return genEInt;
        }

        //----------------------------------------------------------------------------
        // Metoda sloužící pro ověření přijatého tokenu
        //---------------------------------------------------------------------------- 
        public bool overeni(string z, string g, string a, string c, string e, string p)
        {
            bool overeno = false;

            BigInt zB = new BigInt(z);
            BigInt gB = new BigInt(g);
            BigInt aB = new BigInt(a);
            BigInt cB = new BigInt(c);
            BigInt eB = new BigInt(e);
            BigInt pB = new BigInt(p);

            // left = (g^z) mod p
            BigInt left = gB.PowerMod(zB, pB);
            // right = (a*c^e) mod p
            BigInt pomB = cB.PowerMod(eB, pB);                      // c^e mod p
            BigInt right = ((aB.Mod(pB)).Multiply(pomB)).Mod(pB);   // ((a mod p)*pomB) mod p

            if (left == right)
            {
                overeno = true;
            }

            return overeno;
        }

        //----------------------------------------------------------------------------
        // Metody sloužící pro ověření podpisu na přijatý token
        //---------------------------------------------------------------------------- 
        /// <summary>
        /// Načte cizí veřejný klíč RSA a inicializuje ho pro potřeby RSA
        /// </summary>
        /// <param name="pubKey">Cizí veřejný klíč RSA ve xml formatu</param>
        public void RSAimportVK(string pubKey)
        {
            //Vytvoření unicode enkodéru
            Unicode = new UnicodeEncoding();

            //Vytvoření instance RSA
            RSACryptoServiceProvider inst = new RSACryptoServiceProvider();

            //Import RSA parametrů
            //keys_import = param;
            inst.FromXmlString(pubKey);

            //Export RSA parametrů do RSAinfo
            RSAinfo_import = inst.ExportParameters(false);

            RSA_import = inst;
            init_RSA_OK = true;
        }
        
        /// <summary>
        /// Oveření RSA podpisu
        /// </summary>
        /// <param name="m">zpráva ve stringu co ma být oveřena</param>
        /// <param name="sig">podepsaná zpráva ve stringu</param>
        /// <returns>vrací true při úspěšném ověření</returns>
        public bool RSAoveritPodpis(string m, string sig)
        {
            MD5CryptoServiceProvider h = new MD5CryptoServiceProvider();

            bool result = false;

            //Import parametrů RSA
            RSA_import.ImportParameters(RSAinfo_import);

            //Ověření podepsané zprávy
            result = RSA_import.VerifyData(Unicode.GetBytes(m), h, Convert.FromBase64String(sig));

            return result;
        }
    }
}
