コード例 #1
0
        private static BigInteger[] LucasSequenceHelper(BigInteger P, BigInteger Q, BigInteger k, BigInteger n, BigInteger constant, int s)
        {
            BigInteger[] result = new BigInteger[3];
            if ((k & 0x01) == 0)
            {
                throw (new ArgumentException("Значение аргумента k должно быть четным"));
            }
            int  numbits = Length(k);
            uint mask    = (uint)0x1 << ((numbits & 0x1F) - 1);
            // v = v0, v1 = v1, u1 = u1, Q_k = Q^0
            BigInteger v = 2 % n, Q_k = 1 % n, v1 = P % n, u1 = Q_k;
            bool       flag = true;

            uint[] k_data = SupportEDS.BigIntegerToUintArray(k);
            for (int i = k_data.Length - 2; i >= 0; i--)
            {
                while (mask != 0)
                {
                    if (i == 0 && mask == 0x00000001)
                    {
                        break;
                    }
                    if ((k_data[i] & mask) != 0)
                    {
                        u1 = (u1 * v1) % n;
                        v  = ((v * v1) - (P * Q_k)) % n;
                        v1 = BarrettReduction(v1 * v1, n, constant);
                        v1 = (v1 - ((Q_k * Q) << 1)) % n;
                        if (flag)
                        {
                            flag = false;
                        }
                        else
                        {
                            Q_k = BarrettReduction(Q_k * Q_k, n, constant);
                        }
                        Q_k = (Q_k * Q) % n;
                    }
                    else
                    {
                        u1 = ((u1 * v) - Q_k) % n;
                        v1 = ((v * v1) - (P * Q_k)) % n;
                        v  = BarrettReduction(v * v, n, constant);
                        v  = (v - (Q_k << 1)) % n;
                        if (flag)
                        {
                            Q_k  = Q % n;
                            flag = false;
                        }
                        else
                        {
                            Q_k = BarrettReduction(Q_k * Q_k, n, constant);
                        }
                    }
                    mask >>= 1;
                }
                mask = 0x80000000;
            }
            u1 = ((u1 * v) - Q_k) % n;
            v  = ((v * v1) - (P * Q_k)) % n;
            if (flag)
            {
                flag = false;
            }
            else
            {
                Q_k = BarrettReduction(Q_k * Q_k, n, constant);
            }
            Q_k = (Q_k * Q) % n;
            for (int i = 0; i < s; i++)
            {
                u1 = (u1 * v) % n;
                v  = ((v * v) - (Q_k << 1)) % n;
                if (flag)
                {
                    Q_k  = Q % n;
                    flag = false;
                }
                else
                {
                    Q_k = BarrettReduction(Q_k * Q_k, n, constant);
                }
            }
            result[0] = u1;
            result[1] = v;
            result[2] = Q_k;
            return(result);
        }
コード例 #2
0
        private static bool LucasStrongTestHelper(BigInteger thisVal)
        {
            long D = 5, sign = -1, dCount = 0;
            bool done = false;

            while (!done)
            {
                int Jresult = Jacobi(D, thisVal);
                if (Jresult == -1)
                {
                    done = true;    // J(D, this) = 1
                }
                else
                {
                    if (Jresult == 0 && Math.Abs(D) < thisVal) // найден делитель
                    {
                        return(false);
                    }
                    if (dCount == 20)
                    {
                        BigInteger root = Sqrt(thisVal);
                        if (root * root == thisVal)
                        {
                            return(false);
                        }
                    }
                    D    = (Math.Abs(D) + 2) * sign;
                    sign = -sign;
                }
                dCount++;
            }
            long       Q      = (1 - D) >> 2;
            BigInteger p_add1 = thisVal + 1;

            uint[] data = SupportEDS.BigIntegerToUintArray(p_add1);
            int    s    = 0;

            for (int i = 0; i < data.Length - 1; i++)
            {
                uint mask = 0x01;
                for (int j = 0; j < 32; j++)
                {
                    if ((data[i] & mask) != 0)
                    {
                        i = data.Length;
                        break;
                    }
                    mask <<= 1;
                    s++;
                }
            }
            BigInteger t = p_add1 >> s;
            // вычисление константы для Редукции Баррета = b^(2k) / m
            BigInteger constant = new BigInteger();

            uint[] thisVal_data = SupportEDS.BigIntegerToUintArray(thisVal);
            int    nLen         = (thisVal_data.Length - 1) << 1;

            uint[] const_data = new uint[nLen + 2];
            for (int i = 0; i < const_data.Length; i++)
            {
                if (i == nLen)
                {
                    const_data[i] = 0x00000001;
                }
                else
                {
                    const_data[i] = 0x0;
                }
            }
            constant = SupportEDS.BigIntegerFromUintArray(const_data);
            constant = constant / thisVal;
            BigInteger[] lucas   = LucasSequenceHelper(1, Q, t, thisVal, constant, 0);
            bool         isPrime = false;

            if ((lucas[0] == 0) || lucas[1] == 0)
            {
                // u(t) = 0 либо V(t) = 0
                isPrime = true;
            }
            for (int i = 1; i < s; i++)
            {
                if (!isPrime)
                {
                    lucas[1] = BarrettReduction(lucas[1] * lucas[1], thisVal, constant);
                    lucas[1] = (lucas[1] - (lucas[2] << 1)) % thisVal;
                    //lucas[1] = ((lucas[1] * lucas[1]) - (lucas[2] << 1)) % thisVal;
                    if ((lucas[1] == 0))
                    {
                        isPrime = true;
                    }
                }
                lucas[2] = BarrettReduction(lucas[2] * lucas[2], thisVal, constant); //Q^k
            }
            if (isPrime)                                                             // дополнительная проверка на составные числа
            {
                BigInteger g = BigInteger.GreatestCommonDivisor(thisVal, Q);
                if (g == 1)
                {
                    uint[] lucas_data = SupportEDS.BigIntegerToUintArray(lucas[2]);
                    if (lucas[2] < 0)
                    {
                        lucas[2] += thisVal;
                    }
                    BigInteger temp = (Q * Jacobi(Q, thisVal)) % thisVal;
                    if (temp < 0)
                    {
                        temp += thisVal;
                    }
                    if (lucas[2] != temp)
                    {
                        isPrime = false;
                    }
                }
            }
            return(isPrime);
        }
コード例 #3
0
        public static BigInteger BarrettReduction(BigInteger x, BigInteger n, BigInteger constant)
        {
            uint[] n_data    = SupportEDS.BigIntegerToUintArray(n);
            int    k         = Length(n_data.Length - 1),
                   kPlusOne  = k + 1,
                   kMinusOne = k - 1;
            BigInteger q1    = new BigInteger();

            // q1 = x / b^(k-1)
            uint[] x_data  = SupportEDS.BigIntegerToUintArray(x);
            int    new_lng = x_data.Length - kMinusOne;

            uint[] q1_data;
            if (new_lng > 1)
            {
                q1_data = new uint[new_lng];
            }
            else
            {
                q1_data = new uint[2];
            }
            q1_data[q1_data.Length - 1] = 0;
            for (int i = kMinusOne, j = 0; i < x_data.Length - 1; i++, j++)
            {
                q1_data[j] = x_data[i];
            }
            q1 = SupportEDS.BigIntegerFromUintArray(q1_data);
            BigInteger q2 = q1 * constant;

            // q3 = q2 / b^(k+1)
            uint[] q2_data  = SupportEDS.BigIntegerToUintArray(q2);
            int    new_lng2 = q2_data.Length - kPlusOne;

            uint[] q3_data;
            if (new_lng2 > 1)
            {
                q3_data = new uint[new_lng2];
            }
            else
            {
                q3_data = new uint[2];
            }
            q3_data[q3_data.Length - 1] = 0;
            for (int i = kPlusOne, j = 0; i < q2_data.Length - 1; i++, j++)
            {
                q3_data[j] = q2_data[i];
            }
            // r1 = x mod b^(k+1)
            // i.e. keep the lowest (k+1) words
            BigInteger r1           = new BigInteger();
            int        lengthToCopy = ((x_data.Length - 1) > kPlusOne) ? kPlusOne : (x_data.Length - 1);

            uint[] r1_data = new uint[lengthToCopy + 1];
            for (int i = 0; i < lengthToCopy; i++)
            {
                r1_data[i] = x_data[i];
            }
            r1_data[r1_data.Length - 1] = 0;
            // r2 = (q3 * n) mod b^(k+1)
            // partial multiplication of q3 and n
            BigInteger r2 = new BigInteger();

            uint[] r2_data = new uint[kPlusOne + 1];
            for (int i = 0; i < q3_data.Length - 1; i++)
            {
                if (q3_data[i] == 0)
                {
                    continue;
                }
                ulong mcarry = 0;
                int   t      = i;
                for (int j = 0; j < n_data.Length - 1 && t < kPlusOne; j++, t++)
                {
                    // t = i + j
                    ulong val = ((ulong)q3_data[i] * (ulong)n_data[j]) +
                                (ulong)r2_data[t] + mcarry;
                    r2_data[t] = (uint)(val & 0xFFFFFFFF);
                    mcarry     = (val >> 32);
                }
                if (t < kPlusOne)
                {
                    r2_data[t] = (uint)mcarry;
                }
            }
            r2_data[r2_data.Length - 1] = 0;
            r1  = SupportEDS.BigIntegerFromUintArray(r1_data);
            r2  = SupportEDS.BigIntegerFromUintArray(r2_data);
            r1 -= r2;
            if (r1 < 0)
            {
                r1 = -r1;
            }
            while (r1 >= n)
            {
                r1 -= n;
            }
            return(r1);
        }
コード例 #4
0
        public static bool isProbablePrime(BigInteger bi)
        {
            BigInteger thisVal;

            if (bi < 0)
            {
                thisVal = -bi;
            }
            else
            {
                thisVal = bi;
            }
            if (bi < UInt32.MaxValue)
            {
                // проверка малых значений
                if (thisVal == 0 || thisVal == 1)
                {
                    return(false);
                }
                else if (thisVal == 2 || thisVal == 3)
                {
                    return(true);
                }
            }
            // четные числа
            if ((thisVal & 0x1) == 0)
            {
                return(false);
            }
            // тест на делимость на простые < 2000
            long[] primes = GetPrimes(2000);
            for (int p = 0; p < primes.Length; p++)
            {
                BigInteger divisor = primes[p];
                if (divisor >= thisVal)
                {
                    break;
                }
                BigInteger resultNum = thisVal % divisor;
                if ((int)resultNum == 0)
                {
                    return(false);
                }
            }
            // Выполнения теста Рабина-Миллера р.2
            BigInteger p_sub1 = thisVal - 1;
            int        s      = 0;

            uint[] data = SupportEDS.BigIntegerToUintArray(p_sub1);
            for (int i = 0; i < data.Length - 1; i++)
            {
                uint mask = 0x01;
                for (int j = 0; j < 32; j++)
                {
                    if ((data[i] & mask) != 0)
                    {
                        i = data.Length;
                        break;
                    }
                    mask <<= 1;
                    s++;
                }
            }
            BigInteger t    = p_sub1 >> s;
            int        bits = Length(thisVal);
            // b = 2^t mod p
            BigInteger b      = BigInteger.ModPow(2, t, thisVal);
            bool       result = false;

            if (b == 1)         // a^t mod p = 1
            {
                result = true;
            }
            for (int j = 0; result == false && j < s; j++)
            {
                if (b == p_sub1)         // a^((2^j)*t) mod p = p-1 для любого 0 <= j <= s-1
                {
                    result = true;
                    break;
                }

                b = (b * b) % thisVal;
            }
            // если число является сложным псевдопростым по основанию 2, переходим к тяжелому тесту Лукаса
            if (result)
            {
                result = LucasStrongTestHelper(thisVal);
            }

            return(result);
        }
コード例 #5
0
        public static int Jacobi(BigInteger a, BigInteger b)
        {
            if ((b & 0x1) == 0)
            {
                throw (new ArgumentException("Число должно быть нечетным."));
            }

            if (a >= b)
            {
                a %= b;
            }
            if (a == 0)
            {
                return(0);
            }
            if (a == 1)
            {
                return(1);
            }
            uint[] a_data = SupportEDS.BigIntegerToUintArray(a);
            uint[] b_data = SupportEDS.BigIntegerToUintArray(b);
            if (a < 0)
            {
                int kr = 0;
                if (b_data.Length == 2)
                {
                    kr = 1;
                }
                if (((b_data[0] - kr) & 0x2) == 0)
                {
                    return(Jacobi(-a, b));
                }
                else
                {
                    return(-Jacobi(-a, b));
                }
            }
            int e = 0;

            for (int index = 0; index < a_data.Length - 1; index++)
            {
                uint mask = 0x01;
                for (int i = 0; i < 32; i++)
                {
                    if ((a_data[index] & mask) != 0)
                    {
                        index = a_data.Length;
                        break;
                    }
                    mask <<= 1;
                    e++;
                }
            }
            BigInteger a1 = a >> e;

            uint[] a1_data = SupportEDS.BigIntegerToUintArray(a1);
            int    s       = 1;

            if ((e & 0x1) != 0 && ((b_data[0] & 0x7) == 3 || (b_data[0] & 0x7) == 5))
            {
                s = -1;
            }
            if ((b_data[0] & 0x3) == 3 && (a1_data[0] & 0x3) == 3)
            {
                s = -s;
            }
            if (a1 == 1)
            {
                return(s);
            }
            else
            {
                return(s * Jacobi(b % a1, a1));
            }
        }