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(); }
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; } }
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 ); }
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." ); } }
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; } }
internal ModularReduction() { IntMath = new IntegerMath(); XForModPower = new Integer(); ExponentCopy = new Integer(); Quotient = new Integer(); Remainder = new Integer(); TempForModPower = new Integer(); }
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>(); }
// 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]; }
// 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(); }
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>(); }
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 ); }
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]; }
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; } } }
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 ); }
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." ); }
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." )); }
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. }
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(); }
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. }
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; }
// 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 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 ); } }
private void DoGeneralConstructorThings() { ModifyTime = new ECTime(); MostRecentIntegerValue = new Integer(); BitStreamRecArray = new BitStreamRec[8]; }
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 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 ); } }
// 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 )); } }
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 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." ); }