Exemple #1
0
        /// <summary>
        /// Generates a new, random BigInteger of the specified capacity.
        /// </summary>
        /// <param name="bits">The number of bits for the new number.</param>
        /// <param name="rng">A random number generator to use to obtain the bits.</param>
        /// <returns>A random number of the specified capacity.</returns>
        public static BigInteger GenerateRandom( int bits, RandomNumberGenerator rng )
        {
            int dwords = bits >> 5;
            int remBits = bits & 0x1F;

            if ( remBits != 0 )
                dwords++;

            BigInteger ret = new BigInteger(Sign.Positive, ( uint )dwords + 1);
            byte[] random = new byte[dwords << 2];

            rng.GetBytes(random);
            Buffer.BlockCopy(random, 0, ret.data, 0, ( int )dwords << 2);

            if ( remBits != 0 )
            {
                uint mask = ( uint )( 0x01 << ( remBits - 1 ) );
                ret.data[dwords - 1] |= mask;

                mask = ( uint )( 0xFFFFFFFF >> ( 32 - remBits ) );
                ret.data[dwords - 1] &= mask;
            }
            else
                ret.data[dwords - 1] |= 0x80000000;

            ret.Normalize();
            return ret;
        }
Exemple #2
0
            public static BigInteger MultiplyByDword( BigInteger n, uint f )
            {
                BigInteger ret = new BigInteger(Sign.Positive, n.length + 1);

                uint i = 0;
                ulong c = 0;

                do
                {
                    c += ( ulong )n.data[i] * ( ulong )f;
                    ret.data[i] = ( uint )c;
                    c >>= 32;
                } while ( ++i < n.length );
                ret.data[i] = ( uint )c;
                ret.Normalize();
                return ret;

            }
Exemple #3
0
        public static BigInteger operator *( BigInteger bi1, BigInteger bi2 )
        {
            if ( bi1 == 0 || bi2 == 0 )
                return 0;

            //
            // Validate pointers
            //
            if ( bi1.data.Length < bi1.length )
                throw new IndexOutOfRangeException("bi1 out of range");
            if ( bi2.data.Length < bi2.length )
                throw new IndexOutOfRangeException("bi2 out of range");

            BigInteger ret = new BigInteger(Sign.Positive, bi1.length + bi2.length);

            Kernel.Multiply(bi1.data, 0, bi1.length, bi2.data, 0, bi2.length, ret.data, 0);

            ret.Normalize();
            return ret;
        }
Exemple #4
0
            public static BigInteger LeftShift( BigInteger bi, int n )
            {
                if ( n == 0 )
                    return new BigInteger(bi, bi.length + 1);

                int w = n >> 5;
                n &= ( ( 1 << 5 ) - 1 );

                BigInteger ret = new BigInteger(Sign.Positive, bi.length + 1 + ( uint )w);

                uint i = 0, l = bi.length;
                if ( n != 0 )
                {
                    uint x, carry = 0;
                    while ( i < l )
                    {
                        x = bi.data[i];
                        ret.data[i + w] = ( x << n ) | carry;
                        carry = x >> ( 32 - n );
                        i++;
                    }
                    ret.data[i + w] = carry;
                }
                else
                {
                    while ( i < l )
                    {
                        ret.data[i + w] = bi.data[i];
                        i++;
                    }
                }

                ret.Normalize();
                return ret;
            }
Exemple #5
0
            public static BigInteger RightShift( BigInteger bi, int n )
            {
                if ( n == 0 )
                    return new BigInteger(bi);

                int w = n >> 5;
                int s = n & ( ( 1 << 5 ) - 1 );

                BigInteger ret = new BigInteger(Sign.Positive, bi.length - ( uint )w + 1);
                uint l = ( uint )ret.data.Length - 1;

                if ( s != 0 )
                {

                    uint x, carry = 0;

                    while ( l-- > 0 )
                    {
                        x = bi.data[l + w];
                        ret.data[l] = ( x >> n ) | carry;
                        carry = x << ( 32 - n );
                    }
                }
                else
                {
                    while ( l-- > 0 )
                        ret.data[l] = bi.data[l + w];

                }
                ret.Normalize();
                return ret;
            }
Exemple #6
0
            public static BigInteger[] DwordDivMod( BigInteger n, uint d )
            {
                BigInteger ret = new BigInteger(Sign.Positive, n.length);

                ulong r = 0;
                uint i = n.length;

                while ( i-- > 0 )
                {
                    r <<= 32;
                    r |= n.data[i];
                    ret.data[i] = ( uint )( r / d );
                    r %= d;
                }
                ret.Normalize();

                BigInteger rem = ( uint )r;

                return new BigInteger[] { ret, rem };
            }
Exemple #7
0
            public static BigInteger[] multiByteDivide( BigInteger bi1, BigInteger bi2 )
            {
                if ( Kernel.Compare(bi1, bi2) == Sign.Negative )
                    return new BigInteger[2] { 0, new BigInteger(bi1) };

                bi1.Normalize();
                bi2.Normalize();

                if ( bi2.length == 1 )
                    return DwordDivMod(bi1, bi2.data[0]);

                uint remainderLen = bi1.length + 1;
                int divisorLen = ( int )bi2.length + 1;

                uint mask = 0x80000000;
                uint val = bi2.data[bi2.length - 1];
                int shift = 0;
                int resultPos = ( int )bi1.length - ( int )bi2.length;

                while ( mask != 0 && ( val & mask ) == 0 )
                {
                    shift++;
                    mask >>= 1;
                }

                BigInteger quot = new BigInteger(Sign.Positive, bi1.length - bi2.length + 1);
                BigInteger rem = ( bi1 << shift );

                uint[] remainder = rem.data;

                bi2 = bi2 << shift;

                int j = ( int )( remainderLen - bi2.length );
                int pos = ( int )remainderLen - 1;

                uint firstDivisorByte = bi2.data[bi2.length - 1];
                ulong secondDivisorByte = bi2.data[bi2.length - 2];

                while ( j > 0 )
                {
                    ulong dividend = ( ( ulong )remainder[pos] << 32 ) + ( ulong )remainder[pos - 1];

                    ulong q_hat = dividend / ( ulong )firstDivisorByte;
                    ulong r_hat = dividend % ( ulong )firstDivisorByte;

                    do
                    {

                        if ( q_hat == 0x100000000 ||
                            ( q_hat * secondDivisorByte ) > ( ( r_hat << 32 ) + remainder[pos - 2] ) )
                        {
                            q_hat--;
                            r_hat += ( ulong )firstDivisorByte;

                            if ( r_hat < 0x100000000 )
                                continue;
                        }
                        break;
                    } while ( true );

                    //
                    // At this point, q_hat is either exact, or one too large
                    // (more likely to be exact) so, we attempt to multiply the
                    // divisor by q_hat, if we get a borrow, we just subtract
                    // one from q_hat and add the divisor back.
                    //

                    uint t;
                    uint dPos = 0;
                    int nPos = pos - divisorLen + 1;
                    ulong mc = 0;
                    uint uint_q_hat = ( uint )q_hat;
                    do
                    {
                        mc += ( ulong )bi2.data[dPos] * ( ulong )uint_q_hat;
                        t = remainder[nPos];
                        remainder[nPos] -= ( uint )mc;
                        mc >>= 32;
                        if ( remainder[nPos] > t )
                            mc++;
                        dPos++;
                        nPos++;
                    } while ( dPos < divisorLen );

                    nPos = pos - divisorLen + 1;
                    dPos = 0;

                    // Overestimate
                    if ( mc != 0 )
                    {
                        uint_q_hat--;
                        ulong sum = 0;

                        do
                        {
                            sum = ( ( ulong )remainder[nPos] ) + ( ( ulong )bi2.data[dPos] ) + sum;
                            remainder[nPos] = ( uint )sum;
                            sum >>= 32;
                            dPos++;
                            nPos++;
                        } while ( dPos < divisorLen );

                    }

                    quot.data[resultPos--] = ( uint )uint_q_hat;

                    pos--;
                    j--;
                }

                quot.Normalize();
                rem.Normalize();
                BigInteger[] ret = new BigInteger[2] { quot, rem };

                if ( shift != 0 )
                    ret[1] >>= shift;

                return ret;
            }
Exemple #8
0
            public static void PlusEq( BigInteger bi1, BigInteger bi2 )
            {
                uint[] x, y;
                uint yMax, xMax, i = 0;
                bool flag = false;

                // x should be bigger
                if ( bi1.length < bi2.length )
                {
                    flag = true;
                    x = bi2.data;
                    xMax = bi2.length;
                    y = bi1.data;
                    yMax = bi1.length;
                }
                else
                {
                    x = bi1.data;
                    xMax = bi1.length;
                    y = bi2.data;
                    yMax = bi2.length;
                }

                uint[] r = bi1.data;

                ulong sum = 0;

                // Add common parts of both numbers
                do
                {
                    sum += ( ( ulong )x[i] ) + ( ( ulong )y[i] );
                    r[i] = ( uint )sum;
                    sum >>= 32;
                } while ( ++i < yMax );

                // SpecialCopy remainder of longer number while carry propagation is required
                bool carry = ( sum != 0 );

                if ( carry )
                {

                    if ( i < xMax )
                    {
                        do
                            carry = ( ( r[i] = x[i] + 1 ) == 0 );
                        while ( ++i < xMax && carry );
                    }

                    if ( carry )
                    {
                        r[i] = 1;
                        bi1.length = ++i;
                        return;
                    }
                }

                // SpecialCopy the rest
                if ( flag && i < xMax - 1 )
                {
                    do
                        r[i] = x[i];
                    while ( ++i < xMax );
                }

                bi1.length = xMax + 1;
                bi1.Normalize();
            }
Exemple #9
0
            /// <summary>
            /// Performs n / i and n % i in one operation.
            /// </summary>
            /// <param name="n">A BigInteger, upon exit this will hold n / i</param>
            /// <param name="i">The divisor</param>
            /// <returns>n % i</returns>
            public static uint SingleByteDivideInPlace( BigInteger n, uint d )
            {
                ulong r = 0;
                uint i = n.length;

                while ( i-- > 0 )
                {
                    r <<= 32;
                    r |= n.data[i];
                    n.data[i] = ( uint )( r / d );
                    r %= d;
                }
                n.Normalize();

                return ( uint )r;
            }
Exemple #10
0
            public static BigInteger Subtract( BigInteger big, BigInteger small )
            {
                BigInteger result = new BigInteger(Sign.Positive, big.length);

                uint[] r = result.data, b = big.data, s = small.data;
                uint i = 0, c = 0;

                do
                {

                    uint x = s[i];
                    if ( ( ( x += c ) < c ) | ( ( r[i] = b[i] - x ) > ~x ) )
                        c = 1;
                    else
                        c = 0;

                } while ( ++i < small.length );

                if ( i == big.length )
                    goto fixup;

                if ( c == 1 )
                {
                    do
                        r[i] = b[i] - 1;
                    while ( b[i++] == 0 && i < big.length );

                    if ( i == big.length )
                        goto fixup;
                }

                do
                    r[i] = b[i];
                while ( ++i < big.length );

fixup:

                result.Normalize();
                return result;
            }
Exemple #11
0
            /// <summary>
            /// Adds two numbers with the same sign.
            /// </summary>
            /// <param name="bi1">A BigInteger</param>
            /// <param name="bi2">A BigInteger</param>
            /// <returns>bi1 + bi2</returns>
            public static BigInteger AddSameSign( BigInteger bi1, BigInteger bi2 )
            {
                uint[] x, y;
                uint yMax, xMax, i = 0;

                // x should be bigger
                if ( bi1.length < bi2.length )
                {
                    x = bi2.data;
                    xMax = bi2.length;
                    y = bi1.data;
                    yMax = bi1.length;
                }
                else
                {
                    x = bi1.data;
                    xMax = bi1.length;
                    y = bi2.data;
                    yMax = bi2.length;
                }

                BigInteger result = new BigInteger(Sign.Positive, xMax + 1);

                uint[] r = result.data;

                ulong sum = 0;

                // Add common parts of both numbers
                do
                {
                    sum = ( ( ulong )x[i] ) + ( ( ulong )y[i] ) + sum;
                    r[i] = ( uint )sum;
                    sum >>= 32;
                } while ( ++i < yMax );

                // SpecialCopy remainder of longer number while carry propagation is required
                bool carry = ( sum != 0 );

                if ( carry )
                {

                    if ( i < xMax )
                    {
                        do
                            carry = ( ( r[i] = x[i] + 1 ) == 0 );
                        while ( ++i < xMax && carry );
                    }

                    if ( carry )
                    {
                        r[i] = 1;
                        result.length = ++i;
                        return result;
                    }
                }

                // SpecialCopy the rest
                if ( i < xMax )
                {
                    do
                        r[i] = x[i];
                    while ( ++i < xMax );
                }

                result.Normalize();
                return result;
            }
Exemple #12
0
            public static BigInteger ToMont( BigInteger n, BigInteger m )
            {
                n.Normalize();
                m.Normalize();

                n <<= ( int )m.length * 32;
                n %= m;
                return n;
            }
Exemple #13
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;
            }
Exemple #14
0
            public void BarrettReduction( BigInteger x )
            {
                BigInteger n = mod;
                uint k = n.length,
                    kPlusOne = k + 1,
                    kMinusOne = k - 1;

                // x < mod, so nothing to do.
                if ( x.length < k )
                    return;

                BigInteger q3;

                //
                // Validate pointers
                //
                if ( x.data.Length < x.length )
                    throw new IndexOutOfRangeException("x out of range");

                // q1 = x / m^ (j-1)
                // q2 = q1 * constant
                // q3 = q2 / m^ (j+1), Needs to be accessed with an offset of kPlusOne

                // TODO: We should the method in HAC p 604 to do this (14.45)
                q3 = new BigInteger(Sign.Positive, x.length - kMinusOne + constant.length);
                Kernel.Multiply(x.data, kMinusOne, x.length - kMinusOne, constant.data, 0, constant.length, q3.data, 0);

                // r1 = x mod m^ (j+1)
                // i.e. keep the lowest (j+1) words

                uint lengthToCopy = ( x.length > kPlusOne ) ? kPlusOne : x.length;

                x.length = lengthToCopy;
                x.Normalize();

                // r2 = (q3 * n) mod m^ (j+1)
                // partial multiplication of q3 and n

                BigInteger r2 = new BigInteger(Sign.Positive, kPlusOne);
                Kernel.MultiplyMod2p32pmod(q3.data, ( int )kPlusOne, ( int )q3.length - ( int )kPlusOne, n.data, 0, ( int )n.length, r2.data, 0, ( int )kPlusOne);

                r2.Normalize();

                if ( r2 <= x )
                {
                    Kernel.MinusEq(x, r2);
                }
                else
                {
                    BigInteger val = new BigInteger(Sign.Positive, kPlusOne + 1);
                    val.data[kPlusOne] = 0x00000001;

                    Kernel.MinusEq(val, r2);
                    Kernel.PlusEq(x, val);
                }

                while ( x >= n )
                    Kernel.MinusEq(x, n);
            }