Exemple #1
0
        internal void SetFromString(Integer Result, string InString)
        {
            if (InString == null)
            {
                throw(new Exception("InString was null in SetFromString()."));
            }

            if (InString.Length < 1)
            {
                Result.SetToZero();
                return;
            }

            Base10Number Base10N = new Base10Number();
            Integer      Tens    = new Integer();
            Integer      OnePart = new Integer();

            // This might throw an exception if the string is bad.
            Base10N.SetFromString(InString);
            Result.SetFromULong(Base10N.GetD(0));
            Tens.SetFromULong(10);
            for (int Count = 1; Count <= Base10N.GetIndex(); Count++)
            {
                OnePart.SetFromULong(Base10N.GetD(Count));
                Multiplier.Multiply(OnePart, Tens);
                Result.Add(OnePart);
                Multiplier.MultiplyULong(Tens, 10);
            }
        }
        // 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));
            }
        }
Exemple #3
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));
            }
        }
Exemple #4
0
        internal void Subtract(Integer Result, Integer ToSub)
        {
            // This checks that the sign is equal too.
            if (Result.IsEqual(ToSub))
            {
                Result.SetToZero();
                return;
            }

            // ParamIsGreater() handles positive and negative values, so if the
            // parameter is more toward the positive side then it's true.  It's greater.
            // The most common form.  They are both positive.
            if (!Result.IsNegative && !ToSub.IsNegative)
            {
                if (ToSub.ParamIsGreater(Result))
                {
                    SubtractPositive(Result, ToSub);
                    return;
                }

                // ToSub is bigger.
                TempSub1.Copy(Result);
                TempSub2.Copy(ToSub);
                SubtractPositive(TempSub2, TempSub1);
                Result.Copy(TempSub2);
                Result.IsNegative = true;
                return;
            }

            if (Result.IsNegative && !ToSub.IsNegative)
            {
                TempSub1.Copy(Result);
                TempSub1.IsNegative = false;
                TempSub1.Add(ToSub);
                Result.Copy(TempSub1);
                Result.IsNegative = true;
                return;
            }

            if (!Result.IsNegative && ToSub.IsNegative)
            {
                TempSub1.Copy(ToSub);
                TempSub1.IsNegative = false;
                Result.Add(TempSub1);
                return;
            }

            if (Result.IsNegative && ToSub.IsNegative)
            {
                TempSub1.Copy(Result);
                TempSub1.IsNegative = false;
                TempSub2.Copy(ToSub);
                TempSub2.IsNegative = false;
                // -12 - -7 = -12 + 7 = -5
                // Comparing the positive numbers here.
                if (TempSub2.ParamIsGreater(TempSub1))
                {
                    SubtractPositive(TempSub1, TempSub2);
                    Result.Copy(TempSub1);
                    Result.IsNegative = true;
                    return;
                }

                // -7 - -12 = -7 + 12 = 5
                SubtractPositive(TempSub2, TempSub1);
                Result.Copy(TempSub2);
                Result.IsNegative = false;
                return;
            }
        }
Exemple #5
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);
        }
Exemple #6
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 )"));
            }
        }
Exemple #7
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."));
            }
        }
Exemple #8
0
        internal bool MultiplicativeInverse(Integer X, Integer Modulus, Integer MultInverse)
        {
            // This is the extended Euclidean Algorithm.
            // A*X + B*Y = Gcd
            // A*X + B*Y = 1 If there's a multiplicative inverse.
            // A*X = 1 - B*Y so A is the multiplicative inverse of X mod Y.
            if (X.IsZero())
            {
                throw(new Exception("Doing Multiplicative Inverse with a parameter that is zero."));
            }

            if (Modulus.IsZero())
            {
                throw(new Exception("Doing Multiplicative Inverse with a parameter that is zero."));
            }

            // This happens sometimes:
            // if( Modulus.ParamIsGreaterOrEq( X ))
            // throw( new Exception( "Modulus.ParamIsGreaterOrEq( X ) for Euclid." ));

            // Worker.ReportProgress( 0, " " );
            // Worker.ReportProgress( 0, " " );
            // Worker.ReportProgress( 0, "Top of mod inverse." );
            // U is the old part to keep.
            U0.SetToZero();
            U1.SetToOne();
            U2.Copy(Modulus); // Don't change the original numbers that came in as parameters.
            // V is the new part.
            V0.SetToOne();
            V1.SetToZero();
            V2.Copy(X);
            T0.SetToZero();
            T1.SetToZero();
            T2.SetToZero();
            Quotient.SetToZero();
            // while( not forever if there's a problem )
            for (int Count = 0; Count < 10000; Count++)
            {
                if (U2.IsNegative)
                {
                    throw(new Exception("U2 was negative."));
                }

                if (V2.IsNegative)
                {
                    throw(new Exception("V2 was negative."));
                }

                IntMath.Divider.Divide(U2, V2, Quotient, Remainder);
                if (Remainder.IsZero())
                {
                    // Worker.ReportProgress( 0, "Remainder is zero. No multiplicative-inverse." );
                    return(false);
                }

                TempEuclid1.Copy(U0);
                TempEuclid2.Copy(V0);
                IntMath.Multiplier.Multiply(TempEuclid2, Quotient);
                IntMath.Subtract(TempEuclid1, TempEuclid2);
                T0.Copy(TempEuclid1);
                TempEuclid1.Copy(U1);
                TempEuclid2.Copy(V1);
                IntMath.Multiplier.Multiply(TempEuclid2, Quotient);
                IntMath.Subtract(TempEuclid1, TempEuclid2);
                T1.Copy(TempEuclid1);
                TempEuclid1.Copy(U2);
                TempEuclid2.Copy(V2);
                IntMath.Multiplier.Multiply(TempEuclid2, Quotient);
                IntMath.Subtract(TempEuclid1, TempEuclid2);
                T2.Copy(TempEuclid1);
                U0.Copy(V0);
                U1.Copy(V1);
                U2.Copy(V2);
                V0.Copy(T0);
                V1.Copy(T1);
                V2.Copy(T2);
                if (Remainder.IsOne())
                {
                    // Worker.ReportProgress( 0, " " );
                    // Worker.ReportProgress( 0, "Remainder is 1. There is a multiplicative-inverse." );
                    break;
                }
            }

            MultInverse.Copy(T0);
            if (MultInverse.IsNegative)
            {
                IntMath.Add(MultInverse, Modulus);
            }

            // Worker.ReportProgress( 0, "MultInverse: " + ToString10( MultInverse ));
            TestForModInverse1.Copy(MultInverse);
            TestForModInverse2.Copy(X);
            IntMath.Multiplier.Multiply(TestForModInverse1, TestForModInverse2);
            IntMath.Divider.Divide(TestForModInverse1, Modulus, Quotient, Remainder);
            if (!Remainder.IsOne()) // By the definition of Multiplicative inverse:
            {
                throw(new Exception("MultInverse is wrong: " + IntMath.ToString10(Remainder)));
            }

            // Worker.ReportProgress( 0, "MultInverse is the right number: " + ToString10( MultInverse ));
            return(true);
        }
Exemple #9
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);
            }
        }