internal void Copy( ChineseRemainder ToCopy ) { for( int Count = 0; Count < DigitsArraySize; Count++ ) { DigitsArray[Count] = ToCopy.DigitsArray[Count]; } }
internal CRTBaseMath( BackgroundWorker UseWorker, CRTMath UseCRTMath ) { // Most of these are created ahead of time so that // they don't have to be created inside a loop. Worker = UseWorker; IntMath = new IntegerMath(); CRTMath1 = UseCRTMath; Quotient = new Integer(); Remainder = new Integer(); CRTAccumulateBase = new ChineseRemainder( IntMath ); CRTAccumulateBasePart = new ChineseRemainder( IntMath ); CRTAccumulateForBaseMultiples = new ChineseRemainder( IntMath ); CRTAccumulatePart = new ChineseRemainder( IntMath ); BaseModArrayModulus = new Integer(); CRTTempForIsEqual = new ChineseRemainder( IntMath ); CRTWorkingTemp = new ChineseRemainder( IntMath ); ExponentCopy = new Integer(); CRTXForModPower = new ChineseRemainder( IntMath ); CRTAccumulate = new ChineseRemainder( IntMath ); CRTCopyForSquare = new ChineseRemainder( IntMath ); FermatExponent = new Integer(); CRTFermatModulus = new ChineseRemainder( IntMath ); FermatModulus = new Integer(); CRTTestFermat = new ChineseRemainder( IntMath ); Worker.ReportProgress( 0, "Setting up numbers array." ); SetupNumbersArray(); Worker.ReportProgress( 0, "Setting up base array." ); SetupBaseArray(); Worker.ReportProgress( 0, "Setting up multiplicative inverses." ); SetMultiplicativeInverses(); }
internal void Add( ChineseRemainder ToAdd ) { for( int Count = 0; Count < DigitsArraySize; Count++ ) { // Operations like this could be very fast if they were done in // hardware, and the small mod operations could be done in very // small hardware lookup tables. They could also be done in parallel, // which would make it a lot faster than the way this is done, one // digit at a time. Notice that there is no carry operation here. // As Claud Shannon would say, there is no diffusion here. // Like he wrote about in A Mathematical Theory of Cryptography. DigitsArray[Count].Value += ToAdd.DigitsArray[Count].Value; if( DigitsArray[Count].Value >= DigitsArray[Count].Prime ) DigitsArray[Count].Value -= DigitsArray[Count].Prime; // DigitsArray[Count].Value = DigitsArray[Count].Value % DigitsArray[Count].Prime; } }
internal void Add( ChineseRemainder ToAdd ) { for( int Count = 0; Count < DigitsArraySize; Count++ ) { // Operations like this could be very fast if // they were done in hardware, and the small // mod operations could be done in very small // hardware lookup tables. They could also be // done in parallel, which would make it a lot // faster than the way this is done, one digit // at a time. Notice that there is no carry // operation here. As Claud Shannon would say, // there is no diffusion here. DigitsArray[Count] += ToAdd.DigitsArray[Count]; int Prime = (int)IntMath.GetPrimeAt( Count ); if( DigitsArray[Count] >= Prime ) DigitsArray[Count] -= Prime; // DigitsArray[Count] = DigitsArray[Count] % Prime; } }
internal bool IsEqual( ChineseRemainder ToCheck ) { for( int Count = 0; Count < DigitsArraySize; Count++ ) { if( DigitsArray[Count].Value != ToCheck.DigitsArray[Count].Value ) return false; } return true; }
private void SetupNumbersArray() { try { uint BiggestPrime = IntMath.GetPrimeAt( CRTBase.DigitsArraySize + 1 ); NumbersArray = new ChineseRemainder[BiggestPrime]; Integer SetNumber = new Integer(); for( uint Count = 0; Count < BiggestPrime; Count++ ) { SetNumber.SetFromULong( Count ); ChineseRemainder CRTSetNumber = new ChineseRemainder( IntMath ); CRTSetNumber.SetFromTraditionalInteger( SetNumber ); NumbersArray[Count] = CRTSetNumber; } } catch( Exception Except ) { throw( new Exception( "Exception in SetupNumbersArray(): " + 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 )); } }
// 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 )); } }
// Copyright Eric Chauvin. internal void Multiply( ChineseRemainder ToMul ) { for( int Count = 0; Count < DigitsArraySize; Count++ ) { // There is no Diffusion here either, like the // kind that Claude Shannon wrote about in // A Mathematical Theory of Cryptography. DigitsArray[Count] *= ToMul.DigitsArray[Count]; DigitsArray[Count] %= (int)IntMath.GetPrimeAt( Count ); } }
internal void Subtract( ChineseRemainder ToSub ) { for( int Count = 0; Count < DigitsArraySize; Count++ ) { DigitsArray[Count].Value -= ToSub.DigitsArray[Count].Value; if( DigitsArray[Count].Value < 0 ) DigitsArray[Count].Value += DigitsArray[Count].Prime; } }
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 ); }
// http://en.wikipedia.org/wiki/Primality_test // http://en.wikipedia.org/wiki/Fermat_primality_test internal bool IsFermatPrimeForOneValue( ChineseRemainder CRTToTest, uint Base ) { // http://en.wikipedia.org/wiki/Carmichael_number // Assume ToTest is not a small number. (Not the size of a small prime.) // Normally it would be something like a 1024 bit number or bigger, // but I assume it's at least bigger than a 32 bit number. // Assume this has already been checked to see if it's divisible // by a small prime. // A has to be coprime to P and it is here because ToTest is not // divisible by a small prime. // Fermat's little theorem: // A ^ (P - 1) is congruent to 1 mod P if P is a prime. // Or: A^P - A is congrunt to A mod P. // If you multiply A by itself P times then divide it by P, // the remainder is A. (A^P / P) // 5^3 = 125. 125 - 5 = 120. A multiple of 5. // 2^7 = 128. 128 - 2 = 7 * 18 (a multiple of 7.) CRTMath1.GetTraditionalInteger( FermatExponent, CRTToTest ); IntMath.SubtractULong( FermatExponent, 1 ); // This is a very small Modulus since it's being set from a uint. CRTTestFermat.SetFromUInt( Base ); CRTFermatModulus.Copy( CRTToTest ); CRTMath1.GetTraditionalInteger( FermatModulus, CRTFermatModulus ); ModularPower( CRTTestFermat, FermatExponent, CRTFermatModulus, false ); if( CRTTestFermat.IsOne()) return true; // It passed the test. It _might_ be a prime. else return false; // It is _definitely_ a composite number. }
internal bool IsFermatPrime( ChineseRemainder CRTToTest, int HowMany ) { // Also see Rabin-Miller test. // Also see Solovay-Strassen test. // This Fermat primality test is usually described // as using random primes to test with, and you // could do it that way too. // IntegerMath.PrimeArrayLength = 1024 * 32; int StartAt = 1024 * 16; // Or much bigger. for( int Count = StartAt; Count < (HowMany + StartAt); Count++ ) { if( !IsFermatPrimeForOneValue( CRTToTest, IntMath.GetPrimeAt( Count ))) return false; } // It _might_ be a prime if it passed this test. // Increasing HowMany increases the probability that it's a prime. return true; }
internal bool IsEqualToInteger( ChineseRemainder CRTTest, Integer Test ) { CRTTempForIsEqual.SetFromTraditionalInteger( Test ); if( CRTTest.IsEqual( CRTTempForIsEqual )) return true; else return false; }
internal void Subtract( ChineseRemainder ToSub ) { for( int Count = 0; Count < DigitsArraySize; Count++ ) { DigitsArray[Count] -= ToSub.DigitsArray[Count]; if( DigitsArray[Count] < 0 ) DigitsArray[Count] += (int)IntMath.GetPrimeAt( Count ); } }
// This is the closest this has to Divide(). internal void ModularInverse( ChineseRemainder ToDivide ) { // ToDivide times what equals this number? for( int Count = 0; Count < DigitsArraySize; Count++ ) { for( int CountPrime = 0; CountPrime < DigitsArray[Count].Prime; CountPrime++ ) { int Test = CountPrime * ToDivide.DigitsArray[Count].Value; Test = Test % DigitsArray[Count].Prime; if( Test == DigitsArray[Count].Value ) { DigitsArray[Count].Value = CountPrime; break; } } } }
internal void Multiply( ChineseRemainder ToMul ) { for( int Count = 0; Count < DigitsArraySize; Count++ ) { // There is no Diffusion here either, like the kind that // Claude Shannon wrote about in A Mathematical Theory of // Cryptography. DigitsArray[Count].Value *= ToMul.DigitsArray[Count].Value; DigitsArray[Count].Value %= DigitsArray[Count].Prime; } }
// 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 int SetFromCRTNumber( CRTBase ToSet, ChineseRemainder SetFrom ) { try { if( NumbersArray == null ) throw( new Exception( "Bug: The NumbersArray should have been set up already." )); // ToSet.SetToZero(); // CRTBaseArray[0] is 1. if( SetFrom.GetDigitAt( 0 ) == 1 ) { ToSet.SetToOne(); // 1 times 1 for this base. CRTAccumulateForBaseMultiples.SetToOne(); } else { ToSet.SetToZero(); CRTAccumulateForBaseMultiples.SetToZero(); } int HighestNonZeroDigit = 1; // Count starts at 1, so it's at the prime 3. for( int Count = 1; Count < ChineseRemainder.DigitsArraySize; Count++ ) { int Prime = (int)IntMath.GetPrimeAt( Count ); int AccumulateDigit = CRTAccumulateForBaseMultiples.GetDigitAt( Count ); int CRTInputTestDigit = SetFrom.GetDigitAt( Count ); int BaseDigit = CRTBaseArray[Count].GetDigitAt( Count ); if( BaseDigit == 0 ) throw( new Exception( "This never happens. BaseDigit == 0." )); int BaseMult = CRTInputTestDigit; if( BaseMult < AccumulateDigit ) BaseMult += Prime; BaseMult -= AccumulateDigit; int Inverse = MultInverseArray[Count, BaseDigit]; BaseMult = (BaseMult * Inverse) % Prime; ToSet.SetDigitAt( BaseMult, Count ); if( BaseMult != 0 ) HighestNonZeroDigit = Count; // Notice that this is using CRTBaseArray and not // CRTBaseModArray. // This would be very fast in parallel hardware, // but not in software that has to do each digit // one at a time. CRTAccumulatePart.Copy( CRTBaseArray[Count] ); CRTAccumulatePart.Multiply( NumbersArray[BaseMult] ); CRTAccumulateForBaseMultiples.Add( CRTAccumulatePart ); } return HighestNonZeroDigit; } catch( Exception Except ) { throw( new Exception( "Exception in SetFromCRTNumber(): " + Except.Message )); } }
private void DoCRTTest( Integer StartingNumber ) { CRTMath CRTMath1 = new CRTMath( Worker ); ECTime CRTTestTime = new ECTime(); ChineseRemainder CRTTest = new ChineseRemainder( IntMath ); ChineseRemainder CRTTest2 = new ChineseRemainder( IntMath ); ChineseRemainder CRTAccumulate = new ChineseRemainder( IntMath ); ChineseRemainder CRTToTest = new ChineseRemainder( IntMath ); ChineseRemainder CRTTempEqual = new ChineseRemainder( IntMath ); ChineseRemainder CRTTestEqual = new ChineseRemainder( IntMath ); Integer BigBase = new Integer(); Integer ToTest = new Integer(); Integer Accumulate = new Integer(); Integer Test1 = new Integer(); Integer Test2 = new Integer(); CRTTest.SetFromTraditionalInteger( StartingNumber ); // If the digit array size isn't set right in relation to // Integer.DigitArraySize then it can cause an error here. CRTMath1.GetTraditionalInteger( Accumulate, CRTTest ); if( !Accumulate.IsEqual( StartingNumber )) throw( new Exception( " !Accumulate.IsEqual( Result )." )); CRTTestEqual.SetFromTraditionalInteger( Accumulate ); if( !CRTMath1.IsEqualToInteger( CRTTestEqual, Accumulate )) throw( new Exception( "IsEqualToInteger() didn't work." )); // Make sure it works with even numbers too. Test1.Copy( StartingNumber ); Test1.SetD( 0, Test1.GetD( 0 ) & 0xFE ); CRTTest.SetFromTraditionalInteger( Test1 ); CRTMath1.GetTraditionalInteger( Accumulate, CRTTest ); if( !Accumulate.IsEqual( Test1 )) throw( new Exception( "For even numbers. !Accumulate.IsEqual( Test )." )); //////////// // Make sure the size of this works with the Integer size because // an overflow is hard to find. CRTTestTime.SetToNow(); Test1.SetToMaxValueForCRT(); CRTTest.SetFromTraditionalInteger( Test1 ); CRTMath1.GetTraditionalInteger( Accumulate, CRTTest ); if( !Accumulate.IsEqual( Test1 )) throw( new Exception( "For the max value. !Accumulate.IsEqual( Test1 )." )); // Worker.ReportProgress( 0, "CRT Max test seconds: " + CRTTestTime.GetSecondsToNow().ToString( "N1" )); // Worker.ReportProgress( 0, "MaxValue: " + IntMath.ToString10( Accumulate )); // Worker.ReportProgress( 0, "MaxValue.Index: " + Accumulate.GetIndex().ToString()); // Multiplicative Inverse test: Integer TestDivideBy = new Integer(); Integer TestProduct = new Integer(); ChineseRemainder CRTTestDivideBy = new ChineseRemainder( IntMath ); ChineseRemainder CRTTestProduct = new ChineseRemainder( IntMath ); TestDivideBy.Copy( StartingNumber ); TestProduct.Copy( StartingNumber ); IntMath.Multiply( TestProduct, TestDivideBy ); CRTTestDivideBy.SetFromTraditionalInteger( TestDivideBy ); CRTTestProduct.SetFromTraditionalInteger( TestDivideBy ); CRTTestProduct.Multiply( CRTTestDivideBy ); CRTMath1.GetTraditionalInteger( Accumulate, CRTTestProduct ); if( !Accumulate.IsEqual( TestProduct )) throw( new Exception( "Multiply test was bad." )); IntMath.Divide( TestProduct, TestDivideBy, Quotient, Remainder ); if( !Remainder.IsZero()) throw( new Exception( "This test won't work unless it divides it exactly." )); ChineseRemainder CRTTestQuotient = new ChineseRemainder( IntMath ); CRTMath1.MultiplicativeInverse( CRTTestProduct, CRTTestDivideBy, CRTTestQuotient ); // Yes, multiplicative inverse is the same number // as with regular division. Integer TestQuotient = new Integer(); CRTMath1.GetTraditionalInteger( TestQuotient, CRTTestQuotient ); if( !TestQuotient.IsEqual( Quotient )) throw( new Exception( "Modular Inverse in DoCRTTest didn't work." )); // Subtract Test1.Copy( StartingNumber ); IntMath.SetFromString( Test2, "12345678901234567890123456789012345" ); CRTTest.SetFromTraditionalInteger( Test1 ); CRTTest2.SetFromTraditionalInteger( Test2 ); CRTTest.Subtract( CRTTest2 ); IntMath.Subtract( Test1, Test2 ); CRTMath1.GetTraditionalInteger( Accumulate, CRTTest ); if( !Accumulate.IsEqual( Test1 )) throw( new Exception( "Subtract test was bad." )); // Add Test1.Copy( StartingNumber ); IntMath.SetFromString( Test2, "12345678901234567890123456789012345" ); CRTTest.SetFromTraditionalInteger( Test1 ); CRTTest2.SetFromTraditionalInteger( Test2 ); CRTTest.Add( CRTTest2 ); IntMath.Add( Test1, Test2 ); CRTMath1.GetTraditionalInteger( Accumulate, CRTTest ); if( !Accumulate.IsEqual( Test1 )) throw( new Exception( "Add test was bad." )); ///////// CRTBaseMath CBaseMath = new CRTBaseMath( Worker, CRTMath1 ); ChineseRemainder CRTInput = new ChineseRemainder( IntMath ); CRTInput.SetFromTraditionalInteger( StartingNumber ); Test1.Copy( StartingNumber ); IntMath.SetFromString( Test2, "12345678901234567890123456789012345" ); IntMath.Add( Test1, Test2 ); Integer TestModulus = new Integer(); TestModulus.Copy( Test1 ); ChineseRemainder CRTTestModulus = new ChineseRemainder( IntMath ); CRTTestModulus.SetFromTraditionalInteger( TestModulus ); Integer Exponent = new Integer(); Exponent.SetFromULong( PubKeyExponentUint ); CBaseMath.ModularPower( CRTInput, Exponent, CRTTestModulus, false ); IntMath.IntMathNew.ModularPower( StartingNumber, Exponent, TestModulus, false ); if( !CRTMath1.IsEqualToInteger( CRTInput, StartingNumber )) throw( new Exception( "CRTBase ModularPower() didn't work." )); CRTBase ExpTest = new CRTBase( IntMath ); CBaseMath.SetFromCRTNumber( ExpTest, CRTInput ); CBaseMath.GetExponentForm( ExpTest, 37 ); // Worker.ReportProgress( 0, "CRT was good." ); }