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; }
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 )); } }
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; }
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; } } }