예제 #1
0
        // This is another optimization.  This is used
        // when the top digit is 1 and all of the other
        // digits are zero.  This is effectively just a
        // shift-left operation.
        internal void MultiplyTopOne(Integer Result, Integer ToMul)
        {
            // try
            // {
            int TotalIndex = Result.GetIndex() + ToMul.GetIndex();

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

            int ToMulIndex  = ToMul.GetIndex();
            int ResultIndex = Result.GetIndex();

            for (int Column = 0; Column <= ToMulIndex; Column++)
            {
                Result.SetD(Column + ResultIndex, ToMul.GetD(Column));
            }

            for (int Column = 0; Column < ResultIndex; Column++)
            {
                Result.SetD(Column, 0);
            }

            // No Carrys need to be done.
            Result.SetIndex(TotalIndex);

            /*
             * }
             * catch( Exception ) // Except )
             * {
             * // "Exception in MultiplyTopOne: " + Except.Message
             * }
             */
        }
예제 #2
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);
        }
예제 #3
0
        // 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));
            }
        }
예제 #4
0
        // This is an optimization for multiplying when
        // only the top digit of a number has been set and
        // all of the other digits are zero.
        internal void MultiplyTop(Integer Result, Integer ToMul)
        {
            // try
            // {
            int TotalIndex = Result.GetIndex() + ToMul.GetIndex();

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

            // Just like Multiply() except that all the other
            // rows are zero:
            int ToMulIndex  = ToMul.GetIndex();
            int ResultIndex = Result.GetIndex();

            for (int Column = 0; Column <= ToMulIndex; Column++)
            {
                M[Column + ResultIndex, ResultIndex] = Result.GetD(ResultIndex) * ToMul.GetD(Column);
            }

            for (int Column = 0; Column < ResultIndex; Column++)
            {
                Result.SetD(Column, 0);
            }

            ulong Carry = 0;

            for (int Column = 0; Column <= ToMulIndex; Column++)
            {
                ulong Total = M[Column + ResultIndex, ResultIndex] + Carry;
                Result.SetD(Column + ResultIndex, Total & 0xFFFFFFFF);
                Carry = Total >> 32;
            }

            Result.SetIndex(TotalIndex);
            if (Carry != 0)
            {
                Result.SetIndex(Result.GetIndex() + 1);
                if (Result.GetIndex() >= Integer.DigitArraySize)
                {
                    throw(new Exception("MultiplyTop() overflow."));
                }

                Result.SetD(Result.GetIndex(), Carry);
            }

            /*
             * }
             * catch( Exception ) // Except )
             * {
             * // "Exception in MultiplyTop: " + Except.Message
             * }
             */
        }
예제 #5
0
        internal int MultiplyUIntFromCopy(Integer Result, Integer FromCopy, ulong ToMul)
        {
            int FromCopyIndex = FromCopy.GetIndex();

            Result.SetIndex(FromCopyIndex);
            for (int Column = 0; Column <= FromCopyIndex; Column++)
            {
                Scratch[Column] = ToMul * FromCopy.GetD(Column);
            }

            // Add these up with a carry.
            Result.SetD(0, Scratch[0] & 0xFFFFFFFF);
            ulong Carry = Scratch[0] >> 32;

            for (int Column = 1; Column <= FromCopyIndex; Column++)
            {
                ulong Total = Scratch[Column] + Carry;
                Result.SetD(Column, Total & 0xFFFFFFFF);
                Carry = Total >> 32;
            }

            if (Carry != 0)
            {
                Result.IncrementIndex(); // This might throw an exception if it overflows.
                Result.SetD(FromCopyIndex + 1, Carry);
            }

            return(Result.GetIndex());
        }
예제 #6
0
        internal void MultiplyUInt(Integer Result, ulong ToMul)
        {
            try
            {
                if (ToMul == 0)
                {
                    Result.SetToZero();
                    return;
                }

                if (ToMul == 1)
                {
                    return;
                }

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

                // Add these up with a carry.
                Result.SetD(0, M[0, 0] & 0xFFFFFFFF);
                ulong Carry = M[0, 0] >> 32;
                CountTo = Result.GetIndex();
                for (int Column = 1; Column <= CountTo; Column++)
                {
                    // Using a compile-time check on this constant,
                    // this Test value does not overflow:
                    // const ulong Test = ((ulong)0xFFFFFFFF * (ulong)(0xFFFFFFFF)) + 0xFFFFFFFF;
                    // ulong Total = checked( M[Column, 0] + Carry );
                    ulong Total = M[Column, 0] + Carry;
                    Result.SetD(Column, Total & 0xFFFFFFFF);
                    Carry = Total >> 32;
                }

                if (Carry != 0)
                {
                    Result.IncrementIndex(); // This might throw an exception if it overflows.
                    Result.SetD(Result.GetIndex(), Carry);
                }
            }
            catch (Exception Except)
            {
                throw(new Exception("Exception in MultiplyUInt(): " + Except.Message));
            }
        }
예제 #7
0
        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);
            }
        }
예제 #8
0
        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);
            }
        }
예제 #9
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);
        }
예제 #10
0
        internal void MultiplyULong(Integer Result, ulong ToMul)
        {
            // Using compile-time checks, this one overflows:
            // const ulong Test = ((ulong)0xFFFFFFFF + 1) * ((ulong)0xFFFFFFFF + 1);
            // This one doesn't:
            // const ulong Test = (ulong)0xFFFFFFFF * ((ulong)0xFFFFFFFF + 1);
            if (Result.IsZero())
            {
                return; // Then the answer is zero, which it already is.
            }
            if (ToMul == 0)
            {
                Result.SetToZero();
                return;
            }

            ulong B0 = ToMul & 0xFFFFFFFF;
            ulong B1 = ToMul >> 32;

            if (B1 == 0)
            {
                MultiplyUInt(Result, (uint)B0);
                return;
            }

            // Since B1 is not zero:
            if ((Result.GetIndex() + 1) >= Integer.DigitArraySize)
            {
                throw(new Exception("Overflow in MultiplyULong."));
            }

            int CountTo = Result.GetIndex();

            for (int Column = 0; Column <= CountTo; Column++)
            {
                ulong Digit = Result.GetD(Column);
                M[Column, 0] = B0 * Digit;
                // Column + 1 and Row is 1, so it's just like pen and paper.
                M[Column + 1, 1] = B1 * Digit;
            }

            // Since B1 is not zero, the index is set one higher.
            Result.IncrementIndex();     // Might throw an exception if it goes out of range.
            M[Result.GetIndex(), 0] = 0; // Otherwise it would be undefined
                                         // when it's added up below.
            // Add these up with a carry.
            Result.SetD(0, M[0, 0] & 0xFFFFFFFF);
            ulong Carry = M[0, 0] >> 32;

            CountTo = Result.GetIndex();
            for (int Column = 1; Column <= CountTo; Column++)
            {
                // This does overflow:
                // const ulong Test = ((ulong)0xFFFFFFFF * (ulong)(0xFFFFFFFF))
                //                  + ((ulong)0xFFFFFFFF * (ulong)(0xFFFFFFFF));
                // Split the ulongs into right and left sides
                // so that they don't overflow.
                ulong TotalLeft  = 0;
                ulong TotalRight = 0;
                // There's only the two rows for this.
                for (int Row = 0; Row <= 1; Row++)
                {
                    ulong MValue = M[Column, Row];
                    TotalRight += MValue & 0xFFFFFFFF;
                    TotalLeft  += MValue >> 32;
                }

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

            if (Carry != 0)
            {
                Result.IncrementIndex(); // This can throw an exception.
                Result.SetD(Result.GetIndex(), Carry);
            }
        }
예제 #11
0
        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);
        }
예제 #12
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);
        }
예제 #13
0
        private bool MakeAPrime(Integer Result, int SetToIndex, int HowMany)
        {
            try
            {
                int Attempts = 0;
                while (true)
                {
                    Attempts++;
                    if (Worker.CancellationPending)
                    {
                        return(false);
                    }

                    // Let other things run on my cheap laptop.
                    Thread.Sleep(1);

                    int    HowManyBytes = (SetToIndex * 4) + 4;
                    byte[] RandBytes    = MakeRandomBytes(HowManyBytes);
                    if (RandBytes == null)
                    {
                        Worker.ReportProgress(0, "Error making random bytes in MakeAPrime().");
                        return(false);
                    }

                    if (!Result.MakeRandomOdd(SetToIndex, RandBytes))
                    {
                        Worker.ReportProgress(0, "Error making random number in MakeAPrime().");
                        return(false);
                    }

                    // Make sure that it's the size I think it is.
                    if (Result.GetIndex() < SetToIndex)
                    {
                        throw(new Exception("The size of the random prime is not right."));
                    }

                    uint TestPrime = IntMath.IsDivisibleBySmallPrime(Result);
                    if (0 != TestPrime)
                    {
                        continue;
                    }

                    if (!IntMath.IsFermatPrime(Result, HowMany))
                    {
                        Worker.ReportProgress(0, "Did not pass Fermat test.");
                        continue;
                    }

                    // IsFermatPrime() could take a long time.
                    if (Worker.CancellationPending)
                    {
                        return(false);
                    }

                    Worker.ReportProgress(0, " ");
                    Worker.ReportProgress(0, "Found a probable prime.");
                    Worker.ReportProgress(0, "Attempts: " + Attempts.ToString());
                    Worker.ReportProgress(0, " ");
                    return(true); // With Result.
                }
            }
            catch (Exception Except)
            {
                Worker.ReportProgress(0, "Error in MakeAPrime()");
                Worker.ReportProgress(0, Except.Message);
                return(false);
            }
        }
예제 #14
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.
            }
        }
예제 #15
0
        internal void DoSquare(Integer ToSquare)
        {
            if (ToSquare.GetIndex() == 0)
            {
                ToSquare.Square0();
                return;
            }

            if (ToSquare.GetIndex() == 1)
            {
                ToSquare.Square1();
                return;
            }

            if (ToSquare.GetIndex() == 2)
            {
                ToSquare.Square2();
                return;
            }

            // Now Index is at least 3:
            int DoubleIndex = ToSquare.GetIndex() << 1;

            if (DoubleIndex >= Integer.DigitArraySize)
            {
                throw(new Exception("Square() overflowed."));
            }

            for (int Row = 0; Row <= ToSquare.GetIndex(); Row++)
            {
                if (ToSquare.GetD(Row) == 0)
                {
                    for (int Column = 0; Column <= ToSquare.GetIndex(); Column++)
                    {
                        M[Column + Row, Row] = 0;
                    }
                }
                else
                {
                    for (int Column = 0; Column <= ToSquare.GetIndex(); Column++)
                    {
                        M[Column + Row, Row] = ToSquare.GetD(Row) * ToSquare.GetD(Column);
                    }
                }
            }

            // Add the columns up with a carry.
            ToSquare.SetD(0, M[0, 0] & 0xFFFFFFFF);
            ulong Carry = M[0, 0] >> 32;

            for (int Column = 1; Column <= DoubleIndex; Column++)
            {
                ulong TotalLeft  = 0;
                ulong TotalRight = 0;
                for (int Row = 0; Row <= Column; Row++)
                {
                    if (Row > ToSquare.GetIndex())
                    {
                        break;
                    }

                    if (Column > (ToSquare.GetIndex() + Row))
                    {
                        continue;
                    }

                    TotalRight += M[Column, Row] & 0xFFFFFFFF;
                    TotalLeft  += M[Column, Row] >> 32;
                }

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

            ToSquare.SetIndex(DoubleIndex);
            if (Carry != 0)
            {
                ToSquare.SetIndex(ToSquare.GetIndex() + 1);
                if (ToSquare.GetIndex() >= Integer.DigitArraySize)
                {
                    throw(new Exception("Square() overflow."));
                }

                ToSquare.SetD(ToSquare.GetIndex(), Carry);
            }
        }
예제 #16
0
        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()."));
            }
        }
예제 #17
0
        // 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);
            }
        }
예제 #18
0
        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);
        }
예제 #19
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 )"));
            }
        }
예제 #20
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);
        }
예제 #21
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."));
            }
        }