C#與Java的RSA(3)
原創文章,轉載請註明出處 http://boytnt.blog.51cto.com/966121/1351207。
在上一篇文章裡,我們已經成功的解析出了公鑰加密至關重要的modulus和publicExponent,勝利在望,心急的同學肯定要開始這麼寫了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/*********** 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)。
怎麼辦? 自己實現標準RSA加密吧。modulus和publicExponent都有了,再加上密碼,都轉化成大整數,做一個ModPow操作,就得到結果密文了。正好.NetFramework從4.0起在System.Numerics名稱空間下直接提供BigInterger類了,上手試試:
1
2
3
4
5
6
7
8
9
10
11
12
|
/*********** 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!!! 還是不行,為什麼?
是位元組序在搗亂,我們上面分析ASN.1結構時得到的所有資料都是大位元組序的,而System.Numerics.BigInteger是小位元組序的,需要轉化之後才能使用。這點很煩人,要轉來轉去的。
1
2
3
4
5
6
7
8
9
10
11
12
|
/*********** 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了。
問題完美解決了嗎? 很遺憾,沒有,因為System.Numerics.BigInteger是4.0以上版本才提供的,低於此版本的只好去使用第三方的實現,比如這個:http://www.codeproject.com/Articles/2728/Csharp-BigInteger-Class,但要注意以下2點:
1、它預設只支援560bit,程式碼最開頭有寫:private const int maxLength = 70;
把maxLength改成256才能支援2048位的RSA運算了。
2、它是大位元組序的,在使用時不用反轉modulus和publicExponent對應的byte[]。
3、我們得到的modulus是257個位元組,需要去掉首位元組的0,用剩下的256個位元組例項化BigInteger。
好,至此問題算是告一段落了,實測通過。以後想起來什麼再繼續補充吧。
我沒有提供完整解決方案的程式碼,只給出了部分程式碼片斷,希望對此問題有興趣的同學把重點放在理解過程上,而不是僅僅搬程式碼。
本文轉自 BoyTNT 51CTO部落格,原文連結:http://blog.51cto.com/boytnt/1351207,如需轉載請自行聯絡原作者
相關文章
- JAVA/PHP/C#版RSA驗籤JavaPHPC#
- 10:c# mds5與des與rsa加密C#加密
- C#和JAVA的RSA金鑰、公鑰轉換C#Java
- C# RSA 加密C#加密
- C#通過java生成的RSA公鑰加密和解密C#Java加密解密
- java/php/c#版rsa簽名以及java驗籤實現JavaPHPC#
- C# RSA 分段加解密C#解密
- java RSA 解密Java解密
- c#與java的區別C#Java
- security.js RSA加密與java客戶端解密JS加密Java客戶端解密
- RSA加密與解密加密解密
- 一篇搞定RSA加密與SHA簽名|與Java完全同步加密Java
- Java RSA 分段加解密Java解密
- java與c#間徘徊JavaC#
- C# 與 Java 的不同點總結C#Java
- Java之RSA加解密解析Java解密
- java RSA公私鑰與其base64編碼之間的轉換Java
- .NET和java的RSA互通,僅此而已Java
- python中rsa的RSAPython
- java字串“==”與“equals”的差異及與c#的區別Java字串C#
- JAVA和C# 3DES加密解密JavaC#3D加密解密
- RSA演算法原理——(3)RSA加解密過程及公式論證演算法解密公式
- Android、Java RSA加密踩坑記AndroidJava加密
- Porting .Net RSA xml keys to JavaXMLJava
- 10 建立SSL與RSA證書與金鑰
- 【轉載】C#之int與Java之Integer的區別C#Java
- Java實現AES和RSA演算法Java演算法
- java程式設計之:生成rsa金鑰Java程式設計
- 微信支付 V3 RSA 加簽踩坑
- RSA的傻瓜原理
- RSA演算法與Python實現演算法Python
- Pycrypto與RSA密碼技術筆記密碼筆記
- 前後端java+vue 實現rsa 加解密與摘要簽名演算法後端JavaVue解密演算法
- “不給力啊,老溼!”:RSA加密與破解加密
- RSA加密遇到的坑加密
- Java RSA (SHA1withRSA)簽名和驗籤Java
- java使用RSA加密方式,實現數字簽名Java加密
- RSA加密解密及數字簽名Java實現加密解密Java