// Copyright Eric Chauvin. internal void ModularReduction( ChineseRemainder CRTInput, ChineseRemainder CRTAccumulate ) { try { if( NumbersArray == null ) throw( new Exception( "Bug: The NumbersArray should have been set up already." )); if( CRTBaseModArray == null ) throw( new Exception( "Bug: The BaseModArray should have been set up already." )); // This first one has the prime 2 as its base so it's going to // be set to either zero or one. if( CRTInput.GetDigitAt( 0 ) == 1 ) { CRTAccumulate.SetToOne(); } else { CRTAccumulate.SetToZero(); } CRTBase CRTBaseInput = new CRTBase( IntMath ); int HowManyToAdd = SetFromCRTNumber( CRTBaseInput, CRTInput ); // Integer Test = new Integer(); // ChineseRemainder CRTTest = new ChineseRemainder( IntMath ); // GetTraditionalInteger( CRTBaseInput, Test ); // CRTTest.SetFromTraditionalInteger( Test ); // if( !CRTTest.IsEqual( CRTInput )) // throw( new Exception( "CRTTest for CRTInput isn't right." )); // Count starts at 1, so it's the prime 3. for( int Count = 1; Count <= HowManyToAdd; Count++ ) { // BaseMultiple is a number that is not bigger // than the prime at this point. (The prime at: // IntMath.GetPrimeAt( Count ).) uint BaseMultiple = (uint)CRTBaseInput.GetDigitAt( Count ); // It uses the CRTBaseModArray here: CRTWorkingTemp.Copy( CRTBaseModArray[Count] ); CRTWorkingTemp.Multiply( NumbersArray[BaseMultiple] ); CRTAccumulate.Add( CRTWorkingTemp ); } } catch( Exception Except ) { throw( new Exception( "Exception in ModularReduction(): " + Except.Message )); } }
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 ); }