// 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.")); } }