Exemplo n.º 1
0
        internal void SubtractPositive(Integer Result, Integer ToSub)
        {
            if (ToSub.IsULong())
            {
                SubtractULong(Result, ToSub.GetAsULong());
                return;
            }

            if (ToSub.GetIndex() > Result.GetIndex())
            {
                throw(new Exception("In Subtract() ToSub.Index > Index."));
            }

            int Max = ToSub.GetIndex();

            for (int Count = 0; Count <= Max; Count++)
            {
                SignedD[Count] = (long)Result.GetD(Count) - (long)ToSub.GetD(Count);
            }

            Max = Result.GetIndex();
            for (int Count = ToSub.GetIndex() + 1; Count <= Max; Count++)
            {
                SignedD[Count] = (long)Result.GetD(Count);
            }

            Max = Result.GetIndex();
            for (int Count = 0; Count < Max; Count++)
            {
                if (SignedD[Count] < 0)
                {
                    SignedD[Count] += (long)0xFFFFFFFF + 1;
                    SignedD[Count + 1]--;
                }
            }

            if (SignedD[Result.GetIndex()] < 0)
            {
                throw(new Exception("Subtract() SignedD[Index] < 0."));
            }

            Max = Result.GetIndex();
            for (int Count = 0; Count <= Max; Count++)
            {
                Result.SetD(Count, (ulong)SignedD[Count]);
            }

            for (int Count = Result.GetIndex(); Count >= 0; Count--)
            {
                if (Result.GetD(Count) != 0)
                {
                    Result.SetIndex(Count);
                    return;
                }
            }

            // If it never found a non-zero digit it would get down to here.
            Result.SetIndex(0);
        }
Exemplo n.º 2
0
        // 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);
        }
Exemplo n.º 3
0
        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);
            }
        }
Exemplo n.º 4
0
        // This is a variation on ShortDivide() to get the
        // remainder only.
        internal ulong GetMod32(Integer ToDivideOriginal, ulong DivideByU)
        {
            if ((DivideByU >> 32) != 0)
            {
                throw(new Exception("GetMod32: (DivideByU >> 32) != 0."));
            }

            // If this is _equal_ to a small prime it would return zero.
            if (ToDivideOriginal.IsULong())
            {
                ulong Result = ToDivideOriginal.GetAsULong();
                return(Result % DivideByU);
            }

            ToDivide.Copy(ToDivideOriginal);
            ulong RemainderU = 0;

            if (DivideByU <= ToDivide.GetD(ToDivide.GetIndex()))
            {
                ulong OneDigit = ToDivide.GetD(ToDivide.GetIndex());
                RemainderU = OneDigit % DivideByU;
                ToDivide.SetD(ToDivide.GetIndex(), RemainderU);
            }

            for (int Count = ToDivide.GetIndex(); Count >= 1; Count--)
            {
                ulong TwoDigits = ToDivide.GetD(Count);
                TwoDigits <<= 32;
                TwoDigits  |= ToDivide.GetD(Count - 1);
                RemainderU  = TwoDigits % DivideByU;
                ToDivide.SetD(Count, 0);
                ToDivide.SetD(Count - 1, RemainderU);
            }

            return(RemainderU);
        }
Exemplo n.º 5
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);
        }
Exemplo n.º 6
0
        internal void SubtractULong(Integer Result, ulong ToSub)
        {
            if (Result.IsULong())
            {
                ulong ResultU = Result.GetAsULong();
                if (ToSub > ResultU)
                {
                    throw(new Exception("SubULong() (IsULong() and (ToSub > Result)."));
                }

                ResultU = ResultU - ToSub;
                Result.SetD(0, ResultU & 0xFFFFFFFF);
                Result.SetD(1, ResultU >> 32);
                if (Result.GetD(1) == 0)
                {
                    Result.SetIndex(0);
                }
                else
                {
                    Result.SetIndex(1);
                }

                return;
            }

            // If it got this far then Index is at least 2.
            SignedD[0] = (long)Result.GetD(0) - (long)(ToSub & 0xFFFFFFFF);
            SignedD[1] = (long)Result.GetD(1) - (long)(ToSub >> 32);
            if ((SignedD[0] >= 0) && (SignedD[1] >= 0))
            {
                // No need to reorganize it.
                Result.SetD(0, (ulong)SignedD[0]);
                Result.SetD(1, (ulong)SignedD[1]);
                return;
            }

            int Max = Result.GetIndex();

            for (int Count = 2; Count <= Max; Count++)
            {
                SignedD[Count] = (long)Result.GetD(Count);
            }

            Max = Result.GetIndex();
            for (int Count = 0; Count < Max; Count++)
            {
                if (SignedD[Count] < 0)
                {
                    SignedD[Count] += (long)0xFFFFFFFF + 1;
                    SignedD[Count + 1]--;
                }
            }

            if (SignedD[Result.GetIndex()] < 0)
            {
                throw(new Exception("SubULong() SignedD[Index] < 0."));
            }

            Max = Result.GetIndex();
            for (int Count = 0; Count <= Max; Count++)
            {
                Result.SetD(Count, (ulong)SignedD[Count]);
            }

            Max = Result.GetIndex();
            for (int Count = Max; Count >= 0; Count--)
            {
                if (Result.GetD(Count) != 0)
                {
                    Result.SetIndex(Count);
                    return;
                }
            }

            // If this was zero it wouldn't find a nonzero
            // digit to set the Index to and it would end up down here.
            Result.SetIndex(0);
        }
Exemplo n.º 7
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.
            }
        }
Exemplo n.º 8
0
        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 )"));
            }
        }
Exemplo n.º 9
0
        internal ulong GetMod64(Integer ToDivideOriginal, ulong DivideBy)
        {
            if (ToDivideOriginal.IsULong())
            {
                return(ToDivideOriginal.GetAsULong() % DivideBy);
            }

            ToDivide.Copy(ToDivideOriginal);
            ulong Digit1;
            ulong Digit0;
            ulong Remainder;

            if (ToDivide.GetIndex() == 2)
            {
                Digit1  = ToDivide.GetD(2);
                Digit0  = ToDivide.GetD(1) << 32;
                Digit0 |= ToDivide.GetD(0);
                return(GetMod64FromTwoULongs(Digit1, Digit0, DivideBy));
            }

            if (ToDivide.GetIndex() == 3)
            {
                Digit1  = ToDivide.GetD(3) << 32;
                Digit1 |= ToDivide.GetD(2);
                Digit0  = ToDivide.GetD(1) << 32;
                Digit0 |= ToDivide.GetD(0);
                return(GetMod64FromTwoULongs(Digit1, Digit0, DivideBy));
            }

            int Where = ToDivide.GetIndex();

            while (true)
            {
                if (Where <= 3)
                {
                    if (Where < 2) // This can't happen.
                    {
                        throw(new Exception("GetMod64(): Where < 2."));
                    }

                    if (Where == 2)
                    {
                        Digit1  = ToDivide.GetD(2);
                        Digit0  = ToDivide.GetD(1) << 32;
                        Digit0 |= ToDivide.GetD(0);
                        return(GetMod64FromTwoULongs(Digit1, Digit0, DivideBy));
                    }

                    if (Where == 3)
                    {
                        Digit1  = ToDivide.GetD(3) << 32;
                        Digit1 |= ToDivide.GetD(2);
                        Digit0  = ToDivide.GetD(1) << 32;
                        Digit0 |= ToDivide.GetD(0);
                        return(GetMod64FromTwoULongs(Digit1, Digit0, DivideBy));
                    }
                }
                else
                {
                    // The index is bigger than 3.
                    // This part would get called at least once.
                    Digit1    = ToDivide.GetD(Where) << 32;
                    Digit1   |= ToDivide.GetD(Where - 1);
                    Digit0    = ToDivide.GetD(Where - 2) << 32;
                    Digit0   |= ToDivide.GetD(Where - 3);
                    Remainder = GetMod64FromTwoULongs(Digit1, Digit0, DivideBy);
                    ToDivide.SetD(Where, 0);
                    ToDivide.SetD(Where - 1, 0);
                    ToDivide.SetD(Where - 2, Remainder >> 32);
                    ToDivide.SetD(Where - 3, Remainder & 0xFFFFFFFF);
                }

                Where -= 2;
            }
        }
Exemplo n.º 10
0
        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;
            }

            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;
            }
        }
Exemplo n.º 11
0
        internal void Multiply(Integer Result, Integer ToMul)
        {
            // try
            // {
            if (Result.IsZero())
            {
                return;
            }

            if (ToMul.IsULong())
            {
                MultiplyULong(Result, ToMul.GetAsULong());
                SetMultiplySign(Result, ToMul);
                return;
            }

            // It could never get here if ToMul is zero because GetIsULong()
            // would be true for zero.
            // if( ToMul.IsZero())
            int TotalIndex = Result.GetIndex() + ToMul.GetIndex();

            if (TotalIndex >= Integer.DigitArraySize)
            {
                throw(new Exception("Multiply() overflow."));
            }

            int CountTo = ToMul.GetIndex();

            for (int Row = 0; Row <= CountTo; Row++)
            {
                if (ToMul.GetD(Row) == 0)
                {
                    int CountZeros = Result.GetIndex();
                    for (int Column = 0; Column <= CountZeros; Column++)
                    {
                        M[Column + Row, Row] = 0;
                    }
                }
                else
                {
                    int CountMult = Result.GetIndex();
                    for (int Column = 0; Column <= CountMult; Column++)
                    {
                        M[Column + Row, Row] = ToMul.GetD(Row) * Result.GetD(Column);
                    }
                }
            }

            // Add the columns up with a carry.
            Result.SetD(0, M[0, 0] & 0xFFFFFFFF);
            ulong Carry       = M[0, 0] >> 32;
            int   ResultIndex = Result.GetIndex();
            int   MulIndex    = ToMul.GetIndex();

            for (int Column = 1; Column <= TotalIndex; Column++)
            {
                ulong TotalLeft  = 0;
                ulong TotalRight = 0;
                for (int Row = 0; Row <= MulIndex; Row++)
                {
                    if (Row > Column)
                    {
                        break;
                    }

                    if (Column > (ResultIndex + Row))
                    {
                        continue;
                    }

                    // Split the ulongs into right and left sides
                    // so that they don't overflow.
                    TotalRight += M[Column, Row] & 0xFFFFFFFF;
                    TotalLeft  += M[Column, Row] >> 32;
                }

                TotalRight += Carry;
                Result.SetD(Column, TotalRight & 0xFFFFFFFF);
                Carry  = TotalRight >> 32;
                Carry += TotalLeft;
            }

            Result.SetIndex(TotalIndex);
            if (Carry != 0)
            {
                Result.IncrementIndex(); // This can throw an exception if it overflowed the index.
                Result.SetD(Result.GetIndex(), Carry);
            }

            SetMultiplySign(Result, ToMul);
        }