예제 #1
0
        internal CRTBaseMath( BackgroundWorker UseWorker, CRTMath UseCRTMath )
        {
            // Most of these are created ahead of time so that
            // they don't have to be created inside a loop.
            Worker = UseWorker;
            IntMath = new IntegerMath();
            CRTMath1 = UseCRTMath;
            Quotient = new Integer();
            Remainder = new Integer();
            CRTAccumulateBase = new ChineseRemainder( IntMath );
            CRTAccumulateBasePart = new ChineseRemainder( IntMath );
            CRTAccumulateForBaseMultiples = new ChineseRemainder( IntMath );
            CRTAccumulatePart = new ChineseRemainder( IntMath );
            BaseModArrayModulus = new Integer();
            CRTTempForIsEqual = new ChineseRemainder( IntMath );
            CRTWorkingTemp = new ChineseRemainder( IntMath );
            ExponentCopy = new Integer();
            CRTXForModPower = new ChineseRemainder( IntMath );
            CRTAccumulate = new ChineseRemainder( IntMath );
            CRTCopyForSquare = new ChineseRemainder( IntMath );
            FermatExponent = new Integer();
            CRTFermatModulus = new ChineseRemainder( IntMath );
            FermatModulus = new Integer();
            CRTTestFermat = new ChineseRemainder( IntMath );

            Worker.ReportProgress( 0, "Setting up numbers array." );
            SetupNumbersArray();

            Worker.ReportProgress( 0, "Setting up base array." );
            SetupBaseArray();

            Worker.ReportProgress( 0, "Setting up multiplicative inverses." );
            SetMultiplicativeInverses();
        }
예제 #2
0
        internal void GetMaximumValues()
        {
            string RSA2048 = "2519590847565789349402718324004839857142928212620403202777713783604366202070" +
               "7595556264018525880784406918290641249515082189298559149176184502808489120072" +
               "8449926873928072877767359714183472702618963750149718246911650776133798590957" +
               "0009733045974880842840179742910064245869181719511874612151517265463228221686" +
               "9987549182422433637259085141865462043576798423387184774447920739934236584823" +
               "8242811981638150106748104516603773060562016196762561338441436038339044149526" +
               "3443219011465754445417842402092461651572335077870774981712577246796292638635" +
               "6373289912154831438167899885040445364023527381951378636564391212010397122822" +
               "120720357";

            Integer BigRSA = new Integer();
            IntMath.SetFromString( BigRSA, RSA2048 );
            // Do a basic sanity-check just to make sure the
            // RSA number was copied right.
            if( 0 != IntMath.IsDivisibleBySmallPrime( BigRSA ))
              throw( new Exception( "BigRSA was not copied right." ));

            // One factor is smaller than the square root.
            // So it's the biggest one that's less than the
            // square root.
            Integer BiggestFactor = new Integer();
            IntMath.SquareRoot( BigRSA, BiggestFactor );
            Integer BigBase = MakeBigBase( BiggestFactor );
            if( BigBase == null )
              {
              ShowStatus( "BigBase was null." );
              return;
              }
        }
예제 #3
0
        internal RSACryptoSystem( BackgroundWorker UseWorker, RSACryptoWorkerInfo UseWInfo )
        {
            Worker = UseWorker;
            WorkerInfo = UseWInfo;
            StartTime = new ECTime();
            StartTime.SetToNow();

            RngCsp = new RNGCryptoServiceProvider();
            IntMath = new IntegerMath();
            IntMathNewForP = new IntegerMathNew( IntMath );
            IntMathNewForQ = new IntegerMathNew( IntMath );

            Worker.ReportProgress( 0, IntMath.GetStatusString() );
            Quotient = new Integer();
            Remainder = new Integer();
            PrimeP = new Integer();
            PrimeQ = new Integer();
            PrimePMinus1 = new Integer();
            PrimeQMinus1 = new Integer();
            PubKeyN = new Integer();
            PubKeyExponent = new Integer();
            PrivKInverseExponent = new Integer();
            PrivKInverseExponentDP = new Integer();
            PrivKInverseExponentDQ = new Integer();
            QInv = new Integer();
            PhiN = new Integer();
            TestForDecrypt = new Integer();
            M1ForInverse = new Integer();
            M2ForInverse = new Integer();
            HForQInv = new Integer();
            M1MinusM2 = new Integer();
            M1M2SizeDiff = new Integer();

            PubKeyExponent.SetFromULong( PubKeyExponentUint );
        }
예제 #4
0
        internal MultiplyBits( MainForm UseForm )
        {
            MForm = UseForm;
            try
            {
            IntMath = new IntegerMath();
            // MForm.ShowStatus( IntMath.GetStatusString());

            InputOutputDictionary = new SortedDictionary<uint, uint>();

            Product = new Integer();
            TestProduct = new Integer();
            Factor1 = new Integer();
            Factor2 = new Integer();
            Quotient = new Integer();
            Remainder = new Integer();

            MultArray = new LineRec[MultArraySize];
            MultArrayCopyForMult2 = new LineRec[MultArraySize];
            for( int Count = 0; Count < MultArraySize; Count++ )
              {
              MultArray[Count].OneLine = new uint[MultArraySize];
              MultArrayCopyForMult2[Count].OneLine = new uint[MultArraySize];
              }

            SetupFermatLittle( 107 );

            }
            catch( Exception )
              {
              MForm.ShowStatus( "Not enough RAM for the MultArray." );
              }
        }
예제 #5
0
        internal void Add( Integer ToAdd )
        {
            // There is a separate IntegerMath.Add() that is a wrapper to handle
            // negative numbers too.

            if( IsNegative )
              throw( new Exception( "Integer.Add() is being called when it's negative." ));

            if( ToAdd.IsNegative )
              throw( new Exception( "Integer.Add() is being called when ToAdd is negative." ));

            if( ToAdd.IsULong() )
              {
              AddULong( ToAdd.GetAsULong() );
              return;
              }

            // Tell the compiler these aren't going to change for the for-loop.
            int LocalIndex = Index;
            int LocalToAddIndex = ToAdd.Index;

            if( LocalIndex < ToAdd.Index )
              {
              for( int Count = LocalIndex + 1; Count <= LocalToAddIndex; Count++ )
            D[Count] = ToAdd.D[Count];

              for( int Count = 0; Count <= LocalIndex; Count++ )
            D[Count] += ToAdd.D[Count];

              Index = ToAdd.Index;
              }
            else
              {
              for( int Count = 0; Count <= LocalToAddIndex; Count++ )
            D[Count] += ToAdd.D[Count];

              }

            // After they've been added, reorganize it.
            ulong Carry = D[0] >> 32;
            D[0] = D[0] & 0xFFFFFFFF;
            LocalIndex = Index;
            for( int Count = 1; Count <= LocalIndex; Count++ )
              {
              ulong Total = Carry + D[Count];
              D[Count] = Total & 0xFFFFFFFF;
              Carry = Total >> 32;
              }

            if( Carry != 0 )
              {
              Index++;
              if( Index >= DigitArraySize )
            throw( new Exception( "Integer.Add() overflow." ));

              D[Index] = Carry;
              }
        }
예제 #6
0
 internal ModularReduction()
 {
     IntMath = new IntegerMath();
     XForModPower = new Integer();
     ExponentCopy = new Integer();
     Quotient = new Integer();
     Remainder = new Integer();
     TempForModPower = new Integer();
 }
예제 #7
0
 internal FindFactors(  BackgroundWorker UseWorker, IntegerMath UseIntMath )
 {
     Worker = UseWorker;
     IntMath = UseIntMath;
     Quotient = new Integer();
     Remainder = new Integer();
     OriginalFindFrom = new Integer();
     FindFrom = new Integer();
     FactorsArray = new OneFactorRec[8];
     SortIndexArray = new int[8];
     StatsDictionary = new SortedDictionary<uint, uint>();
 }
예제 #8
0
        // internal ExponentVectorNumber( BackgroundWorker UseWorker, IntegerMath UseIntMath )
        internal ExponentVectorNumber( IntegerMath UseIntMath )
        {
            // Worker = UseWorker;
            IntMath = UseIntMath;
            Quotient = new Integer();
            Remainder = new Integer();
            ExtraValue = new Integer();
            PartAForAdd = new Integer();
            PartBForAdd = new Integer();

            VectorValuesArray = new VectorValueRec[IncreaseArraySizeBy];
        }
예제 #9
0
 // private uint GBaseSmallModulus = 0;
 internal IntegerMathNew( IntegerMath UseIntMath )
 {
     IntMath = UseIntMath;
     Quotient = new Integer();
     Remainder = new Integer();
     XForModPower = new Integer();
     ExponentCopy = new Integer();
     TempForModPower = new Integer();
     TestForModPower = new Integer();
     AccumulateBase = new Integer();
     TestForModInverse1 = new Integer();
 }
예제 #10
0
        internal FactorDictionary( MainForm UseForm )
        {
            MForm = UseForm;
            IntMath = new IntegerMath();
            Product = new Integer();
            SolutionP = new Integer();
            SolutionQ = new Integer();
            Quotient = new Integer();
            Remainder = new Integer();

            MainDictionary = new SortedDictionary<uint, ListRec>();
            NumberList = new List<NumberRec>();
        }
예제 #11
0
        internal EquationParts( QuadResWorkerInfo UseWInfo, BackgroundWorker UseWorker )
        {
            WInfo = UseWInfo;
            Worker = UseWorker;
            IntMath = new IntegerMath();
            Quotient = new Integer();
            Remainder = new Integer();
            Product = new Integer();
            SolutionP = new Integer();
            SolutionQ = new Integer();
            ProductSqrRoot = new Integer();
            MaxX = new Integer();
            FindFactors1 = new FindFactors(  Worker, IntMath );

            IntMath.SetFromString( Product, WInfo.PublicKeyModulus );
        }
예제 #12
0
        internal QuadResCombinatorics( QuadResWorkerInfo UseWInfo, BackgroundWorker UseWorker )
        {
            WInfo = UseWInfo;
            Worker = UseWorker;
            IntMath = new IntegerMath();
            Quotient = new Integer();
            Remainder = new Integer();
            Product = new Integer();
            SolutionP = new Integer();
            SolutionQ = new Integer();
            ToDivideMod32 = new Integer();
            LastAccumulateValue = new Integer();
            GetValueBasePart = new Integer();
            StartTime = new ECTime();
            StartTime.SetToNow();

            IntMath.SetFromString( Product, WInfo.PublicKeyModulus );
            QuadResDigitsArray = new QuadResDigitsRec[DigitsArrayLength];
        }
예제 #13
0
        internal void AddDelimString( string ToAdd )
        {
            // string DelimS = IntMath.ToString10( Y ) + "\t" +
            //                         ExpNumber.ToDelimString();

            string[] SplitS = ToAdd.Split( new Char[] { '\t' } );
            if( SplitS.Length < 2 )
              return;

            // MForm.ShowStatus( "Adding: " + ToAdd );
            Integer Y = new Integer();
            IntMath.SetFromString( Y, SplitS[0] );

            ExponentVectorNumber X = new ExponentVectorNumber( IntMath );
            X.SetFromDelimString( SplitS[1] );

            for( int Count = 0; ; Count++ )
              {
              VectorValueRec Rec = X.GetValueRecordAt( Count );
              if( Rec.Prime == 0 )
            break;

              // The one X number is being added as a reference in every
              // dictionary it belongs to.
              NumberRec NRec = new NumberRec();
              NRec.Y = Y;
              NRec.X = X;

              NumberList.Add( NRec );

              if( MainDictionary.ContainsKey( Rec.Prime ))
            {
            MainDictionary[Rec.Prime].OnePrimeList.Add( NRec );
            }
              else
            {
            ListRec LRec = new ListRec();
            LRec.OnePrimeList = new List<NumberRec>();
            LRec.OnePrimeList.Add( NRec );
            MainDictionary[Rec.Prime] = LRec;
            }
              }
        }
예제 #14
0
 internal FactorBase( QuadResWorkerInfo UseWInfo, BackgroundWorker UseWorker )
 {
     WInfo = UseWInfo;
     Worker = UseWorker;
     IntMath = new IntegerMath();
     Quotient = new Integer();
     Remainder = new Integer();
     Product = new Integer();
     ProductSqrRoot = new Integer();
     EulerExponent = new Integer();
     EulerResult = new Integer();
     EulerModulus = new Integer();
     OneMainFactor = new Integer();
     ExpOneMainFactor = new ExponentVectorNumber( IntMath );
     StartTime = new ECTime();
     StartTime.SetToNow();
     IntMath.SetFromString( Product, WInfo.PublicKeyModulus );
     IntMath.SquareRoot( Product, ProductSqrRoot );
 }
예제 #15
0
        private void SetupQuadResArray( Integer Product )
        {
            // I'm doing this differently from finding y^2 = x^2 - N,
            // which I think would be faster, unless it complicates it too
            // much by having to use large Integers and doing subtraction.
            // Here it's looking for when
            // P + x^2 = y^2.

            // private uint[] QuadResArraySmall;
            // private uint[] QuadResArray;
            uint SmallBase = 2 * 3 * 5 * 7 * 11 * 13; // 30,030
            //               2   3   3   4    6    7
            int SmallBaseArraySize = 2 * 3 * 3 * 4 * 6 * 7; // This is not exact.
            uint[] QuadResArraySmall = new uint[SmallBaseArraySize];
            uint QuadResArraySmallLast = 0;
            uint ProductModSmall = (uint)IntMath.GetMod32( Product, SmallBase );
            QuadResArraySmallLast = 0;
            uint ProdMod4 = (uint)Product.GetD( 0 ) & 3;
            for( ulong Count = 0; Count < SmallBase; Count++ )
              {
              // P is odd.
              // if x is even then y is odd.
              // if x is odd then y is even.
              // If x is even then x^2 is divisible by 4.
              // If y is even then y^2 is divisible by 4.

              ulong Test = ProductModSmall + (Count * Count); // The Product plus a square.
              Test = Test % SmallBase;
              if( !IntegerMath.IsSmallQuadResidue( (uint)Test ))
            continue;

              // What Count was used to make a quad residue?
              QuadResArraySmall[QuadResArraySmallLast] = (uint)Count;
              QuadResArraySmallLast++;
              if( QuadResArraySmallLast >= SmallBaseArraySize )
            throw( new Exception( "Went past the small quad res array." ));

              }

            // Worker.ReportProgress( 0, "Finished setting up small quad res array." );

            QuadResBigBase = SmallBase * 17 * 19 * 23; // 223,092,870
            //                                             17   19   23
            int QuadResBaseArraySize = SmallBaseArraySize * 9 * 10 * 12; // This is not exact.

            QuadResArray = new uint[QuadResBaseArraySize];

            uint ProductMod = (uint)IntMath.GetMod32( Product, QuadResBigBase );
            int MaxLength = QuadResArray.Length;

            QuadResArrayLast = 0;
            for( ulong Count23 = 0; Count23 < (17 * 19 * 23); Count23++ )
              {
              if( Worker.CancellationPending )
            return;

              ulong BasePart = Count23 * SmallBase;
              for( uint Count = 0; Count < QuadResArraySmallLast; Count++ )
            {
            ulong CountPart = BasePart + QuadResArraySmall[Count];
            ulong Test = ProductMod + (CountPart * CountPart); // The Product plus a square.
            Test = Test % QuadResBigBase;
            if( !IntegerMath.IsQuadResidue17To23( (uint)Test ))
              continue;

            // What Count was used to make a quad residue?
            QuadResArray[QuadResArrayLast] = (uint)CountPart;
            QuadResArrayLast++;
            if( QuadResArrayLast >= MaxLength )
              throw( new Exception( "Went past the quad res array." ));

            }
              }

            Worker.ReportProgress( 0, "Finished setting up main quad res array." );
        }
예제 #16
0
        internal void VerifyFactors()
        {
            Integer TestFactors = new Integer();
            TestFactors.SetToOne();
            for( int Count = 0; Count < FactorsArrayLast; Count++ )
              IntMath.Multiply( TestFactors, FactorsArray[Count].Factor );

            if( !TestFactors.IsEqual( OriginalFindFrom ))
              throw( new Exception( "VerifyFactors didn't come out right." ));
        }
예제 #17
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.
        }
예제 #18
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();
        }
예제 #19
0
        internal uint NumberIsDivisibleByUInt( Integer ToCheck )
        {
            if( DivisionArray == null )
              SetupDivisionArray(); // Set it up once, when it's needed.

            uint Max = 0;
            if( ToCheck.IsULong())
              {
              ulong ForMax = ToCheck.GetAsULong();
              // It can't be bigger than the square root.
              Max = (uint)IntMath.FindULSqrRoot( ForMax );
              }

            uint Base = 2 * 3 * 5 * 7 * 11 * 13 * 17;
            uint EulerPhi = 2 * 4 * 6 * 10 * 12 * 16;
            uint Base19 = Base * 19;
            uint Base23 = Base19 * 23;

            // The first few base numbers like this:
            // 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

            // These loops count up to 223,092,870 - 1.
            for( uint Count23 = 0; Count23 < 23; Count23++ )
              {
              Worker.ReportProgress( 0, "Count23 loop: " + Count23.ToString());

              uint Base23Part = (Base19 * Count23);
              for( uint Count19 = 0; Count19 < 19; Count19++ )
            {
            uint Base19Part = Base * Count19;
            if( Worker.CancellationPending )
              return 0;

            for( int Count = 0; Count < EulerPhi; Count++ )
              {
              if( Worker.CancellationPending )
            return 0;

              uint Test = Base23Part + Base19Part + DivisionArray[Count];
              if( Test == 1 )
            continue;

              if( (Test % 19) == 0 )
            continue;

              if( (Test % 23) == 0 )
            continue;

              if( Max > 0 )
            {
            if( Test > Max )
              return 0;

            }

              if( 0 == IntMath.GetMod32( ToCheck, Test ))
            {
            Worker.ReportProgress( 0, "The number is divisible by: " + Test.ToString( "N0" ));
            return Test;
            }
              }
            }
              }

            return 0; // Didn't find a number to divide it.
        }
예제 #20
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;
        }
예제 #21
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." ));
        }
예제 #22
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 );
              }
        }
예제 #23
0
 private void DoGeneralConstructorThings()
 {
     ModifyTime = new ECTime();
     MostRecentIntegerValue = new Integer();
     BitStreamRecArray = new BitStreamRec[8];
 }
예제 #24
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 ));
              }
        }
예제 #25
0
        internal uint ModularPowerSmall( ulong Input, Integer Exponent, uint Modulus )
        {
            if( Input == 0 )
              return 0;

            if( Input == Modulus )
              {
              // It is congruent to zero % Modulus.
              return 0;
              }

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

            ulong Result = Input;
            if( Input > Modulus )
              Result = Input % Modulus;

            if( Exponent.IsOne())
              return (uint)Result;

            ulong XForModPowerU = Result;
            ExponentCopy.Copy( Exponent );
            int TestIndex = 0;

            Result = 1;
            while( true )
              {
              if( (ExponentCopy.GetD( 0 ) & 1) == 1 ) // If the bottom bit is 1.
            {
            Result = Result * XForModPowerU;
            Result = Result % Modulus;
            }

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

              // Square it.
              XForModPowerU = XForModPowerU * XForModPowerU;
              XForModPowerU = XForModPowerU % Modulus;
              }

            return (uint)Result;
        }
 internal void SetFromTraditionalInteger( Integer SetFrom )
 {
     for( int Count = 0; Count < DigitsArraySize; Count++ )
       {
       DigitsArray[Count].Value = (int)IntMath.GetMod32( SetFrom, (uint)DigitsArray[Count].Prime );
       }
 }
예제 #27
0
        // Copyright Eric Chauvin 2015.
        private int ModularReduction( Integer Result, Integer ToReduce )
        {
            try
            {
            if( GeneralBaseArray == null )
              throw( new Exception( "SetupGeneralBaseArray() should have already been called." ));

            Result.SetToZero();

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

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

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

              if( CheckIndex > BiggestIndex )
            BiggestIndex = CheckIndex;

              Result.Add( AccumulateBase );
              }

            return Result.GetIndex();
            }
            catch( Exception Except )
              {
              throw( new Exception( "Exception in ModularReduction(): " + Except.Message ));
              }
        }
        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 ));
              }
        }
예제 #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;
        }
예제 #30
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." );
        }