internal RSACryptoSystem(BackgroundWorker UseWorker, RSACryptoWorkerInfo UseWInfo) { Worker = UseWorker; WorkerInfo = UseWInfo; StartTime = new ECTime(); StartTime.SetToNow(); RngCsp = new RNGCryptoServiceProvider(); IntMath = new IntegerMath(null); IntMathForP = new IntegerMath(null); IntMathForQ = new IntegerMath(null); // Worker.ReportProgress( 0, IntMath.GetStatusString() ); Quotient = new Integer(); Remainder = new Integer(); PrimeP = new Integer(); PrimeQ = new Integer(); PrimePMinus1 = new Integer(); PrimeQMinus1 = new Integer(); PubKeyN = new Integer(); PubKeyExponent = new Integer(); PrivKInverseExponent = new Integer(); PrivKInverseExponentDP = new Integer(); PrivKInverseExponentDQ = new Integer(); QInv = new Integer(); PhiN = new Integer(); TestForDecrypt = new Integer(); M1ForInverse = new Integer(); M2ForInverse = new Integer(); HForQInv = new Integer(); M1MinusM2 = new Integer(); M1M2SizeDiff = new Integer(); PubKeyExponent.SetFromULong(PubKeyExponentUint); }
internal void SetFromString(Integer Result, string InString) { if (InString == null) { throw(new Exception("InString was null in SetFromString().")); } if (InString.Length < 1) { Result.SetToZero(); return; } Base10Number Base10N = new Base10Number(); Integer Tens = new Integer(); Integer OnePart = new Integer(); // This might throw an exception if the string is bad. Base10N.SetFromString(InString); Result.SetFromULong(Base10N.GetD(0)); Tens.SetFromULong(10); for (int Count = 1; Count <= Base10N.GetIndex(); Count++) { OnePart.SetFromULong(Base10N.GetD(Count)); Multiplier.Multiply(OnePart, Tens); Result.Add(OnePart); Multiplier.MultiplyULong(Tens, 10); } }
internal bool IsFermatPrimeForOneValue(Integer ToTest, ulong Base) { // 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.) Fermat1.Copy(ToTest); IntMath.SubtractULong(Fermat1, 1); TestFermat.SetFromULong(Base); // ModularPower( Result, Exponent, Modulus, UsePresetBaseArray ) ModularPower(TestFermat, Fermat1, ToTest, false); // if( !TestFermat.IsEqual( Fermat2 )) // throw( new Exception( "!TestFermat.IsEqual( Fermat2 )." )); if (TestFermat.IsOne()) { return(true); // It passed the test. It _might_ be a prime. } else { return(false); // It is _definitely_ a composite number. } }
internal void SetupGeneralBaseArray(Integer GeneralBase) { // The word 'Base' comes from the base of a number // system. Like normal decimal numbers have base // 10, binary numbers have base 2, etc. CurrentModReductionBase.Copy(GeneralBase); // The input to the accumulator can be twice the // bit length of GeneralBase. int HowManyDigits = ((GeneralBase.GetIndex() + 1) * 2) + 10; // Plus some extra for carries... GeneralBaseArray = new Integer[HowManyDigits]; // int HowManyPrimes = 100; // Row, Column // SmallBasesArray = new uint[HowManyDigits, HowManyPrimes]; Integer Base = new Integer(); Base.SetFromULong(256); // 0x100 IntMath.MultiplyUInt(Base, 256); // 0x10000 IntMath.MultiplyUInt(Base, 256); // 0x1000000 IntMath.MultiplyUInt(Base, 256); // 0x100000000 is the base of this number system. // 0x1 0000 0000 Integer BaseValue = new Integer(); BaseValue.SetFromULong(1); for (int Column = 0; Column < HowManyDigits; Column++) { if (GeneralBaseArray[Column] == null) { GeneralBaseArray[Column] = new Integer(); } IntMath.Divider.Divide(BaseValue, GeneralBase, Quotient, Remainder); GeneralBaseArray[Column].Copy(Remainder); /* * for( int Row = 0; Row < HowManyPrimes; Row++ ) * { * This base value mod this prime? * * SmallBasesArray[Row, Column] = what? * } */ // Done at the bottom for the next round of the // loop. BaseValue.Copy(Remainder); IntMath.Multiply(BaseValue, Base); } }
// This is a variation on ShortDivide that returns // the remainder. // Also, DivideBy is a ulong. internal ulong ShortDivideRem(Integer ToDivideOriginal, ulong DivideByU, Integer Quotient) { if (ToDivideOriginal.IsULong()) { ulong ToDiv = ToDivideOriginal.GetAsULong(); ulong Q = ToDiv / DivideByU; Quotient.SetFromULong(Q); return(ToDiv % DivideByU); } ToDivide.Copy(ToDivideOriginal); Quotient.Copy(ToDivide); ulong RemainderU = 0; if (DivideByU > Quotient.GetD(Quotient.GetIndex())) { Quotient.SetD(Quotient.GetIndex(), 0); } else { ulong OneDigit = Quotient.GetD(Quotient.GetIndex()); Quotient.SetD(Quotient.GetIndex(), OneDigit / DivideByU); RemainderU = OneDigit % DivideByU; ToDivide.SetD(ToDivide.GetIndex(), RemainderU); } for (int Count = Quotient.GetIndex(); Count >= 1; Count--) { ulong TwoDigits = ToDivide.GetD(Count); TwoDigits <<= 32; TwoDigits |= ToDivide.GetD(Count - 1); Quotient.SetD(Count - 1, TwoDigits / DivideByU); RemainderU = TwoDigits % DivideByU; ToDivide.SetD(Count, 0); ToDivide.SetD(Count - 1, RemainderU); } for (int Count = Quotient.GetIndex(); Count >= 0; Count--) { if (Quotient.GetD(Count) != 0) { Quotient.SetIndex(Count); break; } } return(RemainderU); }
internal void Divide(Integer ToDivideOriginal, Integer DivideByOriginal, Integer Quotient, Integer Remainder) { if (ToDivideOriginal.IsNegative) { throw(new Exception("Divide() can't be called with negative numbers.")); } if (DivideByOriginal.IsNegative) { throw(new Exception("Divide() can't be called with negative numbers.")); } // Returns true if it divides exactly with zero remainder. // This first checks for some basics before trying to divide it: if (DivideByOriginal.IsZero()) { throw(new Exception("Divide() dividing by zero.")); } ToDivide.Copy(ToDivideOriginal); DivideBy.Copy(DivideByOriginal); if (ToDivide.ParamIsGreater(DivideBy)) { Quotient.SetToZero(); Remainder.Copy(ToDivide); return; // false; } if (ToDivide.IsEqual(DivideBy)) { Quotient.SetFromULong(1); Remainder.SetToZero(); return; // true; } // At this point DivideBy is smaller than ToDivide. if (ToDivide.IsULong()) { ulong ToDivideU = ToDivide.GetAsULong(); ulong DivideByU = DivideBy.GetAsULong(); ulong QuotientU = ToDivideU / DivideByU; ulong RemainderU = ToDivideU % DivideByU; Quotient.SetFromULong(QuotientU); Remainder.SetFromULong(RemainderU); // if( RemainderU == 0 ) return; // true; // else // return false; } if (DivideBy.GetIndex() == 0) { ShortDivide(ToDivide, DivideBy, Quotient, Remainder); return; } Integer ToDivideTest2 = new Integer(); Integer DivideByTest2 = new Integer(); Integer QuotientTest2 = new Integer(); Integer RemainderTest2 = new Integer(); Integer ToDivideTest3 = new Integer(); Integer DivideByTest3 = new Integer(); Integer QuotientTest3 = new Integer(); Integer RemainderTest3 = new Integer(); ToDivideTest2.Copy(ToDivide); ToDivideTest3.Copy(ToDivide); DivideByTest2.Copy(DivideBy); DivideByTest3.Copy(DivideBy); LongDivide1(ToDivideTest2, DivideByTest2, QuotientTest2, RemainderTest2); LongDivide2(ToDivideTest3, DivideByTest3, QuotientTest3, RemainderTest3); LongDivide3(ToDivide, DivideBy, Quotient, Remainder); if (!Quotient.IsEqual(QuotientTest2)) { throw(new Exception("!Quotient.IsEqual( QuotientTest2 )")); } if (!Quotient.IsEqual(QuotientTest3)) { throw(new Exception("!Quotient.IsEqual( QuotientTest3 )")); } if (!Remainder.IsEqual(RemainderTest2)) { throw(new Exception("!Remainder.IsEqual( RemainderTest2 )")); } if (!Remainder.IsEqual(RemainderTest3)) { throw(new Exception("!Remainder.IsEqual( RemainderTest3 )")); } }
// 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.")); } }