// CRTBaseModArray doesn't have the pattern of zeros // down to the end like in CRTBaseArray. internal void SetupBaseModArray( Integer Modulus ) { try { BaseModArrayModulus = Modulus; if( NumbersArray == null ) throw( new Exception( "NumbersArray should have already been setup in SetupBaseModArray()." )); CRTBaseModArray = new ChineseRemainder[ChineseRemainder.DigitsArraySize]; ChineseRemainder CRTSetBase = new ChineseRemainder( IntMath ); Integer BigBase = new Integer(); ChineseRemainder CRTBigBase = new ChineseRemainder( IntMath ); BigBase.SetFromULong( 2 ); CRTBigBase.SetFromUInt( 2 ); CRTSetBase.SetToOne(); CRTBaseModArray[0] = CRTSetBase; ChineseRemainder CRTTemp = new ChineseRemainder( IntMath ); for( int Count = 1; Count < ChineseRemainder.DigitsArraySize; Count++ ) { CRTSetBase = new ChineseRemainder( IntMath ); CRTSetBase.Copy( CRTBigBase ); CRTBaseModArray[Count] = CRTSetBase; // Multiply it for the next BigBase. IntMath.MultiplyUInt( BigBase, IntMath.GetPrimeAt( Count )); IntMath.Divide( BigBase, Modulus, Quotient, Remainder ); BigBase.Copy( Remainder ); CRTBigBase.SetFromTraditionalInteger( BigBase ); } } catch( Exception Except ) { throw( new Exception( "Exception in SetupBaseModArray(): " + Except.Message )); } }
// These bottom digits are 0 for each prime that gets // multiplied by the base. So they keep getting one // more zero at the bottom of each one. // But the digits in BaseModArray only have the zeros // at the bottom on the ones that are smaller than the // modulus. // At BaseArray[0] it's 1, 1, 1, 1, 1, .... for all of them. // 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0 // 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 0, 0 // 30, 30, 30, 30, 1, 7, 11, 13, 4, 8, 2, 0, 0, 0 private void SetupBaseArray() { // The first few numbers for the base: // 2 2 // 3 6 // 5 30 // 7 210 // 11 2,310 // 13 30,030 // 17 510,510 // 19 9,699,690 // 23 223,092,870 try { if( NumbersArray == null ) throw( new Exception( "NumbersArray should have already been setup in SetupBaseArray()." )); BaseStringsArray = new string[ChineseRemainder.DigitsArraySize]; BaseArray = new Integer[ChineseRemainder.DigitsArraySize]; CRTBaseArray = new ChineseRemainder[ChineseRemainder.DigitsArraySize]; Integer SetBase = new Integer(); ChineseRemainder CRTSetBase = new ChineseRemainder( IntMath ); Integer BigBase = new Integer(); ChineseRemainder CRTBigBase = new ChineseRemainder( IntMath ); BigBase.SetFromULong( 2 ); CRTBigBase.SetFromUInt( 2 ); string BaseS = "2"; SetBase.SetToOne(); CRTSetBase.SetToOne(); // The base at zero is 1. BaseArray[0] = SetBase; CRTBaseArray[0] = CRTSetBase; BaseStringsArray[0] = "1"; ChineseRemainder CRTTemp = new ChineseRemainder( IntMath ); // The first time through the loop the base // is set to 2. // So BaseArray[0] = 1; // So BaseArray[1] = 2; // So BaseArray[2] = 6; // So BaseArray[3] = 30; // And so on... // In BaseArray[3] digits at 2, 3 and 5 are set to zero. // In BaseArray[4] digits at 2, 3, 5 and 7 are set to zero. for( int Count = 1; Count < ChineseRemainder.DigitsArraySize; Count++ ) { SetBase = new Integer(); CRTSetBase = new ChineseRemainder( IntMath ); SetBase.Copy( BigBase ); CRTSetBase.Copy( CRTBigBase ); BaseStringsArray[Count] = BaseS; BaseArray[Count] = SetBase; CRTBaseArray[Count] = CRTSetBase; // if( Count < 50 ) // Worker.ReportProgress( 0, CRTBaseArray[Count].GetString() ); if( !IsEqualToInteger( CRTBaseArray[Count], BaseArray[Count] )) throw( new Exception( "Bug. The bases aren't equal." )); // Multiply it for the next BigBase. uint Prime = IntMath.GetPrimeAt( Count ); BaseS = BaseS + "*" + Prime.ToString(); IntMath.MultiplyUInt( BigBase, Prime ); CRTBigBase.Multiply( NumbersArray[IntMath.GetPrimeAt( Count )] ); } } catch( Exception Except ) { throw( new Exception( "Exception in SetupBaseArray(): " + 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 ); }