錯誤:javax.crypto.BadPaddingException:Blocktypemismatch
1.最近做RSA加密用於增強android客戶機與伺服器(JavaEE)資料傳輸的安全性。發現在andorid機器上生成的(金鑰對由伺服器在windowsxp下生成並將公鑰發給客戶端儲存)密碼無法在伺服器透過私鑰解密。
2.為了測試,在伺服器本地加解密正常,另外,在android上加解密也正常,但是在伺服器中加密(使用相同公鑰)後的密碼同樣無法在android系統解密(使用相同私鑰)。
3.由於對RSA加密演算法不瞭解,而且對JavaRSA的加密過程也不清楚、谷歌一番,才瞭解到可能是加密過程中的填充字元長度不同,這跟加解密時指定的RSA演算法有關係。
4.比如,在A機中使用標準RSA透過公鑰加密,然後在B系統中使用“RSA/ECB/NoPadding”使用私鑰解密,結果可以解密,但是你會發現解密後的原文前面帶有很多特殊字元,這就是在加密前填充的空字元;如果在B系統中仍然使用標準的RSA演算法解密,這在相同型別的JDK虛擬機器環境下當然是完全一樣的,關鍵是android系統使用的虛擬機器(dalvik)跟SUN標準JDK是有所區別的,其中他們預設的RSA實現就不同。
5.更形象一點,在加密的時候加密的原文“abc”,你直接使用“abc”.getBytes()方法獲得的bytes長度可能只有3,但是系統卻先把它放到一個512位的byte數組裡,newbyte[512],再進行加密。但是解密的時候你使用的是“加密後的密碼”.getBytes()來解密,解密後的原文自然就是512長度的資料,即是在“abc”之外另外填充了500多位元組的其他空字元。 引用: Afterssomehoursoftrying,confirmingthatthekeypairsarethesame,usingdifferentoptionsofsavingthepublickeyintheAndroidfilesystem,etc.IfinallyfoundapoststatingthatAndroidisusingtheBouncycastleSecurityprovider.Bouncycastle’sdefaultRSAimplementationis:“RSA/None/NoPadding”,whereasSun’sdefaultsecurityproviderimplementationis“RSA/None/PKCS1Padding”.So,nodecryptionpossiblewhenjustusing Cipher.getInstance("RSA") becauseofthedifferentpaddingsused. SoforasolutionIdownloadedthebouncycastleJar,addedbounycastleasaSecurityprovidertomyJavaApp,andnowuse Cipher.getInstance("RSA","BC"); Itworksfinenow. EOF.這位仁兄分析說android系統的RSA實現是"RSA/None/NoPadding",而標準JDK實現是"RSA/None/PKCS1Padding",這造成了在android機上加密後無法在伺服器上解密的原因(伺服器使用的是SUNJDK6.0)。 我自己的總結:其實只要載入bouncycastleJar到PC服務端和android客戶端即可。 另外 KeyPairGeneratorkeyPairGen=KeyPairGenerator.getInstance("RSA", neworg.bouncycastle.jce.provider.BouncyCastleProvider()); 所有getInstantce方法裡必須寫成如上形式才可。
錯誤:javax.crypto.BadPaddingException:Blocktypemismatch
1.最近做RSA加密用於增強android客戶機與伺服器(JavaEE)資料傳輸的安全性。發現在andorid機器上生成的(金鑰對由伺服器在windowsxp下生成並將公鑰發給客戶端儲存)密碼無法在伺服器透過私鑰解密。
2.為了測試,在伺服器本地加解密正常,另外,在android上加解密也正常,但是在伺服器中加密(使用相同公鑰)後的密碼同樣無法在android系統解密(使用相同私鑰)。
3.由於對RSA加密演算法不瞭解,而且對JavaRSA的加密過程也不清楚、谷歌一番,才瞭解到可能是加密過程中的填充字元長度不同,這跟加解密時指定的RSA演算法有關係。
4.比如,在A機中使用標準RSA透過公鑰加密,然後在B系統中使用“RSA/ECB/NoPadding”使用私鑰解密,結果可以解密,但是你會發現解密後的原文前面帶有很多特殊字元,這就是在加密前填充的空字元;如果在B系統中仍然使用標準的RSA演算法解密,這在相同型別的JDK虛擬機器環境下當然是完全一樣的,關鍵是android系統使用的虛擬機器(dalvik)跟SUN標準JDK是有所區別的,其中他們預設的RSA實現就不同。
5.更形象一點,在加密的時候加密的原文“abc”,你直接使用“abc”.getBytes()方法獲得的bytes長度可能只有3,但是系統卻先把它放到一個512位的byte數組裡,newbyte[512],再進行加密。但是解密的時候你使用的是“加密後的密碼”.getBytes()來解密,解密後的原文自然就是512長度的資料,即是在“abc”之外另外填充了500多位元組的其他空字元。 引用: Afterssomehoursoftrying,confirmingthatthekeypairsarethesame,usingdifferentoptionsofsavingthepublickeyintheAndroidfilesystem,etc.IfinallyfoundapoststatingthatAndroidisusingtheBouncycastleSecurityprovider.Bouncycastle’sdefaultRSAimplementationis:“RSA/None/NoPadding”,whereasSun’sdefaultsecurityproviderimplementationis“RSA/None/PKCS1Padding”.So,nodecryptionpossiblewhenjustusing Cipher.getInstance("RSA") becauseofthedifferentpaddingsused. SoforasolutionIdownloadedthebouncycastleJar,addedbounycastleasaSecurityprovidertomyJavaApp,andnowuse Cipher.getInstance("RSA","BC"); Itworksfinenow. EOF.這位仁兄分析說android系統的RSA實現是"RSA/None/NoPadding",而標準JDK實現是"RSA/None/PKCS1Padding",這造成了在android機上加密後無法在伺服器上解密的原因(伺服器使用的是SUNJDK6.0)。 我自己的總結:其實只要載入bouncycastleJar到PC服務端和android客戶端即可。 另外 KeyPairGeneratorkeyPairGen=KeyPairGenerator.getInstance("RSA", neworg.bouncycastle.jce.provider.BouncyCastleProvider()); 所有getInstantce方法裡必須寫成如上形式才可。