コード例 #1
0
        private bool MakeAPrime( Integer Result, int SetToIndex, int HowMany )
        {
            try
            {
            int Attempts = 0;
            while( true )
              {
              Attempts++;

              if( Worker.CancellationPending )
            return false;

              // Don't hog the server's resources too much.
              Thread.Sleep( 1 ); // Give up the time slice.  Let other things run.

              int HowManyBytes = (SetToIndex * 4) + 4;
              byte[] RandBytes = MakeRandomBytes( HowManyBytes );
              if( RandBytes == null )
            {
            Worker.ReportProgress( 0, "Error making random bytes in MakeAPrime()." );
            return false;
            }

              if( !Result.MakeRandomOdd( SetToIndex, RandBytes ))
            {
            Worker.ReportProgress( 0, "Error making random number in MakeAPrime()." );
            return false;
            }

              // Make sure that it's the size I think it is.
              if( Result.GetIndex() < SetToIndex )
            throw( new Exception( "Bug. The size of the random prime is not right." ));

              uint TestPrime = IntMath.IsDivisibleBySmallPrime( Result );
              if( 0 != TestPrime)
            continue;

              if( !IntMath.IsFermatPrime( Result, HowMany ))
            {
            Worker.ReportProgress( 0, "Did not pass Fermat test." );
            continue;
            }

              // IsFermatPrime() could take a long time.
              if( Worker.CancellationPending )
            return false;

              Worker.ReportProgress( 0, " " );
              Worker.ReportProgress( 0, "Found a probable prime." );
              Worker.ReportProgress( 0, "Attempts: " + Attempts.ToString() );
              Worker.ReportProgress( 0, " " );
              return true; // With Result.
              }
            }
            catch( Exception Except )
              {
              Worker.ReportProgress( 0, "Error in MakeAPrime()" );
              Worker.ReportProgress( 0, Except.Message );
              return false;
              }
        }
コード例 #2
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.
              }
        }