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 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 )); } }
// 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." )); }
/* 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 ); } }
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; }
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; } }
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()." )); }
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 ); }
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 ); }
internal bool DecryptWithQInverse( Integer EncryptedNumber, Integer DecryptedNumber, Integer TestDecryptedNumber, Integer PubKeyN, Integer PrivKInverseExponentDP, Integer PrivKInverseExponentDQ, Integer PrimeP, Integer PrimeQ, BackgroundWorker Worker ) { Worker.ReportProgress( 0, " " ); Worker.ReportProgress( 0, "Top of DecryptWithQInverse()." ); // QInv and the dP and dQ numbers are normally already set up before // you start your listening socket. ECTime DecryptTime = new ECTime(); DecryptTime.SetToNow(); // See section 5.1.2 of RFC 2437 for these steps: // http://tools.ietf.org/html/rfc2437 // 2.2 Let m_1 = c^dP mod p. // 2.3 Let m_2 = c^dQ mod q. // 2.4 Let h = qInv ( m_1 - m_2 ) mod p. // 2.5 Let m = m_2 + hq. Worker.ReportProgress( 0, "EncryptedNumber: " + IntMath.ToString10( EncryptedNumber )); // 2.2 Let m_1 = c^dP mod p. TestForDecrypt.Copy( EncryptedNumber ); IntMathNewForP.ModularPower( TestForDecrypt, PrivKInverseExponentDP, PrimeP, true ); if( Worker.CancellationPending ) return false; M1ForInverse.Copy( TestForDecrypt ); // 2.3 Let m_2 = c^dQ mod q. TestForDecrypt.Copy( EncryptedNumber ); IntMathNewForQ.ModularPower( TestForDecrypt, PrivKInverseExponentDQ, PrimeQ, true ); if( Worker.CancellationPending ) return false; M2ForInverse.Copy( TestForDecrypt ); // 2.4 Let h = qInv ( m_1 - m_2 ) mod p. // How many is optimal to avoid the division? int HowManyIsOptimal = (PrimeP.GetIndex() * 3); for( int Count = 0; Count < HowManyIsOptimal; Count++ ) { if( M1ForInverse.ParamIsGreater( M2ForInverse )) M1ForInverse.Add( PrimeP ); else break; } if( M1ForInverse.ParamIsGreater( M2ForInverse )) { M1M2SizeDiff.Copy( M2ForInverse ); IntMath.Subtract( M1M2SizeDiff, M1ForInverse ); // Unfortunately this long Divide() has to be done. IntMath.Divide( M1M2SizeDiff, PrimeP, Quotient, Remainder ); Quotient.AddULong( 1 ); Worker.ReportProgress( 0, "The Quotient for M1M2SizeDiff is: " + IntMath.ToString10( Quotient )); IntMath.Multiply( Quotient, PrimeP ); M1ForInverse.Add( Quotient ); } M1MinusM2.Copy( M1ForInverse ); IntMath.Subtract( M1MinusM2, M2ForInverse ); if( M1MinusM2.IsNegative ) throw( new Exception( "This is a bug. M1MinusM2.IsNegative is true." )); if( QInv.IsNegative ) throw( new Exception( "This is a bug. QInv.IsNegative is true." )); HForQInv.Copy( M1MinusM2 ); IntMath.Multiply( HForQInv, QInv ); if( HForQInv.IsNegative ) throw( new Exception( "This is a bug. HForQInv.IsNegative is true." )); if( PrimeP.ParamIsGreater( HForQInv )) { IntMath.Divide( HForQInv, PrimeP, Quotient, Remainder ); HForQInv.Copy( Remainder ); } // 2.5 Let m = m_2 + hq. DecryptedNumber.Copy( HForQInv ); IntMath.Multiply( DecryptedNumber, PrimeQ ); DecryptedNumber.Add( M2ForInverse ); if( !TestDecryptedNumber.IsEqual( DecryptedNumber )) throw( new Exception( "!TestDecryptedNumber.IsEqual( DecryptedNumber )." )); Worker.ReportProgress( 0, " " ); Worker.ReportProgress( 0, "DecryptedNumber: " + IntMath.ToString10( DecryptedNumber )); Worker.ReportProgress( 0, " " ); Worker.ReportProgress( 0, "TestDecryptedNumber: " + IntMath.ToString10( TestDecryptedNumber )); Worker.ReportProgress( 0, " " ); Worker.ReportProgress( 0, "Decrypt with QInv time seconds: " + DecryptTime.GetSecondsToNow().ToString( "N2" )); Worker.ReportProgress( 0, " " ); return true; }
private bool GetFactors( Integer Y, ExponentVectorNumber XExp ) { Integer XRoot = new Integer(); Integer X = new Integer(); Integer XwithY = new Integer(); Integer Gcd = new Integer(); XExp.GetTraditionalInteger( X ); if( !IntMath.SquareRoot( X, XRoot )) throw( new Exception( "Bug. X should have an exact square root." )); XwithY.Copy( Y ); XwithY.Add( XRoot ); IntMath.GreatestCommonDivisor( Product, XwithY, Gcd ); if( !Gcd.IsOne()) { if( !Gcd.IsEqual( Product )) { SolutionP.Copy( Gcd ); IntMath.Divide( Product, SolutionP, Quotient, Remainder ); if( !Remainder.IsZero()) throw( new Exception( "The Remainder with SolutionP can't be zero." )); SolutionQ.Copy( Quotient ); MForm.ShowStatus( "SolutionP: " + IntMath.ToString10( SolutionP )); MForm.ShowStatus( "SolutionQ: " + IntMath.ToString10( SolutionQ )); return true; } else { MForm.ShowStatus( "GCD was Product." ); } } else { MForm.ShowStatus( "GCD was one." ); } MForm.ShowStatus( "XRoot: " + IntMath.ToString10( XRoot )); MForm.ShowStatus( "Y: " + IntMath.ToString10( Y )); XwithY.Copy( Y ); if( Y.ParamIsGreater( XRoot )) throw( new Exception( "This can't be right. XRoot is bigger than Y." )); IntMath.Subtract( Y, XRoot ); IntMath.GreatestCommonDivisor( Product, XwithY, Gcd ); if( !Gcd.IsOne()) { if( !Gcd.IsEqual( Product )) { SolutionP.Copy( Gcd ); IntMath.Divide( Product, SolutionP, Quotient, Remainder ); if( !Remainder.IsZero()) throw( new Exception( "The Remainder with SolutionP can't be zero." )); SolutionQ.Copy( Quotient ); MForm.ShowStatus( "SolutionP: " + IntMath.ToString10( SolutionP )); MForm.ShowStatus( "SolutionQ: " + IntMath.ToString10( SolutionQ )); return true; } else { MForm.ShowStatus( "GCD was Product." ); } } else { MForm.ShowStatus( "GCD was one." ); } return false; }
internal void ModularPower( Integer Result, Integer Exponent, Integer GeneralBase ) { // The square and multiply method is in Wikipedia: // https://en.wikipedia.org/wiki/Exponentiation_by_squaring // x^n = (x^2)^((n - 1)/2) if n is odd. // x^n = (x^2)^(n/2) if n is even. if( Result.IsZero()) return; // With Result still zero. if( Result.IsEqual( GeneralBase )) { // It is congruent to zero % ModN. Result.SetToZero(); return; } // Result is not zero at this point. if( Exponent.IsZero() ) { Result.SetFromULong( 1 ); return; } if( GeneralBase.ParamIsGreater( Result )) { // throw( new Exception( "This is not supposed to be input for RSA plain text." )); IntMath.Divide( Result, GeneralBase, Quotient, Remainder ); Result.Copy( Remainder ); } if( Exponent.IsEqualToULong( 1 )) { // Result stays the same. return; } // This could also be called ahead of time if the base (the modulus) // doesn't change. Like when your public key doesn't change. SetupGeneralBaseArray( GeneralBase ); XForModPower.Copy( Result ); ExponentCopy.Copy( Exponent ); int TestIndex = 0; Result.SetFromULong( 1 ); while( true ) { if( (ExponentCopy.GetD( 0 ) & 1) == 1 ) // If the bottom bit is 1. { IntMath.Multiply( Result, XForModPower ); // Modular Reduction: AddByGeneralBaseArrays( TempForModPower, Result ); Result.Copy( TempForModPower ); } ExponentCopy.ShiftRight( 1 ); // Divide by 2. if( ExponentCopy.IsZero()) break; // Square it. IntMath.Multiply( XForModPower, XForModPower ); // Modular Reduction: AddByGeneralBaseArrays( TempForModPower, XForModPower ); XForModPower.Copy( TempForModPower ); } // When AddByGeneralBaseArrays() gets called it multiplies a number // by a uint sized digit. So that can make the result one digit bigger // than GeneralBase. Then when they are added up you can get carry // bits that can make it a little bigger. // If by chance you got a carry bit on _every_ addition that was done // in AddByGeneralBaseArrays() then this number could increase in size // by 1 bit for each addition that was done. It would take 32 bits of // carrying for HowBig to increase by 1. // See HowManyToAdd in AddByGeneralBaseArrays() for why this check is done. int HowBig = Result.GetIndex() - GeneralBase.GetIndex(); if( HowBig > 2 ) // I have not seen this happen yet. throw( new Exception( "The difference in index size was more than 2. Diff: " + HowBig.ToString() )); // So this Quotient has only one or two 32-bit digits in it. // And this Divide() is only called once at the end. Not in the loop. IntMath.Divide( Result, GeneralBase, Quotient, Remainder ); Result.Copy( Remainder ); }