コード例 #1
0
ファイル: Integer.cs プロジェクト: Eric7Apps/BlogSource
        internal void Add( Integer ToAdd )
        {
            // There is a separate IntegerMath.Add() that is a wrapper to handle
            // negative numbers too.

            if( IsNegative )
              throw( new Exception( "Integer.Add() is being called when it's negative." ));

            if( ToAdd.IsNegative )
              throw( new Exception( "Integer.Add() is being called when ToAdd is negative." ));

            if( ToAdd.IsULong() )
              {
              AddULong( ToAdd.GetAsULong() );
              return;
              }

            // Tell the compiler these aren't going to change for the for-loop.
            int LocalIndex = Index;
            int LocalToAddIndex = ToAdd.Index;

            if( LocalIndex < ToAdd.Index )
              {
              for( int Count = LocalIndex + 1; Count <= LocalToAddIndex; Count++ )
            D[Count] = ToAdd.D[Count];

              for( int Count = 0; Count <= LocalIndex; Count++ )
            D[Count] += ToAdd.D[Count];

              Index = ToAdd.Index;
              }
            else
              {
              for( int Count = 0; Count <= LocalToAddIndex; Count++ )
            D[Count] += ToAdd.D[Count];

              }

            // After they've been added, reorganize it.
            ulong Carry = D[0] >> 32;
            D[0] = D[0] & 0xFFFFFFFF;
            LocalIndex = Index;
            for( int Count = 1; Count <= LocalIndex; Count++ )
              {
              ulong Total = Carry + D[Count];
              D[Count] = Total & 0xFFFFFFFF;
              Carry = Total >> 32;
              }

            if( Carry != 0 )
              {
              Index++;
              if( Index >= DigitArraySize )
            throw( new Exception( "Integer.Add() overflow." ));

              D[Index] = Carry;
              }
        }
コード例 #2
0
        internal bool FindMultiplicativeInverseSmall( Integer ToFind, Integer KnownNumber, Integer Modulus, BackgroundWorker Worker )
        {
            // This method is for: KnownNumber * ToFind = 1 mod Modulus
            // An example:
            // PublicKeyExponent * X = 1 mod PhiN.
            // PublicKeyExponent * X = 1 mod (P - 1)(Q - 1).
            // This means that
            // (PublicKeyExponent * X) = (Y * PhiN) + 1
            // X is less than PhiN.
            // So Y is less than PublicKExponent.
            // Y can't be zero.
            // If this equation can be solved then it can be solved modulo
            // any number.  So it has to be solvable mod PublicKExponent.
            // See: Hasse Principle.
            // This also depends on the idea that the KnownNumber is prime and
            // that there is one unique modular inverse.

            // if( !KnownNumber-is-a-prime )
            //    then it won't work.

            if( !KnownNumber.IsULong())
              throw( new Exception( "FindMultiplicativeInverseSmall() was called with too big of a KnownNumber." ));

            ulong KnownNumberULong  = KnownNumber.GetAsULong();
            //                       65537
            if( KnownNumberULong > 1000000 )
              throw( new Exception( "KnownNumberULong > 1000000. FindMultiplicativeInverseSmall() was called with too big of an exponent." ));

            // (Y * PhiN) + 1 mod PubKExponent has to be zero if Y is a solution.
            ulong ModulusModKnown = IntMath.GetMod32( Modulus, KnownNumberULong );
            Worker.ReportProgress( 0, "ModulusModExponent: " + ModulusModKnown.ToString( "N0" ));
            if( Worker.CancellationPending )
              return false;

            // Y can't be zero.
            // The exponent is a small number like 65537.
            for( uint Y = 1; Y < (uint)KnownNumberULong; Y++ )
              {
              ulong X = (ulong)Y * ModulusModKnown;
              X++; // Add 1 to it for (Y * PhiN) + 1.
              X = X % KnownNumberULong;
              if( X == 0 )
            {
            if( Worker.CancellationPending )
              return false;

            // What is PhiN mod 65537?
            // That gives me Y.
            // The private key exponent is X*65537 + ModPart
            // The CipherText raised to that is the PlainText.

            // P + zN = C^(X*65537 + ModPart)
            // P + zN = C^(X*65537)(C^ModPart)
            // P + zN = ((C^65537)^X)(C^ModPart)

            Worker.ReportProgress( 0, "Found Y at: " + Y.ToString( "N0" ));
            ToFind.Copy( Modulus );
            IntMath.MultiplyULong( ToFind, Y );
            ToFind.AddULong( 1 );
            IntMath.Divide( ToFind, KnownNumber, Quotient, Remainder );
            if( !Remainder.IsZero())
              throw( new Exception( "This can't happen. !Remainder.IsZero()" ));

            ToFind.Copy( Quotient );
            // Worker.ReportProgress( 0, "ToFind: " + ToString10( ToFind ));
            break;
            }
              }

            if( Worker.CancellationPending )
              return false;

            TestForModInverse1.Copy( ToFind );
            IntMath.MultiplyULong( TestForModInverse1, KnownNumberULong );
            IntMath.Divide( TestForModInverse1, Modulus, Quotient, Remainder );
            if( !Remainder.IsOne())
              {
              // The definition is that it's congruent to 1 mod the modulus,
              // so this has to be 1.

              // I've only seen this happen once.  Were the primes P and Q not
              // really primes?
              throw( new Exception( "This is a bug. Remainder has to be 1: " + IntMath.ToString10( Remainder ) ));
              }

            return true;
        }
コード例 #3
0
ファイル: FindFactors.cs プロジェクト: Eric7Apps/BlogSource
        private bool IsFermatPrimeAdded( Integer FindFrom )
        {
            if( FindFrom.IsULong())
              {
              // The biggest size that NumberIsDivisibleByUInt() will check to
              // see if it has primes for sure.
              if( FindFrom.GetAsULong() < (223092870UL * 223092870UL))
            return false; // Factor this.

              }

            int HowManyTimes = 20; // How many primes it will be checked with.
            if( !IntMath.IsFermatPrime( FindFrom, HowManyTimes ))
              return false;

            Integer OneFactor = new Integer();
            OneFactor.Copy( FindFrom );
            OneFactorRec Rec = new OneFactorRec();
            Rec.Factor = OneFactor;
            // Neither one of these is set to true here because it's probably
            // a prime, but not definitely.
            // Rec.IsDefinitelyAPrime = false;
            // Rec.IsDefinitelyNotAPrime = false;
            AddFactorRec( Rec );
            Worker.ReportProgress( 0, "Fermat thinks this one is a prime." );
            return true; // It's a Fermat prime and it was added.
        }
コード例 #4
0
ファイル: FindFactors.cs プロジェクト: Eric7Apps/BlogSource
        internal uint NumberIsDivisibleByUInt( Integer ToCheck )
        {
            if( DivisionArray == null )
              SetupDivisionArray(); // Set it up once, when it's needed.

            uint Max = 0;
            if( ToCheck.IsULong())
              {
              ulong ForMax = ToCheck.GetAsULong();
              // It can't be bigger than the square root.
              Max = (uint)IntMath.FindULSqrRoot( ForMax );
              }

            uint Base = 2 * 3 * 5 * 7 * 11 * 13 * 17;
            uint EulerPhi = 2 * 4 * 6 * 10 * 12 * 16;
            uint Base19 = Base * 19;
            uint Base23 = Base19 * 23;

            // The first few base numbers like this:
            // 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

            // These loops count up to 223,092,870 - 1.
            for( uint Count23 = 0; Count23 < 23; Count23++ )
              {
              Worker.ReportProgress( 0, "Count23 loop: " + Count23.ToString());

              uint Base23Part = (Base19 * Count23);
              for( uint Count19 = 0; Count19 < 19; Count19++ )
            {
            uint Base19Part = Base * Count19;
            if( Worker.CancellationPending )
              return 0;

            for( int Count = 0; Count < EulerPhi; Count++ )
              {
              if( Worker.CancellationPending )
            return 0;

              uint Test = Base23Part + Base19Part + DivisionArray[Count];
              if( Test == 1 )
            continue;

              if( (Test % 19) == 0 )
            continue;

              if( (Test % 23) == 0 )
            continue;

              if( Max > 0 )
            {
            if( Test > Max )
              return 0;

            }

              if( 0 == IntMath.GetMod32( ToCheck, Test ))
            {
            Worker.ReportProgress( 0, "The number is divisible by: " + Test.ToString( "N0" ));
            return Test;
            }
              }
            }
              }

            return 0; // Didn't find a number to divide it.
        }
コード例 #5
0
        /*
          private bool IsQuadResidue( uint Test, int Index )
        {
        uint TestMod = Test % IntMath.GetPrimeAt( Index );
        return QuadResToPrimesArray[Index].QuadRes[TestMod];
        }
        */
        private uint GetMod32( Integer ToDivideOriginal, uint DivideByU )
        {
            if( ToDivideOriginal.IsULong())
              {
              ulong Result = ToDivideOriginal.GetAsULong();
              return (uint)(Result % DivideByU);
              }

            ToDivideMod32.Copy( ToDivideOriginal );
            ulong RemainderU = 0;

            if( DivideByU <= ToDivideMod32.GetD( ToDivideMod32.GetIndex() ))
              {
              ulong OneDigit = ToDivideMod32.GetD( ToDivideMod32.GetIndex() );
              RemainderU = OneDigit % DivideByU;
              ToDivideMod32.SetD( ToDivideMod32.GetIndex(), RemainderU );
              }

            for( int Count = ToDivideMod32.GetIndex(); Count >= 1; Count-- )
              {
              ulong TwoDigits = ToDivideMod32.GetD( Count );
              TwoDigits <<= 32;
              TwoDigits |= ToDivideMod32.GetD( Count - 1 );
              RemainderU = TwoDigits % DivideByU;
              ToDivideMod32.SetD( Count, 0 );
              ToDivideMod32.SetD( Count - 1, RemainderU );
              }

            return (uint)RemainderU;
        }
コード例 #6
0
ファイル: IntegerMath.cs プロジェクト: Eric7Apps/BlogSource
        internal ulong GetMod64( Integer ToDivideOriginal, ulong DivideBy )
        {
            if( ToDivideOriginal.IsULong())
              return ToDivideOriginal.GetAsULong() % DivideBy;

            ToDivide.Copy( ToDivideOriginal );

            ulong Digit1;
            ulong Digit0;
            ulong Remainder;

            if( ToDivide.GetIndex() == 2 )
              {
              Digit1 = ToDivide.GetD( 2 );
              Digit0 = ToDivide.GetD( 1 ) << 32;
              Digit0 |= ToDivide.GetD( 0 );
              return GetMod64FromTwoULongs( Digit1, Digit0, DivideBy );
              }

            if( ToDivide.GetIndex() == 3 )
              {
              Digit1 = ToDivide.GetD( 3 ) << 32;
              Digit1 |= ToDivide.GetD( 2 );
              Digit0 = ToDivide.GetD( 1 ) << 32;
              Digit0 |= ToDivide.GetD( 0 );
              return GetMod64FromTwoULongs( Digit1, Digit0, DivideBy );
              }

            int Where = ToDivide.GetIndex();
            while( true )
              {
              if( Where <= 3 )
            {
            if( Where < 2 ) // This can't happen.
              throw( new Exception( "Bug: GetMod64(): Where < 2." ));

            if( Where == 2 )
              {
              Digit1 = ToDivide.GetD( 2 );
              Digit0 = ToDivide.GetD( 1 ) << 32;
              Digit0 |= ToDivide.GetD( 0 );
              return GetMod64FromTwoULongs( Digit1, Digit0, DivideBy );
              }

            if( Where == 3 )
              {
              Digit1 = ToDivide.GetD( 3 ) << 32;
              Digit1 |= ToDivide.GetD( 2 );
              Digit0 = ToDivide.GetD( 1 ) << 32;
              Digit0 |= ToDivide.GetD( 0 );
              return GetMod64FromTwoULongs( Digit1, Digit0, DivideBy );
              }
            }
              else
            {
            // The index is bigger than 3.
            // This part would get called at least once.
            Digit1 = ToDivide.GetD( Where ) << 32;
            Digit1 |= ToDivide.GetD( Where - 1 );
            Digit0 = ToDivide.GetD( Where - 2 ) << 32;
            Digit0 |= ToDivide.GetD( Where - 3 );
            Remainder = GetMod64FromTwoULongs( Digit1, Digit0, DivideBy );

            ToDivide.SetD( Where, 0 );
            ToDivide.SetD( Where - 1, 0 );
            ToDivide.SetD( Where - 2, Remainder >> 32 );
            ToDivide.SetD( Where - 3, Remainder & 0xFFFFFFFF );
            }

              Where -= 2;
              }
        }
コード例 #7
0
ファイル: IntegerMath.cs プロジェクト: Eric7Apps/BlogSource
        // This is a variation on ShortDivide() to get the remainder only.
        internal ulong GetMod32( Integer ToDivideOriginal, ulong DivideByU )
        {
            if( (DivideByU >> 32) != 0 )
              throw( new Exception( "GetMod32: (DivideByU >> 32) != 0." ));

            // If this is _equal_ to a small prime it would return zero.
            if( ToDivideOriginal.IsULong())
              {
              ulong Result = ToDivideOriginal.GetAsULong();
              return Result % DivideByU;
              }

            ToDivide.Copy( ToDivideOriginal );
            ulong RemainderU = 0;

            if( DivideByU <= ToDivide.GetD( ToDivide.GetIndex() ))
              {
              ulong OneDigit = ToDivide.GetD( ToDivide.GetIndex() );
              RemainderU = OneDigit % DivideByU;
              ToDivide.SetD( ToDivide.GetIndex(), RemainderU );
              }

            for( int Count = ToDivide.GetIndex(); Count >= 1; Count-- )
              {
              ulong TwoDigits = ToDivide.GetD( Count );
              TwoDigits <<= 32;
              TwoDigits |= ToDivide.GetD( Count - 1 );
              RemainderU = TwoDigits % DivideByU;
              ToDivide.SetD( Count, 0 );
              ToDivide.SetD( Count - 1, RemainderU );
              }

            return RemainderU;
        }
コード例 #8
0
ファイル: IntegerMath.cs プロジェクト: Eric7Apps/BlogSource
        internal string ToString10( Integer From )
        {
            if( From.IsULong())
              {
              ulong N = From.GetAsULong();
              if( From.IsNegative )
            return "-" + N.ToString( "N0" );
              else
            return N.ToString( "N0" );

              }

            string Result = "";
            ToDivide.Copy( From );
            int CommaCount = 0;
            while( !ToDivide.IsZero())
              {
              uint Digit = (uint)ShortDivideRem( ToDivide, 10, Quotient );
              ToDivide.Copy( Quotient );
              if( ((CommaCount % 3) == 0) && (CommaCount != 0) )
            Result = Digit.ToString() + "," + Result; // Or use a StringBuilder.
              else
            Result = Digit.ToString() + Result;

              CommaCount++;
              }

            if( From.IsNegative )
              return "-" + Result;
            else
              return Result;
        }
コード例 #9
0
ファイル: IntegerMath.cs プロジェクト: Eric7Apps/BlogSource
        // Finding the square root of a number is similar to division since
        // it is a search algorithm.  The TestSqrtBits method shown next is
        // very much like TestDivideBits().  It works the same as
        // FindULSqrRoot(), but on a bigger scale.
        /*
          private void TestSqrtBits( int TestIndex, Integer Square, Integer SqrRoot )
        {
        Integer Test1 = new Integer();

        uint BitTest = 0x80000000;
        for( int BitCount = 31; BitCount >= 0; BitCount-- )
          {
          Test1.Copy( SqrRoot );
          Test1.D[TestIndex] |= BitTest;
          Test1.Square();
          if( !Square.ParamIsGreater( Test1 ) )
        SqrRoot.D[TestIndex] |= BitTest; // Use the bit.

          BitTest >>= 1;
          }
        }
        */
        // In the SquareRoot() method SqrRoot.Index is half of Square.Index.
        // Compare this to the Square() method where the Carry might or
        // might not increment the index to an odd number.  (So if the Index
        // was 5 its square root would have an Index of 5 / 2 = 2.)
        // The SquareRoot1() method uses FindULSqrRoot() either to find the
        // whole answer, if it's a small number, or it uses it to find the
        // top part.  Then from there it goes on to a bit by bit search
        // with TestSqrtBits().
        public bool SquareRoot( Integer Square, Integer SqrRoot )
        {
            ulong ToMatch;
            if( Square.IsULong() )
              {
              ToMatch = Square.GetAsULong();
              SqrRoot.SetD( 0, FindULSqrRoot( ToMatch ));
              SqrRoot.SetIndex( 0 );
              if( (SqrRoot.GetD(0 ) * SqrRoot.GetD( 0 )) == ToMatch )
            return true;
              else
            return false;

              }

            int TestIndex = Square.GetIndex() >> 1; // LgSquare.Index / 2;
            SqrRoot.SetDigitAndClear( TestIndex, 1 );
            // if( (TestIndex * 2) > (LgSquare.Index - 1) )
            if( (TestIndex << 1) > (Square.GetIndex() - 1) )
              {
              ToMatch = Square.GetD( Square.GetIndex());
              }
            else
              {
              // LgSquare.Index is at least 2 here.
              ToMatch = Square.GetD( Square.GetIndex()) << 32;
              ToMatch |= Square.GetD( Square.GetIndex() - 1 );
              }

            SqrRoot.SetD( TestIndex, FindULSqrRoot( ToMatch ));

            TestIndex--;
            while( true )
              {
              // TestSqrtBits( TestIndex, LgSquare, LgSqrRoot );
              SearchSqrtXPart( TestIndex, Square, SqrRoot );
              if( TestIndex == 0 )
            break;

              TestIndex--;
              }

            // Avoid squaring the whole thing to see if it's an exact square root:
            if( ((SqrRoot.GetD( 0 ) * SqrRoot.GetD( 0 )) & 0xFFFFFFFF) != Square.GetD( 0 ))
              return false;

            TestForSquareRoot.Copy( SqrRoot );
            DoSquare( TestForSquareRoot );
            if( Square.IsEqual( TestForSquareRoot ))
              return true;
            else
              return false;
        }
コード例 #10
0
ファイル: IntegerMath.cs プロジェクト: Eric7Apps/BlogSource
        internal void SubtractULong( Integer Result, ulong ToSub )
        {
            if( Result.IsULong())
              {
              ulong ResultU = Result.GetAsULong();
              if( ToSub > ResultU )
            throw( new Exception( "SubULong() (IsULong() and (ToSub > Result)." ));

              ResultU = ResultU - ToSub;
              Result.SetD( 0, ResultU & 0xFFFFFFFF );
              Result.SetD( 1, ResultU >> 32 );
              if( Result.GetD( 1 ) == 0 )
            Result.SetIndex( 0 );
              else
            Result.SetIndex( 1 );

              return;
              }

            // If it got this far then Index is at least 2.
            SignedD[0] = (long)Result.GetD( 0 ) - (long)(ToSub & 0xFFFFFFFF);
            SignedD[1] = (long)Result.GetD( 1 ) - (long)(ToSub >> 32);

            if( (SignedD[0] >= 0) && (SignedD[1] >= 0) )
              {
              // No need to reorganize it.
              Result.SetD( 0, (ulong)SignedD[0] );
              Result.SetD( 1, (ulong)SignedD[1] );
              return;
              }

            for( int Count = 2; Count <= Result.GetIndex(); Count++ )
              SignedD[Count] = (long)Result.GetD( Count );

            for( int Count = 0; Count < Result.GetIndex(); Count++ )
              {
              if( SignedD[Count] < 0 )
            {
            SignedD[Count] += (long)0xFFFFFFFF + 1;
            SignedD[Count + 1]--;
            }
              }

            if( SignedD[Result.GetIndex()] < 0 )
              throw( new Exception( "SubULong() SignedD[Index] < 0." ));

            for( int Count = 0; Count <= Result.GetIndex(); Count++ )
              Result.SetD( Count, (ulong)SignedD[Count] );

            for( int Count = Result.GetIndex(); Count >= 0; Count-- )
              {
              if( Result.GetD( Count ) != 0 )
            {
            Result.SetIndex( Count );
            return;
            }
              }

            // If this was zero it wouldn't find a nonzero
            // digit to set the Index to and it would end up down here.
            Result.SetIndex( 0 );
        }
コード例 #11
0
ファイル: IntegerMath.cs プロジェクト: Eric7Apps/BlogSource
        internal void SubtractPositive( Integer Result, Integer ToSub )
        {
            if( ToSub.IsULong() )
              {
              SubtractULong( Result, ToSub.GetAsULong());
              return;
              }

            if( ToSub.GetIndex() > Result.GetIndex() )
              throw( new Exception( "In Subtract() ToSub.Index > Index." ));

            for( int Count = 0; Count <= ToSub.GetIndex(); Count++ )
              SignedD[Count] = (long)Result.GetD( Count ) - (long)ToSub.GetD( Count );

            for( int Count = ToSub.GetIndex() + 1; Count <= Result.GetIndex(); Count++ )
              SignedD[Count] = (long)Result.GetD( Count );

            for( int Count = 0; Count < Result.GetIndex(); Count++ )
              {
              if( SignedD[Count] < 0 )
            {
            SignedD[Count] += (long)0xFFFFFFFF + 1;
            SignedD[Count + 1]--;
            }
              }

            if( SignedD[Result.GetIndex()] < 0 )
              throw( new Exception( "Subtract() SignedD[Index] < 0." ));

            for( int Count = 0; Count <= Result.GetIndex(); Count++ )
              Result.SetD( Count, (ulong)SignedD[Count] );

            for( int Count = Result.GetIndex(); Count >= 0; Count-- )
              {
              if( Result.GetD( Count ) != 0 )
            {
            Result.SetIndex( Count );
            return;
            }
              }

            // If it never found a non-zero digit it would get down to here.
            Result.SetIndex( 0 );
        }
コード例 #12
0
ファイル: IntegerMath.cs プロジェクト: Eric7Apps/BlogSource
        // 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;
        }
コード例 #13
0
ファイル: IntegerMath.cs プロジェクト: Eric7Apps/BlogSource
        // See also: http://en.wikipedia.org/wiki/Karatsuba_algorithm
        internal void Multiply( Integer Result, Integer ToMul )
        {
            // try
            // {

            if( Result.IsZero())
              return;

            if( ToMul.IsULong())
              {
              MultiplyULong( Result, ToMul.GetAsULong());
              SetMultiplySign( Result, ToMul );
              return;
              }

            // It could never get here if ToMul is zero because GetIsULong()
            // would be true for zero.
            // if( ToMul.IsZero())

            int TotalIndex = Result.GetIndex() + ToMul.GetIndex();
            if( TotalIndex >= Integer.DigitArraySize )
              throw( new Exception( "Multiply() overflow." ));

            for( int Row = 0; Row <= ToMul.GetIndex(); Row++ )
              {
              if( ToMul.GetD( Row ) == 0 )
            {
            for( int Column = 0; Column <= Result.GetIndex(); Column++ )
              M[Column + Row, Row] = 0;

            }
              else
            {
            for( int Column = 0; Column <= Result.GetIndex(); Column++ )
              M[Column + Row, Row] = ToMul.GetD( Row ) * Result.GetD( Column );

            }
              }

            // Add the columns up with a carry.
            Result.SetD( 0, M[0, 0] & 0xFFFFFFFF );
            ulong Carry = M[0, 0] >> 32;
            for( int Column = 1; Column <= TotalIndex; Column++ )
              {
              ulong TotalLeft = 0;
              ulong TotalRight = 0;
              for( int Row = 0; Row <= ToMul.GetIndex(); Row++ )
            {
            if( Row > Column )
              break;

            if( Column > (Result.GetIndex() + Row) )
              continue;

            // Split the ulongs into right and left sides
            // so that they don't overflow.
            TotalRight += M[Column, Row] & 0xFFFFFFFF;
            TotalLeft += M[Column, Row] >> 32;
            }

              TotalRight += Carry;
              Result.SetD( Column, TotalRight & 0xFFFFFFFF );
              Carry = TotalRight >> 32;
              Carry += TotalLeft;
              }

            Result.SetIndex( TotalIndex );
            if( Carry != 0 )
              {
              Result.IncrementIndex(); // This can throw an exception if it overflowed the index.
              Result.SetD( Result.GetIndex(), Carry );
              }

            SetMultiplySign( Result, ToMul );
        }
コード例 #14
0
        internal void MakeRSAKeys()
        {
            int ShowBits = (PrimeIndex + 1) * 32;
            // int TestLoops = 0;

            Worker.ReportProgress( 0, "Making RSA keys." );
            Worker.ReportProgress( 0, "Bits size is: " + ShowBits.ToString());

            // ulong Loops = 0;
            while( true )
              {
              if( Worker.CancellationPending )
            return;

              Thread.Sleep( 1 ); // Give up the time slice.  Let other things on the server run.

              // Make two prime factors.
              // Normally you'd only make new primes when you pay the Certificate
              // Authority for a new certificate.
              if( !MakeAPrime( PrimeP, PrimeIndex, 20 ))
            return;

              IntegerBase TestP = new IntegerBase();
              IntegerBaseMath IntBaseMath = new IntegerBaseMath( IntMath );
              string TestS = IntMath.ToString10( PrimeP );
              IntBaseMath.SetFromString( TestP, TestS );
              string TestS2 = IntBaseMath.ToString10( TestP );
              if( TestS != TestS2 )
            throw( new Exception( "TestS != TestS2 for IntegerBase." ));

              if( Worker.CancellationPending )
            return;

              if( !MakeAPrime( PrimeQ, PrimeIndex, 20 ))
            return;

              if( Worker.CancellationPending )
            return;

              // This is extremely unlikely.
              Integer Gcd = new Integer();
              IntMath.GreatestCommonDivisor( PrimeP, PrimeQ, Gcd );
              if( !Gcd.IsOne())
            {
            Worker.ReportProgress( 0, "They had a GCD: " + IntMath.ToString10( Gcd ));
            continue;
            }

              if( Worker.CancellationPending )
            return;

              // This would never happen since the public key exponent used here
              // is one of the small primes in the array in IntegerMath that it
              // was checked against.  But it does show here in the code that
              // they have to be co-prime to each other.  And in the future it
              // might be found that the public key exponent has to be much larger
              // than the one used here.
              IntMath.GreatestCommonDivisor( PrimeP, PubKeyExponent, Gcd );
              if( !Gcd.IsOne())
            {
            Worker.ReportProgress( 0, "They had a GCD with PubKeyExponent: " + IntMath.ToString10( Gcd ));
            continue;
            }

              if( Worker.CancellationPending )
            return;

              IntMath.GreatestCommonDivisor( PrimeQ, PubKeyExponent, Gcd );
              if( !Gcd.IsOne())
            {
            Worker.ReportProgress( 0, "2) They had a GCD with PubKeyExponent: " + IntMath.ToString10( Gcd ));
            continue;
            }

              // For Modular Reduction.  This only has to be done
              // once, when P and Q are made.
              IntMathNewForP.SetupGeneralBaseArray( PrimeP );
              IntMathNewForQ.SetupGeneralBaseArray( PrimeQ );

              PrimePMinus1.Copy( PrimeP );
              IntMath.SubtractULong( PrimePMinus1, 1 );
              PrimeQMinus1.Copy( PrimeQ );
              IntMath.SubtractULong( PrimeQMinus1, 1 );

              // These checks should be more thorough.

              if( Worker.CancellationPending )
            return;

              Worker.ReportProgress( 0, "The Index of Prime P is: " + PrimeP.GetIndex().ToString() );
              Worker.ReportProgress( 0, "Prime P:" );
              Worker.ReportProgress( 0, IntMath.ToString10( PrimeP ));
              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "Prime Q:" );
              Worker.ReportProgress( 0, IntMath.ToString10( PrimeQ ));
              Worker.ReportProgress( 0, " " );

              PubKeyN.Copy( PrimeP );
              IntMath.Multiply( PubKeyN, PrimeQ );

              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "PubKeyN:" );
              Worker.ReportProgress( 0, IntMath.ToString10( PubKeyN ));
              Worker.ReportProgress( 0, " " );

              // Euler's Theorem:
              // https://en.wikipedia.org/wiki/Euler's_theorem
              // if x ≡ y (mod φ(n)),
              // then a^x ≡ a^y (mod n).

              // Euler's Phi function (aka Euler's Totient function) is calculated
              // next.

              // PhiN is made from the two factors: (P - 1)(Q - 1)
              // PhiN is: (P - 1)(Q - 1) = PQ - P - Q + 1
              // If I add (P - 1) to PhiN I get:
              // PQ - P - Q + 1 + (P - 1) = PQ - Q.
              // If I add (Q - 1) to that I get:
              // PQ - Q + (Q - 1) = PQ - 1.
              // (P - 1)(Q - 1) + (P - 1) + (Q - 1) = PQ - 1

              // If (P - 1) and (Q - 1) had a larger GCD then PQ - 1 would have
              // that same factor too.

              IntMath.GreatestCommonDivisor( PrimePMinus1, PrimeQMinus1, Gcd );
              Worker.ReportProgress( 0, "GCD of PrimePMinus1, PrimeQMinus1 is: " + IntMath.ToString10( Gcd ));

              if( !Gcd.IsULong())
            {
            Worker.ReportProgress( 0, "This GCD number is too big: " + IntMath.ToString10( Gcd ));
            continue;
            }
              else
            {
            ulong TooBig = Gcd.GetAsULong();
            // How big of a GCD is too big?
            if( TooBig > 1234567 )
              {
              // (P - 1)(Q - 1) + (P - 1) + (Q - 1) = PQ - 1
              Worker.ReportProgress( 0, "This GCD number is bigger than 1234567: " + IntMath.ToString10( Gcd ));
              continue;
              }
            }

              Integer Temp1 = new Integer();

              PhiN.Copy( PrimePMinus1 );
              Temp1.Copy( PrimeQMinus1 );
              IntMath.Multiply( PhiN, Temp1 );

              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "PhiN:" );
              Worker.ReportProgress( 0, IntMath.ToString10( PhiN ));
              Worker.ReportProgress( 0, " " );
              if( Worker.CancellationPending )
            return;

              // In RFC 2437 there are commonly used letters/symbols to represent
              // the numbers used.  So the number e is the public exponent.
              // The number e that is used here is called PubKeyExponentUint = 65537.
              // In the RFC the private key d is the multiplicative inverse of
              // e mod PhiN.  Which is mod (P - 1)(Q - 1).  It's called
              // PrivKInverseExponent here.

              if( !IntMath.IntMathNew.FindMultiplicativeInverseSmall( PrivKInverseExponent, PubKeyExponent, PhiN, Worker ))
            return;

              if( PrivKInverseExponent.IsZero())
            continue;

              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "PrivKInverseExponent: " + IntMath.ToString10( PrivKInverseExponent ));

              if( Worker.CancellationPending )
            return;

              // In RFC 2437 it defines a number dP which is the multiplicative
              // inverse, mod (P - 1) of e.  That dP is named PrivKInverseExponentDP here.
              Worker.ReportProgress( 0, " " );
              if( !IntMath.IntMathNew.FindMultiplicativeInverseSmall( PrivKInverseExponentDP, PubKeyExponent, PrimePMinus1, Worker ))
            return;

              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "PrivKInverseExponentDP: " + IntMath.ToString10( PrivKInverseExponentDP ));
              if( PrivKInverseExponentDP.IsZero())
            continue;

              // PrivKInverseExponentDP is PrivKInverseExponent mod PrimePMinus1.
              Integer Test1 = new Integer();
              Test1.Copy( PrivKInverseExponent );
              IntMath.Divide( Test1, PrimePMinus1, Quotient, Remainder );
              Test1.Copy( Remainder );
              if( !Test1.IsEqual( PrivKInverseExponentDP ))
            throw( new Exception( "Bug. This does not match the definition of PrivKInverseExponentDP." ));

              if( Worker.CancellationPending )
            return;

              // In RFC 2437 it defines a number dQ which is the multiplicative
              // inverse, mod (Q - 1) of e.  That dQ is named PrivKInverseExponentDQ here.
              Worker.ReportProgress( 0, " " );
              if( !IntMath.IntMathNew.FindMultiplicativeInverseSmall( PrivKInverseExponentDQ, PubKeyExponent, PrimeQMinus1, Worker ))
            return;

              if( PrivKInverseExponentDQ.IsZero())
            continue;

              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "PrivKInverseExponentDQ: " + IntMath.ToString10( PrivKInverseExponentDQ ));
              if( Worker.CancellationPending )
            return;

              Test1.Copy( PrivKInverseExponent );
              IntMath.Divide( Test1, PrimeQMinus1, Quotient, Remainder );
              Test1.Copy( Remainder );
              if( !Test1.IsEqual( PrivKInverseExponentDQ ))
            throw( new Exception( "Bug. This does not match the definition of PrivKInverseExponentDQ." ));

              // Make a random number to test encryption/decryption.
              Integer ToEncrypt = new Integer();
              int HowManyBytes = PrimeIndex * 4;
              byte[] RandBytes = MakeRandomBytes( HowManyBytes );
              if( RandBytes == null )
            {
            Worker.ReportProgress( 0, "Error making random bytes in MakeRSAKeys()." );
            return;
            }

              if( !ToEncrypt.MakeRandomOdd( PrimeIndex - 1, RandBytes ))
            {
            Worker.ReportProgress( 0, "Error making random number ToEncrypt." );
            return;
            }

              Integer PlainTextNumber = new Integer();
              PlainTextNumber.Copy( ToEncrypt );

              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "Before encrypting number: " + IntMath.ToString10( ToEncrypt ));
              Worker.ReportProgress( 0, " " );

              IntMath.IntMathNew.ModularPower( ToEncrypt, PubKeyExponent, PubKeyN, false );
              if( Worker.CancellationPending )
            return;

              Worker.ReportProgress( 0, IntMath.GetStatusString() );

              Integer CipherTextNumber = new Integer();
              CipherTextNumber.Copy( ToEncrypt );

              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "Encrypted number: " + IntMath.ToString10( CipherTextNumber ));
              Worker.ReportProgress( 0, " " );

              ECTime DecryptTime = new ECTime();
              DecryptTime.SetToNow();
              IntMath.IntMathNew.ModularPower( ToEncrypt, PrivKInverseExponent, PubKeyN, false );
              Worker.ReportProgress( 0, "Decrypted number: " + IntMath.ToString10( ToEncrypt ));

              if( !PlainTextNumber.IsEqual( ToEncrypt ))
            {
            throw( new Exception( "PlainTextNumber not equal to unencrypted value." ));
            // Because P or Q wasn't really a prime?
            // Worker.ReportProgress( 0, "PlainTextNumber not equal to unencrypted value." );
            // continue;
            }

              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "Decrypt time seconds: " + DecryptTime.GetSecondsToNow().ToString( "N2" ));
              Worker.ReportProgress( 0, " " );
              if( Worker.CancellationPending )
            return;

              // Test the standard optimized way of decrypting:
              if( !ToEncrypt.MakeRandomOdd( PrimeIndex - 1, RandBytes ))
            {
            Worker.ReportProgress( 0, "Error making random number in MakeRSAKeys()." );
            return;
            }

              PlainTextNumber.Copy( ToEncrypt );
              IntMath.IntMathNew.ModularPower( ToEncrypt, PubKeyExponent, PubKeyN, false );
              if( Worker.CancellationPending )
            return;

              CipherTextNumber.Copy( ToEncrypt );

              // QInv is the multiplicative inverse of PrimeQ mod PrimeP.
              if( !IntMath.MultiplicativeInverse( PrimeQ, PrimeP, QInv, Worker ))
            throw( new Exception( "MultiplicativeInverse() returned false." ));

              if( QInv.IsNegative )
            throw( new Exception( "This is a bug. QInv is negative." ));

              Worker.ReportProgress( 0, "QInv is: " + IntMath.ToString10( QInv ));

              DecryptWithQInverse( CipherTextNumber,
                           ToEncrypt, // Decrypt it to this.
                           PlainTextNumber, // Test it against this.
                           PubKeyN,
                           PrivKInverseExponentDP,
                           PrivKInverseExponentDQ,
                           PrimeP,
                           PrimeQ,
                           Worker );

              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "Found the values:" );
              Worker.ReportProgress( 0, "Seconds: " + StartTime.GetSecondsToNow().ToString( "N0" ));
              Worker.ReportProgress( 0, " " );

              Worker.ReportProgress( 1, "Prime1: " + IntMath.ToString10( PrimeP ));
              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 1, "Prime2: " + IntMath.ToString10( PrimeQ ));
              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 1, "PubKeyN: " + IntMath.ToString10( PubKeyN ));
              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 1, "PrivKInverseExponent: " + IntMath.ToString10( PrivKInverseExponent ));

              /*
              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, " " );
              DoCRTTest( PrivKInverseExponent );
              Worker.ReportProgress( 0, "Finished CRT test." );
              Worker.ReportProgress( 0, " " );
              */

              return; // Comment this out to just leave it while( true ) for testing.
              }
        }