/// <summary>
        /// Determines whether BigInteger is prime number with probability that can be greater than requested probability
        /// </summary>
        /// <param name="number">The BigInteger to check</param>
        /// <param name="probability">Probability of error</param>
        /// <returns></returns>
        public bool IsPrime(BigInteger number, BigNumDec probability)
        {
            if (probability.Equals(0) || probability.Equals(1))
                throw new ArgumentException("Probability must be in range (0; 1)");

            int iterations = 1;
            BigNum baseNum = 0.25;
            while (true)
            {
                if (baseNum <= probability)
                    break;

                baseNum *= 0.25;
                iterations++;
            }

            while (iterations > 0)
            {
                if (!IsPrime(number))
                    return false;

                --iterations;
            }

            return true;
        }
Example #2
0
        /// <summary>Calculates Pi, but is inaccuate beyond 4 digits for some reason. Not recommended.</summary>
        public static BigNum CalculatePi(Int32 iterations)
        {
            BigNum retVal = new BigNumDec();

            for (int i = 0; i < iterations; i++)
            {
                // calculate inner polynomial
                // numerator
                BigNum innerPolynomialNumerator = new BigNumDec(
                    120 * new BigNumDec(i).Power(2) +
                    151 * new BigNumDec(i) +
                    47
                    );

                BigNum innerPolynomrialDenominator = new BigNumDec(
                    512 * new BigNumDec(i).Power(4) +
                    1024 * new BigNumDec(i).Power(3) +
                    712 * new BigNumDec(i).Power(2) +
                    192 * new BigNumDec(i) +
                    15
                    );

                BigNum innerPolynomial = innerPolynomialNumerator / innerPolynomrialDenominator;

                BigNum outerReciprocal = new BigNumDec(1) / new BigNumDec(16).Power(i);

                BigNum result = outerReciprocal * innerPolynomial;

                retVal += result;
            }

            return(retVal);
        }
Example #3
0
        /// <summary>Calculates Pi, but is inaccuate beyond 4 digits for some reason. Not recommended.</summary>
        public static BigNum CalculatePi(Int32 iterations)
        {
            BigNum retVal = new BigNumDec();

            for(int i=0;i<iterations;i++) {

                // calculate inner polynomial
                // numerator
                BigNum innerPolynomialNumerator = new BigNumDec(
                    120 * new BigNumDec(i).Power(2) +
                    151 * new BigNumDec(i) +
                     47
                );

                BigNum innerPolynomrialDenominator = new BigNumDec(
                     512 * new BigNumDec(i).Power(4) +
                    1024 * new BigNumDec(i).Power(3) +
                     712 * new BigNumDec(i).Power(2) +
                     192 * new BigNumDec(i) +
                      15
                );

                BigNum innerPolynomial = innerPolynomialNumerator / innerPolynomrialDenominator;

                BigNum outerReciprocal = new BigNumDec( 1 ) / new BigNumDec( 16 ).Power(i);

                BigNum result = outerReciprocal * innerPolynomial;

                retVal += result;

            }

            return retVal;
        }
        private void GenerateButton_Click_1(object sender, RoutedEventArgs e)
        {
            ShowComputing();
            BigNumDec prob;

            try
            {
                prob = new BigNumDec(probabilityTextBox.Text.Replace(',', '.'));
            }
            catch (Exception ex)
            {
                MessageBox.Show("Probability is entered incorrectly", Title, MessageBoxButton.OK, MessageBoxImage.Error);
                CloseComputing();
                return;
            }

            int n;
            int b;
            try
            {
                n = Int32.Parse(nTextBox.Text, new CultureInfo("ru-RU"));
                b = Int32.Parse(bTextBox.Text, new CultureInfo("ru-RU"));
            }
            catch (Exception ex)
            {
                MessageBox.Show("N or B is entered incorrectly", Title, MessageBoxButton.OK, MessageBoxImage.Error);
                CloseComputing();
                return;
            }

            Generator gen = new Generator();
            try
            {
                var primeNumbers = gen.Next(n, b, prob);
                pTextBox.Text = primeNumbers.Item1.ToString();
                qTextBox.Text = primeNumbers.Item2.ToString();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error occurred: " + ex.Message, Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }

            CloseComputing();
        }
        private int GetInterationsAmount(BigNumDec probability)
        {
            if (probability.Equals(0) || probability.Equals(1))
                throw new ArgumentException("Probability must be in range (0; 1)");

            int iterations = 1;
            BigNum baseNum = 0.25;
            while (true)
            {
                if (baseNum <= probability)
                    break;

                baseNum *= 0.25;
                iterations++;
            }

            return iterations;
        }
        /// <summary>
        /// Generates 2 prime numbers 
        /// </summary>
        /// <param name="n">Number to generate L where L - 1 = B * 160 + N. This value must be in range between 0 and 160</param>
        /// <param name="b">Number to generate L where L - 1 = B * 160 + N. This value must be in range between 0 and 160</param>
        /// <param name="probability"></param>
        /// <returns>Returns Tuple with 2 prime numbers where Item1 = p and Item2 = q</returns>
        public Tuple<BigInteger, BigInteger> Next(int n, int b, BigNumDec probability)
        {
            if (n > 160 || b > 160 || n < 0 || b < 0)
                throw new ArgumentException("n and b must be in range between 0 and 160");

            int L = n * 160 + b + 1;
            BigInteger twoInLminusOne = BigInteger.Pow(2, L - 1);
            int iterationsAmount = GetInterationsAmount(probability);

            while (true)
            {
                // Шаг 1. Выбираем произвольную последовательность из как минимум 160 бит и называем ее "seed". Пусть "SequenceLength" – длина "seed" в битах
                byte[] seedArray = new byte[SequenceLength >> 3];
                _provider.GetBytes(seedArray);
                byte[] positiveSeedArray = seedArray.Reverse().Concat(new byte[] { 0 }).ToArray(); // set "positive" byte
                Seed = new BigInteger(positiveSeedArray);

                // Шаг 2. Вычисляем U = SHA[SEED] XOR SHA[(SEED+1) mod 2^SequenceLength ]
                byte[] U = _sha.ComputeHash(seedArray).Xor(_sha.ComputeHash( ((Seed + 1) % BigInteger.Pow(2, SequenceLength)).ToByteArray() ) );

                // Шаг 3. Создаем q из U устанавливая младший и старший бит равным 1:
                // q = U OR 2^159 OR 1
                // Заметим, что 2^159 < q < 2^160
                byte[] qArray = (byte[]) U.Clone();
                qArray[0] |= 128;
                qArray[qArray.Length - 1] |= 1;
                byte[] positiveQArray = qArray.Reverse().Concat(new byte[] {0}).ToArray();
                BigInteger q = new BigInteger(positiveQArray);

                // Шаг 4. Проверяем q на простоту
                // IsPrime()

                // Шаг 5. Если q непростое, переходим на шаг 1
                if (!IsPrime(q, iterationsAmount))
                {
                    continue;
                }

                // Шаг 6. Пусть counter = 0 и offset = 2
                Counter = 0;
                int offset = 2;

                while (true)
                {
                    // Шаг 7. Для k = 0, ... , n вычисляем Vk = SHA[(SEED + offset + k) mod 2^g]
                    // GetVk()

                    // Шаг 8. Вычисляем W = V0 + V1 * 2^160 + ... + Vn-1 * 2^((n-1)*160) + (Vn mod 2^b) * 2^(n*160)
                    // X = W + 2^(L-1)
                    // Заметим, что 0 < = W < 2^(L-1)  и 2^(L-1) < = X < 2^L.
                    BigInteger W = new BigInteger(0);
                    for (int i = 0; i < n; i++)
                    {
                        BigInteger Vk = GetVk(Seed, offset, i);
                        Vk *= Twoin160 * BigInteger.Pow(2, i);
                        W += Vk;
                    }
                    W += (GetVk(Seed, offset, n) % BigInteger.Pow(2, b)) * Twoin160 * BigInteger.Pow(2, n);
                    BigInteger X = W + BigInteger.Pow(2, L - 1);

                    // Шаг 9. Пусть c = X mod 2q и p = X - (c - 1). Заметим, что p равно 1 mod 2q
                    BigInteger c = X % (2 * q);
                    BigInteger p = X - c + 1;

                    // Шаг 10. Если p < 2^(L-1), тогда переходим на шаг 13
                    if (p < twoInLminusOne)
                    {
                        // Шаг 13. Counter = Counter + 1 и offset = offset + n + 1
                        Counter++;
                        offset += n + 1;

                        // Шаг 14. Если counter >= 2^12 = 4096 переходим на шаг 1, иначе переходим на шаг 7
                        if (Counter > 4096)
                        {
                            break;
                        }
                        else
                        {
                            continue;
                        }
                    }

                    // Шаг 11. Проверяем p на простоту
                    if (IsPrime(p, iterationsAmount))
                    {
                        // Шаг 12. Если p прошло тест переходим на шаг 15
                        // Шаг 15. Сохраняем SEED и Counter для  того, чтобы подтвердить правильную генерацию p и q
                        return new Tuple<BigInteger, BigInteger>(p, q);
                    }
                    else
                    {
                        // Шаг 13. Counter = Counter + 1 и offset = offset + n + 1
                        Counter++;
                        offset += n + 1;

                        // Шаг 14. Если counter >= 2^12 = 4096 переходим на шаг 1, иначе переходим на шаг 7
                        if (Counter > 4096)
                        {
                            break;
                        }
                        else
                        {
                            continue;
                        }
                    }
                }
            }
        }