/// <summary>
        /// Generates a key pair using a portable BES approach.
        /// </summary>
        /// <param name="keyGen"></param>
        /// <param name="keySize"></param>
        /// <returns></returns>
        public AsymmetricCipherKeyPair GenerateKeyPair(IBasylKeyGenerator keyGen, int keySize)
        {
            gSize = keySize;
            gen   = keyGen;

            Thread thread  = new Thread(new ThreadStart(GenerateP)),
                   thread2 = new Thread(new ThreadStart(GenerateQ));

            thread.Start();
            thread2.Start();


            thread.Join();
            thread2.Join();

            var n   = p * q;
            var e   = 65537;
            var phi = (p - 1) * (q - 1);


            var d = (new Org.BouncyCastle.Math.BigInteger(e.ToString())).ModInverse(phi.Convert());

            var dP   = d.Remainder((p - 1).Convert());
            var dQ   = d.Remainder((q - 1).Convert());
            var qInv = q.Convert().ModInverse(p.Convert());



            return(new AsymmetricCipherKeyPair(
                       new RsaKeyParameters(false, n.Convert(), new Org.BouncyCastle.Math.BigInteger(e.ToString())),
                       new RsaPrivateCrtKeyParameters(n.Convert(), new Org.BouncyCastle.Math.BigInteger(e.ToString()), d, p.Convert(), q.Convert(), dP, dQ, qInv)));
        }
        /// <summary>
        /// Generates a random large prime near the given bit size.
        /// </summary>
        /// <param name="generator"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        private static BigInteger GetRandomLargePrime(IBasylKeyGenerator generator, int size)
        {
            //fills an array with random bytes. This is used for the prime search.
            byte[] vals = new byte[(int)Math.Ceiling(size / 8.0f)];

            lock (generator)
            {
                for (int i = 0; i < 20; i++)
                {
                    generator.FillBytes(vals);
                }

                for (int k = 0; k < 2; k++)
                {
                    for (int i = 0; i < vals.Length; i++)
                    {
                        for (int n = 0; n < 3; n++)
                        {
                            generator.GetRandomByte();
                        }
                        generator.EncryptByte(ref vals[i]);
                    }
                }
            }

            //searches for the prime number, decreases until it finds one that tests to be prime.
            BigInteger gco = new BigInteger(vals);

            if (gco < 0)
            {
                gco *= -1;
            }

            if (gco.IsEven)
            {
                gco -= 1;
            }

            var bouncyCastleBig = gco.Convert();
            var amt             = new BigInteger(2).Convert();

            while (!bouncyCastleBig.IsProbablePrime(1))
            {
                bouncyCastleBig = bouncyCastleBig.Subtract(amt);
                gco            -= 2;
            }
            //Bouncy castles isProbablePrime method is severely optimized compared to a naive approach.

            return(gco);
        }