原創文章,轉載請註明出處 http://boytnt.blog.51cto.com/966121/1351207。c#
在上一篇文章裏,咱們已經成功的解析出了公鑰加密相當重要的modulus和publicExponent,勝利在望,心急的同窗確定要開始這麼寫了:安全
/*********** C#代碼 ***********/ //設定RSA參數,用於指定modulus和exponent var parameter = new RSAParameters(); parameter.Modulus = modulusBytes; //modulusBytes是轉化後的byte[] parameter.Exponent = exponentBytes; //加密 var rsa = RSACryptoServiceProvider.Create("RSA"); rsa.ImportParameters(parameter); byte[] result = rsa.EncryptValue(Encoding.UTF8.GetBytes("PASSWORD")); //把密文轉化爲HEX形式 string resultHex = BitConverter.ToString(result).Replace("-", "");
對不起要無情的打擊你了,這麼作行不通,由於C#的RSA加密不是標準RSA,爲了增強安全性,它強制使用了PKCS1填充(或OAEP填充),致使密文在Java端解密失敗,由於Java端用的是無填充模式(RSA/ECB/NoPadding)。ide
怎麼辦? 本身實現標準RSA加密吧。modulus和publicExponent都有了,再加上密碼,都轉化成大整數,作一個ModPow操做,就獲得結果密文了。正好.NetFramework從4.0起在System.Numerics命名空間下直接提供BigInterger類了,上手試試:加密
/*********** C#代碼 ***********/ //把3個變量轉化爲System.Numerics.BigInteger var modulus = new BigInteger(modulusBytes); var exponent = new BigInteger(exponentBytes); var data = new BigInteger(Encoding.UTF8.GetBytes("PASSWORD")); //作ModPow運算獲得密文,也是BigInteger var result = BigInteger.ModPow(data, exponent, modulus); //把密文BigInteger對應的byte[]轉化爲HEX形式 string resultHex = BitConverter.ToString(result.ToByteArray()).Replace("-", "");
OH MY GOD!!! 仍是不行,爲何?spa
是字節序在搗亂,咱們上面分析ASN.1結構時獲得的全部數據都是大字節序的,而System.Numerics.BigInteger是小字節序的,須要轉化以後才能使用。這點很煩人,要轉來轉去的。code
/*********** C#代碼 ***********/ //把3個變量轉化爲System.Numerics.BigInteger var modulus = new BigInteger(modulusBytes.Reverse().ToArray()); var exponent = new BigInteger(exponentBytes.Reverse().ToArray()); var data = new BigInteger(Encoding.UTF8.GetBytes("PASSWORD").Reverse().ToArray()); //作ModPow運算獲得密文,也是BigInteger var result = BigInteger.ModPow(d, e, m); //把密文BigInteger對應的byte[]轉化爲HEX形式 string resultHex = BitConverter.ToString(result.ToByteArray().Reverse().ToArray()).Replace("-", "");
再試一下,這下終於OK了。blog
問題完美解決了嗎? 很遺憾,沒有,由於System.Numerics.BigInteger是4.0以上版本才提供的,低於此版本的只好去使用第三方的實現,好比這個:http://www.codeproject.com/Articles/2728/Csharp-BigInteger-Class,但要注意如下2點:get
一、它默認只支持560bit,代碼最開頭有寫:private const int maxLength = 70;string
把maxLength改爲256才能支持2048位的RSA運算了。
it
二、它是大字節序的,在使用時不用反轉modulus和publicExponent對應的byte[]。
三、咱們獲得的modulus是257個字節,須要去掉首字節的0,用剩下的256個字節實例化BigInteger。
好,至此問題算是告一段落了,實測經過。之後想起來什麼再繼續補充吧。
我沒有提供完整解決方案的代碼,只給出了部分代碼片段,但願對此問題有興趣的同窗把重點放在理解過程上,而不是僅僅搬代碼。