예제 #1
0
        // This is the standard modular power algorithm that
        // you could find in any reference, but its use of
        // the new modular reduction algorithm is new.
        // The square and multiply method is in Wikipedia:
        // https://en.wikipedia.org/wiki/Exponentiation_by_squaring
        // x^n = (x^2)^((n - 1)/2) if n is odd.
        // x^n = (x^2)^(n/2)       if n is even.
        internal void ModularPower( Integer Result, Integer Exponent, Integer Modulus, bool UsePresetBaseArray )
        {
            if( Result.IsZero())
              return; // With Result still zero.

            if( Result.IsEqual( Modulus ))
              {
              // It is congruent to zero % ModN.
              Result.SetToZero();
              return;
              }

            // Result is not zero at this point.
            if( Exponent.IsZero() )
              {
              Result.SetFromULong( 1 );
              return;
              }

            if( Modulus.ParamIsGreater( Result ))
              {
              // throw( new Exception( "This is not supposed to be input for RSA plain text." ));
              IntMath.Divide( Result, Modulus, Quotient, Remainder );
              Result.Copy( Remainder );
              }

            if( Exponent.IsOne())
              {
              // Result stays the same.
              return;
              }

            if( !UsePresetBaseArray )
              SetupGeneralBaseArray( Modulus );

            XForModPower.Copy( Result );
            ExponentCopy.Copy( Exponent );
            int TestIndex = 0;
            Result.SetFromULong( 1 );
            while( true )
              {
              if( (ExponentCopy.GetD( 0 ) & 1) == 1 ) // If the bottom bit is 1.
            {
            IntMath.Multiply( Result, XForModPower );
            ModularReduction( TempForModPower, Result );
            Result.Copy( TempForModPower );
            }

              ExponentCopy.ShiftRight( 1 ); // Divide by 2.
              if( ExponentCopy.IsZero())
            break;

              // Square it.
              IntMath.Multiply( XForModPower, XForModPower );
              ModularReduction( TempForModPower, XForModPower );
              XForModPower.Copy( TempForModPower );
              }

            // When ModularReduction() gets called it multiplies a base number
            // by a uint sized digit.  So that can make the result one digit bigger
            // than GeneralBase.  Then when they are added up you can get carry
            // bits that can make it a little bigger.
            int HowBig = Result.GetIndex() - Modulus.GetIndex();
            // if( HowBig > 1 )
              // throw( new Exception( "This does happen. Diff: " + HowBig.ToString() ));

            if( HowBig > 2 )
              throw( new Exception( "The never happens. Diff: " + HowBig.ToString() ));

            ModularReduction( TempForModPower, Result );
            Result.Copy( TempForModPower );

            IntMath.Divide( Result, Modulus, Quotient, Remainder );
            Result.Copy( Remainder );

            if( Quotient.GetIndex() > 1 )
              throw( new Exception( "This never happens. The quotient index is never more than 1." ));
        }
예제 #2
0
        // Copyright Eric Chauvin 2015.
        private int ModularReduction( Integer Result, Integer ToReduce )
        {
            try
            {
            if( GeneralBaseArray == null )
              throw( new Exception( "SetupGeneralBaseArray() should have already been called." ));

            Result.SetToZero();

            int HowManyToAdd = ToReduce.GetIndex() + 1;
            if( HowManyToAdd > GeneralBaseArray.Length )
              throw( new Exception( "Bug. The Input number should have been reduced first. HowManyToAdd > GeneralBaseArray.Length" ));

            int BiggestIndex = 0;
            for( int Count = 0; Count < HowManyToAdd; Count++ )
              {
              // The size of the numbers in GeneralBaseArray are
              // all less than the size of GeneralBase.
              // This multiplication by a uint is with a number
              // that is not bigger than GeneralBase.  Compare
              // this with the two full Muliply() calls done on
              // each digit of the quotient in LongDivide3().

              // AccumulateBase is set to a new value here.
              int CheckIndex = IntMath.MultiplyUIntFromCopy( AccumulateBase, GeneralBaseArray[Count], ToReduce.GetD( Count ));

              if( CheckIndex > BiggestIndex )
            BiggestIndex = CheckIndex;

              Result.Add( AccumulateBase );
              }

            return Result.GetIndex();
            }
            catch( Exception Except )
              {
              throw( new Exception( "Exception in ModularReduction(): " + Except.Message ));
              }
        }
예제 #3
0
        internal void MakeBaseNumbers()
        {
            try
            {
            MakeYBaseToPrimesArray();
            if( Worker.CancellationPending )
              return;

            Integer YTop = new Integer();
            Integer Y = new Integer();
            Integer XSquared = new Integer();
            Integer Test = new Integer();
            YTop.SetToZero();
            uint XSquaredBitLength = 1;

            ExponentVectorNumber ExpNumber = new ExponentVectorNumber( IntMath );

            uint Loops = 0;
            uint BSmoothCount = 0;
            uint BSmoothTestsCount = 0;
            uint IncrementYBy = 0;
            while( true )
              {
              if( Worker.CancellationPending )
            return;

              Loops++;
              if( (Loops & 0xF) == 0 )
            {
            Worker.ReportProgress( 0, " " );
            Worker.ReportProgress( 0, "Loops: " + Loops.ToString( "N0" ));
            Worker.ReportProgress( 0, "BSmoothCount: " + BSmoothCount.ToString( "N0" ));
            Worker.ReportProgress( 0, "BSmoothTestsCount: " + BSmoothTestsCount.ToString( "N0" ));
            if( BSmoothTestsCount != 0 )
              {
              double TestsRatio = (double)BSmoothCount / (double)BSmoothTestsCount;
              Worker.ReportProgress( 0, "TestsRatio: " + TestsRatio.ToString( "N3" ));
              }
            }

              /*
              if( (Loops & 0xFFFFF) == 0 )
            {
            // Use Task Manager to tweak the CPU Utilization if you want
            // it be below 100 percent.
            Thread.Sleep( 1 );
            }
            */

              // About 98 percent of the time it is running IncrementBy().
              IncrementYBy += IncrementConst;
              uint BitLength = IncrementBy();

              const uint SomeOptimumBitLength = 2;
              if( BitLength < SomeOptimumBitLength )
            continue;

              // This BitLength has to do with how many small factors you want
              // in the number.  But it doesn't limit your factor base at all.
              // You can still have any size prime in your factor base (up to
              // IntegerMath.PrimeArrayLength).  Compare the size of
              // YBaseToPrimesArrayLast to IntegerMath.PrimeArrayLength.
              BSmoothTestsCount++;
              YTop.AddULong( IncrementYBy );
              IncrementYBy = 0;
              Y.Copy( ProductSqrRoot );
              Y.Add( YTop );
              XSquared.Copy( Y );
              IntMath.DoSquare( XSquared );
              if( XSquared.ParamIsGreater( Product ))
            throw( new Exception( "Bug. XSquared.ParamIsGreater( Product )." ));

              IntMath.Subtract( XSquared, Product );

              XSquaredBitLength = (uint)(XSquared.GetIndex() * 32);
              uint TopDigit = (uint)XSquared.GetD( XSquared.GetIndex());
              uint TopLength = GetBitLength( TopDigit );
              XSquaredBitLength += TopLength;
              if( XSquaredBitLength == 0 )
            XSquaredBitLength = 1;

              // if( ItIsTheAnswerAlready( XSquared ))  It's too unlikely.
              // QuadResCombinatorics could run in parallel to check for that,
              // and it would be way ahead of this.

              GetOneMainFactor();
              if( OneMainFactor.IsEqual( XSquared ))
            {
            MakeFastExpNumber( ExpNumber );
            }
              else
            {
            if( OneMainFactor.IsZero())
              throw( new Exception( "OneMainFactor.IsZero()." ));

            IntMath.Divide( XSquared, OneMainFactor, Quotient, Remainder );
            ExpNumber.SetFromTraditionalInteger( Quotient );
            ExpNumber.Multiply( ExpOneMainFactor );
            ExpNumber.GetTraditionalInteger( Test );
            if( !Test.IsEqual( XSquared ))
              throw( new Exception( "!Test.IsEqual( XSquared )." ));

            }

              if( ExpNumber.IsBSmooth())
            {
            BSmoothCount++;
            string DelimS = IntMath.ToString10( Y ) + "\t" +
                        ExpNumber.ToDelimString();

            Worker.ReportProgress( 1, DelimS );

            if( (BSmoothCount & 0x3F) == 0 )
              {
              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "BitLength: " + BitLength.ToString());
              Worker.ReportProgress( 0, "XSquaredBitLength: " + XSquaredBitLength.ToString());
              Worker.ReportProgress( 0, ExpNumber.ToString() );

              // What should BSmoothLimit be?
              // (Since FactorDictionary.cs will reduce the final factor base.)
              if( BSmoothCount > BSmoothLimit )
            {
            Worker.ReportProgress( 0, "Found enough to make the matrix." );
            Worker.ReportProgress( 0, "BSmoothCount: " + BSmoothCount.ToString( "N0" ));
            Worker.ReportProgress( 0, "BSmoothLimit: " + BSmoothLimit.ToString( "N0" ));
            Worker.ReportProgress( 0, "Seconds: " + StartTime.GetSecondsToNow().ToString( "N1" ));
            double Seconds = StartTime.GetSecondsToNow();
            int Minutes = (int)Seconds / 60;
            int Hours = Minutes / 60;
            Minutes = Minutes % 60;
            Seconds = Seconds % 60;
            string ShowS = "Hours: " + Hours.ToString( "N0" ) +
                   "  Minutes: " + Minutes.ToString( "N0" ) +
                   "  Seconds: " + Seconds.ToString( "N0" );

            Worker.ReportProgress( 0, ShowS );

            return;
            }
              }
            }
              }
            }
            catch( Exception Except )
              {
              throw( new Exception( "Exception in MakeBaseNumbers():\r\n" + Except.Message ));
              }
        }
예제 #4
0
        internal bool FindTwoFactorsWithFermat( Integer Product, Integer P, Integer Q, ulong MinimumX )
        {
            ECTime StartTime = new ECTime();
            StartTime.SetToNow();

            Integer TestSqrt = new Integer();
            Integer TestSquared = new Integer();
            Integer SqrRoot = new Integer();

            TestSquared.Copy( Product );
            IntMath.Multiply( TestSquared, Product );
            IntMath.SquareRoot( TestSquared, SqrRoot );
            TestSqrt.Copy( SqrRoot );
            IntMath.DoSquare( TestSqrt );
            // IntMath.Multiply( TestSqrt, SqrRoot );
            if( !TestSqrt.IsEqual( TestSquared ))
              throw( new Exception( "The square test was bad." ));

            // Some primes:
            // 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
            // 101, 103, 107

            P.SetToZero();
            Q.SetToZero();
            Integer TestX = new Integer();
            SetupQuadResArray( Product );

            ulong BaseTo37 = QuadResBigBase * 29UL * 31UL * 37UL;
            // ulong BaseTo31 = QuadResBigBase * 29UL * 31UL;
            ulong ProdModTo37 = IntMath.GetMod64( Product, BaseTo37 );
            // ulong ProdModTo31 = IntMath.GetMod64( Product, BaseTo31 );
            for( ulong BaseCount = 0; BaseCount < (29 * 31 * 37); BaseCount++ )
              {
              if( (BaseCount & 0xF) == 0 )
            Worker.ReportProgress( 0, "Find with Fermat BaseCount: " + BaseCount.ToString() );

              if( Worker.CancellationPending )
            return false;

              ulong Base = (BaseCount + 1) * QuadResBigBase; // BaseCount times 223,092,870.
              if( Base < MinimumX )
            continue;

              Base = BaseCount * QuadResBigBase; // BaseCount times 223,092,870.
              for( uint Count = 0; Count < QuadResArrayLast; Count++ )
            {
            // The maximum CountPart can be is just under half the size of
            // the Product. (Like if Y - X was equal to 1, and Y + X was
            // equal to the Product.)  If it got anywhere near that big it
            // would be inefficient to try and find it this way.
            ulong CountPart = Base + QuadResArray[Count];
            ulong Test = ProdModTo37 + (CountPart * CountPart);
            // ulong Test = ProdModTo31 + (CountPart * CountPart);
            Test = Test % BaseTo37;
            // Test = Test % BaseTo31;
            if( !IntegerMath.IsQuadResidue29( Test ))
              continue;

            if( !IntegerMath.IsQuadResidue31( Test ))
              continue;

            if( !IntegerMath.IsQuadResidue37( Test ))
              continue;

            ulong TestBytes = (CountPart & 0xFFFFF);
            TestBytes *= (CountPart & 0xFFFFF);
            ulong ProdBytes = Product.GetD( 1 );
            ProdBytes <<= 8;
            ProdBytes |= Product.GetD( 0 );

            uint FirstBytes = (uint)(TestBytes + ProdBytes);
            if( !IntegerMath.FirstBytesAreQuadRes( FirstBytes ))
              {
              // Worker.ReportProgress( 0, "First bytes aren't quad res." );
              continue;
              }

            TestX.SetFromULong( CountPart );
            IntMath.MultiplyULong( TestX, CountPart );
            TestX.Add( Product );

            // uint Mod37 = (uint)IntMath.GetMod32( TestX, 37 );
            // if( !IntegerMath.IsQuadResidue37( Mod37 ))
              // continue;

            // Do more of these tests with 41, 43, 47...
            // if( !IntegerMath.IsQuadResidue41( Mod37 ))
              // continue;

            // Avoid doing this square root at all costs.
            if( IntMath.SquareRoot( TestX, SqrRoot ))
              {
              Worker.ReportProgress( 0, " " );
              if( (CountPart & 1) == 0 )
            Worker.ReportProgress( 0, "CountPart was even." );
              else
            Worker.ReportProgress( 0, "CountPart was odd." );

              // Found an exact square root.
              // P + (CountPart * CountPart) = Y*Y
              // P = (Y + CountPart)Y - CountPart)

              P.Copy( SqrRoot );
              Integer ForSub = new Integer();
              ForSub.SetFromULong( CountPart );
              IntMath.Subtract( P, ForSub );

              // Make Q the bigger one and put them in order.
              Q.Copy( SqrRoot );
              Q.AddULong( CountPart );

              if( P.IsOne() || Q.IsOne())
            {
            // This happens when testing with small primes.
            Worker.ReportProgress( 0, " " );
            Worker.ReportProgress( 0, " " );
            Worker.ReportProgress( 0, "Went all the way to 1 in FindTwoFactorsWithFermat()." );
            Worker.ReportProgress( 0, " " );
            Worker.ReportProgress( 0, " " );
            P.SetToZero(); // It has no factors.
            Q.SetToZero();
            return true; // Tested everything, so it's a prime.
            }

              Worker.ReportProgress( 0, "Found P: " + IntMath.ToString10( P ) );
              Worker.ReportProgress( 0, "Found Q: " + IntMath.ToString10( Q ) );
              Worker.ReportProgress( 0, "Seconds: " + StartTime.GetSecondsToNow().ToString( "N1" ));
              Worker.ReportProgress( 0, " " );
              throw( new Exception( "Testing this." ));
              // return true; // With P and Q.
              }
            // else
              // Worker.ReportProgress( 0, "It was not an exact square root." );

            }
              }

            // P and Q would still be zero if it never found them.
            return false;
        }
예제 #5
0
        internal void Subtract( Integer Result, Integer ToSub )
        {
            // This checks that the sign is equal too.
            if( Result.IsEqual( ToSub ))
              {
              Result.SetToZero();
              return;
              }

            // ParamIsGreater() handles positive and negative values, so if the
            // parameter is more toward the positive side then it's true.  It's greater.

            // The most common form.  They are both positive.
            if( !Result.IsNegative && !ToSub.IsNegative )
              {
              if( ToSub.ParamIsGreater( Result ))
            {
            SubtractPositive( Result, ToSub );
            return;
            }

              // ToSub is bigger.
              TempSub1.Copy( Result );
              TempSub2.Copy( ToSub );
              SubtractPositive( TempSub2, TempSub1 );
              Result.Copy( TempSub2 );
              Result.IsNegative = true;
              return;
              }

            if( Result.IsNegative && !ToSub.IsNegative )
              {
              TempSub1.Copy( Result );
              TempSub1.IsNegative = false;
              TempSub1.Add( ToSub );
              Result.Copy( TempSub1 );
              Result.IsNegative = true;
              return;
              }

            if( !Result.IsNegative && ToSub.IsNegative )
              {
              TempSub1.Copy( ToSub );
              TempSub1.IsNegative = false;
              Result.Add( TempSub1 );
              return;
              }

            if( Result.IsNegative && ToSub.IsNegative )
              {
              TempSub1.Copy( Result );
              TempSub1.IsNegative = false;
              TempSub2.Copy( ToSub );
              TempSub2.IsNegative = false;

              // -12 - -7 = -12 + 7 = -5
              // Comparing the positive numbers here.
              if( TempSub2.ParamIsGreater( TempSub1 ))
            {
            SubtractPositive( TempSub1, TempSub2 );
            Result.Copy( TempSub1 );
            Result.IsNegative = true;
            return;
            }

              // -7 - -12 = -7 + 12 = 5
              SubtractPositive( TempSub2, TempSub1 );
              Result.Copy( TempSub2 );
              Result.IsNegative = false;
              return;
              }
        }
예제 #6
0
        internal void Divide( Integer ToDivideOriginal,
                        Integer DivideByOriginal,
                        Integer Quotient,
                        Integer Remainder )
        {
            if( ToDivideOriginal.IsNegative )
              throw( new Exception( "Divide() can't be called with negative numbers." ));

            if( DivideByOriginal.IsNegative )
              throw( new Exception( "Divide() can't be called with negative numbers." ));

            // Returns true if it divides exactly with zero remainder.
            // This first checks for some basics before trying to divide it:

            if( DivideByOriginal.IsZero() )
              throw( new Exception( "Divide() dividing by zero." ));

            ToDivide.Copy( ToDivideOriginal );
            DivideBy.Copy( DivideByOriginal );

            if( ToDivide.ParamIsGreater( DivideBy ))
              {
              Quotient.SetToZero();
              Remainder.Copy( ToDivide );
              return; //  false;
              }

            if( ToDivide.IsEqual( DivideBy ))
              {
              Quotient.SetFromULong( 1 );
              Remainder.SetToZero();
              return; //  true;
              }

            // At this point DivideBy is smaller than ToDivide.

            if( ToDivide.IsULong() )
              {
              ulong ToDivideU = ToDivide.GetAsULong();
              ulong DivideByU = DivideBy.GetAsULong();
              ulong QuotientU = ToDivideU / DivideByU;
              ulong RemainderU = ToDivideU % DivideByU;
              Quotient.SetFromULong( QuotientU );
              Remainder.SetFromULong( RemainderU );
              // if( RemainderU == 0 )
            return; //  true;
              // else
            // return false;
              }

            if( DivideBy.GetIndex() == 0 )
              {
              ShortDivide( ToDivide, DivideBy, Quotient, Remainder );
              return;
              }

            // return LongDivide1( ToDivide, DivideBy, Quotient, Remainder );
            // return LongDivide2( ToDivide, DivideBy, Quotient, Remainder );
            LongDivide3( ToDivide, DivideBy, Quotient, Remainder );
        }
예제 #7
0
        internal void MultiplyULong( Integer Result, ulong ToMul )
        {
            // Using compile-time checks, this one overflows:
            // const ulong Test = ((ulong)0xFFFFFFFF + 1) * ((ulong)0xFFFFFFFF + 1);
            // This one doesn't:
            // const ulong Test = (ulong)0xFFFFFFFF * ((ulong)0xFFFFFFFF + 1);

            if( Result.IsZero())
              return; // Then the answer is zero, which it already is.

            if( ToMul == 0 )
              {
              Result.SetToZero();
              return;
              }

            ulong B0 = ToMul & 0xFFFFFFFF;
            ulong B1 = ToMul >> 32;

            if( B1 == 0 )
              {
              MultiplyUInt( Result, (uint)B0 );
              return;
              }

            // Since B1 is not zero:
            if( (Result.GetIndex() + 1) >= Integer.DigitArraySize )
              throw( new Exception( "Overflow in MultiplyULong." ));

            for( int Column = 0; Column <= Result.GetIndex(); Column++ )
              {
              M[Column, 0] = B0 * Result.GetD( Column );
              // Column + 1 and Row is 1, so it's just like pen and paper.
              M[Column + 1, 1] = B1 * Result.GetD( Column );
              }

            // Since B1 is not zero, the index is set one higher.
            Result.IncrementIndex(); // Might throw an exception if it goes out of range.

            M[Result.GetIndex(), 0] = 0; // Otherwise it would be undefined
                                 // when it's added up below.

            // Add these up with a carry.
            Result.SetD( 0, M[0, 0] & 0xFFFFFFFF );
            ulong Carry = M[0, 0] >> 32;
            for( int Column = 1; Column <= Result.GetIndex(); Column++ )
              {
              // This does overflow:
              // const ulong Test = ((ulong)0xFFFFFFFF * (ulong)(0xFFFFFFFF))
              //                  + ((ulong)0xFFFFFFFF * (ulong)(0xFFFFFFFF));
              // Split the ulongs into right and left sides
              // so that they don't overflow.
              ulong TotalLeft = 0;
              ulong TotalRight = 0;
              // There's only the two rows for this.
              for( int Row = 0; Row <= 1; Row++ )
            {
            TotalRight += M[Column, Row] & 0xFFFFFFFF;
            TotalLeft += M[Column, Row] >> 32;
            }

              TotalRight += Carry;
              Result.SetD( Column, TotalRight & 0xFFFFFFFF );
              Carry = TotalRight >> 32;
              Carry += TotalLeft;
              }

            if( Carry != 0 )
              {
              Result.IncrementIndex(); // This can throw an exception.
              Result.SetD( Result.GetIndex(), Carry );
              }
        }
예제 #8
0
        internal void SetFromString( Integer Result, string InString )
        {
            if( InString == null )
              throw( new Exception( "InString was null in SetFromString()." ));

            if( InString.Length < 1 )
              {
              Result.SetToZero();
              return;
              }

            Base10Number Base10N = new Base10Number();
            Integer Tens = new Integer();
            Integer OnePart = new Integer();

            // This might throw an exception if the string is bad.
            Base10N.SetFromString( InString );

            Result.SetFromULong( Base10N.GetD( 0 ));
            Tens.SetFromULong( 10 );

            for( int Count = 1; Count <= Base10N.GetIndex(); Count++ )
              {
              OnePart.SetFromULong( Base10N.GetD( Count ));
              Multiply( OnePart, Tens );
              Result.Add( OnePart );
              MultiplyULong( Tens, 10 );
              }
        }
예제 #9
0
        internal void MultiplyUInt( Integer Result, ulong ToMul )
        {
            try
            {
            if( ToMul == 0 )
              {
              Result.SetToZero();
              return;
              }

            if( ToMul == 1 )
              return;

            for( int Column = 0; Column <= Result.GetIndex(); Column++ )
              M[Column, 0] = ToMul * Result.GetD( Column );

            // Add these up with a carry.
            Result.SetD( 0, M[0, 0] & 0xFFFFFFFF );
            ulong Carry = M[0, 0] >> 32;
            for( int Column = 1; Column <= Result.GetIndex(); Column++ )
              {
              // Using a compile-time check on this constant,
              // this Test value does not overflow:
              // const ulong Test = ((ulong)0xFFFFFFFF * (ulong)(0xFFFFFFFF)) + 0xFFFFFFFF;

              // ulong Total = checked( M[Column, 0] + Carry );
              ulong Total = M[Column, 0] + Carry;
              Result.SetD( Column, Total & 0xFFFFFFFF );
              Carry = Total >> 32;
              }

            if( Carry != 0 )
              {
              Result.IncrementIndex(); // This might throw an exception if it overflows.
              Result.SetD( Result.GetIndex(), Carry );
              }
            }
            catch( Exception Except )
              {
              throw( new Exception( "Exception in MultiplyUInt(): " + Except.Message ));
              }
        }
예제 #10
0
        internal void GetTraditionalInteger( CRTBase ToGetFrom, Integer ToSet )
        {
            try
            {
            if( CRTBaseArray == null )
              throw( new Exception( "Bug: The BaseArray should have been set up already." ));

            // This first one has the prime 2 as its base so
            // it's going to be set to either zero or one.
            if( ToGetFrom.GetDigitAt( 0 ) == 1 )
              ToSet.SetToOne();
            else
              ToSet.SetToZero();

            Integer WorkingBase = new Integer();
            for( int Count = 1; Count < ChineseRemainder.DigitsArraySize; Count++ )
              {
              int BaseMult = ToGetFrom.GetDigitAt( Count );
              WorkingBase.Copy( BaseArray[Count] );
              IntMath.MultiplyUInt( WorkingBase, (uint)BaseMult );
              ToSet.Add( WorkingBase );
              }
            }
            catch( Exception Except )
              {
              throw( new Exception( "Exception in GetTraditionalInteger(): " + Except.Message ));
              }
        }
예제 #11
0
        internal void ModularPower( Integer Result, Integer Exponent, Integer GeneralBase )
        {
            // The square and multiply method is in Wikipedia:
            // https://en.wikipedia.org/wiki/Exponentiation_by_squaring
            // x^n = (x^2)^((n - 1)/2) if n is odd.
            // x^n = (x^2)^(n/2)       if n is even.

            if( Result.IsZero())
              return; // With Result still zero.

            if( Result.IsEqual( GeneralBase ))
              {
              // It is congruent to zero % ModN.
              Result.SetToZero();
              return;
              }

            // Result is not zero at this point.
            if( Exponent.IsZero() )
              {
              Result.SetFromULong( 1 );
              return;
              }

            if( GeneralBase.ParamIsGreater( Result ))
              {
              // throw( new Exception( "This is not supposed to be input for RSA plain text." ));
              IntMath.Divide( Result, GeneralBase, Quotient, Remainder );
              Result.Copy( Remainder );
              }

            if( Exponent.IsEqualToULong( 1 ))
              {
              // Result stays the same.
              return;
              }

            // This could also be called ahead of time if the base (the modulus)
            // doesn't change.  Like when your public key doesn't change.
            SetupGeneralBaseArray( GeneralBase );

            XForModPower.Copy( Result );
            ExponentCopy.Copy( Exponent );
            int TestIndex = 0;
            Result.SetFromULong( 1 );
            while( true )
              {
              if( (ExponentCopy.GetD( 0 ) & 1) == 1 ) // If the bottom bit is 1.
            {
            IntMath.Multiply( Result, XForModPower );

            // Modular Reduction:
            AddByGeneralBaseArrays( TempForModPower, Result );
            Result.Copy( TempForModPower );
            }

              ExponentCopy.ShiftRight( 1 ); // Divide by 2.
              if( ExponentCopy.IsZero())
            break;

              // Square it.
              IntMath.Multiply( XForModPower, XForModPower );

              // Modular Reduction:
              AddByGeneralBaseArrays( TempForModPower, XForModPower );
              XForModPower.Copy( TempForModPower );
              }

            // When AddByGeneralBaseArrays() gets called it multiplies a number
            // by a uint sized digit.  So that can make the result one digit bigger
            // than GeneralBase.  Then when they are added up you can get carry
            // bits that can make it a little bigger.
            // If by chance you got a carry bit on _every_ addition that was done
            // in AddByGeneralBaseArrays() then this number could increase in size
            // by 1 bit for each addition that was done.  It would take 32 bits of
            // carrying for HowBig to increase by 1.
            // See HowManyToAdd in AddByGeneralBaseArrays() for why this check is done.
            int HowBig = Result.GetIndex() - GeneralBase.GetIndex();
            if( HowBig > 2 ) // I have not seen this happen yet.
              throw( new Exception( "The difference in index size was more than 2. Diff: " + HowBig.ToString() ));

            // So this Quotient has only one or two 32-bit digits in it.
            // And this Divide() is only called once at the end.  Not in the loop.
            IntMath.Divide( Result, GeneralBase, Quotient, Remainder );
            Result.Copy( Remainder );
        }
예제 #12
0
        // This is the Modular Reduction algorithm.  It reduces
        // ToAdd to Result.
        private int AddByGeneralBaseArrays( Integer Result, Integer ToAdd )
        {
            try
            {
            if( GeneralBaseArray == null )
              throw( new Exception( "SetupGeneralBaseArray() should have already been called." ));

            Result.SetToZero();

            // The Index size of ToAdd is usually double the length of the modulus
            // this is reducing it to.  Like if you multiply P and Q to get N, then
            // the ToAdd that comes in here is about the size of N and the GeneralBase
            // is about the size of P.  So the amount of work done here is proportional
            // to P times N.

            int HowManyToAdd = ToAdd.GetIndex() + 1;
            int BiggestIndex = 0;
            for( int Count = 0; Count < HowManyToAdd; Count++ )
              {
              // The size of the numbers in GeneralBaseArray are all less than
              // the size of GeneralBase.
              // This multiplication by a uint is with a number that is not bigger
              // than GeneralBase.  Compare this with the two full Muliply()
              // calls done on each digit of the quotient in LongDivide3().

              // AccumulateArray[Count] is set to a new value here.
              int CheckIndex = IntMath.MultiplyUIntFromCopy( AccumulateArray[Count], GeneralBaseArray[Count], ToAdd.GetD( Count ));
              if( CheckIndex > BiggestIndex )
            BiggestIndex = CheckIndex;

              }

            // Add all of them up at once.
            AddUpAccumulateArray( Result, HowManyToAdd, BiggestIndex );

            return Result.GetIndex();
            }
            catch( Exception Except )
              {
              throw( new Exception( "Exception in AddByGeneralBaseArrays(): " + Except.Message ));
              }
        }
예제 #13
0
        internal bool GetProduct( Integer BigIntToSet )
        {
            BigIntToSet.SetToZero();
            if( !AllProductBitsAreKnown())
              return false;

            int Highest = GetHighestProductBitIndex();
            for( int Row = Highest; Row >= 0; Row-- )
              {
              // The first time through it will just shift zero
              // to the left, so nothing happens with zero.
              BigIntToSet.ShiftLeft( 1 );

              uint ToSet = MultArray[Row].OneLine[0];
              if( GetAccumOutValue( ToSet ))
            {
            ulong D = BigIntToSet.GetD( 0 );
            D |= 1;
            BigIntToSet.SetD( 0, D );
            }
              }

            return true;
        }