C#與Java的RSA(3)

原創文章,轉載請註明出處 http://boytnt.blog.51cto.com/966121/1351207c#


在上一篇文章裏,咱們已經成功的解析出了公鑰加密相當重要的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。



好,至此問題算是告一段落了,實測經過。之後想起來什麼再繼續補充吧。

我沒有提供完整解決方案的代碼,只給出了部分代碼片段,但願對此問題有興趣的同窗把重點放在理解過程上,而不是僅僅搬代碼。

相關文章
相關標籤/搜索