背景:接口方開發環境是Java,要求我使用私鑰對數據進行加密,他使用公鑰進行解密。
開發時遇到的問題:
1).Net平臺默認是使用公鑰進行加密,私鑰進行解密。私鑰加密需要自己實現或者使用第三方dll。
2)雙方平臺不一致,出現了我加密的數據對方不能解密,對方加密的數據我不能解密,但是自身是可以正常加密解密。
解決辦法:
1)使用第三方dll,此處使用的是C#的BouncyCastle.Crypto進行加密及解密。在官網http://www.bouncycastle.org/csharp/ 下載最新dll。
2)設置Cipher爲“RSA/ECB/PKCS1Padding”,與Java平臺統一。
這是實現的方法,方法後面是解決過程,有興趣可以看一看。如果這個代碼不能解決你的問題,建議看下後面的解決過程,裏面的鏈接也許對你有幫助。
/// <summary>用私鑰給數據進行RSA加密
///
/// </summary>
/// <param name="xmlPrivateKey">私鑰</param>
/// <param name="m_strEncryptString">待加密數據</param>
/// <returns>加密後的數據(Base64)</returns>
public static string RSAEncryptByPrivateKey(string xmlPrivateKey, string strEncryptString)
{
//加載私鑰
RSACryptoServiceProvider privateRsa = new RSACryptoServiceProvider();
privateRsa.FromXmlString(xmlPrivateKey);
//轉換密鑰
AsymmetricCipherKeyPair keyPair = DotNetUtilities.GetKeyPair(privateRsa);
IBufferedCipher c = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");// 參數與Java中加密解密的參數一致
//第一個參數爲true表示加密,爲false表示解密;第二個參數表示密鑰
c.Init(true, keyPair.Private);
byte[] DataToEncrypt = Encoding.UTF8.GetBytes(strEncryptString);
byte[] outBytes = c.DoFinal(DataToEncrypt);//加密
string strBase64 = Convert.ToBase64String(outBytes);
return strBase64;
}
-------------------------------------解決過程-------------------------------------
1.確認是使用私鑰進行加密後,發現.Net沒有使用私鑰進行加密的方法。搜索後得知需要自己實現。
2.搜索實現方式,但得到的方法裏需要兩個BigInteger,由於對私鑰的xml並不瞭解,不清楚參數該用什麼值。只好放棄這種方式。不過後來查資料找到私鑰xml中各節點的含義以及加密時該用哪些節點的值。不過這是後話了。
微軟對公鑰私鑰各節點的解釋:RSAParameters 結構 https://msdn.microsoft.com/zh-cn/library/system.security.cryptography.rsaparameters%28v=vs.110%29.aspx
加密解密時該使用什麼節點:http://blog.csdn.net/a351945755/article/details/21965533
3.找到一個已經封裝好的方法,只需要把密鑰和加密數據傳進去就可以實現的方法。但是加密出來的結果本身可以解密,但是對方無法解密。對方提供的加密數據使用此方法無法解密。
此處使用的代碼:http://www.codeproject.com/Articles/38739/RSA-Private-Key-Encryption
4.在前兩步搜索資料的時候,得知BouncyCastle。看到相關介紹,於是使用其提供的dll進行加密解密操作。但是此時網上找到的都是BouncyCastle自動生成密鑰進行加密解密而不是讀取.Net的密鑰進行加密解密。
使用BouncyCastle進行加密解密的代碼是:http://blog.csdn.net/popozhu/article/details/5789382
5.查找密鑰轉換方式,找到以下資料:http://stackoverflow.com/questions/3240222/get-private-key-from-bouncycastle-x509-certificate-c-sharp
使用“CriGoT”或者“majkinetor”提供的代碼都可以進行私鑰的轉換。
6.通過第四步和第五步可以獲得完整的加密解密方法。在使用此方法進行私鑰加密後對方解密時報錯“javax.crypto.BadPaddingException: Blocktype mismatch: 0”,查找資料後得知,也許與Cipher.getInstance("RSA")中的參數有關,需要改爲“RSA/ECB/PKCS1Padding”。但對方排查後應當默認就是“RSA/ECB/PKCS1Padding”。最終在 http://www.xuebuyuan.com/301023.html 找到另一種調用的方法可以傳入“RSA/ECB/PKCS1Padding”。
至此.Net和Java之間RSA私鑰加密公鑰解密進行數據交互完成。