コード例 #1
0
        internal uint ModularPowerSmall( ulong Input, Integer Exponent, uint Modulus )
        {
            if( Input == 0 )
              return 0;

            if( Input == Modulus )
              {
              // It is congruent to zero % Modulus.
              return 0;
              }

            // Result is not zero at this point.
            if( Exponent.IsZero() )
              return 1;

            ulong Result = Input;
            if( Input > Modulus )
              Result = Input % Modulus;

            if( Exponent.IsOne())
              return (uint)Result;

            ulong XForModPowerU = Result;
            ExponentCopy.Copy( Exponent );
            int TestIndex = 0;

            Result = 1;
            while( true )
              {
              if( (ExponentCopy.GetD( 0 ) & 1) == 1 ) // If the bottom bit is 1.
            {
            Result = Result * XForModPowerU;
            Result = Result % Modulus;
            }

              ExponentCopy.ShiftRight( 1 ); // Divide by 2.
              if( ExponentCopy.IsZero())
            break;

              // Square it.
              XForModPowerU = XForModPowerU * XForModPowerU;
              XForModPowerU = XForModPowerU % Modulus;
              }

            return (uint)Result;
        }
コード例 #2
0
ファイル: FindFactors.cs プロジェクト: Eric7Apps/BlogSource
        internal void FindAllFactors( Integer FindFromNotChanged )
        {
            // ShowStats(); // So far.

            OriginalFindFrom.Copy( FindFromNotChanged );
            FindFrom.Copy( FindFromNotChanged );

            NumbersTested++;
            ClearFactorsArray();
            Integer OneFactor;
            OneFactorRec Rec;

            // while( not forever )
            for( int Count = 0; Count < 1000; Count++ )
              {
              if( Worker.CancellationPending )
            return;

              uint SmallPrime = IntMath.IsDivisibleBySmallPrime( FindFrom );
              if( SmallPrime == 0 )
            break; // No more small primes.

              // Worker.ReportProgress( 0, "Found a small prime factor: " + SmallPrime.ToString() );
              AddToStats( SmallPrime );
              OneFactor = new Integer();
              OneFactor.SetFromULong( SmallPrime );
              Rec = new OneFactorRec();
              Rec.Factor = OneFactor;
              Rec.IsDefinitelyAPrime = true;
              AddFactorRec( Rec );
              if( FindFrom.IsULong())
            {
            ulong CheckLast = FindFrom.GetAsULong();
            if( CheckLast == SmallPrime )
              {
              Worker.ReportProgress( 0, "It only had small prime factors." );
              VerifyFactors();
              return; // It had only small prime factors.
              }
            }

              IntMath.Divide( FindFrom, OneFactor, Quotient, Remainder );
              if( !Remainder.IsZero())
            throw( new Exception( "Bug in FindAllFactors. Remainder is not zero." ));

              FindFrom.Copy( Quotient );
              if( FindFrom.IsOne())
            throw( new Exception( "Bug in FindAllFactors. This was already checked for 1." ));

              }

            // Worker.ReportProgress( 0, "No more small primes." );

            if( IsFermatPrimeAdded( FindFrom ))
              {
              VerifyFactors();
              return;
              }

            // while( not forever )
            for( int Count = 0; Count < 1000; Count++ )
              {
              if( Worker.CancellationPending )
            return;

              // If FindFrom is a ulong then this will go up to the square root of
              // FindFrom and return zero if it doesn't find it there.  So it can't
              // go up to the whole value of FindFrom.
              uint SmallFactor = NumberIsDivisibleByUInt( FindFrom );
              if( SmallFactor == 0 )
            break;

              // This is necessarily a prime because it was the smallest one found.
              AddToStats( SmallFactor );

              // Worker.ReportProgress( 0, "Found a small factor: " + SmallFactor.ToString( "N0" ));
              OneFactor = new Integer();
              OneFactor.SetFromULong( SmallFactor );
              Rec = new OneFactorRec();
              Rec.Factor = OneFactor;
              Rec.IsDefinitelyAPrime = true; // The smallest factor.  It is necessarily a prime.
              AddFactorRec( Rec );

              IntMath.Divide( FindFrom, OneFactor, Quotient, Remainder );
              if( !Remainder.IsZero())
            throw( new Exception( "Bug in FindAllFactors. Remainder is not zero. Second part." ));

              if( Quotient.IsOne())
            throw( new Exception( "This can't happen here.  It can't go that high." ));

              FindFrom.Copy( Quotient );

              if( IsFermatPrimeAdded( FindFrom ))
            {
            VerifyFactors();
            return;
            }
              }

            if( IsFermatPrimeAdded( FindFrom ))
              {
              VerifyFactors();
              return;
              }

            // If it got this far then it's definitely composite or definitely
            // small enough to factor.
            Integer P = new Integer();
            Integer Q = new Integer();
            bool TestedAllTheWay = FindTwoFactorsWithFermat( FindFrom, P, Q, 0 );

            if( !P.IsZero())
              {
              // Q is necessarily prime because it's bigger than the square root.
              // But P is not necessarily prime.
              // P is the smaller one, so add it first.
              if( IsFermatPrimeAdded( P ))
            {
            Worker.ReportProgress( 0, "P from Fermat method was probably a prime." );
            }
              else
            {
            OneFactor = new Integer();
            OneFactor.Copy( P );
            Rec = new OneFactorRec();
            Rec.Factor = OneFactor;
            Rec.IsDefinitelyNotAPrime = true;
            AddFactorRec( Rec );
            }

              Worker.ReportProgress( 0, "Q is necessarily prime." );
              OneFactor = new Integer();
              OneFactor.Copy( Q );
              Rec = new OneFactorRec();
              Rec.Factor = OneFactor;
              Rec.IsDefinitelyAPrime = true;
              AddFactorRec( Rec );
              }
            else
              {
              // Didn't find any with Fermat.
              OneFactor = new Integer();
              OneFactor.Copy( FindFrom );
              Rec = new OneFactorRec();
              Rec.Factor = OneFactor;
              if( TestedAllTheWay )
            Rec.IsDefinitelyAPrime = true;
              else
            Rec.IsDefinitelyNotAPrime = true;

              AddFactorRec( Rec );
              }

            Worker.ReportProgress( 0, "That's all it could find." );
            VerifyFactors();
        }
コード例 #3
0
        // This is the standard modular power algorithm that
        // you could find in any reference, but its use of
        // the new modular reduction algorithm is new.
        // The square and multiply method is in Wikipedia:
        // https://en.wikipedia.org/wiki/Exponentiation_by_squaring
        // x^n = (x^2)^((n - 1)/2) if n is odd.
        // x^n = (x^2)^(n/2)       if n is even.
        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.Divide( Result, Modulus, Quotient, Remainder );
              Result.Copy( Remainder );
              }

            if( Exponent.IsOne())
              {
              // Result stays the same.
              return;
              }

            if( !UsePresetBaseArray )
              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.Multiply( Result, XForModPower );
            ModularReduction( TempForModPower, Result );
            Result.Copy( TempForModPower );
            }

              ExponentCopy.ShiftRight( 1 ); // Divide by 2.
              if( ExponentCopy.IsZero())
            break;

              // Square it.
              IntMath.Multiply( XForModPower, XForModPower );
              ModularReduction( 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() ));

            if( HowBig > 2 )
              throw( new Exception( "The never happens. Diff: " + HowBig.ToString() ));

            ModularReduction( TempForModPower, Result );
            Result.Copy( TempForModPower );

            IntMath.Divide( Result, Modulus, Quotient, Remainder );
            Result.Copy( Remainder );

            if( Quotient.GetIndex() > 1 )
              throw( new Exception( "This never happens. The quotient index is never more than 1." ));
        }
コード例 #4
0
ファイル: IntegerMath.cs プロジェクト: Eric7Apps/BlogSource
        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;
              }

            // return LongDivide1( ToDivide, DivideBy, Quotient, Remainder );
            // return LongDivide2( ToDivide, DivideBy, Quotient, Remainder );
            LongDivide3( ToDivide, DivideBy, Quotient, Remainder );
        }
コード例 #5
0
ファイル: IntegerMath.cs プロジェクト: Eric7Apps/BlogSource
        /*
          internal void ModularPowerOld( Integer Result, Integer Exponent, Integer ModN )
        {
        if( Result.IsZero())
          return; // With Result still zero.

        if( Result.IsEqual( ModN ))
          {
          // It is congruent to zero % ModN.
          Result.SetToZero();
          return;
          }

        // Result is not zero at this point.
        if( Exponent.IsZero() )
          {
          Result.SetFromULong( 1 );
          return;
          }

        if( ModN.ParamIsGreater( Result ))
          {
          Divide( Result, ModN, Quotient, Remainder );
          Result.Copy( Remainder );
          }

        if( Exponent.IsEqualToULong( 1 ))
          {
          // Result stays the same.
          return;
          }

        XForModPower.Copy( Result );
        ExponentCopy.Copy( Exponent );
        Result.SetFromULong( 1 );
        while( !ExponentCopy.IsZero())
          {
          // If the bit is 1, then do a lot more work here.
          if( (ExponentCopy.GetD( 0 ) & 1) == 1 )
        {
        // This is a multiplication for every _bit_.  So a 1024-bit
        // modulus means this gets called roughly 512 times.
        // The commonly used public exponent is 65537, which has
        // only two bits set to 1, the rest are all zeros.  But the
        // private key exponents are long randomish numbers.
        // (See: Hamming Weight.)
        Multiply( Result, XForModPower );
        SubtractULong( ExponentCopy, 1 );
        // Usually it's true that the Result is greater than ModN.
        if( ModN.ParamIsGreater( Result ))
          {
          // Here is where that really long division algorithm gets used a
          // lot in a loop.  And this Divide() gets called roughly about
          // 512 times.
          Divide( Result, ModN, Quotient, Remainder );
          Result.Copy( Remainder );
          }
        }

          // Square it.
          // This is a multiplication for every _bit_.  So a 1024-bit
          // modulus means this gets called 1024 times.
          Multiply( XForModPower, XForModPower );
          ExponentCopy.ShiftRight( 1 ); // Divide by 2.
          if( ModN.ParamIsGreater( XForModPower ))
        {
        // And this Divide() gets called about 1024 times.
        Divide( XForModPower, ModN, Quotient, Remainder );
        XForModPower.Copy( Remainder );
        }
          }
        }
        */
        internal void GreatestCommonDivisor( Integer X, Integer Y, Integer Gcd )
        {
            // This is the basic Euclidean Algorithm.
            if( X.IsZero())
              throw( new Exception( "Doing GCD with a parameter that is zero." ));

            if( Y.IsZero())
              throw( new Exception( "Doing GCD with a parameter that is zero." ));

            if( X.IsEqual( Y ))
              {
              Gcd.Copy( X );
              return;
              }

            // Don't change the original numbers that came in as parameters.
            if( X.ParamIsGreater( Y ))
              {
              GcdX.Copy( Y );
              GcdY.Copy( X );
              }
            else
              {
              GcdX.Copy( X );
              GcdY.Copy( Y );
              }

            while( true )
              {
              Divide( GcdX, GcdY, Quotient, Remainder );
              if( Remainder.IsZero())
            {
            Gcd.Copy( GcdY ); // It's the smaller one.
            // It can't return from this loop until the remainder is zero.
            return;
            }

              GcdX.Copy( GcdY );
              GcdY.Copy( Remainder );
              }
        }
コード例 #6
0
ファイル: IntegerMath.cs プロジェクト: Eric7Apps/BlogSource
        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." ));

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

            // 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;
            for( int Column = 1; Column <= Result.GetIndex(); 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++ )
            {
            TotalRight += M[Column, Row] & 0xFFFFFFFF;
            TotalLeft += M[Column, Row] >> 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 );
              }
        }
コード例 #7
0
ファイル: IntegerMath.cs プロジェクト: Eric7Apps/BlogSource
        internal void Add( Integer Result, Integer ToAdd )
        {
            if( ToAdd.IsZero())
              return;

            // The most common form.  They are both positive.
            if( !Result.IsNegative && !ToAdd.IsNegative )
              {
              Result.Add( ToAdd );
              return;
              }

            if( !Result.IsNegative && ToAdd.IsNegative )
              {
              TempAdd1.Copy( ToAdd );
              TempAdd1.IsNegative = false;
              if( TempAdd1.ParamIsGreater( Result ))
            {
            Subtract( Result, TempAdd1 );
            return;
            }
              else
            {
            Subtract( TempAdd1, Result );
            Result.Copy( TempAdd1 );
            Result.IsNegative = true;
            return;
            }
              }

            if( Result.IsNegative && !ToAdd.IsNegative )
              {
              TempAdd1.Copy( Result );
              TempAdd1.IsNegative = false;
              TempAdd2.Copy( ToAdd );

              if( TempAdd1.ParamIsGreater( TempAdd2 ))
            {
            Subtract( TempAdd2, TempAdd1 );
            Result.Copy( TempAdd2 );
            return;
            }
              else
            {
            Subtract( TempAdd1, TempAdd2 );
            Result.Copy( TempAdd2 );
            Result.IsNegative = true;
            return;
            }
              }

            if( Result.IsNegative && ToAdd.IsNegative )
              {
              TempAdd1.Copy( Result );
              TempAdd1.IsNegative = false;
              TempAdd2.Copy( ToAdd );
              TempAdd2.IsNegative = false;
              TempAdd1.Add( TempAdd2 );
              Result.Copy( TempAdd1 );
              Result.IsNegative = true;
              return;
              }
        }
コード例 #8
0
ファイル: IntegerMath.cs プロジェクト: Eric7Apps/BlogSource
        internal bool MultiplicativeInverse( Integer X, Integer Modulus, Integer MultInverse, BackgroundWorker Worker )
        {
            // 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." ));

              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 );
              Multiply( TempEuclid2, Quotient );
              Subtract( TempEuclid1, TempEuclid2 );
              T0.Copy( TempEuclid1 );

              TempEuclid1.Copy( U1 );
              TempEuclid2.Copy( V1 );
              Multiply( TempEuclid2, Quotient );
              Subtract( TempEuclid1, TempEuclid2 );
              T1.Copy( TempEuclid1 );

              TempEuclid1.Copy( U2 );
              TempEuclid2.Copy( V2 );
              Multiply( TempEuclid2, Quotient );
              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 )
              {
              Add( MultInverse, Modulus );
              }

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

            // Worker.ReportProgress( 0, "MultInverse is the right number: " + ToString10( MultInverse ));
            return true;
        }
コード例 #9
0
ファイル: IntegerMath.cs プロジェクト: Eric7Apps/BlogSource
        // See also: http://en.wikipedia.org/wiki/Karatsuba_algorithm
        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." ));

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

            }
              else
            {
            for( int Column = 0; Column <= Result.GetIndex(); 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;
            for( int Column = 1; Column <= TotalIndex; Column++ )
              {
              ulong TotalLeft = 0;
              ulong TotalRight = 0;
              for( int Row = 0; Row <= ToMul.GetIndex(); Row++ )
            {
            if( Row > Column )
              break;

            if( Column > (Result.GetIndex() + 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 );
        }
コード例 #10
0
ファイル: CRTBaseMath.cs プロジェクト: Eric7Apps/BlogSource
        internal void ModularPower( ChineseRemainder CRTResult,
                              Integer Exponent,
                              ChineseRemainder CRTModulus,
                              bool UsePresetBaseArray )
        {
            // The square and multiply method is in Wikipedia:
            // https://en.wikipedia.org/wiki/Exponentiation_by_squaring

            if( Worker.CancellationPending )
              return;

            if( CRTResult.IsZero())
              return; // With CRTResult still zero.

            if( CRTResult.IsEqual( CRTModulus ))
              {
              // It is congruent to zero % ModN.
              CRTResult.SetToZero();
              return;
              }

            // Result is not zero at this point.
            if( Exponent.IsZero() )
              {
              CRTResult.SetToOne();
              return;
              }

            Integer Result = new Integer();
            CRTMath1.GetTraditionalInteger( Result, CRTResult );

            Integer Modulus = new Integer();
            CRTMath1.GetTraditionalInteger( Modulus, CRTModulus );

            if( Modulus.ParamIsGreater( Result ))
              {
              // throw( new Exception( "This is not supposed to be input for RSA plain text." ));
              IntMath.Divide( Result, Modulus, Quotient, Remainder );
              Result.Copy( Remainder );
              CRTResult.SetFromTraditionalInteger( Remainder );
              }

            if( Exponent.IsEqualToULong( 1 ))
              {
              // Result stays the same.
              return;
              }

            if( !UsePresetBaseArray )
              SetupBaseModArray( Modulus );

            if( CRTBaseModArray == null )
              throw( new Exception( "SetupBaseModArray() should have already been done here." ));

            CRTXForModPower.Copy( CRTResult );
            ExponentCopy.Copy( Exponent );
            int TestIndex = 0;
            CRTResult.SetToOne();

            int LoopsTest = 0;
            while( true )
              {
              LoopsTest++;
              if( (ExponentCopy.GetD( 0 ) & 1) == 1 ) // If the bottom bit is 1.
            {
            CRTResult.Multiply( CRTXForModPower );
            ModularReduction( CRTResult, CRTAccumulate );
            CRTResult.Copy( CRTAccumulate );
            }

              ExponentCopy.ShiftRight( 1 ); // Divide by 2.
              if( ExponentCopy.IsZero())
            break;

              // Square it.
              CRTCopyForSquare.Copy( CRTXForModPower );
              CRTXForModPower.Multiply( CRTCopyForSquare );
              ModularReduction( CRTXForModPower, CRTAccumulate );
              CRTXForModPower.Copy( CRTAccumulate );
              }

            ModularReduction( CRTResult, CRTAccumulate );
            CRTResult.Copy( CRTAccumulate );

            // Division is never used in the loop above.

            // This is a very small Quotient.
            // See SetupBaseMultiples() for a description of how to calculate
            // the maximum size of this quotient.
            CRTMath1.GetTraditionalInteger( Result, CRTResult );
            IntMath.Divide( Result, Modulus, Quotient, Remainder );

            // Is the Quotient bigger than a 32 bit integer?
            if( Quotient.GetIndex() > 0 )
              throw( new Exception( "I haven't ever seen this happen. Quotient.GetIndex() > 0.  It is: " + Quotient.GetIndex().ToString() ));

            QuotientForTest = Quotient.GetAsULong();
            if( QuotientForTest > 2097867 )
              throw( new Exception( "This can never happen unless I increase ChineseRemainder.DigitsArraySize." ));

            Result.Copy( Remainder );
            CRTResult.SetFromTraditionalInteger( Remainder );
        }
コード例 #11
0
        internal void ModularPower( Integer Result, Integer Exponent, Integer GeneralBase )
        {
            // The square and multiply method is in Wikipedia:
            // https://en.wikipedia.org/wiki/Exponentiation_by_squaring
            // x^n = (x^2)^((n - 1)/2) if n is odd.
            // x^n = (x^2)^(n/2)       if n is even.

            if( Result.IsZero())
              return; // With Result still zero.

            if( Result.IsEqual( GeneralBase ))
              {
              // It is congruent to zero % ModN.
              Result.SetToZero();
              return;
              }

            // Result is not zero at this point.
            if( Exponent.IsZero() )
              {
              Result.SetFromULong( 1 );
              return;
              }

            if( GeneralBase.ParamIsGreater( Result ))
              {
              // throw( new Exception( "This is not supposed to be input for RSA plain text." ));
              IntMath.Divide( Result, GeneralBase, Quotient, Remainder );
              Result.Copy( Remainder );
              }

            if( Exponent.IsEqualToULong( 1 ))
              {
              // Result stays the same.
              return;
              }

            // This could also be called ahead of time if the base (the modulus)
            // doesn't change.  Like when your public key doesn't change.
            SetupGeneralBaseArray( GeneralBase );

            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.Multiply( Result, XForModPower );

            // Modular Reduction:
            AddByGeneralBaseArrays( TempForModPower, Result );
            Result.Copy( TempForModPower );
            }

              ExponentCopy.ShiftRight( 1 ); // Divide by 2.
              if( ExponentCopy.IsZero())
            break;

              // Square it.
              IntMath.Multiply( XForModPower, XForModPower );

              // Modular Reduction:
              AddByGeneralBaseArrays( TempForModPower, XForModPower );
              XForModPower.Copy( TempForModPower );
              }

            // When AddByGeneralBaseArrays() gets called it multiplies a 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.
            // If by chance you got a carry bit on _every_ addition that was done
            // in AddByGeneralBaseArrays() then this number could increase in size
            // by 1 bit for each addition that was done.  It would take 32 bits of
            // carrying for HowBig to increase by 1.
            // See HowManyToAdd in AddByGeneralBaseArrays() for why this check is done.
            int HowBig = Result.GetIndex() - GeneralBase.GetIndex();
            if( HowBig > 2 ) // I have not seen this happen yet.
              throw( new Exception( "The difference in index size was more than 2. Diff: " + HowBig.ToString() ));

            // So this Quotient has only one or two 32-bit digits in it.
            // And this Divide() is only called once at the end.  Not in the loop.
            IntMath.Divide( Result, GeneralBase, Quotient, Remainder );
            Result.Copy( Remainder );
        }
コード例 #12
0
ファイル: MultiplyBits.cs プロジェクト: Eric7Apps/BlogSource
        // Product is along the right side diagonal.
        internal void SetProduct( Integer UseBigIntToSet )
        {
            Integer BigIntToSet = new Integer();
            BigIntToSet.Copy( UseBigIntToSet );

            // Primes: 29, 31, 37, 41, 43, 47, 53, 59, 61, 67,
            // 71, 73, 79, 83, 89, 97, 101, 103, 107

            if( (BigIntToSet.GetD( 0 ) & 1 ) != 1 )
              throw( new Exception( "Product can't be even." ));

            int Where = 0;
            uint ToSet = 0;
            for( int Row = 0; Row < MultArraySize; Row++ )
              {
              ToSet = MultArray[Row].OneLine[0];
              if( (BigIntToSet.GetD( 0 ) & 1 ) == 1 )
            ToSet = SetAccumOut( ToSet );
              else
            ToSet = ClearAccumOut( ToSet );

              MultArray[Row].OneLine[0] = ToSet;

              Where = Row;
              BigIntToSet.ShiftRight( 1 );
              if( BigIntToSet.IsZero())
            break;

              }

            ProductBitIndex = Where;
            int HowMany = ProductBitIndex + 1;
            MForm.ShowStatus( "There were " + HowMany.ToString() + " bits in the product." );

            // At the last 1 bit.
            ToSet = MultArray[Where].OneLine[0];
            ToSet = ClearCarryOut( ToSet );
            MultArray[Where].OneLine[0] = ToSet;

            // The ProductBits can be:
            // Factor1Bits + Factor2Bits
            // or it can be:
            // Factor1Bits + Factor2Bits + 1
            // ProductBits - Factor1Bits = Factor2Bits ( + 1 or not)
            int Factor1Bits = GetHighestMult1BitIndex() + 1;
            int ProductBits = (Where + 1);
            // Factor2Bits might be this or it might be one
            // less than this.
            int MaximumFactor2Bits = ProductBits - Factor1Bits;
            // Factor2BitIndex = Factor2Bits - 1;

            // Test if the top bit of Factor2 is in the right place.
            // ToSet = MultArray[Factor2BitIndex].OneLine[0];
            // ToSet = SetMult( ToSet );
            // MultArray[Factor2BitIndex].OneLine[0] = ToSet;

            for( int Row = MaximumFactor2Bits + 1; Row < MultArraySize; Row++ )
              {
              ToSet = MultArray[Row].OneLine[0];
              ToSet = ClearMult2( ToSet );
              MultArray[Row].OneLine[0] = ToSet;
              }

            for( int Row = Where + 1; Row < MultArraySize; Row++ )
              {
              ToSet = MultArray[Row].OneLine[0];
              ToSet = ClearMult2( ToSet );
              ToSet = ClearMult( ToSet );
              ToSet = ClearAccumOut( ToSet );
              ToSet = ClearCarryOut( ToSet );
              MultArray[Row].OneLine[0] = ToSet;
              }
        }
コード例 #13
0
ファイル: MultiplyBits.cs プロジェクト: Eric7Apps/BlogSource
        // Factor 2 is along the right side diagonal.
        internal void SetFactor2( Integer UseBigIntToSet )
        {
            Integer BigIntToSet = new Integer();
            BigIntToSet.Copy( UseBigIntToSet );

            if( (BigIntToSet.GetD( 0 ) & 1 ) != 1 )
              throw( new Exception( "Factor2 can't be even." ));

            uint ToSet = MultArray[0].OneLine[0];
            ToSet = SetMult1( ToSet );
            ToSet = SetMult2( ToSet );
            ToSet = SetMult( ToSet );
            ToSet = SetAccumOut( ToSet );
            ToSet = ClearCarryOut( ToSet );
            MultArray[0].OneLine[0] = ToSet;

            // Factor2 has to be odd so Mult2 is set to
            // 1 all the way across the top.
            SetMult2AtRow( 0 );

            BigIntToSet.ShiftRight( 1 );
            if( BigIntToSet.IsZero())
              throw( new Exception( "Factor2 can't be 1." ));

            // 107 = 64 + 32 + 8 + 2 + 1
            int Where = 1;
            for( int Row = 1; Row < MultArraySize; Row++ )
              {
              ToSet = MultArray[Row].OneLine[0];
              if( (BigIntToSet.GetD( 0 ) & 1 ) == 1 )
            ToSet = SetMult2( ToSet );
              else
            ToSet = ClearMult2( ToSet );

              MultArray[Row].OneLine[0] = ToSet;

              Where = Row;
              BigIntToSet.ShiftRight( 1 );
              if( BigIntToSet.IsZero())
            break;

              }

            // At the last 1 bit.
            // ToSet = MultArray[Where].OneLine[0];

            for( int Row = Where + 1; Row < MultArraySize; Row++ )
              {
              ToSet = MultArray[Row].OneLine[0];
              ToSet = ClearMult2( ToSet );
              MultArray[Row].OneLine[0] = ToSet;
              }
        }
コード例 #14
0
ファイル: MultiplyBits.cs プロジェクト: Eric7Apps/BlogSource
        // Factor1 is along the top.
        internal void SetFactor1( Integer UseBigIntToSet )
        {
            Integer BigIntToSet = new Integer();
            BigIntToSet.Copy( UseBigIntToSet );

            if( (BigIntToSet.GetD( 0 ) & 1 ) != 1 )
              throw( new Exception( "Factor1 can't be even." ));

            uint ToSet = MultArray[0].OneLine[0];
            ToSet = SetMult1( ToSet );
            ToSet = SetMult2( ToSet );
            ToSet = SetMult( ToSet );
            ToSet = SetAccumOut( ToSet );
            ToSet = ClearCarryOut( ToSet );
            MultArray[0].OneLine[0] = ToSet;

            // Factor1 has to be odd so Mult1 is set to
            // 1 all the way down the side.

            SetMult1AtColumn( 0 );

            BigIntToSet.ShiftRight( 1 );
            if( BigIntToSet.IsZero())
              throw( new Exception( "Factor1 can't be 1." ));

            // 107 = 64 + 32 + 8 + 2 + 1
            int Where = 1;
            for( int Column = 1; Column < MultArraySize; Column++ )
              {
              ToSet = MultArray[0].OneLine[Column];
              if( (BigIntToSet.GetD( 0 ) & 1 ) == 1 )
            ToSet = SetMult1( ToSet );
              else
            ToSet = ClearMult1( ToSet );

              MultArray[0].OneLine[Column] = ToSet;

              Where = Column;
              BigIntToSet.ShiftRight( 1 );
              if( BigIntToSet.IsZero())
            break;

              }

            // At the last 1 bit.
            // ToSet = MultArray[0].OneLine[Where];

            for( int Column = Where + 1; Column < MultArraySize; Column++ )
              {
              ToSet = MultArray[0].OneLine[Column];
              ToSet = ClearMult1( ToSet );
              ToSet = ClearMult( ToSet );
              ToSet = ClearAccumOut( ToSet );
              ToSet = ClearCarryOut( ToSet );
              MultArray[0].OneLine[Column] = ToSet;
              }
        }