How to calculate D for RSA encryption from P,Q and E
我正在尝试使用
根据此答案和此答案以及使用以下方法对此问题进行更新,我应该得到
为了对此进行测试,我生成了密钥对,并尝试从现有组件中计算出组件,并将结果与??原始组件进行比较。除
如果有人能告诉我我做错了,那就太好了。
测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | using System; using System.Numerics; using System.Security.Cryptography; using System.Text; class Program { static RSAParameters key = new RSAParameters() { P = new byte[]{ 0xDE, 0xA6, 0x35, 0x0B, 0x0A, 0xA5, 0xD7, 0xA0, 0x5C, 0x49, 0xEA, 0xD1, 0x3F, 0xA6, 0xF5, 0x12, 0x19, 0x06, 0x25, 0x8A, 0xD9, 0xA7, 0x07, 0xE7, 0x0D, 0x8A, 0x7C, 0xB1, 0xD4, 0x81, 0x64, 0xFD, 0x04, 0xEC, 0x47, 0x33, 0x42, 0x0B, 0x22, 0xF2, 0x60, 0xBB, 0x75, 0x62, 0x53, 0x3E, 0x1A, 0x97, 0x9D, 0xEF, 0x25, 0xA7, 0xE5, 0x24, 0x3A, 0x30, 0x36, 0xA5, 0xF9, 0x8A, 0xF5, 0xFF, 0x1D, 0x1B }, Q = new byte[]{ 0xBE, 0xB9, 0x60, 0x12, 0x05, 0xB1, 0x61, 0xD9, 0x22, 0xD8, 0x84, 0x6E, 0x9A, 0x7B, 0xD1, 0x9B, 0x17, 0xA5, 0xDD, 0x02, 0x5E, 0x9D, 0xD8, 0x24, 0x06, 0x1B, 0xF3, 0xD8, 0x2F, 0x79, 0xFE, 0x78, 0x74, 0x3D, 0xC4, 0xE6, 0x17, 0xD2, 0xB7, 0x68, 0x78, 0x6F, 0x53, 0xE0, 0x38, 0x00, 0x86, 0xFB, 0x20, 0x2A, 0x1B, 0xBD, 0x91, 0x76, 0x3E, 0x33, 0x85, 0x9A, 0x31, 0xE6, 0x88, 0x60, 0x91, 0x81 }, DP = new byte[]{ 0xAC, 0x28, 0x92, 0x6D, 0x46, 0x3F, 0x74, 0x1A, 0xA0, 0x21, 0xDB, 0xBB, 0x0E, 0xDF, 0xD7, 0x31, 0xB6, 0x3D, 0xC5, 0x7B, 0xB6, 0xCE, 0x6B, 0xD2, 0xE1, 0xEA, 0x8A, 0x7E, 0xAA, 0xD5, 0x9E, 0xB3, 0xF2, 0x41, 0x8C, 0xD0, 0x7A, 0xA9, 0xC7, 0xCC, 0xE8, 0xB5, 0x2A, 0x8F, 0xEB, 0xD3, 0xE2, 0x96, 0x07, 0xDD, 0xEA, 0x1D, 0x07, 0x96, 0x5A, 0x93, 0xFB, 0x3D, 0x9D, 0x56, 0x30, 0xDE, 0xA1, 0xAF }, DQ = new byte[]{ 0xA6, 0x9C, 0x44, 0x1B, 0x9A, 0x53, 0x89, 0xD9, 0xE8, 0xC1, 0xE2, 0x76, 0xC8, 0x87, 0x6F, 0xE5, 0x1F, 0x74, 0x6A, 0xAC, 0x5E, 0x41, 0x5F, 0x86, 0xA0, 0xBB, 0x9C, 0x79, 0xF7, 0x87, 0x87, 0xD0, 0x6C, 0x23, 0x65, 0xB5, 0x67, 0x8C, 0x51, 0x62, 0x77, 0x0B, 0x31, 0xE7, 0x86, 0xA4, 0x97, 0x46, 0x1B, 0xA4, 0x0D, 0x55, 0xBE, 0x13, 0xE0, 0x64, 0x9B, 0xCA, 0xC6, 0xDA, 0xCF, 0xBA, 0x24, 0x81 }, InverseQ = new byte[]{ 0x02, 0x42, 0x90, 0xAE, 0xFF, 0xFE, 0xB6, 0xCB, 0x53, 0xFF, 0x96, 0x17, 0xC6, 0xE4, 0x3F, 0xE6, 0xC7, 0xBC, 0xB2, 0xEB, 0x53, 0xA9, 0x47, 0xEE, 0x10, 0x36, 0x98, 0xEF, 0xA8, 0x3E, 0x9C, 0xF7, 0xF9, 0xCF, 0x24, 0xE5, 0xD7, 0x9A, 0xAF, 0x09, 0xCF, 0x28, 0xAA, 0x5D, 0x2A, 0xB7, 0x27, 0x73, 0x47, 0x2D, 0x54, 0x54, 0x61, 0xC5, 0xCE, 0x3E, 0xA4, 0x91, 0xF6, 0x9D, 0xF4, 0x65, 0x08, 0xDD }, Exponent = new byte[]{ 0x00, 0x01, 0x00, 0x01, }, Modulus = new byte[]{ 0xA5, 0xE0, 0x95, 0x08, 0x87, 0x69, 0x2B, 0xB4, 0x7F, 0x08, 0xFB, 0x4F, 0x66, 0x85, 0xD9, 0x95, 0x53, 0x0F, 0x7C, 0x99, 0x95, 0x16, 0xF4, 0x0D, 0xAD, 0x9E, 0x31, 0xD8, 0x20, 0xF4, 0x88, 0x63, 0xAE, 0x51, 0x04, 0xC2, 0xE9, 0x92, 0x3C, 0x1C, 0x90, 0xF8, 0xF4, 0x38, 0x6A, 0x86, 0xFD, 0x8F, 0xDE, 0x85, 0x22, 0xDD, 0xE8, 0x7E, 0x8D, 0xF2, 0xC5, 0xC9, 0x4E, 0x71, 0x2B, 0x56, 0x25, 0x1A, 0xEA, 0x66, 0x15, 0x19, 0x63, 0x70, 0x53, 0x79, 0xDF, 0x38, 0x49, 0x30, 0x74, 0x45, 0xBE, 0xA3, 0x28, 0x0D, 0x0E, 0x7A, 0x7D, 0xB6, 0x8B, 0xCA, 0x09, 0x56, 0x21, 0xE7, 0x98, 0x3E, 0x4B, 0x8B, 0xD0, 0x31, 0x27, 0x8E, 0x6F, 0x10, 0xA6, 0x6C, 0x1C, 0x48, 0xB5, 0x5E, 0x89, 0x7B, 0x74, 0x74, 0xB2, 0x57, 0x72, 0x6D, 0x18, 0xEB, 0xF3, 0xF5, 0x53, 0xCA, 0x8C, 0xBE, 0xB7, 0x29, 0xF5, 0x9B }, D = new byte[]{ 0x9F, 0x86, 0xE1, 0x4D, 0x96, 0x8C, 0xFA, 0xCF, 0x57, 0xED, 0x17, 0x64, 0x41, 0x41, 0x31, 0x04, 0x7F, 0x21, 0x41, 0xBF, 0xA2, 0xB6, 0xB4, 0x78, 0x03, 0x25, 0x44, 0xE2, 0x8A, 0xAF, 0x22, 0x0C, 0x5B, 0xB4, 0xE7, 0x53, 0x5C, 0xB6, 0x9A, 0xC1, 0x0E, 0x5B, 0x9E, 0xE4, 0x32, 0xEF, 0x28, 0x24, 0x98, 0xE8, 0x89, 0xA3, 0xC8, 0xD9, 0x0D, 0x43, 0x12, 0x1C, 0x8C, 0x28, 0x22, 0x79, 0x72, 0xAC, 0x66, 0x7B, 0x7D, 0xD2, 0xF9, 0x48, 0x06, 0xCD, 0x9D, 0x9A, 0xE6, 0x42, 0x92, 0xBA, 0x56, 0xA6, 0x63, 0x07, 0x1E, 0x25, 0x4E, 0xC8, 0x07, 0x58, 0x5B, 0x88, 0x60, 0x97, 0x92, 0xE2, 0xD5, 0xB9, 0xC6, 0x70, 0xBB, 0x63, 0x5A, 0xC3, 0xC3, 0xA6, 0x46, 0x5A, 0x1C, 0x9C, 0xBF, 0x61, 0x57, 0x9E, 0x9E, 0xFA, 0xC0, 0xC4, 0x8A, 0xC2, 0xBA, 0x88, 0x46, 0xA9, 0x7A, 0xF2, 0x7D, 0x4F, 0x6C, 0x01 } }; public static BigInteger FromBigEndian(byte[] p) { Array.Reverse(p); if (p[p.Length - 1] > 127) { Array.Resize(ref p, p.Length + 1); p[p.Length - 1] = 0; } return new BigInteger(p); } static void Main(string[] args) { using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider() { PersistKeyInCsp = false }) { rsa.ImportParameters(key); Console.Write("Testing Encrypt/Decrypt ..."); string message ="Testing Some Data to Encrypt"; byte[] buffer = Encoding.ASCII.GetBytes(message); byte[] encoded = rsa.Encrypt(buffer, true); byte[] decoded = rsa.Decrypt(encoded, true); string message1 = ASCIIEncoding.ASCII.GetString(decoded); if (message == message1) { Console.WriteLine("Ok :)"); } else { Console.WriteLine("Bad Encryption :("); Console.ReadKey(); return; } } //Convert Key to BigIntegers BigInteger P = FromBigEndian(key.P); BigInteger Q = FromBigEndian(key.Q); BigInteger DP = FromBigEndian(key.DP); BigInteger DQ = FromBigEndian(key.DQ); BigInteger InverseQ = FromBigEndian(key.InverseQ); BigInteger E = FromBigEndian(key.Exponent); BigInteger M = FromBigEndian(key.Modulus); BigInteger D = FromBigEndian(key.D); Console.WriteLine("Testing Numbers ..."); BigInteger M1 = BigInteger.Multiply(P, Q); // M = P*Q if (M1.CompareTo(M) == 0) { Console.WriteLine(" M Ok :)"); } else { Console.WriteLine(" Bad M:("); Console.ReadKey(); return; } BigInteger PMinus1 = BigInteger.Subtract(P, BigInteger.One); // M = P*Q BigInteger DP1 = BigInteger.Remainder(D, PMinus1); // M = P*Q if (DP1.CompareTo(DP) == 0) { Console.WriteLine(" DP Ok :)"); } else { Console.WriteLine(" Bad DP :("); Console.ReadKey(); return; } BigInteger QMinus1 = BigInteger.Subtract(Q, BigInteger.One); // M = P*Q BigInteger DQ1 = BigInteger.Remainder(D, QMinus1); // M = P*Q if (DQ1.CompareTo(DQ) == 0) { Console.WriteLine(" DQ Ok :)"); } else { Console.WriteLine(" Bad DQ :("); Console.ReadKey(); return; } BigInteger Phi = BigInteger.Multiply(PMinus1, QMinus1); BigInteger PhiMinus1 = BigInteger.Subtract(Phi, BigInteger.One); BigInteger D1 = BigInteger.ModPow(E, PhiMinus1, Phi); if (D1.CompareTo(D) == 0) { Console.WriteLine(" D Ok :)"); } else { Console.WriteLine(" Bad D :("); Console.ReadKey(); return; } Console.ReadKey(); } } |
测试结果
1 2 3 4 5 6 | Testing Encrypt/Decrypt ... Ok :) Testing Numbers ... M Ok :) DP Ok :) DQ Ok :) Bad D :( |
首先,您需要验证
您的代码似乎假设
我建议通过将Wikipedia伪代码移植到C#来使用扩展欧几里得算法。
作为旁注:
上的模n "
扩展的欧几里得算法可用于计算模逆,请使用以下链接:http://www.di-mgt.com.au/euclidean.html#extendedeuclidean以获得详细信息,
我在C#中测试了源代码,如下所示,结果匹配,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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; } |
我用您的参数进行了尝试,它可以正常工作,因此E,D和M必须有效。
D可以通过以下方式计算:
1 2 3 | var qq = BigInteger.Multiply(totient, n); var qw = BigInteger.Multiply(totient, qq); BigInteger d = BigInteger.ModPow(e, (qw - 1), totient); |