Example #1
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." );
        }
Example #2
0
        internal void FindAllFactors( Integer FindFromNotChanged )
        {
            // ShowStats(); // So far.

            OriginalFindFrom.Copy( FindFromNotChanged );
            FindFrom.Copy( FindFromNotChanged );

            NumbersTested++;
            ClearFactorsArray();
            Integer OneFactor;
            OneFactorRec Rec;

            // while( not forever )
            for( int Count = 0; Count < 1000; Count++ )
              {
              if( Worker.CancellationPending )
            return;

              uint SmallPrime = IntMath.IsDivisibleBySmallPrime( FindFrom );
              if( SmallPrime == 0 )
            break; // No more small primes.

              // Worker.ReportProgress( 0, "Found a small prime factor: " + SmallPrime.ToString() );
              AddToStats( SmallPrime );
              OneFactor = new Integer();
              OneFactor.SetFromULong( SmallPrime );
              Rec = new OneFactorRec();
              Rec.Factor = OneFactor;
              Rec.IsDefinitelyAPrime = true;
              AddFactorRec( Rec );
              if( FindFrom.IsULong())
            {
            ulong CheckLast = FindFrom.GetAsULong();
            if( CheckLast == SmallPrime )
              {
              Worker.ReportProgress( 0, "It only had small prime factors." );
              VerifyFactors();
              return; // It had only small prime factors.
              }
            }

              IntMath.Divide( FindFrom, OneFactor, Quotient, Remainder );
              if( !Remainder.IsZero())
            throw( new Exception( "Bug in FindAllFactors. Remainder is not zero." ));

              FindFrom.Copy( Quotient );
              if( FindFrom.IsOne())
            throw( new Exception( "Bug in FindAllFactors. This was already checked for 1." ));

              }

            // Worker.ReportProgress( 0, "No more small primes." );

            if( IsFermatPrimeAdded( FindFrom ))
              {
              VerifyFactors();
              return;
              }

            // while( not forever )
            for( int Count = 0; Count < 1000; Count++ )
              {
              if( Worker.CancellationPending )
            return;

              // If FindFrom is a ulong then this will go up to the square root of
              // FindFrom and return zero if it doesn't find it there.  So it can't
              // go up to the whole value of FindFrom.
              uint SmallFactor = NumberIsDivisibleByUInt( FindFrom );
              if( SmallFactor == 0 )
            break;

              // This is necessarily a prime because it was the smallest one found.
              AddToStats( SmallFactor );

              // Worker.ReportProgress( 0, "Found a small factor: " + SmallFactor.ToString( "N0" ));
              OneFactor = new Integer();
              OneFactor.SetFromULong( SmallFactor );
              Rec = new OneFactorRec();
              Rec.Factor = OneFactor;
              Rec.IsDefinitelyAPrime = true; // The smallest factor.  It is necessarily a prime.
              AddFactorRec( Rec );

              IntMath.Divide( FindFrom, OneFactor, Quotient, Remainder );
              if( !Remainder.IsZero())
            throw( new Exception( "Bug in FindAllFactors. Remainder is not zero. Second part." ));

              if( Quotient.IsOne())
            throw( new Exception( "This can't happen here.  It can't go that high." ));

              FindFrom.Copy( Quotient );

              if( IsFermatPrimeAdded( FindFrom ))
            {
            VerifyFactors();
            return;
            }
              }

            if( IsFermatPrimeAdded( FindFrom ))
              {
              VerifyFactors();
              return;
              }

            // If it got this far then it's definitely composite or definitely
            // small enough to factor.
            Integer P = new Integer();
            Integer Q = new Integer();
            bool TestedAllTheWay = FindTwoFactorsWithFermat( FindFrom, P, Q, 0 );

            if( !P.IsZero())
              {
              // Q is necessarily prime because it's bigger than the square root.
              // But P is not necessarily prime.
              // P is the smaller one, so add it first.
              if( IsFermatPrimeAdded( P ))
            {
            Worker.ReportProgress( 0, "P from Fermat method was probably a prime." );
            }
              else
            {
            OneFactor = new Integer();
            OneFactor.Copy( P );
            Rec = new OneFactorRec();
            Rec.Factor = OneFactor;
            Rec.IsDefinitelyNotAPrime = true;
            AddFactorRec( Rec );
            }

              Worker.ReportProgress( 0, "Q is necessarily prime." );
              OneFactor = new Integer();
              OneFactor.Copy( Q );
              Rec = new OneFactorRec();
              Rec.Factor = OneFactor;
              Rec.IsDefinitelyAPrime = true;
              AddFactorRec( Rec );
              }
            else
              {
              // Didn't find any with Fermat.
              OneFactor = new Integer();
              OneFactor.Copy( FindFrom );
              Rec = new OneFactorRec();
              Rec.Factor = OneFactor;
              if( TestedAllTheWay )
            Rec.IsDefinitelyAPrime = true;
              else
            Rec.IsDefinitelyNotAPrime = true;

              AddFactorRec( Rec );
              }

            Worker.ReportProgress( 0, "That's all it could find." );
            VerifyFactors();
        }
Example #3
0
        internal void SetupGeneralBaseArray( Integer GeneralBase )
        {
            // The input to the accumulator can be twice the bit length of GeneralBase.
            int HowMany = ((GeneralBase.GetIndex() + 1) * 2) + 10; // Plus some extra for carries...
            if( GeneralBaseArray == null )
              {
              GeneralBaseArray = new Integer[HowMany];
              }

            if( GeneralBaseArray.Length < HowMany )
              {
              GeneralBaseArray = new Integer[HowMany];
              }

            Integer Base = new Integer();
            Integer BaseValue = new Integer();
            Base.SetFromULong( 256 ); // 0x100
            IntMath.MultiplyUInt( Base, 256 ); // 0x10000
            IntMath.MultiplyUInt( Base, 256 ); // 0x1000000
            IntMath.MultiplyUInt( Base, 256 ); // 0x100000000 is the base of this number system.

            BaseValue.SetFromULong( 1 );
            for( int Count = 0; Count < HowMany; Count++ )
              {
              if( GeneralBaseArray[Count] == null )
            GeneralBaseArray[Count] = new Integer();

              IntMath.Divide( BaseValue, GeneralBase, Quotient, Remainder );
              GeneralBaseArray[Count].Copy( Remainder );

              // If this ever happened it would be a bug because
              // the point of copying the Remainder in to BaseValue
              // is to keep it down to a reasonable size.
              // And Base here is one bit bigger than a uint.
              if( Base.ParamIsGreater( Quotient ))
            throw( new Exception( "Bug. This never happens: Base.ParamIsGreater( Quotient )" ));

              // Keep it to mod GeneralBase so Divide() doesn't
              // have to do so much work.
              BaseValue.Copy( Remainder );
              IntMath.Multiply( BaseValue, Base );
              }
        }
        internal void GetTraditionalInteger( Integer BigBase,
                                       Integer BasePart,
                                       Integer ToTest,
                                       Integer Accumulate )
        {
            // This takes several seconds for a large number.
            try
            {
            // The first few numbers for the base:
            // 2             2
            // 3             6
            // 5            30
            // 7           210
            // 11        2,310
            // 13       30,030
            // 17      510,510
            // 19    9,699,690
            // 23  223,092,870

            // This first one has the prime 2 as its base so it's going to
            // be set to either zero or one.
            Accumulate.SetFromULong( (uint)DigitsArray[0].Value );
            BigBase.SetFromULong( 2 );

            // Count starts at 1, so it's the prime 3.
            for( int Count = 1; Count < DigitsArraySize; Count++ )
              {
              for( uint CountPrime = 0; CountPrime < DigitsArray[Count].Prime; CountPrime++ )
            {
            ToTest.Copy( BigBase );
            IntMath.MultiplyUInt( ToTest, CountPrime );
            // Notice that the first time through this loop it's zero, so the
            // base part isn't added if it's already congruent to the Value.
            // So even though it goes all the way up through the DigitsArray,
            // this whole thing could add up to a small number like 7.
            // Compare this part with how GetMod32() is used in
            // SetFromTraditionalInteger().  And also, compare this with how
            // IntegerMath.NumberIsDivisibleByUInt() works.
            BasePart.Copy( ToTest );
            ToTest.Add( Accumulate );
            // If it's congruent to the Value mod Prime then it's the right number.
            if( (uint)DigitsArray[Count].Value == IntMath.GetMod32( ToTest, (uint)DigitsArray[Count].Prime ))
              {
              Accumulate.Add( BasePart );
              break;
              }
            }

              // The Integers have to be big enough to multiply this base.
              IntMath.MultiplyUInt( BigBase, (uint)DigitsArray[Count].Prime );
              }

            // Returns with Accumulate for the value.

            }
            catch( Exception Except )
              {
              throw( new Exception( "Exception in GetTraditionalInteger(): " + Except.Message ));
              }
        }
Example #5
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;
        }
        internal bool FindTheFactors()
        {
            MakeQuadResToPrimesArray();
            if( Worker.CancellationPending )
              return false;

            // ===========
            MakeQuadResDigitsArrayRec( 0, 0, 7 );
            MakeQuadResDigitsArrayRec( 1, 8, 9 );
            MakeQuadResDigitsArrayRec( 2, 10, 10 );
            // The last one should have an array that is
            // as large as possible because of
            // IncrementDigitsWithBitTest().
            MakeQuadResDigitsArrayRec( 3, 11, 12 );
            if( Worker.CancellationPending )
              return false;

            SetupBaseValues();
            if( Worker.CancellationPending )
              return false;

            MakeMatchingInverseArrays();
            if( Worker.CancellationPending )
              return false;

            Worker.ReportProgress( 0, "After MakeMatchingInverseArrays()." );

            Integer X = new Integer();
            Integer XSquared = new Integer();
            Integer SqrRoot = new Integer();
            Integer YSquared = new Integer();

            MakeGoodXBitsArray();
            Worker.ReportProgress( 0, "After MakeGoodXBitsArray();." );

            uint Loops = 0;
            while( true )
              {
              if( Worker.CancellationPending )
            return false;

              Loops++;
              if( (Loops & 0x3FFFFF) == 0 )
            {
            Worker.ReportProgress( 0, "Loops: " + Loops.ToString());
            }

              GetIntegerValue( X );
              if( !IsInGoodXBitsArray( (uint)X.GetD( 0 )))
            {
            // This happens with the increment bit test
            // because sometimes it just increments to the
            // next full accumulated value.

            if( !IncrementDigitsWithBitTest())
              {
              Worker.ReportProgress( 0, "Incremented to the end." );
              return false;
              }

            continue;
            }

              if( !IsGoodXForAllPrimes( X ))
            {
            if( !IncrementDigitsWithBitTest())
              {
              Worker.ReportProgress( 0, "Incremented to the end." );
              return false;
              }

            continue;
            }

              XSquared.Copy( X );
              IntMath.DoSquare( XSquared );
              YSquared.Copy( Product );
              YSquared.Add( XSquared );

              if( IntMath.SquareRoot( YSquared, SqrRoot ))
            {
            return IsSolution( X, SqrRoot );
            }

              if( !IncrementDigitsWithBitTest())
            {
            Worker.ReportProgress( 0, "Incremented to the end." );
            return false;
            }
              }
        }
Example #7
0
        internal void TestBigDigits()
        {
            try
            {
            uint Base = 2 * 3 * 5;
            Integer BigBase = new Integer();
            Integer Minus1 = new Integer();
            Integer IntExponent = new Integer();
            Integer IntBase = new Integer();
            Integer Gcd = new Integer();

            BigBase.SetFromULong( Base );
            IntBase.SetFromULong( Base );

            for( uint Count = 2; Count < 200; Count++ )
              {
              // At Count = 2 BigBase will be 100, or 10^2.
              IntMath.MultiplyULong( BigBase, Base );
              uint Exponent = Count + 1;
              IntExponent.SetFromULong( Exponent );
              IntMath.GreatestCommonDivisor( IntBase, IntExponent, Gcd );
              if( !Gcd.IsOne() )
            {
            // ShowStatus( Exponent.ToString() + " has a factor in common with base." );
            continue;
            }

              Minus1.Copy( BigBase );
              IntMath.SubtractULong( Minus1, 1 );

              ShowStatus( " " );
              ulong ModExponent = IntMath.GetMod32( Minus1, Exponent );
              if( ModExponent != 0 )
            ShowStatus( Exponent.ToString() + " is not a prime." );
              else
            ShowStatus( Exponent.ToString() + " might or might not be a prime." );

              uint FirstFactor = IntMath.GetFirstPrimeFactor( Exponent );
              if( (FirstFactor == 0) ||
              (FirstFactor == Exponent))
            {
            ShowStatus( Exponent.ToString() + " is a prime." );
            }
              else
            {
            ShowStatus( Exponent.ToString() + " is composite with a factor of " + FirstFactor.ToString() );
            }
              }

            }
            catch( Exception Except )
              {
              ShowStatus( "Exception in TestDigits()." );
              ShowStatus( Except.Message );
              }
        }
Example #8
0
        // These bottom digits are 0 for each prime that gets
        // multiplied by the base.  So they keep getting one
        // more zero at the bottom of each one.
        // But the digits in BaseModArray only have the zeros
        // at the bottom on the ones that are smaller than the
        // modulus.
        // At BaseArray[0] it's 1, 1, 1, 1, 1, .... for all of them.
        // 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0
        // 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 0, 0
        // 30, 30, 30, 30, 1, 7, 11, 13, 4, 8, 2, 0, 0, 0
        private void SetupBaseArray()
        {
            // The first few numbers for the base:
            // 2             2
            // 3             6
            // 5            30
            // 7           210
            // 11        2,310
            // 13       30,030
            // 17      510,510
            // 19    9,699,690
            // 23  223,092,870

            try
            {
            if( NumbersArray == null )
              throw( new Exception( "NumbersArray should have already been setup in SetupBaseArray()." ));

            BaseStringsArray = new string[ChineseRemainder.DigitsArraySize];
            BaseArray = new Integer[ChineseRemainder.DigitsArraySize];
            CRTBaseArray = new ChineseRemainder[ChineseRemainder.DigitsArraySize];

            Integer SetBase = new Integer();
            ChineseRemainder CRTSetBase = new ChineseRemainder( IntMath );

            Integer BigBase = new Integer();
            ChineseRemainder CRTBigBase = new ChineseRemainder( IntMath );

            BigBase.SetFromULong( 2 );
            CRTBigBase.SetFromUInt( 2 );
            string BaseS = "2";

            SetBase.SetToOne();
            CRTSetBase.SetToOne();

            // The base at zero is 1.
            BaseArray[0] = SetBase;
            CRTBaseArray[0] = CRTSetBase;
            BaseStringsArray[0] = "1";

            ChineseRemainder CRTTemp = new ChineseRemainder( IntMath );

            // The first time through the loop the base
            // is set to 2.
            // So BaseArray[0] = 1;
            // So BaseArray[1] = 2;
            // So BaseArray[2] = 6;
            // So BaseArray[3] = 30;
            // And so on...
            // In BaseArray[3] digits at 2, 3 and 5 are set to zero.
            // In BaseArray[4] digits at 2, 3, 5 and 7 are set to zero.
            for( int Count = 1; Count < ChineseRemainder.DigitsArraySize; Count++ )
              {
              SetBase = new Integer();
              CRTSetBase = new ChineseRemainder( IntMath );

              SetBase.Copy( BigBase );
              CRTSetBase.Copy( CRTBigBase );

              BaseStringsArray[Count] = BaseS;
              BaseArray[Count] = SetBase;
              CRTBaseArray[Count] = CRTSetBase;
              // if( Count < 50 )
            // Worker.ReportProgress( 0, CRTBaseArray[Count].GetString() );

              if( !IsEqualToInteger( CRTBaseArray[Count],
                             BaseArray[Count] ))
            throw( new Exception( "Bug.  The bases aren't equal." ));

              // Multiply it for the next BigBase.
              uint Prime = IntMath.GetPrimeAt( Count );
              BaseS = BaseS + "*" + Prime.ToString();
              IntMath.MultiplyUInt( BigBase, Prime );
              CRTBigBase.Multiply( NumbersArray[IntMath.GetPrimeAt( Count )] );
              }
            }
            catch( Exception Except )
              {
              throw( new Exception( "Exception in SetupBaseArray(): " + Except.Message ));
              }
        }
Example #9
0
        internal bool MultiplicativeInverse( Integer X, Integer Modulus, Integer MultInverse, BackgroundWorker Worker )
        {
            // This is the extended Euclidean Algorithm.

            // A*X + B*Y = Gcd
            // A*X + B*Y = 1 If there's a multiplicative inverse.
            // A*X = 1 - B*Y so A is the multiplicative inverse of X mod Y.

            if( X.IsZero())
              throw( new Exception( "Doing Multiplicative Inverse with a parameter that is zero." ));

            if( Modulus.IsZero())
              throw( new Exception( "Doing Multiplicative Inverse with a parameter that is zero." ));

            // This happens sometimes:
            // if( Modulus.ParamIsGreaterOrEq( X ))
              // throw( new Exception( "Modulus.ParamIsGreaterOrEq( X ) for Euclid." ));

            // Worker.ReportProgress( 0, " " );
            // Worker.ReportProgress( 0, " " );
            // Worker.ReportProgress( 0, "Top of mod inverse." );

            // U is the old part to keep.
            U0.SetToZero();
            U1.SetToOne();
            U2.Copy( Modulus ); // Don't change the original numbers that came in as parameters.

            // V is the new part.
            V0.SetToOne();
            V1.SetToZero();
            V2.Copy( X );

            T0.SetToZero();
            T1.SetToZero();
            T2.SetToZero();
            Quotient.SetToZero();

            // while( not forever if there's a problem )
            for( int Count = 0; Count < 10000; Count++ )
              {
              if( U2.IsNegative )
            throw( new Exception( "U2 was negative." ));

              if( V2.IsNegative )
            throw( new Exception( "V2 was negative." ));

              Divide( U2, V2, Quotient, Remainder );
              if( Remainder.IsZero())
            {
            Worker.ReportProgress( 0, "Remainder is zero. No multiplicative-inverse." );
            return false;
            }

              TempEuclid1.Copy( U0 );
              TempEuclid2.Copy( V0 );
              Multiply( TempEuclid2, Quotient );
              Subtract( TempEuclid1, TempEuclid2 );
              T0.Copy( TempEuclid1 );

              TempEuclid1.Copy( U1 );
              TempEuclid2.Copy( V1 );
              Multiply( TempEuclid2, Quotient );
              Subtract( TempEuclid1, TempEuclid2 );
              T1.Copy( TempEuclid1 );

              TempEuclid1.Copy( U2 );
              TempEuclid2.Copy( V2 );
              Multiply( TempEuclid2, Quotient );
              Subtract( TempEuclid1, TempEuclid2 );
              T2.Copy( TempEuclid1 );

              U0.Copy( V0 );
              U1.Copy( V1 );
              U2.Copy( V2 );

              V0.Copy( T0 );
              V1.Copy( T1 );
              V2.Copy( T2 );

              if( Remainder.IsOne())
            {
            // Worker.ReportProgress( 0, " " );
            // Worker.ReportProgress( 0, "Remainder is 1. There is a multiplicative-inverse." );
            break;
            }
              }

            MultInverse.Copy( T0 );
            if( MultInverse.IsNegative )
              {
              Add( MultInverse, Modulus );
              }

            // Worker.ReportProgress( 0, "MultInverse: " + ToString10( MultInverse ));
            TestForModInverse1.Copy( MultInverse );
            TestForModInverse2.Copy( X );
            Multiply( TestForModInverse1, TestForModInverse2 );
            Divide( TestForModInverse1, Modulus, Quotient, Remainder );
            if( !Remainder.IsOne())  // By the definition of Multiplicative inverse:
              throw( new Exception( "Bug. MultInverse is wrong: " + ToString10( Remainder )));

            // Worker.ReportProgress( 0, "MultInverse is the right number: " + ToString10( MultInverse ));
            return true;
        }
Example #10
0
        internal void ModularPower( ChineseRemainder CRTResult,
                              Integer Exponent,
                              ChineseRemainder CRTModulus,
                              bool UsePresetBaseArray )
        {
            // The square and multiply method is in Wikipedia:
            // https://en.wikipedia.org/wiki/Exponentiation_by_squaring

            if( Worker.CancellationPending )
              return;

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

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

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

            Integer Result = new Integer();
            CRTMath1.GetTraditionalInteger( Result, CRTResult );

            Integer Modulus = new Integer();
            CRTMath1.GetTraditionalInteger( Modulus, CRTModulus );

            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 );
              CRTResult.SetFromTraditionalInteger( Remainder );
              }

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

            if( !UsePresetBaseArray )
              SetupBaseModArray( Modulus );

            if( CRTBaseModArray == null )
              throw( new Exception( "SetupBaseModArray() should have already been done here." ));

            CRTXForModPower.Copy( CRTResult );
            ExponentCopy.Copy( Exponent );
            int TestIndex = 0;
            CRTResult.SetToOne();

            int LoopsTest = 0;
            while( true )
              {
              LoopsTest++;
              if( (ExponentCopy.GetD( 0 ) & 1) == 1 ) // If the bottom bit is 1.
            {
            CRTResult.Multiply( CRTXForModPower );
            ModularReduction( CRTResult, CRTAccumulate );
            CRTResult.Copy( CRTAccumulate );
            }

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

              // Square it.
              CRTCopyForSquare.Copy( CRTXForModPower );
              CRTXForModPower.Multiply( CRTCopyForSquare );
              ModularReduction( CRTXForModPower, CRTAccumulate );
              CRTXForModPower.Copy( CRTAccumulate );
              }

            ModularReduction( CRTResult, CRTAccumulate );
            CRTResult.Copy( CRTAccumulate );

            // Division is never used in the loop above.

            // This is a very small Quotient.
            // See SetupBaseMultiples() for a description of how to calculate
            // the maximum size of this quotient.
            CRTMath1.GetTraditionalInteger( Result, CRTResult );
            IntMath.Divide( Result, Modulus, Quotient, Remainder );

            // Is the Quotient bigger than a 32 bit integer?
            if( Quotient.GetIndex() > 0 )
              throw( new Exception( "I haven't ever seen this happen. Quotient.GetIndex() > 0.  It is: " + Quotient.GetIndex().ToString() ));

            QuotientForTest = Quotient.GetAsULong();
            if( QuotientForTest > 2097867 )
              throw( new Exception( "This can never happen unless I increase ChineseRemainder.DigitsArraySize." ));

            Result.Copy( Remainder );
            CRTResult.SetFromTraditionalInteger( Remainder );
        }
Example #11
0
        // CRTBaseModArray doesn't have the pattern of zeros
        // down to the end like in CRTBaseArray.
        internal void SetupBaseModArray( Integer Modulus )
        {
            try
            {
            BaseModArrayModulus = Modulus;

            if( NumbersArray == null )
              throw( new Exception( "NumbersArray should have already been setup in SetupBaseModArray()." ));

            CRTBaseModArray = new ChineseRemainder[ChineseRemainder.DigitsArraySize];

            ChineseRemainder CRTSetBase = new ChineseRemainder( IntMath );

            Integer BigBase = new Integer();
            ChineseRemainder CRTBigBase = new ChineseRemainder( IntMath );

            BigBase.SetFromULong( 2 );
            CRTBigBase.SetFromUInt( 2 );

            CRTSetBase.SetToOne();
            CRTBaseModArray[0] = CRTSetBase;

            ChineseRemainder CRTTemp = new ChineseRemainder( IntMath );

            for( int Count = 1; Count < ChineseRemainder.DigitsArraySize; Count++ )
              {
              CRTSetBase = new ChineseRemainder( IntMath );
              CRTSetBase.Copy( CRTBigBase );
              CRTBaseModArray[Count] = CRTSetBase;

              // Multiply it for the next BigBase.
              IntMath.MultiplyUInt( BigBase, IntMath.GetPrimeAt( Count ));
              IntMath.Divide( BigBase, Modulus, Quotient, Remainder );
              BigBase.Copy( Remainder );
              CRTBigBase.SetFromTraditionalInteger( BigBase );
              }
            }
            catch( Exception Except )
              {
              throw( new Exception( "Exception in SetupBaseModArray(): " + Except.Message ));
              }
        }
Example #12
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 ));
              }
        }
Example #13
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;
            }
              }
        }
Example #14
0
        private void FindFactorsFromLeft( ulong A,
                                    ulong C,
                                    Integer Left,
                                    Integer Temp,
                                    Integer B )
        {
            if( Worker.CancellationPending )
              return;

            /*
            // (323 - 2*4 / 5) = xy5 + 2y + 4x
            // (315 / 5) = xy5 + 2y + 4x
            // 63 = xy5 + 2y + 4x
            // 21 * 3 = xy5 + 2y + 4x
            // 3*7*3 = xy5 + 2y + 4x
            // 3*7*3 = 3y5 + 2y + 4*3
            // 3*7*3 = 15y + 2y + 12
            // 3*7*3 - 12 = y(15 + 2)
            // 3*7*3 - 3*4 = y(15 + 2)
            // 51 = 3 * 17

            // (323 - 1*3 / 5) = xy5 + 1y + 3x
            // (320 / 5) = xy5 + 1y + 3x
            // 64 = xy5 + 1y + 3x
            // 64 - 3x = xy5 + 1y
            // 64 - 3x = y(x5 + 1)
            // 64 - 3x = y(x5 + 1)
            1 = y(x5 + 1) mod 3
            */

            Left.Copy( Product );
            Temp.SetFromULong( A * C );
            IntMath.Subtract( Left, Temp );
            IntMath.Divide( Left, B, Quotient, Remainder );
            if( !Remainder.IsZero())
              throw( new Exception( "Remainder is not zero for Left." ));

            Left.Copy( Quotient );
            // Worker.ReportProgress( 0, "Left: " + IntMath.ToString10( Left ));
            // Worker.ReportProgress( 0, "A: " + A.ToString() + "  C: " + C.ToString());

            FindFactors1.FindSmallPrimeFactorsOnly( Left );
            FindFactors1.ShowAllFactors();

            MaxX.Copy( ProductSqrRoot );
            Temp.SetFromULong( A );
            if( MaxX.ParamIsGreater( Temp ))
              return; // MaxX would be less than zero.

            IntMath.Subtract( MaxX, Temp );
            IntMath.Divide( MaxX, B, Quotient, Remainder );
            MaxX.Copy( Quotient );
            // Worker.ReportProgress( 0, "MaxX: " + IntMath.ToString10( MaxX ));

            Temp.Copy( MaxX );
            IntMath.MultiplyULong( Temp, C );
            if( Left.ParamIsGreater( Temp ))
              {
              throw( new Exception( "Does this happen?  MaxX can't be that big." ));
              /*
              Worker.ReportProgress( 0, "MaxX can't be that big." );
              MaxX.Copy( Left );
              Temp.SetFromULong( C );
              IntMath.Divide( MaxX, Temp, Quotient, Remainder );
              MaxX.Copy( Quotient );
              Worker.ReportProgress( 0, "MaxX was set to: " + IntMath.ToString10( MaxX ));
              */
              }

            // P = (xB + a)(yB + c)
            // P = (xB + a)(yB + c)
            // P - ac = xyBB + ayB + xBc
            // ((P - ac) / B) = xyB + ay + xc
            // ((P - ac) / B) = y(xB + a) + xc

            // This is congruent to zero mod one really big prime.
            // ((P - ac) / B) - xc = y(xB + a)

            // BottomPart is when x is at max in:
            // ((P - ac) / B) - xc
            Integer BottomPart = new Integer();
            BottomPart.Copy( Left );
            Temp.Copy( MaxX );
            IntMath.MultiplyULong( Temp, C );
            IntMath.Subtract( BottomPart, Temp );
            if( BottomPart.IsNegative )
              throw( new Exception( "Bug.  BottomPart is negative." ));

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

            Integer Gcd = new Integer();
            Temp.SetFromULong( C );
            IntMath.GreatestCommonDivisor( BottomPart, Temp, Gcd );
            if( !Gcd.IsOne())
              throw( new Exception( "This can't happen with the GCD." ));

            // FindFactors1.FindSmallPrimeFactorsOnly( BottomPart );
            // Temp.SetFromULong( C );
            // FindFactors1.FindSmallPrimeFactorsOnly( Temp );
            // FindFactors1.ShowAllFactors();

            MakeXYRecArray( Left, B, A, C );

            FindXTheHardWay( B, Temp, A );
        }
 private void CalculateLastAccumulatePart( Integer Accumulate )
 {
     try
     {
     Accumulate.Copy( LastAccumulateValue );
     uint CurrentBase = QuadResDigitsArray[DigitsArrayLength - 1].Base;
     // uint AccumulateDigit = GetMod32( Accumulate, CurrentBase );
     int DigitsIndex = QuadResDigitsArray[DigitsArrayLength - 1].DigitIndex;
     uint CountB = QuadResDigitsArray[DigitsArrayLength - 1].MatchingInverseArray[DigitsIndex, LastAccumulateDigit];
     GetValueBasePart.Copy( QuadResDigitsArray[DigitsArrayLength - 1].BigBase );
     IntMath.MultiplyUInt( GetValueBasePart, CountB );
     Accumulate.Add( GetValueBasePart );
     }
     catch( Exception Except )
       {
       throw( new Exception( "Exception in CalculateLastAccumulatePart(): " + Except.Message ));
       }
 }
Example #16
0
        // This is a variation on ShortDivide that returns the remainder.
        // Also, DivideBy is a ulong.
        internal ulong ShortDivideRem( Integer ToDivideOriginal,
                               ulong DivideByU,
                               Integer Quotient )
        {
            if( ToDivideOriginal.IsULong())
              {
              ulong ToDiv = ToDivideOriginal.GetAsULong();
              ulong Q = ToDiv / DivideByU;
              Quotient.SetFromULong( Q );
              return ToDiv % DivideByU;
              }

            ToDivide.Copy( ToDivideOriginal );
            Quotient.Copy( ToDivide );

            ulong RemainderU = 0;
            if( DivideByU > Quotient.GetD( Quotient.GetIndex() ))
              {
              Quotient.SetD( Quotient.GetIndex(), 0 );
              }
            else
              {
              ulong OneDigit = Quotient.GetD( Quotient.GetIndex() );
              Quotient.SetD( Quotient.GetIndex(), OneDigit / DivideByU );
              RemainderU = OneDigit % DivideByU;
              ToDivide.SetD( ToDivide.GetIndex(), RemainderU );
              }

            for( int Count = Quotient.GetIndex(); Count >= 1; Count-- )
              {
              ulong TwoDigits = ToDivide.GetD( Count );
              TwoDigits <<= 32;
              TwoDigits |= ToDivide.GetD( Count - 1 );

              Quotient.SetD( Count - 1, TwoDigits / DivideByU );
              RemainderU = TwoDigits % DivideByU;

              ToDivide.SetD( Count, 0 );
              ToDivide.SetD( Count - 1, RemainderU );
              }

            for( int Count = Quotient.GetIndex(); Count >= 0; Count-- )
              {
              if( Quotient.GetD( Count ) != 0 )
            {
            Quotient.SetIndex( Count );
            break;
            }
              }

            return RemainderU;
        }
        private bool IsQuadResModProduct( uint Prime )
        {
            // Euler's Criterion:
            Integer Exponent = new Integer();
            Integer Result = new Integer();
            Integer Modulus = new Integer();

            Exponent.SetFromULong( Prime );
            IntMath.SubtractULong( Exponent, 1 );
            Exponent.ShiftRight( 1 ); // Divide by 2.

            Result.Copy( Product );
            Modulus.SetFromULong( Prime );

            IntMath.IntMathNew.ModularPower( Result, Exponent, Modulus, false );
            if( Result.IsOne() )
              return true;
            else
              return false; // Result should be Prime - 1.
        }
Example #18
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;
              }
        }
Example #19
0
        private Integer MakeBigBase( Integer Max )
        {
            Integer Base = new Integer();
            Base.SetFromULong( 2 );
            Integer LastBase = new Integer();
            // Start at the prime 3.
            for( int Count = 1; Count < IntegerMath.PrimeArrayLength; Count++ )
              {
              uint Prime = IntMath.GetPrimeAt( Count );
              IntMath.MultiplyULong( Base, Prime );
              if( Max.ParamIsGreater( Base ))
            return LastBase;

              LastBase.Copy( Base );
              }

            return null;
        }
Example #20
0
        private void LongDivide3( Integer ToDivide,
                            Integer DivideBy,
                            Integer Quotient,
                            Integer Remainder )
        {
            int TestIndex = ToDivide.GetIndex() - DivideBy.GetIndex();
            if( TestIndex < 0 )
              throw( new Exception( "TestIndex < 0 in Divide3." ));

            if( TestIndex != 0 )
              {
              // Is 1 too high?
              TestForDivide1.SetDigitAndClear( TestIndex, 1 );
              MultiplyTopOne( TestForDivide1, DivideBy );
              if( ToDivide.ParamIsGreater( TestForDivide1 ))
            TestIndex--;

              }

            // Keep a copy of the originals.
            ToDivideKeep.Copy( ToDivide );
            DivideByKeep.Copy( DivideBy );

            ulong TestBits = DivideBy.GetD( DivideBy.GetIndex());
            int ShiftBy = FindShiftBy( TestBits );
            ToDivide.ShiftLeft( ShiftBy ); // Multiply the numerator and the denominator
            DivideBy.ShiftLeft( ShiftBy ); // by the same amount.

            ulong MaxValue;
            if( (ToDivide.GetIndex() - 1) > (DivideBy.GetIndex() + TestIndex) )
              {
              MaxValue = ToDivide.GetD( ToDivide.GetIndex());
              }
            else
              {
              MaxValue = ToDivide.GetD( ToDivide.GetIndex()) << 32;
              MaxValue |= ToDivide.GetD( ToDivide.GetIndex() - 1 );
              }

            ulong Denom = DivideBy.GetD( DivideBy.GetIndex());
            if( Denom != 0 )
              MaxValue = MaxValue / Denom;
            else
              MaxValue = 0xFFFFFFFF;

            if( MaxValue > 0xFFFFFFFF )
              MaxValue = 0xFFFFFFFF;

            if( MaxValue == 0 )
              throw( new Exception( "MaxValue is zero at the top in LongDivide3()." ));

            Quotient.SetDigitAndClear( TestIndex, 1 );
            Quotient.SetD( TestIndex, 0 );

            TestForDivide1.Copy( Quotient );
            TestForDivide1.SetD( TestIndex, MaxValue );
            MultiplyTop( TestForDivide1, DivideBy );

            /*
            Test2.Copy( Quotient );
            Test2.SetD( TestIndex, MaxValue );
            Multiply( Test2, DivideBy );
            if( !Test2.IsEqual( TestForDivide1 ))
              throw( new Exception( "In Divide3() !IsEqual( Test2, TestForDivide1 )" ));
            */

            if( TestForDivide1.ParamIsGreaterOrEq( ToDivide ))
              {
              // ToMatchExactCount++;
              // Most of the time (roughly 5 out of every 6 times)
              // this MaxValue estimate is exactly right:
              Quotient.SetD( TestIndex, MaxValue );
              }
            else
              {
              // MaxValue can't be zero here. If it was it would
              // already be low enough before it got here.
              MaxValue--;

              if( MaxValue == 0 )
            throw( new Exception( "After decrement: MaxValue is zero in LongDivide3()." ));

              TestForDivide1.Copy( Quotient );
              TestForDivide1.SetD( TestIndex, MaxValue );
              MultiplyTop( TestForDivide1, DivideBy );

              /*
              Test2.Copy( Quotient );
              Test2.SetD( TestIndex, MaxValue );
              Multiply( Test2, DivideBy );
              if( !Test2.IsEqual( Test1 ))
            throw( new Exception( "Top one. !Test2.IsEqual( Test1 ) in LongDivide3()" ));
              */

              if( TestForDivide1.ParamIsGreaterOrEq( ToDivide ))
            {
            // ToMatchDecCount++;
            Quotient.SetD( TestIndex, MaxValue );
            }
              else
            {
            // TestDivideBits is done as a last resort, but it's rare.
            // But it does at least limit it to a worst case scenario
            // of trying 32 bits, rather than 4 billion or so decrements.

            TestDivideBits( MaxValue,
                        true,
                        TestIndex,
                        ToDivide,
                        DivideBy,
                        Quotient,
                        Remainder );
            }

              // TestGap = MaxValue - LgQuotient.D[TestIndex];
              // if( TestGap > HighestToMatchGap )
            // HighestToMatchGap = TestGap;

              // HighestToMatchGap: 4,294,967,293
              // uint size:         4,294,967,295 uint
              }

            // If it's done.
            if( TestIndex == 0 )
              {
              TestForDivide1.Copy( Quotient );
              Multiply( TestForDivide1, DivideByKeep );
              Remainder.Copy( ToDivideKeep );
              Subtract( Remainder, TestForDivide1 );
              //if( DivideByKeep.ParamIsGreater( Remainder ))
            // throw( new Exception( "Remainder > DivideBy in LongDivide3()." ));

              return;
              }

            // Now do the rest of the digits.
            TestIndex--;
            while( true )
              {
              TestForDivide1.Copy( Quotient );
              // First Multiply() for each digit.
              Multiply( TestForDivide1, DivideBy );
              // if( ToDivide.ParamIsGreater( TestForDivide1 ))
              //   throw( new Exception( "Bug here in LongDivide3()." ));

              Remainder.Copy( ToDivide );
              Subtract( Remainder, TestForDivide1 );
              MaxValue = Remainder.GetD( Remainder.GetIndex()) << 32;

              int CheckIndex = Remainder.GetIndex() - 1;
              if( CheckIndex > 0 )
            MaxValue |= Remainder.GetD( CheckIndex );

              Denom = DivideBy.GetD( DivideBy.GetIndex());
              if( Denom != 0 )
            MaxValue = MaxValue / Denom;
              else
            MaxValue = 0xFFFFFFFF;

              if( MaxValue > 0xFFFFFFFF )
            MaxValue = 0xFFFFFFFF;

              TestForDivide1.Copy( Quotient );
              TestForDivide1.SetD( TestIndex, MaxValue );
              // There's a minimum of two full Multiply() operations per digit.
              Multiply( TestForDivide1, DivideBy );
              if( TestForDivide1.ParamIsGreaterOrEq( ToDivide ))
            {
            // Most of the time this MaxValue estimate is exactly right:
            // ToMatchExactCount++;
            Quotient.SetD( TestIndex, MaxValue );
            }
              else
            {
            MaxValue--;
            TestForDivide1.Copy( Quotient );
            TestForDivide1.SetD( TestIndex, MaxValue );
            Multiply( TestForDivide1, DivideBy );
            if( TestForDivide1.ParamIsGreaterOrEq( ToDivide ))
              {
              // ToMatchDecCount++;
              Quotient.SetD( TestIndex, MaxValue );
              }
            else
              {
              TestDivideBits( MaxValue,
                          false,
                          TestIndex,
                          ToDivide,
                          DivideBy,
                          Quotient,
                          Remainder );

              // TestGap = MaxValue - LgQuotient.D[TestIndex];
              // if( TestGap > HighestToMatchGap )
            // HighestToMatchGap = TestGap;

              }
            }

              if( TestIndex == 0 )
            break;

              TestIndex--;
              }

            TestForDivide1.Copy( Quotient );
            Multiply( TestForDivide1, DivideByKeep );
            Remainder.Copy( ToDivideKeep );
            Subtract( Remainder, TestForDivide1 );

            // if( DivideByKeep.ParamIsGreater( Remainder ))
              // throw( new Exception( "Remainder > DivideBy in LongDivide3()." ));
        }
Example #21
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 ));
              }
        }
Example #22
0
        // The ShortDivide() algorithm works like dividing a polynomial which
        // looks like:
        // (ax3 + bx2 + cx + d) / N = (ax3 + bx2 + cx + d) * (1/N)
        // The 1/N distributes over the polynomial:
        // (ax3 * (1/N)) + (bx2 * (1/N)) + (cx * (1/N)) + (d * (1/N))
        // (ax3/N) + (bx2/N) + (cx/N) + (d/N)
        // The algorithm goes from left to right and reduces that polynomial
        // expression.  So it starts with Quotient being a copy of ToDivide
        // and then it reduces Quotient from left to right.
        private bool ShortDivide( Integer ToDivide,
                            Integer DivideBy,
                            Integer Quotient,
                            Integer Remainder )
        {
            Quotient.Copy( ToDivide );
            // DivideBy has an Index of zero:
            ulong DivideByU = DivideBy.GetD( 0 );
            ulong RemainderU = 0;

            // Get the first one set up.
            if( DivideByU > Quotient.GetD( Quotient.GetIndex()) )
              {
              Quotient.SetD( Quotient.GetIndex(), 0 );
              }
            else
              {
              ulong OneDigit = Quotient.GetD( Quotient.GetIndex() );
              Quotient.SetD( Quotient.GetIndex(), OneDigit / DivideByU );
              RemainderU = OneDigit % DivideByU;
              ToDivide.SetD( ToDivide.GetIndex(), RemainderU );
              }

            // Now do the rest.
            for( int Count = Quotient.GetIndex(); Count >= 1; Count-- )
              {
              ulong TwoDigits = ToDivide.GetD( Count );
              TwoDigits <<= 32;
              TwoDigits |= ToDivide.GetD( Count - 1 );
              Quotient.SetD( Count - 1, TwoDigits / DivideByU );
              RemainderU = TwoDigits % DivideByU;
              ToDivide.SetD( Count, 0 );
              ToDivide.SetD( Count - 1, RemainderU ); // What's left to divide.
              }

            // Set the index for the quotient.
            // The quotient would have to be at least 1 here,
            // so it will find where to set the index.
            for( int Count = Quotient.GetIndex(); Count >= 0; Count-- )
              {
              if( Quotient.GetD( Count ) != 0 )
            {
            Quotient.SetIndex( Count );
            break;
            }
              }

            Remainder.SetD( 0, RemainderU );
            Remainder.SetIndex( 0 );
            if( RemainderU == 0 )
              return true;
            else
              return false;
        }
Example #23
0
        internal void FindSmallPrimeFactorsOnly( Integer FindFromNotChanged )
        {
            OriginalFindFrom.Copy( FindFromNotChanged );
            FindFrom.Copy( FindFromNotChanged );
            ClearFactorsArray();
            Integer OneFactor;
            OneFactorRec Rec;

            // while( not forever )
            for( int Count = 0; Count < 1000; Count++ )
              {
              if( Worker.CancellationPending )
            return;

              uint SmallPrime = IntMath.IsDivisibleBySmallPrime( FindFrom );
              if( SmallPrime == 0 )
            break; // No more small primes.

              // Worker.ReportProgress( 0, "Found a small prime factor: " + SmallPrime.ToString() );
              OneFactor = new Integer();
              OneFactor.SetFromULong( SmallPrime );
              Rec = new OneFactorRec();
              Rec.Factor = OneFactor;
              Rec.IsDefinitelyAPrime = true;
              AddFactorRec( Rec );
              if( FindFrom.IsULong())
            {
            ulong CheckLast = FindFrom.GetAsULong();
            if( CheckLast == SmallPrime )
              {
              // Worker.ReportProgress( 0, "It only had small prime factors." );
              VerifyFactors();
              return; // It had only small prime factors.
              }
            }

              IntMath.Divide( FindFrom, OneFactor, Quotient, Remainder );
              if( !Remainder.IsZero())
            throw( new Exception( "Bug in FindSmallPrimeFactorsOnly(). Remainder is not zero." ));

              FindFrom.Copy( Quotient );
              if( FindFrom.IsOne())
            throw( new Exception( "Bug in FindSmallPrimeFactorsOnly(). This was already checked for 1." ));

              }

            // Worker.ReportProgress( 0, "One factor was not a small prime." );
            OneFactor = new Integer();
            OneFactor.Copy( FindFrom );
            Rec = new OneFactorRec();
            Rec.Factor = OneFactor;
            AddFactorRec( Rec );

            // Worker.ReportProgress( 0, "No more small primes." );
        }
Example #24
0
        internal void Add( Integer Result, Integer ToAdd )
        {
            if( ToAdd.IsZero())
              return;

            // The most common form.  They are both positive.
            if( !Result.IsNegative && !ToAdd.IsNegative )
              {
              Result.Add( ToAdd );
              return;
              }

            if( !Result.IsNegative && ToAdd.IsNegative )
              {
              TempAdd1.Copy( ToAdd );
              TempAdd1.IsNegative = false;
              if( TempAdd1.ParamIsGreater( Result ))
            {
            Subtract( Result, TempAdd1 );
            return;
            }
              else
            {
            Subtract( TempAdd1, Result );
            Result.Copy( TempAdd1 );
            Result.IsNegative = true;
            return;
            }
              }

            if( Result.IsNegative && !ToAdd.IsNegative )
              {
              TempAdd1.Copy( Result );
              TempAdd1.IsNegative = false;
              TempAdd2.Copy( ToAdd );

              if( TempAdd1.ParamIsGreater( TempAdd2 ))
            {
            Subtract( TempAdd2, TempAdd1 );
            Result.Copy( TempAdd2 );
            return;
            }
              else
            {
            Subtract( TempAdd1, TempAdd2 );
            Result.Copy( TempAdd2 );
            Result.IsNegative = true;
            return;
            }
              }

            if( Result.IsNegative && ToAdd.IsNegative )
              {
              TempAdd1.Copy( Result );
              TempAdd1.IsNegative = false;
              TempAdd2.Copy( ToAdd );
              TempAdd2.IsNegative = false;
              TempAdd1.Add( TempAdd2 );
              Result.Copy( TempAdd1 );
              Result.IsNegative = true;
              return;
              }
        }
Example #25
0
        private bool IsFermatPrimeAdded( Integer FindFrom )
        {
            if( FindFrom.IsULong())
              {
              // The biggest size that NumberIsDivisibleByUInt() will check to
              // see if it has primes for sure.
              if( FindFrom.GetAsULong() < (223092870UL * 223092870UL))
            return false; // Factor this.

              }

            int HowManyTimes = 20; // How many primes it will be checked with.
            if( !IntMath.IsFermatPrime( FindFrom, HowManyTimes ))
              return false;

            Integer OneFactor = new Integer();
            OneFactor.Copy( FindFrom );
            OneFactorRec Rec = new OneFactorRec();
            Rec.Factor = OneFactor;
            // Neither one of these is set to true here because it's probably
            // a prime, but not definitely.
            // Rec.IsDefinitelyAPrime = false;
            // Rec.IsDefinitelyNotAPrime = false;
            AddFactorRec( Rec );
            Worker.ReportProgress( 0, "Fermat thinks this one is a prime." );
            return true; // It's a Fermat prime and it was added.
        }
Example #26
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 );
        }
Example #27
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." ));
        }
Example #28
0
        /*
          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 );
              }
        }
Example #29
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;
        }
Example #30
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.
              }
        }