Beispiel #1
0
        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 );
        }
        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 );
        }