예제 #1
0
        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.
            }
        }
예제 #2
0
        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);
        }
예제 #3
0
        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.
            }
        }
예제 #4
0
        // 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."));
            }
        }
예제 #5
0
        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);
        }