How to calculate D for RSA encryption from P,Q and E

我们两清 提交于 2019-11-28 11:34:03
CodesInChaos

First you need to verify that GCD(e, φ) = 1 because d only exists if that property holds. Then calculate the modular multiplicative inverse of e modulo phi which I describe in my answer to "1/BigInteger in C#".

Your code seems to assume that e^(φ(n)-1) mod φ(n) is that inverse, but that's incorrect. I think the correct formula would be e^(φ(φ(n))-1) mod φ(n), but that's inconvenient to use since you only know φ(n) but not φ(φ(n)).

I recommend using the Extended Euclidean algorithm by porting the wikipedia pseudocode to C#.


As a side-note: There are often multiple equivalent values for d since you don't need e*d mod φ(n)=1 but just e*d mod λ(n)=1 where λ is the Carmichael function see "Why RSA encryption key is based on modulo(phi(n)) rather than modulo n" on crypto.SE

Extended Euclidean algorithm can be used to compute the modular inverse, use this link: http://www.di-mgt.com.au/euclidean.html#extendedeuclidean to get the detail, I tested the source code in C# as below, and the result is matching,

public static BigInteger modinv(BigInteger u, BigInteger v)
{
   BigInteger inv, u1, u3, v1, v3, t1, t3, q;
   BigInteger iter;
   /* Step X1. Initialise */
   u1 = 1;
   u3 = u;
   v1 = 0;
   v3 = v;
   /* Remember odd/even iterations */
   iter = 1;
   /* Step X2. Loop while v3 != 0 */
   while (v3 != 0)
   {
       /* Step X3. Divide and "Subtract" */
       q = u3 / v3;
       t3 = u3 % v3;
       t1 = u1 + q * v1;
       /* Swap */
       u1 = v1; v1 = t1; u3 = v3; v3 = t3;
       iter = -iter;
   }
   /* Make sure u3 = gcd(u,v) == 1 */
   if (u3 != 1)
       return 0;   /* Error: No inverse exists */
       /* Ensure a positive result */
       if (iter < 0)
           inv = v - u1;
       else
           inv = u1;
       return inv;
}

D Can be calculated by:

    var qq = BigInteger.Multiply(totient, n);
    var qw = BigInteger.Multiply(totient, qq);
    BigInteger d = BigInteger.ModPow(e, (qw - 1), totient);
 Console.Write("Testing Encrypt/Decrypt using BigInteger ");
        string message2 = "Testing Some Data to Encrypt";
        byte[] buffer2 = Encoding.ASCII.GetBytes(message2);
        BigInteger m = new BigInteger(buffer2);
        BigInteger c = BigInteger.ModPow(m, E, M); //encrypt
        BigInteger m2 = BigInteger.ModPow(c, D, M); //decrypt, m2 also equals m
        byte[] decoded2 = m2.ToByteArray();

        if (decoded2[0] == 0) 
        {
            decoded2 = decoded2.Where(b => b != 0).ToArray();
        }
        string message3 = ASCIIEncoding.ASCII.GetString(decoded2);

        if (message2 == message3)
        {
            Console.WriteLine("Ok :)");
        }
        else
        {
            Console.WriteLine("Bad Encryption :(");
            Console.ReadKey();
            return;
        }

I tried it with your parametrs and it works, so E, D and M must be valid.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!