示例#1
0
        internal bool FindMultiplicativeInverseSmall( Integer ToFind, Integer KnownNumber, Integer Modulus, BackgroundWorker Worker )
        {
            // This method is for: KnownNumber * ToFind = 1 mod Modulus
            // An example:
            // PublicKeyExponent * X = 1 mod PhiN.
            // PublicKeyExponent * X = 1 mod (P - 1)(Q - 1).
            // This means that
            // (PublicKeyExponent * X) = (Y * PhiN) + 1
            // X is less than PhiN.
            // So Y is less than PublicKExponent.
            // Y can't be zero.
            // If this equation can be solved then it can be solved modulo
            // any number.  So it has to be solvable mod PublicKExponent.
            // See: Hasse Principle.
            // This also depends on the idea that the KnownNumber is prime and
            // that there is one unique modular inverse.

            // if( !KnownNumber-is-a-prime )
            //    then it won't work.

            if( !KnownNumber.IsULong())
              throw( new Exception( "FindMultiplicativeInverseSmall() was called with too big of a KnownNumber." ));

            ulong KnownNumberULong  = KnownNumber.GetAsULong();
            //                       65537
            if( KnownNumberULong > 1000000 )
              throw( new Exception( "KnownNumberULong > 1000000. FindMultiplicativeInverseSmall() was called with too big of an exponent." ));

            // (Y * PhiN) + 1 mod PubKExponent has to be zero if Y is a solution.
            ulong ModulusModKnown = IntMath.GetMod32( Modulus, KnownNumberULong );
            Worker.ReportProgress( 0, "ModulusModExponent: " + ModulusModKnown.ToString( "N0" ));
            if( Worker.CancellationPending )
              return false;

            // Y can't be zero.
            // The exponent is a small number like 65537.
            for( uint Y = 1; Y < (uint)KnownNumberULong; Y++ )
              {
              ulong X = (ulong)Y * ModulusModKnown;
              X++; // Add 1 to it for (Y * PhiN) + 1.
              X = X % KnownNumberULong;
              if( X == 0 )
            {
            if( Worker.CancellationPending )
              return false;

            // What is PhiN mod 65537?
            // That gives me Y.
            // The private key exponent is X*65537 + ModPart
            // The CipherText raised to that is the PlainText.

            // P + zN = C^(X*65537 + ModPart)
            // P + zN = C^(X*65537)(C^ModPart)
            // P + zN = ((C^65537)^X)(C^ModPart)

            Worker.ReportProgress( 0, "Found Y at: " + Y.ToString( "N0" ));
            ToFind.Copy( Modulus );
            IntMath.MultiplyULong( ToFind, Y );
            ToFind.AddULong( 1 );
            IntMath.Divide( ToFind, KnownNumber, Quotient, Remainder );
            if( !Remainder.IsZero())
              throw( new Exception( "This can't happen. !Remainder.IsZero()" ));

            ToFind.Copy( Quotient );
            // Worker.ReportProgress( 0, "ToFind: " + ToString10( ToFind ));
            break;
            }
              }

            if( Worker.CancellationPending )
              return false;

            TestForModInverse1.Copy( ToFind );
            IntMath.MultiplyULong( TestForModInverse1, KnownNumberULong );
            IntMath.Divide( TestForModInverse1, Modulus, Quotient, Remainder );
            if( !Remainder.IsOne())
              {
              // The definition is that it's congruent to 1 mod the modulus,
              // so this has to be 1.

              // I've only seen this happen once.  Were the primes P and Q not
              // really primes?
              throw( new Exception( "This is a bug. Remainder has to be 1: " + IntMath.ToString10( Remainder ) ));
              }

            return true;
        }
示例#2
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 ));
              }
        }
示例#3
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;
        }
示例#4
0
        private void FindXTheHardWay( Integer B, Integer Temp, ulong A )
        {
            Integer CountX = new Integer();
            CountX.SetToOne();
            while( true )
              {
              if( Worker.CancellationPending )
            return;

              Temp.Copy( CountX );
              IntMath.Multiply( Temp, B );
              Temp.AddULong( A );
              IntMath.Divide( Product, Temp, Quotient, Remainder );
              if( Remainder.IsZero())
            {
            if( !Quotient.IsOne())
              {
              SolutionP.Copy( Temp );
              SolutionQ.Copy( Quotient );
              return;
              }
            }

              CountX.Increment();
              if( MaxX.ParamIsGreater( CountX ))
            {
            // Worker.ReportProgress( 0, "Tried everything up to MaxX." );
            return;
            }
              }
        }