为什么RSAParameters模数不等于P和Q的乘积?

P和Q的值与.Net RSAParameters的模数值不匹配。 根据RSA算法和MSDN文档,它应该是:P * Q =模数

我生成了一个512位RSA密钥对,并通过调用将其导出为XML:

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(512); rsa.ToXmlString(true); 

这给了我以下XML:

  rcLI1XTfmXtX05zq67d1wujnUvevBu8dZ5Q5uBUi2mKndH1FZLYCKrjFaDTB/mXW1l5C74YycVLS6msY2NNJYw== AQAB 

1dwGkK5POlcGCjQ96Se5NSPu/hCm8F5EYwyqRpLVzgk=

0AAEMHBj7CP2XHfCG/RzGldw1GdsW13rTo3uEE9Dtws= PO4jMLV4/TYuElowCW235twGC3zTE0jIUzAYk2LiZ4E= ELJ/o5fSHanBZCjk9zOHbezpDNQEmc0PT64LF1oVmIM= NyCDwTra3LiUin05ZCGkdKLwReFC9L8Zf01ZfYabSfQ= EWwFTPmx7aajULFcEJRNd2R4xSXWY8CX1ynSe7WK0BCH42wf/REOS9l8Oiyjf587BhGa3y8jGKhUD7fXANDxcQ==

现在我成功地编写了一个litte测试程序来加密,解密,签名和validation数据。

最后我添加了一些测试代码:

 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(512); rsa.FromXmlString(key); // key = string with XML above RSAParameters param = rsa.ExportParameters(true); BigInteger p = new BigInteger(param.P); BigInteger q = new BigInteger(param.Q); BigInteger n = new BigInteger(param.Modulus); BigInteger myN = BigInteger.Multiply(p, q); Console.WriteLine("n = " + n.ToString()); Console.WriteLine("myN = " + myN.ToString()); 

这给了我们以下输出:

 n = 5200154866521200075264779234483365112866265806746380532891861717388028374942014660490111623133775661411009378522295439774347383363048751390839618325234349 myN = 23508802329434377088477386089844302414021121047189424894399694701810500376591071843028984420422297770783276119852460021668188142735325512873796040092944 

为什么乘以P和Q不等于模数?

我已经检查了很多东西,比如endian,encoding,BigInteger类,成功加密,解密,签名,用上面的XML密钥validation但是找不到任何解释为什么P和Q乘以不等于模数…

任何人都可以帮我解释为什么P * Q不是模数?

所有可读格式的值:

 Modulus = 5200154866521200075264779234483365112866265806746380532891861717388028374942014660490111623133775661411009378522295439774347383363048751390839618325234349 Exponent = 65537 P = 4436260148159638728185416185189716006279182659244174640493183003717504785621 Q = 5299238895894527538601438806093945941831432623367272568173893997325464109264 DP = -57260184070162652127728137041376572684067529466727954512100856352006444159428 DQ = -56270397953566513533764063103154348713259844205844432469862161942601135050224 InverseQ = -5297700950752995201824767053303055736360972826004414985336436365496709603273 D = 5967761894604968266284398550464653556930604493620355473531132912985865955601309375321441883258487907574824598936524238049397825498463180877735939967118353 

更新

根据答案,我为.Net BigInteger类编写了一个小扩展方法,以便与RSAParameters一起正常工作:

 public static class BigIntegerExtension { public static BigInteger FromBase64(this BigInteger i, string base64) { byte[] p = Convert.FromBase64String(base64).Reverse().ToArray(); if (p[p.Length - 1] > 127) { Array.Resize(ref p, p.Length + 1); p[p.Length - 1] = 0; } return new BigInteger(p); } public static BigInteger FromBigEndian(this BigInteger i, byte[] p) { p = p.Reverse().ToArray(); if (p[p.Length - 1] > 127) { Array.Resize(ref p, p.Length + 1); p[p.Length - 1] = 0; } return new BigInteger(p); } } 

用法示例:

 BigInteger modulus1 = new BigInteger().FromBase64("rcLI1XTfmXtX05zq67d1wujnUvevBu8dZ5Q5uBUi2mKndH1FZLYCKrjFaDTB/mXW1l5C74YycVLS6msY2NNJYw=="); BigInteger modulus2 = new BigInteger().FromBigEndian(param.Modulus); 

希望这可以帮助其他人解决同样的问题:-)

这是我对您提供的XML参数的解析:

 N = 9100595563660672087698322262735024483609782000266155222822537546670463733453350686171384417480667378838400923087358115007100900745853538273602044437940579 P = 96731388413554317303099785843734797692955743043844132225634400270674214374921 Q = 94081101418218318334927154927633016498744568046568114230258529096538660255499 

你可以validation,N确实等于P * Q.

你不能按照你的方式使用BigInteger(byte [])构造函数,因为它期望字节数组是小端的,并且因为微软已经做了低估的事情。 而是颠倒字节的顺序。 最后,因为字节数组应该是二进制补码并且数字保证为正数,所以如果高位字节大于或等于128,则必须向数组的高位字节添加零字节。 。

BigInteger将数组解析为带符号的little-endian值。 RSAParameters使用无符号的big-endian。

所以i = new BigInteger(bytes.Reverse().Concat(new byte[]{0}).ToArray()))应该可行。