コード例 #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
ファイル: FindFactors.cs プロジェクト: Eric7Apps/BlogSource
        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;
        }
コード例 #3
0
ファイル: FindFactors.cs プロジェクト: Eric7Apps/BlogSource
        internal void VerifyFactors()
        {
            Integer TestFactors = new Integer();
            TestFactors.SetToOne();
            for( int Count = 0; Count < FactorsArrayLast; Count++ )
              IntMath.Multiply( TestFactors, FactorsArray[Count].Factor );

            if( !TestFactors.IsEqual( OriginalFindFrom ))
              throw( new Exception( "VerifyFactors didn't come out right." ));
        }
コード例 #4
0
ファイル: IntegerMath.cs プロジェクト: Eric7Apps/BlogSource
        /*
          internal void ModularPowerOld( Integer Result, Integer Exponent, Integer ModN )
        {
        if( Result.IsZero())
          return; // With Result still zero.

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

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

        if( ModN.ParamIsGreater( Result ))
          {
          Divide( Result, ModN, Quotient, Remainder );
          Result.Copy( Remainder );
          }

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

        XForModPower.Copy( Result );
        ExponentCopy.Copy( Exponent );
        Result.SetFromULong( 1 );
        while( !ExponentCopy.IsZero())
          {
          // If the bit is 1, then do a lot more work here.
          if( (ExponentCopy.GetD( 0 ) & 1) == 1 )
        {
        // This is a multiplication for every _bit_.  So a 1024-bit
        // modulus means this gets called roughly 512 times.
        // The commonly used public exponent is 65537, which has
        // only two bits set to 1, the rest are all zeros.  But the
        // private key exponents are long randomish numbers.
        // (See: Hamming Weight.)
        Multiply( Result, XForModPower );
        SubtractULong( ExponentCopy, 1 );
        // Usually it's true that the Result is greater than ModN.
        if( ModN.ParamIsGreater( Result ))
          {
          // Here is where that really long division algorithm gets used a
          // lot in a loop.  And this Divide() gets called roughly about
          // 512 times.
          Divide( Result, ModN, Quotient, Remainder );
          Result.Copy( Remainder );
          }
        }

          // Square it.
          // This is a multiplication for every _bit_.  So a 1024-bit
          // modulus means this gets called 1024 times.
          Multiply( XForModPower, XForModPower );
          ExponentCopy.ShiftRight( 1 ); // Divide by 2.
          if( ModN.ParamIsGreater( XForModPower ))
        {
        // And this Divide() gets called about 1024 times.
        Divide( XForModPower, ModN, Quotient, Remainder );
        XForModPower.Copy( Remainder );
        }
          }
        }
        */
        internal void GreatestCommonDivisor( Integer X, Integer Y, Integer Gcd )
        {
            // This is the basic Euclidean Algorithm.
            if( X.IsZero())
              throw( new Exception( "Doing GCD with a parameter that is zero." ));

            if( Y.IsZero())
              throw( new Exception( "Doing GCD with a parameter that is zero." ));

            if( X.IsEqual( Y ))
              {
              Gcd.Copy( X );
              return;
              }

            // Don't change the original numbers that came in as parameters.
            if( X.ParamIsGreater( Y ))
              {
              GcdX.Copy( Y );
              GcdY.Copy( X );
              }
            else
              {
              GcdX.Copy( X );
              GcdY.Copy( Y );
              }

            while( true )
              {
              Divide( GcdX, GcdY, Quotient, Remainder );
              if( Remainder.IsZero())
            {
            Gcd.Copy( GcdY ); // It's the smaller one.
            // It can't return from this loop until the remainder is zero.
            return;
            }

              GcdX.Copy( GcdY );
              GcdY.Copy( Remainder );
              }
        }
コード例 #5
0
ファイル: FactorBase.cs プロジェクト: Eric7Apps/BlogSource
        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 ));
              }
        }
コード例 #6
0
ファイル: IntegerMath.cs プロジェクト: Eric7Apps/BlogSource
        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;
              }
        }
コード例 #7
0
ファイル: IntegerMath.cs プロジェクト: Eric7Apps/BlogSource
        // Finding the square root of a number is similar to division since
        // it is a search algorithm.  The TestSqrtBits method shown next is
        // very much like TestDivideBits().  It works the same as
        // FindULSqrRoot(), but on a bigger scale.
        /*
          private void TestSqrtBits( int TestIndex, Integer Square, Integer SqrRoot )
        {
        Integer Test1 = new Integer();

        uint BitTest = 0x80000000;
        for( int BitCount = 31; BitCount >= 0; BitCount-- )
          {
          Test1.Copy( SqrRoot );
          Test1.D[TestIndex] |= BitTest;
          Test1.Square();
          if( !Square.ParamIsGreater( Test1 ) )
        SqrRoot.D[TestIndex] |= BitTest; // Use the bit.

          BitTest >>= 1;
          }
        }
        */
        // In the SquareRoot() method SqrRoot.Index is half of Square.Index.
        // Compare this to the Square() method where the Carry might or
        // might not increment the index to an odd number.  (So if the Index
        // was 5 its square root would have an Index of 5 / 2 = 2.)
        // The SquareRoot1() method uses FindULSqrRoot() either to find the
        // whole answer, if it's a small number, or it uses it to find the
        // top part.  Then from there it goes on to a bit by bit search
        // with TestSqrtBits().
        public bool SquareRoot( Integer Square, Integer SqrRoot )
        {
            ulong ToMatch;
            if( Square.IsULong() )
              {
              ToMatch = Square.GetAsULong();
              SqrRoot.SetD( 0, FindULSqrRoot( ToMatch ));
              SqrRoot.SetIndex( 0 );
              if( (SqrRoot.GetD(0 ) * SqrRoot.GetD( 0 )) == ToMatch )
            return true;
              else
            return false;

              }

            int TestIndex = Square.GetIndex() >> 1; // LgSquare.Index / 2;
            SqrRoot.SetDigitAndClear( TestIndex, 1 );
            // if( (TestIndex * 2) > (LgSquare.Index - 1) )
            if( (TestIndex << 1) > (Square.GetIndex() - 1) )
              {
              ToMatch = Square.GetD( Square.GetIndex());
              }
            else
              {
              // LgSquare.Index is at least 2 here.
              ToMatch = Square.GetD( Square.GetIndex()) << 32;
              ToMatch |= Square.GetD( Square.GetIndex() - 1 );
              }

            SqrRoot.SetD( TestIndex, FindULSqrRoot( ToMatch ));

            TestIndex--;
            while( true )
              {
              // TestSqrtBits( TestIndex, LgSquare, LgSqrRoot );
              SearchSqrtXPart( TestIndex, Square, SqrRoot );
              if( TestIndex == 0 )
            break;

              TestIndex--;
              }

            // Avoid squaring the whole thing to see if it's an exact square root:
            if( ((SqrRoot.GetD( 0 ) * SqrRoot.GetD( 0 )) & 0xFFFFFFFF) != Square.GetD( 0 ))
              return false;

            TestForSquareRoot.Copy( SqrRoot );
            DoSquare( TestForSquareRoot );
            if( Square.IsEqual( TestForSquareRoot ))
              return true;
            else
              return false;
        }
コード例 #8
0
        private void DoCRTTest( Integer StartingNumber )
        {
            CRTMath CRTMath1 = new CRTMath( Worker );
            ECTime CRTTestTime = new ECTime();
            ChineseRemainder CRTTest = new ChineseRemainder( IntMath );
            ChineseRemainder CRTTest2 = new ChineseRemainder( IntMath );
            ChineseRemainder CRTAccumulate = new ChineseRemainder( IntMath );
            ChineseRemainder CRTToTest = new ChineseRemainder( IntMath );
            ChineseRemainder CRTTempEqual = new ChineseRemainder( IntMath );
            ChineseRemainder CRTTestEqual = new ChineseRemainder( IntMath );
            Integer BigBase = new Integer();
            Integer ToTest = new Integer();
            Integer Accumulate = new Integer();
            Integer Test1 = new Integer();
            Integer Test2 = new Integer();

            CRTTest.SetFromTraditionalInteger( StartingNumber );
            // If the digit array size isn't set right in relation to
            // Integer.DigitArraySize then it can cause an error here.
            CRTMath1.GetTraditionalInteger( Accumulate, CRTTest );

            if( !Accumulate.IsEqual( StartingNumber ))
              throw( new Exception( "  !Accumulate.IsEqual( Result )." ));

            CRTTestEqual.SetFromTraditionalInteger( Accumulate );
            if( !CRTMath1.IsEqualToInteger( CRTTestEqual, Accumulate ))
              throw( new Exception( "IsEqualToInteger() didn't work." ));

            // Make sure it works with even numbers too.
            Test1.Copy( StartingNumber );
            Test1.SetD( 0, Test1.GetD( 0 ) & 0xFE );
            CRTTest.SetFromTraditionalInteger( Test1 );
            CRTMath1.GetTraditionalInteger( Accumulate, CRTTest );

            if( !Accumulate.IsEqual( Test1 ))
              throw( new Exception( "For even numbers.  !Accumulate.IsEqual( Test )." ));
            ////////////

            // Make sure the size of this works with the Integer size because
            // an overflow is hard to find.
            CRTTestTime.SetToNow();
            Test1.SetToMaxValueForCRT();
            CRTTest.SetFromTraditionalInteger( Test1 );
            CRTMath1.GetTraditionalInteger( Accumulate, CRTTest );

            if( !Accumulate.IsEqual( Test1 ))
              throw( new Exception( "For the max value. !Accumulate.IsEqual( Test1 )." ));

            // Worker.ReportProgress( 0, "CRT Max test seconds: " + CRTTestTime.GetSecondsToNow().ToString( "N1" ));
            // Worker.ReportProgress( 0, "MaxValue: " + IntMath.ToString10( Accumulate ));
            // Worker.ReportProgress( 0, "MaxValue.Index: " + Accumulate.GetIndex().ToString());

            // Multiplicative Inverse test:
            Integer TestDivideBy = new Integer();
            Integer TestProduct = new Integer();
            ChineseRemainder CRTTestDivideBy = new ChineseRemainder( IntMath );
            ChineseRemainder CRTTestProduct = new ChineseRemainder( IntMath );

            TestDivideBy.Copy( StartingNumber );
            TestProduct.Copy( StartingNumber );
            IntMath.Multiply( TestProduct, TestDivideBy );

            CRTTestDivideBy.SetFromTraditionalInteger( TestDivideBy );
            CRTTestProduct.SetFromTraditionalInteger( TestDivideBy );
            CRTTestProduct.Multiply( CRTTestDivideBy );

            CRTMath1.GetTraditionalInteger( Accumulate, CRTTestProduct );

            if( !Accumulate.IsEqual( TestProduct ))
              throw( new Exception( "Multiply test was bad." ));

            IntMath.Divide( TestProduct, TestDivideBy, Quotient, Remainder );
            if( !Remainder.IsZero())
              throw( new Exception( "This test won't work unless it divides it exactly." ));

            ChineseRemainder CRTTestQuotient = new ChineseRemainder( IntMath );
            CRTMath1.MultiplicativeInverse( CRTTestProduct, CRTTestDivideBy, CRTTestQuotient );

            // Yes, multiplicative inverse is the same number
            // as with regular division.
            Integer TestQuotient = new Integer();
            CRTMath1.GetTraditionalInteger( TestQuotient, CRTTestQuotient );
            if( !TestQuotient.IsEqual( Quotient ))
              throw( new Exception( "Modular Inverse in DoCRTTest didn't work." ));

            // Subtract
            Test1.Copy( StartingNumber );
            IntMath.SetFromString( Test2, "12345678901234567890123456789012345" );

            CRTTest.SetFromTraditionalInteger( Test1 );
            CRTTest2.SetFromTraditionalInteger( Test2 );

            CRTTest.Subtract( CRTTest2 );
            IntMath.Subtract( Test1, Test2 );

            CRTMath1.GetTraditionalInteger( Accumulate, CRTTest );

            if( !Accumulate.IsEqual( Test1 ))
              throw( new Exception( "Subtract test was bad." ));

            // Add
            Test1.Copy( StartingNumber );
            IntMath.SetFromString( Test2, "12345678901234567890123456789012345" );

            CRTTest.SetFromTraditionalInteger( Test1 );
            CRTTest2.SetFromTraditionalInteger( Test2 );

            CRTTest.Add( CRTTest2 );
            IntMath.Add( Test1, Test2 );

            CRTMath1.GetTraditionalInteger( Accumulate, CRTTest );

            if( !Accumulate.IsEqual( Test1 ))
              throw( new Exception( "Add test was bad." ));

            /////////
            CRTBaseMath CBaseMath = new CRTBaseMath( Worker, CRTMath1 );

            ChineseRemainder CRTInput = new ChineseRemainder( IntMath );
            CRTInput.SetFromTraditionalInteger( StartingNumber );

            Test1.Copy( StartingNumber );
            IntMath.SetFromString( Test2, "12345678901234567890123456789012345" );
            IntMath.Add( Test1, Test2 );

            Integer TestModulus = new Integer();
            TestModulus.Copy( Test1 );
            ChineseRemainder CRTTestModulus = new ChineseRemainder( IntMath );
            CRTTestModulus.SetFromTraditionalInteger( TestModulus );

            Integer Exponent = new Integer();
            Exponent.SetFromULong( PubKeyExponentUint );

            CBaseMath.ModularPower( CRTInput, Exponent, CRTTestModulus, false );
            IntMath.IntMathNew.ModularPower( StartingNumber, Exponent, TestModulus, false );

            if( !CRTMath1.IsEqualToInteger( CRTInput, StartingNumber ))
              throw( new Exception( "CRTBase ModularPower() didn't work." ));

            CRTBase ExpTest = new CRTBase( IntMath );
            CBaseMath.SetFromCRTNumber( ExpTest, CRTInput );
            CBaseMath.GetExponentForm( ExpTest, 37 );

            // Worker.ReportProgress( 0, "CRT was good." );
        }
コード例 #9
0
        internal void MakeRSAKeys()
        {
            int ShowBits = (PrimeIndex + 1) * 32;
            // int TestLoops = 0;

            Worker.ReportProgress( 0, "Making RSA keys." );
            Worker.ReportProgress( 0, "Bits size is: " + ShowBits.ToString());

            // ulong Loops = 0;
            while( true )
              {
              if( Worker.CancellationPending )
            return;

              Thread.Sleep( 1 ); // Give up the time slice.  Let other things on the server run.

              // Make two prime factors.
              // Normally you'd only make new primes when you pay the Certificate
              // Authority for a new certificate.
              if( !MakeAPrime( PrimeP, PrimeIndex, 20 ))
            return;

              IntegerBase TestP = new IntegerBase();
              IntegerBaseMath IntBaseMath = new IntegerBaseMath( IntMath );
              string TestS = IntMath.ToString10( PrimeP );
              IntBaseMath.SetFromString( TestP, TestS );
              string TestS2 = IntBaseMath.ToString10( TestP );
              if( TestS != TestS2 )
            throw( new Exception( "TestS != TestS2 for IntegerBase." ));

              if( Worker.CancellationPending )
            return;

              if( !MakeAPrime( PrimeQ, PrimeIndex, 20 ))
            return;

              if( Worker.CancellationPending )
            return;

              // This is extremely unlikely.
              Integer Gcd = new Integer();
              IntMath.GreatestCommonDivisor( PrimeP, PrimeQ, Gcd );
              if( !Gcd.IsOne())
            {
            Worker.ReportProgress( 0, "They had a GCD: " + IntMath.ToString10( Gcd ));
            continue;
            }

              if( Worker.CancellationPending )
            return;

              // This would never happen since the public key exponent used here
              // is one of the small primes in the array in IntegerMath that it
              // was checked against.  But it does show here in the code that
              // they have to be co-prime to each other.  And in the future it
              // might be found that the public key exponent has to be much larger
              // than the one used here.
              IntMath.GreatestCommonDivisor( PrimeP, PubKeyExponent, Gcd );
              if( !Gcd.IsOne())
            {
            Worker.ReportProgress( 0, "They had a GCD with PubKeyExponent: " + IntMath.ToString10( Gcd ));
            continue;
            }

              if( Worker.CancellationPending )
            return;

              IntMath.GreatestCommonDivisor( PrimeQ, PubKeyExponent, Gcd );
              if( !Gcd.IsOne())
            {
            Worker.ReportProgress( 0, "2) They had a GCD with PubKeyExponent: " + IntMath.ToString10( Gcd ));
            continue;
            }

              // For Modular Reduction.  This only has to be done
              // once, when P and Q are made.
              IntMathNewForP.SetupGeneralBaseArray( PrimeP );
              IntMathNewForQ.SetupGeneralBaseArray( PrimeQ );

              PrimePMinus1.Copy( PrimeP );
              IntMath.SubtractULong( PrimePMinus1, 1 );
              PrimeQMinus1.Copy( PrimeQ );
              IntMath.SubtractULong( PrimeQMinus1, 1 );

              // These checks should be more thorough.

              if( Worker.CancellationPending )
            return;

              Worker.ReportProgress( 0, "The Index of Prime P is: " + PrimeP.GetIndex().ToString() );
              Worker.ReportProgress( 0, "Prime P:" );
              Worker.ReportProgress( 0, IntMath.ToString10( PrimeP ));
              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "Prime Q:" );
              Worker.ReportProgress( 0, IntMath.ToString10( PrimeQ ));
              Worker.ReportProgress( 0, " " );

              PubKeyN.Copy( PrimeP );
              IntMath.Multiply( PubKeyN, PrimeQ );

              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "PubKeyN:" );
              Worker.ReportProgress( 0, IntMath.ToString10( PubKeyN ));
              Worker.ReportProgress( 0, " " );

              // Euler's Theorem:
              // https://en.wikipedia.org/wiki/Euler's_theorem
              // if x ≡ y (mod φ(n)),
              // then a^x ≡ a^y (mod n).

              // Euler's Phi function (aka Euler's Totient function) is calculated
              // next.

              // PhiN is made from the two factors: (P - 1)(Q - 1)
              // PhiN is: (P - 1)(Q - 1) = PQ - P - Q + 1
              // If I add (P - 1) to PhiN I get:
              // PQ - P - Q + 1 + (P - 1) = PQ - Q.
              // If I add (Q - 1) to that I get:
              // PQ - Q + (Q - 1) = PQ - 1.
              // (P - 1)(Q - 1) + (P - 1) + (Q - 1) = PQ - 1

              // If (P - 1) and (Q - 1) had a larger GCD then PQ - 1 would have
              // that same factor too.

              IntMath.GreatestCommonDivisor( PrimePMinus1, PrimeQMinus1, Gcd );
              Worker.ReportProgress( 0, "GCD of PrimePMinus1, PrimeQMinus1 is: " + IntMath.ToString10( Gcd ));

              if( !Gcd.IsULong())
            {
            Worker.ReportProgress( 0, "This GCD number is too big: " + IntMath.ToString10( Gcd ));
            continue;
            }
              else
            {
            ulong TooBig = Gcd.GetAsULong();
            // How big of a GCD is too big?
            if( TooBig > 1234567 )
              {
              // (P - 1)(Q - 1) + (P - 1) + (Q - 1) = PQ - 1
              Worker.ReportProgress( 0, "This GCD number is bigger than 1234567: " + IntMath.ToString10( Gcd ));
              continue;
              }
            }

              Integer Temp1 = new Integer();

              PhiN.Copy( PrimePMinus1 );
              Temp1.Copy( PrimeQMinus1 );
              IntMath.Multiply( PhiN, Temp1 );

              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "PhiN:" );
              Worker.ReportProgress( 0, IntMath.ToString10( PhiN ));
              Worker.ReportProgress( 0, " " );
              if( Worker.CancellationPending )
            return;

              // In RFC 2437 there are commonly used letters/symbols to represent
              // the numbers used.  So the number e is the public exponent.
              // The number e that is used here is called PubKeyExponentUint = 65537.
              // In the RFC the private key d is the multiplicative inverse of
              // e mod PhiN.  Which is mod (P - 1)(Q - 1).  It's called
              // PrivKInverseExponent here.

              if( !IntMath.IntMathNew.FindMultiplicativeInverseSmall( PrivKInverseExponent, PubKeyExponent, PhiN, Worker ))
            return;

              if( PrivKInverseExponent.IsZero())
            continue;

              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "PrivKInverseExponent: " + IntMath.ToString10( PrivKInverseExponent ));

              if( Worker.CancellationPending )
            return;

              // In RFC 2437 it defines a number dP which is the multiplicative
              // inverse, mod (P - 1) of e.  That dP is named PrivKInverseExponentDP here.
              Worker.ReportProgress( 0, " " );
              if( !IntMath.IntMathNew.FindMultiplicativeInverseSmall( PrivKInverseExponentDP, PubKeyExponent, PrimePMinus1, Worker ))
            return;

              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "PrivKInverseExponentDP: " + IntMath.ToString10( PrivKInverseExponentDP ));
              if( PrivKInverseExponentDP.IsZero())
            continue;

              // PrivKInverseExponentDP is PrivKInverseExponent mod PrimePMinus1.
              Integer Test1 = new Integer();
              Test1.Copy( PrivKInverseExponent );
              IntMath.Divide( Test1, PrimePMinus1, Quotient, Remainder );
              Test1.Copy( Remainder );
              if( !Test1.IsEqual( PrivKInverseExponentDP ))
            throw( new Exception( "Bug. This does not match the definition of PrivKInverseExponentDP." ));

              if( Worker.CancellationPending )
            return;

              // In RFC 2437 it defines a number dQ which is the multiplicative
              // inverse, mod (Q - 1) of e.  That dQ is named PrivKInverseExponentDQ here.
              Worker.ReportProgress( 0, " " );
              if( !IntMath.IntMathNew.FindMultiplicativeInverseSmall( PrivKInverseExponentDQ, PubKeyExponent, PrimeQMinus1, Worker ))
            return;

              if( PrivKInverseExponentDQ.IsZero())
            continue;

              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "PrivKInverseExponentDQ: " + IntMath.ToString10( PrivKInverseExponentDQ ));
              if( Worker.CancellationPending )
            return;

              Test1.Copy( PrivKInverseExponent );
              IntMath.Divide( Test1, PrimeQMinus1, Quotient, Remainder );
              Test1.Copy( Remainder );
              if( !Test1.IsEqual( PrivKInverseExponentDQ ))
            throw( new Exception( "Bug. This does not match the definition of PrivKInverseExponentDQ." ));

              // Make a random number to test encryption/decryption.
              Integer ToEncrypt = new Integer();
              int HowManyBytes = PrimeIndex * 4;
              byte[] RandBytes = MakeRandomBytes( HowManyBytes );
              if( RandBytes == null )
            {
            Worker.ReportProgress( 0, "Error making random bytes in MakeRSAKeys()." );
            return;
            }

              if( !ToEncrypt.MakeRandomOdd( PrimeIndex - 1, RandBytes ))
            {
            Worker.ReportProgress( 0, "Error making random number ToEncrypt." );
            return;
            }

              Integer PlainTextNumber = new Integer();
              PlainTextNumber.Copy( ToEncrypt );

              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "Before encrypting number: " + IntMath.ToString10( ToEncrypt ));
              Worker.ReportProgress( 0, " " );

              IntMath.IntMathNew.ModularPower( ToEncrypt, PubKeyExponent, PubKeyN, false );
              if( Worker.CancellationPending )
            return;

              Worker.ReportProgress( 0, IntMath.GetStatusString() );

              Integer CipherTextNumber = new Integer();
              CipherTextNumber.Copy( ToEncrypt );

              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "Encrypted number: " + IntMath.ToString10( CipherTextNumber ));
              Worker.ReportProgress( 0, " " );

              ECTime DecryptTime = new ECTime();
              DecryptTime.SetToNow();
              IntMath.IntMathNew.ModularPower( ToEncrypt, PrivKInverseExponent, PubKeyN, false );
              Worker.ReportProgress( 0, "Decrypted number: " + IntMath.ToString10( ToEncrypt ));

              if( !PlainTextNumber.IsEqual( ToEncrypt ))
            {
            throw( new Exception( "PlainTextNumber not equal to unencrypted value." ));
            // Because P or Q wasn't really a prime?
            // Worker.ReportProgress( 0, "PlainTextNumber not equal to unencrypted value." );
            // continue;
            }

              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "Decrypt time seconds: " + DecryptTime.GetSecondsToNow().ToString( "N2" ));
              Worker.ReportProgress( 0, " " );
              if( Worker.CancellationPending )
            return;

              // Test the standard optimized way of decrypting:
              if( !ToEncrypt.MakeRandomOdd( PrimeIndex - 1, RandBytes ))
            {
            Worker.ReportProgress( 0, "Error making random number in MakeRSAKeys()." );
            return;
            }

              PlainTextNumber.Copy( ToEncrypt );
              IntMath.IntMathNew.ModularPower( ToEncrypt, PubKeyExponent, PubKeyN, false );
              if( Worker.CancellationPending )
            return;

              CipherTextNumber.Copy( ToEncrypt );

              // QInv is the multiplicative inverse of PrimeQ mod PrimeP.
              if( !IntMath.MultiplicativeInverse( PrimeQ, PrimeP, QInv, Worker ))
            throw( new Exception( "MultiplicativeInverse() returned false." ));

              if( QInv.IsNegative )
            throw( new Exception( "This is a bug. QInv is negative." ));

              Worker.ReportProgress( 0, "QInv is: " + IntMath.ToString10( QInv ));

              DecryptWithQInverse( CipherTextNumber,
                           ToEncrypt, // Decrypt it to this.
                           PlainTextNumber, // Test it against this.
                           PubKeyN,
                           PrivKInverseExponentDP,
                           PrivKInverseExponentDQ,
                           PrimeP,
                           PrimeQ,
                           Worker );

              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "Found the values:" );
              Worker.ReportProgress( 0, "Seconds: " + StartTime.GetSecondsToNow().ToString( "N0" ));
              Worker.ReportProgress( 0, " " );

              Worker.ReportProgress( 1, "Prime1: " + IntMath.ToString10( PrimeP ));
              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 1, "Prime2: " + IntMath.ToString10( PrimeQ ));
              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 1, "PubKeyN: " + IntMath.ToString10( PubKeyN ));
              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 1, "PrivKInverseExponent: " + IntMath.ToString10( PrivKInverseExponent ));

              /*
              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, " " );
              DoCRTTest( PrivKInverseExponent );
              Worker.ReportProgress( 0, "Finished CRT test." );
              Worker.ReportProgress( 0, " " );
              */

              return; // Comment this out to just leave it while( true ) for testing.
              }
        }
コード例 #10
0
        internal bool DecryptWithQInverse( Integer EncryptedNumber,
                                     Integer DecryptedNumber,
                                     Integer TestDecryptedNumber,
                                     Integer PubKeyN,
                                     Integer PrivKInverseExponentDP,
                                     Integer PrivKInverseExponentDQ,
                                     Integer PrimeP,
                                     Integer PrimeQ,
                                     BackgroundWorker Worker )
        {
            Worker.ReportProgress( 0, " " );
            Worker.ReportProgress( 0, "Top of DecryptWithQInverse()." );

            // QInv and the dP and dQ numbers are normally already set up before
            // you start your listening socket.
            ECTime DecryptTime = new ECTime();
            DecryptTime.SetToNow();

            // See section 5.1.2 of RFC 2437 for these steps:
            // http://tools.ietf.org/html/rfc2437
            //      2.2 Let m_1 = c^dP mod p.
            //      2.3 Let m_2 = c^dQ mod q.
            //      2.4 Let h = qInv ( m_1 - m_2 ) mod p.
            //      2.5 Let m = m_2 + hq.

            Worker.ReportProgress( 0, "EncryptedNumber: " + IntMath.ToString10( EncryptedNumber ));

            //      2.2 Let m_1 = c^dP mod p.
            TestForDecrypt.Copy( EncryptedNumber );
            IntMathNewForP.ModularPower( TestForDecrypt, PrivKInverseExponentDP, PrimeP, true );
            if( Worker.CancellationPending )
              return false;

            M1ForInverse.Copy( TestForDecrypt );

            //      2.3 Let m_2 = c^dQ mod q.
            TestForDecrypt.Copy( EncryptedNumber );
            IntMathNewForQ.ModularPower( TestForDecrypt, PrivKInverseExponentDQ, PrimeQ, true );

            if( Worker.CancellationPending )
              return false;

            M2ForInverse.Copy( TestForDecrypt );

            //      2.4 Let h = qInv ( m_1 - m_2 ) mod p.

            // How many is optimal to avoid the division?
            int HowManyIsOptimal = (PrimeP.GetIndex() * 3);
            for( int Count = 0; Count < HowManyIsOptimal; Count++ )
              {
              if( M1ForInverse.ParamIsGreater( M2ForInverse ))
            M1ForInverse.Add( PrimeP );
              else
            break;

              }

            if( M1ForInverse.ParamIsGreater( M2ForInverse ))
              {
              M1M2SizeDiff.Copy( M2ForInverse );
              IntMath.Subtract( M1M2SizeDiff, M1ForInverse );
              // Unfortunately this long Divide() has to be done.
              IntMath.Divide( M1M2SizeDiff, PrimeP, Quotient, Remainder );
              Quotient.AddULong( 1 );
              Worker.ReportProgress( 0, "The Quotient for M1M2SizeDiff is: " + IntMath.ToString10( Quotient ));
              IntMath.Multiply( Quotient, PrimeP );
              M1ForInverse.Add( Quotient );
              }

            M1MinusM2.Copy( M1ForInverse );
            IntMath.Subtract( M1MinusM2, M2ForInverse );

            if( M1MinusM2.IsNegative )
              throw( new Exception( "This is a bug. M1MinusM2.IsNegative is true." ));

            if( QInv.IsNegative )
              throw( new Exception( "This is a bug. QInv.IsNegative is true." ));

            HForQInv.Copy( M1MinusM2 );
            IntMath.Multiply( HForQInv, QInv );

            if( HForQInv.IsNegative )
              throw( new Exception( "This is a bug. HForQInv.IsNegative is true." ));

            if( PrimeP.ParamIsGreater( HForQInv ))
              {
              IntMath.Divide( HForQInv, PrimeP, Quotient, Remainder );
              HForQInv.Copy( Remainder );
              }

            //      2.5 Let m = m_2 + hq.
            DecryptedNumber.Copy( HForQInv );
            IntMath.Multiply( DecryptedNumber, PrimeQ );
            DecryptedNumber.Add( M2ForInverse );
            if( !TestDecryptedNumber.IsEqual( DecryptedNumber ))
              throw( new Exception( "!TestDecryptedNumber.IsEqual( DecryptedNumber )." ));

            Worker.ReportProgress( 0, " " );
            Worker.ReportProgress( 0, "DecryptedNumber: " + IntMath.ToString10( DecryptedNumber ));
            Worker.ReportProgress( 0, " " );
            Worker.ReportProgress( 0, "TestDecryptedNumber: " + IntMath.ToString10( TestDecryptedNumber ));
            Worker.ReportProgress( 0, " " );
            Worker.ReportProgress( 0, "Decrypt with QInv time seconds: " + DecryptTime.GetSecondsToNow().ToString( "N2" ));
            Worker.ReportProgress( 0, " " );
            return true;
        }
コード例 #11
0
        private bool GetFactors( Integer Y, ExponentVectorNumber XExp )
        {
            Integer XRoot = new Integer();
            Integer X = new Integer();
            Integer XwithY = new Integer();
            Integer Gcd = new Integer();
            XExp.GetTraditionalInteger( X );
            if( !IntMath.SquareRoot( X, XRoot ))
              throw( new Exception( "Bug. X should have an exact square root." ));

            XwithY.Copy( Y );
            XwithY.Add( XRoot );
            IntMath.GreatestCommonDivisor( Product, XwithY, Gcd );
            if( !Gcd.IsOne())
              {
              if( !Gcd.IsEqual( Product ))
            {
            SolutionP.Copy( Gcd );
            IntMath.Divide( Product, SolutionP, Quotient, Remainder );
            if( !Remainder.IsZero())
              throw( new Exception( "The Remainder with SolutionP can't be zero." ));

            SolutionQ.Copy( Quotient );
            MForm.ShowStatus( "SolutionP: " + IntMath.ToString10( SolutionP ));
            MForm.ShowStatus( "SolutionQ: " + IntMath.ToString10( SolutionQ ));
            return true;
            }
              else
            {
            MForm.ShowStatus( "GCD was Product." );
            }
              }
            else
              {
              MForm.ShowStatus( "GCD was one." );
              }

            MForm.ShowStatus( "XRoot: " + IntMath.ToString10( XRoot ));
            MForm.ShowStatus( "Y: " + IntMath.ToString10( Y ));

            XwithY.Copy( Y );
            if( Y.ParamIsGreater( XRoot ))
              throw( new Exception( "This can't be right. XRoot is bigger than Y." ));

            IntMath.Subtract( Y, XRoot );
            IntMath.GreatestCommonDivisor( Product, XwithY, Gcd );
            if( !Gcd.IsOne())
              {
              if( !Gcd.IsEqual( Product ))
            {
            SolutionP.Copy( Gcd );
            IntMath.Divide( Product, SolutionP, Quotient, Remainder );
            if( !Remainder.IsZero())
              throw( new Exception( "The Remainder with SolutionP can't be zero." ));

            SolutionQ.Copy( Quotient );
            MForm.ShowStatus( "SolutionP: " + IntMath.ToString10( SolutionP ));
            MForm.ShowStatus( "SolutionQ: " + IntMath.ToString10( SolutionQ ));
            return true;
            }
              else
            {
            MForm.ShowStatus( "GCD was Product." );
            }
              }
            else
              {
              MForm.ShowStatus( "GCD was one." );
              }

            return false;
        }
コード例 #12
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 );
        }