錯誤:javax.crypto.BadPaddingException: Blocktype mismatch html
1.最近作RSA加密用於加強android客戶機與服務器(JavaEE)數據傳輸的安全性。發如今andorid上生成的(密鑰對由服務器在windows下生成並將公鑰發給客戶端保存)密碼沒法在服務器經過私鑰解密。 java
2.爲了測試,在服務器本地加解密正常,另外,在android上加解密也正常,可是在服務器中加密(使用相同公鑰)後的密碼一樣沒法在android系統解密(使用相同私鑰)。 android
3.谷歌一番,才瞭解到多是加密過程當中的填充字符長度不一樣,這跟加解密時指定的RSA算法有關係。 web
4.譬如,在A機中使用標準RSA算法經過公鑰加密,而後在B系統中使用「RSA/ECB/NoPadding」的方式使用私鑰解密,結果能夠解密,可是你會發現解密後的原文前面帶有不少特殊字符,這就是在加密前填充的空字符;若是在B系統中仍然使用標準的RSA算法解密,這在相同類型的JDK虛擬機環境下固然是徹底同樣的,關鍵是android系統使用的虛擬機(dalvik)跟SUN標準JDK是有所區別的,其中他們默認的RSA實現就不一樣。 算法
5.更形象一點,在加密的時候加密的原文「abc」,你直接使用「abc」.getBytes()方法得到的bytes長度可能只有3,可是系統卻先把它放到一個512位的byte數組裏,new byte[512],再進行加密。可是解密的時候你使用的是「加密後的密碼」.getBytes()來解密,解密後的原文天然就是512長度的數據,便是在「abc」以外另外填充了500多字節的其餘空字符。 windows
引用: 數組
Afters some hours of trying, confirming that the key pairs are the same, using different options of saving the public key in the Android filesystem, etc. I finally found a post stating that Android is using the Bouncycastle Security provider. Bouncycastle’s default RSA implementation is: 「RSA/None/NoPadding」, whereas Sun’s default security provider implementation is 「RSA/None/PKCS1Padding」. So, no decryption possible when just using 安全
Cipher.getInstance("RSA")
because of the different paddings used. 服務器
So for a solution I downloaded the bouncycastle Jar, added bounycastle as a Security provider to my Java App, and now use 架構
Cipher.getInstance("RSA", "BC");
It works fine now.
EOF.這位仁兄分析說android系統的RSA實現是「RSA/ECB/NoPadding」,而標準JDK實現是「RSA/None/PKCS1Padding」,這形成了在android機上加密後沒法在服務器上解密的緣由(服務器使用的是SUN JDK6.0)。其餘JDK,如OpenJDK等可能也有不只是虛擬機性能和垃圾回收機制等架構上的區別,一些默認的實現也可能不一樣。
參考:
Struggling with RSA & Bouncycastle on Android、RSA BadPadding Exception
https://forums.oracle.com/forums/thread.jspa?threadID=1526306
Decrypting RSA with Java.security - Hex to dec conversion and byte arrays...