// This is a variation on ShortDivide that returns // the remainder. // Also, DivideBy is a ulong. internal ulong ShortDivideRem(Integer ToDivideOriginal, ulong DivideByU, Integer Quotient) { if (ToDivideOriginal.IsULong()) { ulong ToDiv = ToDivideOriginal.GetAsULong(); ulong Q = ToDiv / DivideByU; Quotient.SetFromULong(Q); return(ToDiv % DivideByU); } ToDivide.Copy(ToDivideOriginal); Quotient.Copy(ToDivide); ulong RemainderU = 0; if (DivideByU > Quotient.GetD(Quotient.GetIndex())) { Quotient.SetD(Quotient.GetIndex(), 0); } else { ulong OneDigit = Quotient.GetD(Quotient.GetIndex()); Quotient.SetD(Quotient.GetIndex(), OneDigit / DivideByU); RemainderU = OneDigit % DivideByU; ToDivide.SetD(ToDivide.GetIndex(), RemainderU); } for (int Count = Quotient.GetIndex(); Count >= 1; Count--) { ulong TwoDigits = ToDivide.GetD(Count); TwoDigits <<= 32; TwoDigits |= ToDivide.GetD(Count - 1); Quotient.SetD(Count - 1, TwoDigits / DivideByU); RemainderU = TwoDigits % DivideByU; ToDivide.SetD(Count, 0); ToDivide.SetD(Count - 1, RemainderU); } for (int Count = Quotient.GetIndex(); Count >= 0; Count--) { if (Quotient.GetD(Count) != 0) { Quotient.SetIndex(Count); break; } } return(RemainderU); }
internal bool IsFermatPrimeForOneValue(Integer ToTest, ulong Base) { // Assume ToTest is not a small number. (Not the size of a small prime.) // Normally it would be something like a 1024 bit number or bigger, // but I assume it's at least bigger than a 32 bit number. // Assume this has already been checked to see if it's divisible // by a small prime. // A has to be coprime to P and it is here because ToTest is not // divisible by a small prime. // Fermat's little theorem: // A ^ (P - 1) is congruent to 1 mod P if P is a prime. // Or: A^P - A is congrunt to A mod P. // If you multiply A by itself P times then divide it by P, // the remainder is A. (A^P / P) // 5^3 = 125. 125 - 5 = 120. A multiple of 5. // 2^7 = 128. 128 - 2 = 7 * 18 (a multiple of 7.) Fermat1.Copy(ToTest); IntMath.SubtractULong(Fermat1, 1); TestFermat.SetFromULong(Base); // ModularPower( Result, Exponent, Modulus, UsePresetBaseArray ) ModularPower(TestFermat, Fermat1, ToTest, false); // if( !TestFermat.IsEqual( Fermat2 )) // throw( new Exception( "!TestFermat.IsEqual( Fermat2 )." )); if (TestFermat.IsOne()) { return(true); // It passed the test. It _might_ be a prime. } else { return(false); // It is _definitely_ a composite number. } }
private bool ShortDivide(Integer ToDivide, Integer DivideBy, Integer Quotient, Integer Remainder) { Quotient.Copy(ToDivide); // DivideBy has an Index of zero: ulong DivideByU = DivideBy.GetD(0); ulong RemainderU = 0; // Get the first one set up. if (DivideByU > Quotient.GetD(Quotient.GetIndex())) { Quotient.SetD(Quotient.GetIndex(), 0); } else { ulong OneDigit = Quotient.GetD(Quotient.GetIndex()); Quotient.SetD(Quotient.GetIndex(), OneDigit / DivideByU); RemainderU = OneDigit % DivideByU; ToDivide.SetD(ToDivide.GetIndex(), RemainderU); } // Now do the rest. for (int Count = Quotient.GetIndex(); Count >= 1; Count--) { ulong TwoDigits = ToDivide.GetD(Count); TwoDigits <<= 32; TwoDigits |= ToDivide.GetD(Count - 1); Quotient.SetD(Count - 1, TwoDigits / DivideByU); RemainderU = TwoDigits % DivideByU; ToDivide.SetD(Count, 0); ToDivide.SetD(Count - 1, RemainderU); // What's left to divide. } // Set the index for the quotient. // The quotient would have to be at least 1 here, // so it will find where to set the index. for (int Count = Quotient.GetIndex(); Count >= 0; Count--) { if (Quotient.GetD(Count) != 0) { Quotient.SetIndex(Count); break; } } Remainder.SetD(0, RemainderU); Remainder.SetIndex(0); if (RemainderU == 0) { return(true); } else { return(false); } }
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) { IntMath.Divider.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); } }
internal string ToString10(Integer From) { if (From.IsULong()) { ulong N = From.GetAsULong(); if (From.IsNegative) { return("-" + N.ToString("N0")); } else { return(N.ToString("N0")); } } string Result = ""; ToDivide.Copy(From); int CommaCount = 0; while (!ToDivide.IsZero()) { uint Digit = (uint)Divider.ShortDivideRem(ToDivide, 10, Quotient); ToDivide.Copy(Quotient); if (((CommaCount % 3) == 0) && (CommaCount != 0)) { Result = Digit.ToString() + "," + Result; // Or use a StringBuilder. } else { Result = Digit.ToString() + Result; } CommaCount++; } if (From.IsNegative) { return("-" + Result); } else { return(Result); } }
// Copyright Eric Chauvin 2015 - 2018. internal int Reduce(Integer Result, Integer ToReduce) { try { if (ToReduce.ParamIsGreater(CurrentModReductionBase)) { Result.Copy(ToReduce); return(Result.GetIndex()); } if (GeneralBaseArray == null) { throw(new Exception("SetupGeneralBaseArray() should have already been called.")); } Result.SetToZero(); int TopOfToReduce = ToReduce.GetIndex() + 1; if (TopOfToReduce > GeneralBaseArray.Length) { throw(new Exception("The Input number should have been reduced first. HowManyToAdd > GeneralBaseArray.Length")); } // If it gets this far then ToReduce is at // least this big. int HighestCopyIndex = CurrentModReductionBase.GetIndex(); Result.CopyUpTo(ToReduce, HighestCopyIndex - 1); int BiggestIndex = 0; for (int Count = HighestCopyIndex; Count < TopOfToReduce; 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 SetupGeneralBaseArray(Integer GeneralBase) { // The word 'Base' comes from the base of a number // system. Like normal decimal numbers have base // 10, binary numbers have base 2, etc. CurrentModReductionBase.Copy(GeneralBase); // The input to the accumulator can be twice the // bit length of GeneralBase. int HowManyDigits = ((GeneralBase.GetIndex() + 1) * 2) + 10; // Plus some extra for carries... GeneralBaseArray = new Integer[HowManyDigits]; // int HowManyPrimes = 100; // Row, Column // SmallBasesArray = new uint[HowManyDigits, HowManyPrimes]; Integer Base = 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. // 0x1 0000 0000 Integer BaseValue = new Integer(); BaseValue.SetFromULong(1); for (int Column = 0; Column < HowManyDigits; Column++) { if (GeneralBaseArray[Column] == null) { GeneralBaseArray[Column] = new Integer(); } IntMath.Divider.Divide(BaseValue, GeneralBase, Quotient, Remainder); GeneralBaseArray[Column].Copy(Remainder); /* * for( int Row = 0; Row < HowManyPrimes; Row++ ) * { * This base value mod this prime? * * SmallBasesArray[Row, Column] = what? * } */ // Done at the bottom for the next round of the // loop. BaseValue.Copy(Remainder); IntMath.Multiply(BaseValue, Base); } }
private void TestDivideBits(ulong MaxValue, bool IsTop, int TestIndex, Integer ToDivide, Integer DivideBy, Integer Quotient, Integer Remainder) { // For a particular value of TestIndex, this does // the for-loop to test each bit. uint BitTest = 0x80000000; for (int BitCount = 31; BitCount >= 0; BitCount--) { if ((Quotient.GetD(TestIndex) | BitTest) > MaxValue) { // If it's more than the MaxValue then the // multiplication test can be skipped for // this bit. // SkippedMultiplies++; BitTest >>= 1; continue; } TestForBits.Copy(Quotient); // Is it only doing the multiplication for the // top digit? if (IsTop) { TestForBits.SetD(TestIndex, TestForBits.GetD(TestIndex) | BitTest); IntMath.MultiplyTop(TestForBits, DivideBy); } else { TestForBits.SetD(TestIndex, TestForBits.GetD(TestIndex) | BitTest); IntMath.Multiply(TestForBits, DivideBy); } if (TestForBits.ParamIsGreaterOrEq(ToDivide)) { // It passed the test, so keep the bit. Quotient.SetD(TestIndex, Quotient.GetD(TestIndex) | BitTest); } BitTest >>= 1; } }
internal bool MultiplicativeInverse(Integer X, Integer Modulus, Integer MultInverse) { // This is the extended Euclidean Algorithm. // A*X + B*Y = Gcd // A*X + B*Y = 1 If there's a multiplicative inverse. // A*X = 1 - B*Y so A is the multiplicative inverse of X mod Y. if (X.IsZero()) { throw(new Exception("Doing Multiplicative Inverse with a parameter that is zero.")); } if (Modulus.IsZero()) { throw(new Exception("Doing Multiplicative Inverse with a parameter that is zero.")); } // This happens sometimes: // if( Modulus.ParamIsGreaterOrEq( X )) // throw( new Exception( "Modulus.ParamIsGreaterOrEq( X ) for Euclid." )); // Worker.ReportProgress( 0, " " ); // Worker.ReportProgress( 0, " " ); // Worker.ReportProgress( 0, "Top of mod inverse." ); // U is the old part to keep. U0.SetToZero(); U1.SetToOne(); U2.Copy(Modulus); // Don't change the original numbers that came in as parameters. // V is the new part. V0.SetToOne(); V1.SetToZero(); V2.Copy(X); T0.SetToZero(); T1.SetToZero(); T2.SetToZero(); Quotient.SetToZero(); // while( not forever if there's a problem ) for (int Count = 0; Count < 10000; Count++) { if (U2.IsNegative) { throw(new Exception("U2 was negative.")); } if (V2.IsNegative) { throw(new Exception("V2 was negative.")); } IntMath.Divider.Divide(U2, V2, Quotient, Remainder); if (Remainder.IsZero()) { // Worker.ReportProgress( 0, "Remainder is zero. No multiplicative-inverse." ); return(false); } TempEuclid1.Copy(U0); TempEuclid2.Copy(V0); IntMath.Multiplier.Multiply(TempEuclid2, Quotient); IntMath.Subtract(TempEuclid1, TempEuclid2); T0.Copy(TempEuclid1); TempEuclid1.Copy(U1); TempEuclid2.Copy(V1); IntMath.Multiplier.Multiply(TempEuclid2, Quotient); IntMath.Subtract(TempEuclid1, TempEuclid2); T1.Copy(TempEuclid1); TempEuclid1.Copy(U2); TempEuclid2.Copy(V2); IntMath.Multiplier.Multiply(TempEuclid2, Quotient); IntMath.Subtract(TempEuclid1, TempEuclid2); T2.Copy(TempEuclid1); U0.Copy(V0); U1.Copy(V1); U2.Copy(V2); V0.Copy(T0); V1.Copy(T1); V2.Copy(T2); if (Remainder.IsOne()) { // Worker.ReportProgress( 0, " " ); // Worker.ReportProgress( 0, "Remainder is 1. There is a multiplicative-inverse." ); break; } } MultInverse.Copy(T0); if (MultInverse.IsNegative) { IntMath.Add(MultInverse, Modulus); } // Worker.ReportProgress( 0, "MultInverse: " + ToString10( MultInverse )); TestForModInverse1.Copy(MultInverse); TestForModInverse2.Copy(X); IntMath.Multiplier.Multiply(TestForModInverse1, TestForModInverse2); IntMath.Divider.Divide(TestForModInverse1, Modulus, Quotient, Remainder); if (!Remainder.IsOne()) // By the definition of Multiplicative inverse: { throw(new Exception("MultInverse is wrong: " + IntMath.ToString10(Remainder))); } // Worker.ReportProgress( 0, "MultInverse is the right number: " + ToString10( MultInverse )); return(true); }
internal bool FindMultiplicativeInverseSmall(Integer ToFind, Integer KnownNumber, Integer Modulus) { // 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 = Divider.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); Multiplier.MultiplyULong(ToFind, Y); ToFind.AddULong(1); Divider.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); Multiplier.MultiplyULong(TestForModInverse1, KnownNumberULong); Divider.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("Remainder has to be 1: " + ToString10(Remainder))); } return(true); }
internal void Add(Integer Result, Integer ToAdd) { if (ToAdd.IsZero()) { return; } // The most common form. They are both positive. if (!Result.IsNegative && !ToAdd.IsNegative) { Result.Add(ToAdd); return; } if (!Result.IsNegative && ToAdd.IsNegative) { TempAdd1.Copy(ToAdd); TempAdd1.IsNegative = false; if (TempAdd1.ParamIsGreater(Result)) { Subtract(Result, TempAdd1); return; } else { Subtract(TempAdd1, Result); Result.Copy(TempAdd1); Result.IsNegative = true; return; } } if (Result.IsNegative && !ToAdd.IsNegative) { TempAdd1.Copy(Result); TempAdd1.IsNegative = false; TempAdd2.Copy(ToAdd); if (TempAdd1.ParamIsGreater(TempAdd2)) { Subtract(TempAdd2, TempAdd1); Result.Copy(TempAdd2); return; } else { Subtract(TempAdd1, TempAdd2); Result.Copy(TempAdd2); Result.IsNegative = true; return; } } if (Result.IsNegative && ToAdd.IsNegative) { TempAdd1.Copy(Result); TempAdd1.IsNegative = false; TempAdd2.Copy(ToAdd); TempAdd2.IsNegative = false; TempAdd1.Add(TempAdd2); Result.Copy(TempAdd1); Result.IsNegative = true; return; } }
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; } }
internal void MakeRSAKeys() { int ShowBits = (PrimeIndex + 1) * 32; // int TestLoops = 0; Worker.ReportProgress(0, "Making RSA keys."); Worker.ReportProgress(0, "Bits size is: " + ShowBits.ToString()); // ulong Loops = 0; while (true) { if (Worker.CancellationPending) { return; } Thread.Sleep(1); // Let other things run. // Make two prime factors. // Normally you'd only make new primes when you pay the Certificate // Authority for a new certificate. if (!MakeAPrime(PrimeP, PrimeIndex, 20)) { return; } if (Worker.CancellationPending) { return; } if (!MakeAPrime(PrimeQ, PrimeIndex, 20)) { return; } if (Worker.CancellationPending) { return; } // This is extremely unlikely. Integer Gcd = new Integer(); IntMath.GreatestCommonDivisor(PrimeP, PrimeQ, Gcd); if (!Gcd.IsOne()) { Worker.ReportProgress(0, "They had a GCD: " + IntMath.ToString10(Gcd)); continue; } if (Worker.CancellationPending) { return; } IntMath.GreatestCommonDivisor(PrimeP, PubKeyExponent, Gcd); if (!Gcd.IsOne()) { Worker.ReportProgress(0, "They had a GCD with PubKeyExponent: " + IntMath.ToString10(Gcd)); continue; } if (Worker.CancellationPending) { return; } IntMath.GreatestCommonDivisor(PrimeQ, PubKeyExponent, Gcd); if (!Gcd.IsOne()) { Worker.ReportProgress(0, "2) They had a GCD with PubKeyExponent: " + IntMath.ToString10(Gcd)); continue; } // For Modular Reduction. This only has to be done // once, when P and Q are made. IntMathForP.ModReduction.SetupGeneralBaseArray(PrimeP); IntMathForQ.ModReduction.SetupGeneralBaseArray(PrimeQ); PrimePMinus1.Copy(PrimeP); IntMath.SubtractULong(PrimePMinus1, 1); PrimeQMinus1.Copy(PrimeQ); IntMath.SubtractULong(PrimeQMinus1, 1); if (Worker.CancellationPending) { return; } // These checks should be more thorough to // make sure the primes P and Q are numbers // that can be used in a secure way. Worker.ReportProgress(0, "The Index of Prime P is: " + PrimeP.GetIndex().ToString()); Worker.ReportProgress(0, "Prime P:"); Worker.ReportProgress(0, IntMath.ToString10(PrimeP)); Worker.ReportProgress(0, " "); Worker.ReportProgress(0, "Prime Q:"); Worker.ReportProgress(0, IntMath.ToString10(PrimeQ)); Worker.ReportProgress(0, " "); PubKeyN.Copy(PrimeP); IntMath.Multiply(PubKeyN, PrimeQ); Worker.ReportProgress(0, " "); Worker.ReportProgress(0, "PubKeyN:"); Worker.ReportProgress(0, IntMath.ToString10(PubKeyN)); Worker.ReportProgress(0, " "); // Test Division: Integer QuotientTest = new Integer(); Integer RemainderTest = new Integer(); IntMath.Divider.Divide(PubKeyN, PrimeP, QuotientTest, RemainderTest); if (!RemainderTest.IsZero()) { throw(new Exception("RemainderTest should be zero after divide by PrimeP.")); } IntMath.Multiply(QuotientTest, PrimeP); if (!QuotientTest.IsEqual(PubKeyN)) { throw(new Exception("QuotientTest didn't come out right.")); } // Euler's Theorem: // https://en.wikipedia.org/wiki/Euler's_theorem // ========== // Work on the Least Common Multiple thing for // P - 1 and Q - 1. // ===== IntMath.GreatestCommonDivisor(PrimePMinus1, PrimeQMinus1, Gcd); Worker.ReportProgress(0, "GCD of PrimePMinus1, PrimeQMinus1 is: " + IntMath.ToString10(Gcd)); if (!Gcd.IsULong()) { Worker.ReportProgress(0, "This GCD number is too big: " + IntMath.ToString10(Gcd)); continue; } else { ulong TooBig = Gcd.GetAsULong(); // How big of a GCD is too big? // ============== if (TooBig > 1234567) { // (P - 1)(Q - 1) + (P - 1) + (Q - 1) = PQ - 1 Worker.ReportProgress(0, "This GCD number is bigger than 1234567: " + IntMath.ToString10(Gcd)); continue; } } Integer Temp1 = new Integer(); PhiN.Copy(PrimePMinus1); Temp1.Copy(PrimeQMinus1); IntMath.Multiply(PhiN, Temp1); Worker.ReportProgress(0, " "); Worker.ReportProgress(0, "PhiN:"); Worker.ReportProgress(0, IntMath.ToString10(PhiN)); Worker.ReportProgress(0, " "); if (Worker.CancellationPending) { return; } // In RFC 2437 there are commonly used letters/symbols to represent // the numbers used. So the number e is the public exponent. // The number e that is used here is called PubKeyExponentUint = 65537. // In the RFC the private key d is the multiplicative inverse of // e mod PhiN. Which is mod (P - 1)(Q - 1). It's called // PrivKInverseExponent here. if (!IntMath.FindMultiplicativeInverseSmall(PrivKInverseExponent, PubKeyExponent, PhiN, Worker)) { return; } if (PrivKInverseExponent.IsZero()) { continue; } Worker.ReportProgress(0, " "); Worker.ReportProgress(0, "PrivKInverseExponent: " + IntMath.ToString10(PrivKInverseExponent)); if (Worker.CancellationPending) { return; } // In RFC 2437 it defines a number dP which is the multiplicative // inverse, mod (P - 1) of e. That dP is named PrivKInverseExponentDP here. Worker.ReportProgress(0, " "); if (!IntMath.FindMultiplicativeInverseSmall(PrivKInverseExponentDP, PubKeyExponent, PrimePMinus1, Worker)) { return; } Worker.ReportProgress(0, " "); Worker.ReportProgress(0, "PrivKInverseExponentDP: " + IntMath.ToString10(PrivKInverseExponentDP)); if (PrivKInverseExponentDP.IsZero()) { continue; } // PrivKInverseExponentDP is PrivKInverseExponent mod PrimePMinus1. Integer Test1 = new Integer(); Test1.Copy(PrivKInverseExponent); IntMath.Divider.Divide(Test1, PrimePMinus1, Quotient, Remainder); Test1.Copy(Remainder); if (!Test1.IsEqual(PrivKInverseExponentDP)) { throw(new Exception("This does not match the definition of PrivKInverseExponentDP.")); } if (Worker.CancellationPending) { return; } // In RFC 2437 it defines a number dQ which is the multiplicative // inverse, mod (Q - 1) of e. That dQ is named PrivKInverseExponentDQ here. Worker.ReportProgress(0, " "); if (!IntMath.FindMultiplicativeInverseSmall(PrivKInverseExponentDQ, PubKeyExponent, PrimeQMinus1, Worker)) { return; } if (PrivKInverseExponentDQ.IsZero()) { continue; } Worker.ReportProgress(0, " "); Worker.ReportProgress(0, "PrivKInverseExponentDQ: " + IntMath.ToString10(PrivKInverseExponentDQ)); if (Worker.CancellationPending) { return; } Test1.Copy(PrivKInverseExponent); IntMath.Divider.Divide(Test1, PrimeQMinus1, Quotient, Remainder); Test1.Copy(Remainder); if (!Test1.IsEqual(PrivKInverseExponentDQ)) { throw(new Exception("This does not match the definition of PrivKInverseExponentDQ.")); } // Make a random number to test encryption/decryption. Integer ToEncrypt = new Integer(); int HowManyBytes = PrimeIndex * 4; byte[] RandBytes = MakeRandomBytes(HowManyBytes); if (RandBytes == null) { Worker.ReportProgress(0, "Error making random bytes in MakeRSAKeys()."); return; } if (!ToEncrypt.MakeRandomOdd(PrimeIndex - 1, RandBytes)) { Worker.ReportProgress(0, "Error making random number ToEncrypt."); return; } Integer PlainTextNumber = new Integer(); PlainTextNumber.Copy(ToEncrypt); Worker.ReportProgress(0, " "); Worker.ReportProgress(0, "Before encrypting number: " + IntMath.ToString10(ToEncrypt)); Worker.ReportProgress(0, " "); IntMath.ModReduction.ModularPower(ToEncrypt, PubKeyExponent, PubKeyN, false); if (Worker.CancellationPending) { return; } // Worker.ReportProgress( 0, IntMath.GetStatusString() ); Integer CipherTextNumber = new Integer(); CipherTextNumber.Copy(ToEncrypt); Worker.ReportProgress(0, " "); Worker.ReportProgress(0, "Encrypted number: " + IntMath.ToString10(CipherTextNumber)); Worker.ReportProgress(0, " "); ECTime DecryptTime = new ECTime(); DecryptTime.SetToNow(); IntMath.ModReduction.ModularPower(ToEncrypt, PrivKInverseExponent, PubKeyN, false); Worker.ReportProgress(0, "Decrypted number: " + IntMath.ToString10(ToEncrypt)); if (!PlainTextNumber.IsEqual(ToEncrypt)) { throw(new Exception("PlainTextNumber not equal to unencrypted value.")); // Because P or Q wasn't really a prime? // Worker.ReportProgress( 0, "PlainTextNumber not equal to unencrypted value." ); // continue; } Worker.ReportProgress(0, " "); Worker.ReportProgress(0, "Decrypt time seconds: " + DecryptTime.GetSecondsToNow().ToString("N2")); Worker.ReportProgress(0, " "); if (Worker.CancellationPending) { return; } // Test the standard optimized way of decrypting: if (!ToEncrypt.MakeRandomOdd(PrimeIndex - 1, RandBytes)) { Worker.ReportProgress(0, "Error making random number in MakeRSAKeys()."); return; } PlainTextNumber.Copy(ToEncrypt); IntMath.ModReduction.ModularPower(ToEncrypt, PubKeyExponent, PubKeyN, false); if (Worker.CancellationPending) { return; } CipherTextNumber.Copy(ToEncrypt); // QInv is the multiplicative inverse of PrimeQ mod PrimeP. if (!IntMath.MultiplicativeInverse(PrimeQ, PrimeP, QInv, Worker)) { throw(new Exception("MultiplicativeInverse() returned false.")); } if (QInv.IsNegative) { throw(new Exception("QInv is negative.")); } Worker.ReportProgress(0, "QInv is: " + IntMath.ToString10(QInv)); DecryptWithQInverse(CipherTextNumber, ToEncrypt, // Decrypt it to this. PlainTextNumber, // Test it against this. PubKeyN, PrivKInverseExponentDP, PrivKInverseExponentDQ, PrimeP, PrimeQ, Worker); Worker.ReportProgress(0, " "); Worker.ReportProgress(0, "Found the values:"); Worker.ReportProgress(0, "Seconds: " + StartTime.GetSecondsToNow().ToString("N0")); Worker.ReportProgress(0, " "); Worker.ReportProgress(1, "Prime1: " + IntMath.ToString10(PrimeP)); Worker.ReportProgress(0, " "); Worker.ReportProgress(1, "Prime2: " + IntMath.ToString10(PrimeQ)); Worker.ReportProgress(0, " "); Worker.ReportProgress(1, "PubKeyN: " + IntMath.ToString10(PubKeyN)); Worker.ReportProgress(0, " "); Worker.ReportProgress(1, "PrivKInverseExponent: " + IntMath.ToString10(PrivKInverseExponent)); // return; // Comment this out to just leave it while( true ) for testing. } }
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); IntMathForP.ModReduction.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); IntMathForQ.ModReduction.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.Divider.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("M1MinusM2.IsNegative is true.")); } if (QInv.IsNegative) { throw(new Exception("QInv.IsNegative is true.")); } HForQInv.Copy(M1MinusM2); IntMath.Multiply(HForQInv, QInv); if (HForQInv.IsNegative) { throw(new Exception("HForQInv.IsNegative is true.")); } if (PrimeP.ParamIsGreater(HForQInv)) { IntMath.Divider.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 void LongDivide3(Integer ToDivide, Integer DivideBy, Integer Quotient, Integer Remainder) { ////////////////// Integer Test2 = new Integer(); ///////////////// 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); IntMath.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); IntMath.MultiplyTop(TestForDivide1, DivideBy); ///////////// Test2.Copy(Quotient); Test2.SetD(TestIndex, MaxValue); IntMath.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); IntMath.MultiplyTop(TestForDivide1, DivideBy); 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); IntMath.Multiply(TestForDivide1, DivideByKeep); Remainder.Copy(ToDivideKeep); IntMath.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. IntMath.Multiply(TestForDivide1, DivideBy); if (ToDivide.ParamIsGreater(TestForDivide1)) { throw(new Exception("Problem here in LongDivide3().")); } Remainder.Copy(ToDivide); IntMath.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. IntMath.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); IntMath.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); IntMath.Multiply(TestForDivide1, DivideByKeep); Remainder.Copy(ToDivideKeep); IntMath.Subtract(Remainder, TestForDivide1); if (DivideByKeep.ParamIsGreater(Remainder)) { throw(new Exception("Remainder > DivideBy in LongDivide3().")); } }
// This is the standard modular power algorithm that // you could find in any reference, but its use of // my modular reduction algorithm in it is new (in 2015). // (I mean as opposed to using some other modular reduction // algorithm.) // The square and multiply method is in Wikipedia: // https://en.wikipedia.org/wiki/Exponentiation_by_squaring 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.Divider.Divide(Result, Modulus, Quotient, Remainder); Result.Copy(Remainder); } if (Exponent.IsOne()) { // Result stays the same. return; } if (!UsePresetBaseArray) { IntMath.ModReduction.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.Multiplier.Multiply(Result, XForModPower); // if( Result.ParamIsGreater( CurrentModReductionBase )) // TestForModReduction2.Copy( Result ); IntMath.ModReduction.Reduce(TempForModPower, Result); // ModularReduction2( TestForModReduction2ForModPower, TestForModReduction2 ); // if( !TestForModReduction2ForModPower.IsEqual( TempForModPower )) // { // throw( new Exception( "Mod Reduction 2 is not right." )); // } Result.Copy(TempForModPower); } ExponentCopy.ShiftRight(1); // Divide by 2. if (ExponentCopy.IsZero()) { break; } // Square it. IntMath.Multiplier.Multiply(XForModPower, XForModPower); // if( XForModPower.ParamIsGreater( CurrentModReductionBase )) IntMath.ModReduction.Reduce(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() )); // Do a proof for how big this can be. if (HowBig > 2) { throw(new Exception("This never happens. Diff: " + HowBig.ToString())); } IntMath.ModReduction.Reduce(TempForModPower, Result); Result.Copy(TempForModPower); // Notice that this Divide() is done once. Not // a thousand or two thousand times. /* * Integer ResultTest = new Integer(); * Integer ModulusTest = new Integer(); * Integer QuotientTest = new Integer(); * Integer RemainderTest = new Integer(); * * ResultTest.Copy( Result ); * ModulusTest.Copy( Modulus ); * IntMath.Divider.DivideForSmallQuotient( ResultTest, * ModulusTest, * QuotientTest, * RemainderTest ); * */ IntMath.Divider.Divide(Result, Modulus, Quotient, Remainder); // if( !RemainderTest.IsEqual( Remainder )) // throw( new Exception( "DivideForSmallQuotient() !RemainderTest.IsEqual( Remainder )." )); // if( !QuotientTest.IsEqual( Quotient )) // throw( new Exception( "DivideForSmallQuotient() !QuotientTest.IsEqual( Quotient )." )); Result.Copy(Remainder); if (Quotient.GetIndex() > 1) { throw(new Exception("This never happens. The quotient index is never more than 1.")); } }
// This works like LongDivide1 except that it // estimates the maximum value for the digit and // the for-loop for bit testing is called // as a separate function. private bool LongDivide2(Integer ToDivide, Integer DivideBy, Integer Quotient, Integer Remainder) { Integer Test1 = new Integer(); int TestIndex = ToDivide.GetIndex() - DivideBy.GetIndex(); // See if TestIndex is too high. if (TestIndex != 0) { // Is 1 too high? Test1.SetDigitAndClear(TestIndex, 1); IntMath.MultiplyTopOne(Test1, DivideBy); if (ToDivide.ParamIsGreater(Test1)) { TestIndex--; } } // If you were multiplying 99 times 97 you'd get // 9,603 and the upper two digits [96] are used // to find the MaxValue. But if you multiply // 12 * 13 you'd have 156 and only the upper one // digit is used to find the MaxValue. // Here it checks if it should use one digit or // two: 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); } MaxValue = MaxValue / DivideBy.GetD(DivideBy.GetIndex()); Quotient.SetDigitAndClear(TestIndex, 1); Quotient.SetD(TestIndex, 0); TestDivideBits(MaxValue, true, TestIndex, ToDivide, DivideBy, Quotient, Remainder); if (TestIndex == 0) { Test1.Copy(Quotient); IntMath.Multiply(Test1, DivideBy); Remainder.Copy(ToDivide); IntMath.Subtract(Remainder, Test1); /////////////// if (DivideBy.ParamIsGreater(Remainder)) { throw(new Exception("Remainder > DivideBy in LongDivide2().")); } ////////////// if (Remainder.IsZero()) { return(true); } else { return(false); } } TestIndex--; while (true) { // This remainder is used the same way you do // long division with paper and pen and you // keep working with a remainder until the // remainder is reduced to something smaller // than DivideBy. You look at the remainder // to estimate your next quotient digit. Test1.Copy(Quotient); IntMath.Multiply(Test1, DivideBy); Remainder.Copy(ToDivide); IntMath.Subtract(Remainder, Test1); MaxValue = Remainder.GetD(Remainder.GetIndex()) << 32; MaxValue |= Remainder.GetD(Remainder.GetIndex() - 1); MaxValue = MaxValue / DivideBy.GetD(DivideBy.GetIndex()); TestDivideBits(MaxValue, false, TestIndex, ToDivide, DivideBy, Quotient, Remainder); if (TestIndex == 0) { break; } TestIndex--; } Test1.Copy(Quotient); IntMath.Multiply(Test1, DivideBy); Remainder.Copy(ToDivide); IntMath.Subtract(Remainder, Test1); ////////////////////////////// if (DivideBy.ParamIsGreater(Remainder)) { throw(new Exception("Remainder > DivideBy in LongDivide2().")); } //////////////////////////////// if (Remainder.IsZero()) { return(true); } else { return(false); } }
internal void Divide(Integer ToDivideOriginal, Integer DivideByOriginal, Integer Quotient, Integer Remainder) { if (ToDivideOriginal.IsNegative) { throw(new Exception("Divide() can't be called with negative numbers.")); } if (DivideByOriginal.IsNegative) { throw(new Exception("Divide() can't be called with negative numbers.")); } // Returns true if it divides exactly with zero remainder. // This first checks for some basics before trying to divide it: if (DivideByOriginal.IsZero()) { throw(new Exception("Divide() dividing by zero.")); } ToDivide.Copy(ToDivideOriginal); DivideBy.Copy(DivideByOriginal); if (ToDivide.ParamIsGreater(DivideBy)) { Quotient.SetToZero(); Remainder.Copy(ToDivide); return; // false; } if (ToDivide.IsEqual(DivideBy)) { Quotient.SetFromULong(1); Remainder.SetToZero(); return; // true; } // At this point DivideBy is smaller than ToDivide. if (ToDivide.IsULong()) { ulong ToDivideU = ToDivide.GetAsULong(); ulong DivideByU = DivideBy.GetAsULong(); ulong QuotientU = ToDivideU / DivideByU; ulong RemainderU = ToDivideU % DivideByU; Quotient.SetFromULong(QuotientU); Remainder.SetFromULong(RemainderU); // if( RemainderU == 0 ) return; // true; // else // return false; } if (DivideBy.GetIndex() == 0) { ShortDivide(ToDivide, DivideBy, Quotient, Remainder); return; } Integer ToDivideTest2 = new Integer(); Integer DivideByTest2 = new Integer(); Integer QuotientTest2 = new Integer(); Integer RemainderTest2 = new Integer(); Integer ToDivideTest3 = new Integer(); Integer DivideByTest3 = new Integer(); Integer QuotientTest3 = new Integer(); Integer RemainderTest3 = new Integer(); ToDivideTest2.Copy(ToDivide); ToDivideTest3.Copy(ToDivide); DivideByTest2.Copy(DivideBy); DivideByTest3.Copy(DivideBy); LongDivide1(ToDivideTest2, DivideByTest2, QuotientTest2, RemainderTest2); LongDivide2(ToDivideTest3, DivideByTest3, QuotientTest3, RemainderTest3); LongDivide3(ToDivide, DivideBy, Quotient, Remainder); if (!Quotient.IsEqual(QuotientTest2)) { throw(new Exception("!Quotient.IsEqual( QuotientTest2 )")); } if (!Quotient.IsEqual(QuotientTest3)) { throw(new Exception("!Quotient.IsEqual( QuotientTest3 )")); } if (!Remainder.IsEqual(RemainderTest2)) { throw(new Exception("!Remainder.IsEqual( RemainderTest2 )")); } if (!Remainder.IsEqual(RemainderTest3)) { throw(new Exception("!Remainder.IsEqual( RemainderTest3 )")); } }
private bool LongDivide1(Integer ToDivide, Integer DivideBy, Integer Quotient, Integer Remainder) { uint Digit = 0; Integer Test1 = new Integer(); int TestIndex = ToDivide.GetIndex() - DivideBy.GetIndex(); if (TestIndex != 0) { // Is 1 too high? Test1.SetDigitAndClear(TestIndex, 1); IntMath.MultiplyTopOne(Test1, DivideBy); if (ToDivide.ParamIsGreater(Test1)) { TestIndex--; } } Quotient.SetDigitAndClear(TestIndex, 1); Quotient.SetD(TestIndex, 0); uint BitTest = 0x80000000; while (true) { // For-loop to test each bit: for (int BitCount = 31; BitCount >= 0; BitCount--) { Test1.Copy(Quotient); Digit = (uint)Test1.GetD(TestIndex) | BitTest; Test1.SetD(TestIndex, Digit); IntMath.Multiply(Test1, DivideBy); if (Test1.ParamIsGreaterOrEq(ToDivide)) { Digit = (uint)Quotient.GetD(TestIndex) | BitTest; // I want to keep this bit because it // passed the test. Quotient.SetD(TestIndex, Digit); } BitTest >>= 1; } if (TestIndex == 0) { break; } TestIndex--; BitTest = 0x80000000; } Test1.Copy(Quotient); IntMath.Multiply(Test1, DivideBy); if (Test1.IsEqual(ToDivide)) { Remainder.SetToZero(); return(true); // Divides exactly. } Remainder.Copy(ToDivide); IntMath.Subtract(Remainder, Test1); // Does not divide it exactly. return(false); }