Пример #1
0
        private void GenerateKeyPair()
        {
            // p and q values should have a capacity of half the strength in bits
            int bitlength = ( ( KeySize + 1 ) >> 1 );
            //            int qbitlength = (KeySize - pbitlength);
            const uint uint_e = 65537;
            e = uint_e; // fixed

            // generate p, prime and (p-1) relatively prime to e
            for ( ; ; )
            {
                p = BigInteger.GeneratePseudoPrime(bitlength);
                if ( p % uint_e != 1 )
                    break;
            }
            // generate a modulus of the required capacity
            for ( ; ; )
            {
                // generate q, prime and (q-1) relatively prime to e,
                // and not equal to p
                for ( ; ; )
                {
                    q = BigInteger.GeneratePseudoPrime(bitlength);
                    if ( ( q % uint_e != 1 ) && ( p != q ) )
                        break;
                }

                // calculate the modulus
                n = p * q;
                if ( n.BitCount() == KeySize )
                    break;

                // if we get here our primes aren'thread big enough, make the largest
                // of the two p and try again
                if ( p < q )
                    p = q;
            }

            BigInteger pSub1 = ( p - 1 );
            BigInteger qSub1 = ( q - 1 );
            BigInteger phi = pSub1 * qSub1;

            //while (phi.GCD(e) != 1) e+=2;

            // calculate the private exponent
            d = e.ModInverse(phi);

            // calculate the CRT factors
            dp = d % pSub1;
            dq = d % qSub1;
            qInv = q.ModInverse(p);

            keypairGenerated = true;
            isCRTpossible = true;

            if ( KeyGenerated != null )
                KeyGenerated(this, null);
        }
Пример #2
0
        /// <summary>
        ///     Probabilistic prime test based on Rabin-Miller's test
        /// </summary>
        /// <param name="bi" type="BigInteger.BigInteger">
        ///     <para>
        ///         The number to test.
        ///     </para>
        /// </param>
        /// <param name="confidence" type="int">
        ///     <para>
        ///    The number of chosen bases. The test has at least a
        ///    1/4^confidence chance of falsely returning True.
        ///     </para>
        /// </param>
        /// <returns>
        ///    <para>
        ///        True if "this" is a strong pseudoprime to randomly chosen bases.
        ///    </para>
        ///    <para>
        ///        False if "this" is definitely NOT prime.
        ///    </para>
        /// </returns>
        public static bool RabinMillerTest( BigInteger bi, ConfidenceFactor confidence )
        {
            int Rounds = GetSPPRounds(bi, confidence);

            // calculate values of s and thread
            BigInteger p_sub1 = bi - 1;
            int s = p_sub1.LowestSetBit();

            BigInteger t = p_sub1 >> s;

            int bits = bi.BitCount();
            BigInteger a = null;
            BigInteger.ModulusRing mr = new BigInteger.ModulusRing(bi);

            // Applying optimization from HAC section 4.50 (base == 2)
            // not a really random base but an interesting (and speedy) one
            BigInteger b = mr.Pow(2, t);
            if ( b != 1 )
            {
                bool result = false;
                for ( int j = 0; j < s; j++ )
                {
                    if ( b == p_sub1 )
                    {         // a^((2^k)*thread) mod p = p-1 for some 0 <= k <= s-1
                        result = true;
                        break;
                    }

                    b = ( b * b ) % bi;
                }
                if ( !result )
                    return false;
            }

            // still here ? start at round 1 (round 0 was a == 2)
            for ( int round = 1; round < Rounds; round++ )
            {
                while ( true )
                {                   // generate a < n
                    a = BigInteger.GenerateRandom(bits);

                    // make sure "a" is not 0 (and not 2 as we have already tested that)
                    if ( a > 2 && a < bi )
                        break;
                }

                if ( a.GCD(bi) != 1 )
                    return false;

                b = mr.Pow(a, t);

                if ( b == 1 )
                    continue;              // a^thread mod p = 1

                bool result = false;
                for ( int j = 0; j < s; j++ )
                {

                    if ( b == p_sub1 )
                    {         // a^((2^k)*thread) mod p = p-1 for some 0 <= k <= s-1
                        result = true;
                        break;
                    }

                    b = ( b * b ) % bi;
                }

                if ( !result )
                    return false;
            }
            return true;
        }
Пример #3
0
        private static int GetSPPRounds( BigInteger bi, ConfidenceFactor confidence )
        {
            int bc = bi.BitCount();

            int Rounds;

            // Data from HAC, 4.49
            if ( bc <= 100 )
                Rounds = 27;
            else if ( bc <= 150 )
                Rounds = 18;
            else if ( bc <= 200 )
                Rounds = 15;
            else if ( bc <= 250 )
                Rounds = 12;
            else if ( bc <= 300 )
                Rounds = 9;
            else if ( bc <= 350 )
                Rounds = 8;
            else if ( bc <= 400 )
                Rounds = 7;
            else if ( bc <= 500 )
                Rounds = 6;
            else if ( bc <= 600 )
                Rounds = 5;
            else if ( bc <= 800 )
                Rounds = 4;
            else if ( bc <= 1250 )
                Rounds = 3;
            else
                Rounds = 2;

            switch ( confidence )
            {
                case ConfidenceFactor.ExtraLow:
                    Rounds >>= 2;
                    return Rounds != 0 ? Rounds : 1;
                case ConfidenceFactor.Low:
                    Rounds >>= 1;
                    return Rounds != 0 ? Rounds : 1;
                case ConfidenceFactor.Medium:
                    return Rounds;
                case ConfidenceFactor.High:
                    return Rounds << 1;
                case ConfidenceFactor.ExtraHigh:
                    return Rounds << 2;
                case ConfidenceFactor.Provable:
                    throw new Exception("The Rabin-Miller test can not be executed in a way such that its results are provable");
                default:
                    throw new ArgumentOutOfRangeException("confidence");
            }
        }
Пример #4
0
            private unsafe BigInteger EvenPow( uint b, BigInteger exp )
            {
                exp.Normalize();
                uint[] wkspace = new uint[mod.length << 1 + 1];
                BigInteger resultNum = new BigInteger(( BigInteger )b, mod.length << 1 + 1);

                uint pos = ( uint )exp.BitCount() - 2;

                //
                // We know that the first itr will make the val m
                //

                do
                {
                    //
                    // r = r ^ 2 % m
                    //
                    Kernel.SquarePositive(resultNum, ref wkspace);
                    if ( !( resultNum.length < mod.length ) )
                        BarrettReduction(resultNum);

                    if ( exp.TestBit(pos) )
                    {

                        //
                        // r = r * m % m
                        //

                        // TODO: Is Unsafe really speeding things up?
                        fixed ( uint* u = resultNum.data )
                        {

                            uint i = 0;
                            ulong mc = 0;

                            do
                            {
                                mc += ( ulong )u[i] * ( ulong )b;
                                u[i] = ( uint )mc;
                                mc >>= 32;
                            } while ( ++i < resultNum.length );

                            if ( resultNum.length < mod.length )
                            {
                                if ( mc != 0 )
                                {
                                    u[i] = ( uint )mc;
                                    resultNum.length++;
                                    while ( resultNum >= mod )
                                        Kernel.MinusEq(resultNum, mod);
                                }
                            }
                            else if ( mc != 0 )
                            {

                                //
                                // First, we estimate the quotient by dividing
                                // the first part of each of the numbers. Then
                                // we correct this, if necessary, with a subtraction.
                                //

                                uint cc = ( uint )mc;

                                // We would rather have this estimate overshoot,
                                // so we add one to the divisor
                                uint divEstimate = ( uint )( ( ( ( ulong )cc << 32 ) | ( ulong )u[i - 1] ) /
                                    ( mod.data[mod.length - 1] + 1 ) );

                                uint t;

                                i = 0;
                                mc = 0;
                                do
                                {
                                    mc += ( ulong )mod.data[i] * ( ulong )divEstimate;
                                    t = u[i];
                                    u[i] -= ( uint )mc;
                                    mc >>= 32;
                                    if ( u[i] > t )
                                        mc++;
                                    i++;
                                } while ( i < resultNum.length );
                                cc -= ( uint )mc;

                                if ( cc != 0 )
                                {

                                    uint sc = 0, j = 0;
                                    uint[] s = mod.data;
                                    do
                                    {
                                        uint a = s[j];
                                        if ( ( ( a += sc ) < sc ) | ( ( u[j] -= a ) > ~a ) )
                                            sc = 1;
                                        else
                                            sc = 0;
                                        j++;
                                    } while ( j < resultNum.length );
                                    cc -= sc;
                                }
                                while ( resultNum >= mod )
                                    Kernel.MinusEq(resultNum, mod);
                            }
                            else
                            {
                                while ( resultNum >= mod )
                                    Kernel.MinusEq(resultNum, mod);
                            }
                        }
                    }
                } while ( pos-- > 0 );

                return resultNum;
            }
Пример #5
0
            private BigInteger OddPow( BigInteger b, BigInteger exp )
            {
                BigInteger resultNum = new BigInteger(Montgomery.ToMont(1, mod), mod.length << 1);
                BigInteger tempNum = new BigInteger(Montgomery.ToMont(b, mod), mod.length << 1);  // ensures (tempNum * tempNum) < m^ (2k)
                uint mPrime = Montgomery.Inverse(mod.data[0]);
                uint totalBits = ( uint )exp.BitCount();

                uint[] wkspace = new uint[mod.length << 1];

                // perform squaring and multiply exponentiation
                for ( uint pos = 0; pos < totalBits; pos++ )
                {
                    if ( exp.TestBit(pos) )
                    {

                        Array.Clear(wkspace, 0, wkspace.Length);
                        Kernel.Multiply(resultNum.data, 0, resultNum.length, tempNum.data, 0, tempNum.length, wkspace, 0);
                        resultNum.length += tempNum.length;
                        uint[] t = wkspace;
                        wkspace = resultNum.data;
                        resultNum.data = t;

                        Montgomery.Reduce(resultNum, mod, mPrime);
                    }

                    Kernel.SquarePositive(tempNum, ref wkspace);
                    Montgomery.Reduce(tempNum, mod, mPrime);
                }

                Montgomery.Reduce(resultNum, mod, mPrime);
                return resultNum;
            }
Пример #6
0
            public BigInteger EvenPow( BigInteger b, BigInteger exp )
            {
                BigInteger resultNum = new BigInteger(( BigInteger )1, mod.length << 1);
                BigInteger tempNum = new BigInteger(b % mod, mod.length << 1);  // ensures (tempNum * tempNum) < m^ (2k)

                uint totalBits = ( uint )exp.BitCount();

                uint[] wkspace = new uint[mod.length << 1];

                // perform squaring and multiply exponentiation
                for ( uint pos = 0; pos < totalBits; pos++ )
                {
                    if ( exp.TestBit(pos) )
                    {

                        Array.Clear(wkspace, 0, wkspace.Length);
                        Kernel.Multiply(resultNum.data, 0, resultNum.length, tempNum.data, 0, tempNum.length, wkspace, 0);
                        resultNum.length += tempNum.length;
                        uint[] t = wkspace;
                        wkspace = resultNum.data;
                        resultNum.data = t;

                        BarrettReduction(resultNum);
                    }

                    Kernel.SquarePositive(tempNum, ref wkspace);
                    BarrettReduction(tempNum);

                    if ( tempNum == 1 )
                    {
                        return resultNum;
                    }
                }

                return resultNum;
            }