出現這個問題的原因是:java自帶的是PKCS5Padding填充,不支持PKCS7Padding填充
參考:https://stackoverflow.com/questions/20770072/aes-cbc-pkcs5padding-vs-aes-cbc-pkcs7padding-with-256-key-size-performance-java
https://crypto.stackexchange.com/questions/9043/what-is-the-difference-between-pkcs5-padding-and-pkcs7-padding
需要注意的是AES/CBC/PKCS5Padding 這個參數
AES/CBC/PKCS7Padding 如果是7就不可以,部署在centos7 jdk8 的環境下就會報錯“Cannot find any provider supporting AES/ECB/PKCS7Padding”
下面是我微信小程序解密代碼:
import org.apache.commons.codec.binary.Base64; import org.bouncycastle.jce.provider.BouncyCastleProvider; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.io.UnsupportedEncodingException; import java.security.*; import java.security.spec.InvalidParameterSpecException; /** * java對稱解密的方法 */ public class AesUtil { static { //BouncyCastle是一個開源的加解密解決方案,主頁在http://www.bouncycastle.org/ Security.addProvider(new BouncyCastleProvider()); } /** * AES解密 * * @param data //密文,被加密的數據 * @param key //秘鑰 * @param iv //偏移量 * @param encodingFormat //解密后的結果需要進行的編碼 * @return * @throws Exception */ public static String decrypt(String data, String key, String iv, String encodingFormat) throws Exception { //被加密的數據 byte[] dataByte = Base64.decodeBase64(data); //加密秘鑰 byte[] keyByte = Base64.decodeBase64(key); //偏移量 byte[] ivByte = Base64.decodeBase64(iv); try { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); SecretKeySpec spec = new SecretKeySpec(keyByte, "AES"); AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES"); parameters.init(new IvParameterSpec(ivByte)); cipher.init(Cipher.DECRYPT_MODE, spec, parameters);// 初始化 byte[] resultByte = cipher.doFinal(dataByte); if (null != resultByte && resultByte.length > 0) { String result = new String(resultByte, encodingFormat); return result; } return null; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidParameterSpecException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (InvalidAlgorithmParameterException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return null; } }
在這段代碼可以運行之前,還有一個問題需要解決。
Java本身限制密鑰的長度最多128位,而AES256需要的密鑰長度是256位,因此需要到Java官網上下載一個Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files。
官方網站提供了JCE無限制權限策略文件的下載:
JDK6的下載地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html
JDK7的下載地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
JDK8的下載地址:
http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
下載后解壓,可以看到local_policy.jar和US_export_policy.jar以及readme.txt。
如果安裝了JRE,將兩個jar文件放到%JRE_HOME%\lib\security下覆蓋原來文件,記得先備份。
如果安裝了JDK,將兩個jar文件也放到%JDK_HOME%\jre\lib\security下。
只要做了以上兩步,就能正常加解密了。