예제 #1
0
        internal bool FindMultiplicativeInverseSmall(Integer ToFind, Integer KnownNumber, Integer Modulus)
        {
            // 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 = Divider.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);
                    Multiplier.MultiplyULong(ToFind, Y);
                    ToFind.AddULong(1);
                    Divider.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);
            Multiplier.MultiplyULong(TestForModInverse1, KnownNumberULong);
            Divider.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("Remainder has to be 1: " + ToString10(Remainder)));
            }

            return(true);
        }
예제 #2
0
        internal bool DecryptWithQInverse(Integer EncryptedNumber,
                                          Integer DecryptedNumber,
                                          Integer TestDecryptedNumber,
                                          Integer PubKeyN,
                                          Integer PrivKInverseExponentDP,
                                          Integer PrivKInverseExponentDQ,
                                          Integer PrimeP,
                                          Integer PrimeQ,
                                          BackgroundWorker Worker)
        {
            Worker.ReportProgress(0, " ");
            Worker.ReportProgress(0, "Top of DecryptWithQInverse().");
            // QInv and the dP and dQ numbers are normally already set up before
            // you start your listening socket.
            ECTime DecryptTime = new ECTime();

            DecryptTime.SetToNow();
            // See section 5.1.2 of RFC 2437 for these steps:
            // http://tools.ietf.org/html/rfc2437
            //      2.2 Let m_1 = c^dP mod p.
            //      2.3 Let m_2 = c^dQ mod q.
            //      2.4 Let h = qInv ( m_1 - m_2 ) mod p.
            //      2.5 Let m = m_2 + hq.
            Worker.ReportProgress(0, "EncryptedNumber: " + IntMath.ToString10(EncryptedNumber));
            //      2.2 Let m_1 = c^dP mod p.
            TestForDecrypt.Copy(EncryptedNumber);
            IntMathForP.ModReduction.ModularPower(TestForDecrypt, PrivKInverseExponentDP, PrimeP, true);
            if (Worker.CancellationPending)
            {
                return(false);
            }

            M1ForInverse.Copy(TestForDecrypt);
            //      2.3 Let m_2 = c^dQ mod q.
            TestForDecrypt.Copy(EncryptedNumber);
            IntMathForQ.ModReduction.ModularPower(TestForDecrypt, PrivKInverseExponentDQ, PrimeQ, true);
            if (Worker.CancellationPending)
            {
                return(false);
            }

            M2ForInverse.Copy(TestForDecrypt);
            //      2.4 Let h = qInv ( m_1 - m_2 ) mod p.
            // How many is optimal to avoid the division?
            int HowManyIsOptimal = (PrimeP.GetIndex() * 3);

            for (int Count = 0; Count < HowManyIsOptimal; Count++)
            {
                if (M1ForInverse.ParamIsGreater(M2ForInverse))
                {
                    M1ForInverse.Add(PrimeP);
                }
                else
                {
                    break;
                }
            }

            if (M1ForInverse.ParamIsGreater(M2ForInverse))
            {
                M1M2SizeDiff.Copy(M2ForInverse);
                IntMath.Subtract(M1M2SizeDiff, M1ForInverse);
                // Unfortunately this long Divide() has to be done.
                IntMath.Divider.Divide(M1M2SizeDiff, PrimeP, Quotient, Remainder);
                Quotient.AddULong(1);
                Worker.ReportProgress(0, "The Quotient for M1M2SizeDiff is: " + IntMath.ToString10(Quotient));
                IntMath.Multiply(Quotient, PrimeP);
                M1ForInverse.Add(Quotient);
            }

            M1MinusM2.Copy(M1ForInverse);
            IntMath.Subtract(M1MinusM2, M2ForInverse);
            if (M1MinusM2.IsNegative)
            {
                throw(new Exception("M1MinusM2.IsNegative is true."));
            }

            if (QInv.IsNegative)
            {
                throw(new Exception("QInv.IsNegative is true."));
            }

            HForQInv.Copy(M1MinusM2);
            IntMath.Multiply(HForQInv, QInv);
            if (HForQInv.IsNegative)
            {
                throw(new Exception("HForQInv.IsNegative is true."));
            }

            if (PrimeP.ParamIsGreater(HForQInv))
            {
                IntMath.Divider.Divide(HForQInv, PrimeP, Quotient, Remainder);
                HForQInv.Copy(Remainder);
            }

            //      2.5 Let m = m_2 + hq.
            DecryptedNumber.Copy(HForQInv);
            IntMath.Multiply(DecryptedNumber, PrimeQ);
            DecryptedNumber.Add(M2ForInverse);
            if (!TestDecryptedNumber.IsEqual(DecryptedNumber))
            {
                throw(new Exception("!TestDecryptedNumber.IsEqual( DecryptedNumber )."));
            }

            Worker.ReportProgress(0, " ");
            Worker.ReportProgress(0, "DecryptedNumber: " + IntMath.ToString10(DecryptedNumber));
            Worker.ReportProgress(0, " ");
            Worker.ReportProgress(0, "TestDecryptedNumber: " + IntMath.ToString10(TestDecryptedNumber));
            Worker.ReportProgress(0, " ");
            Worker.ReportProgress(0, "Decrypt with QInv time seconds: " + DecryptTime.GetSecondsToNow().ToString("N2"));
            Worker.ReportProgress(0, " ");
            return(true);
        }