1. 程式人生 > >小程式對encryptedData進行解密之javax.crypto.BadPaddingException: pad block corrupted

小程式對encryptedData進行解密之javax.crypto.BadPaddingException: pad block corrupted

  程式碼參考連結:http://blog.csdn.net/l1028386804/article/details/79450115
  出現報錯:javax.crypto.BadPaddingException: pad block corrupted。為了解決這個,心態都崩潰了。
  官方給的步驟如下 :

  1. 對稱解密使用的演算法為 AES-128-CBC,資料採用PKCS#7填充。
  2. 對稱解密的目標密文為 Base64_Decode(encryptedData)。
  3. 對稱解密祕鑰 aeskey = Base64_Decode(session_key), aeskey 是16位元組。
  4. 對稱解密演算法初始向量 為Base64_Decode(iv),其中iv由資料介面返回。
    主要程式碼如下:
    AESUtil.java
package com.ebuy.football.util;

import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import
java.security.Security; 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 org.bouncycastle.jce.provider.BouncyCastleProvider; /** * AES加密 * */
public class AESUtil { public static boolean initialized = false; /** * AES解密 * * @param content * 密文 * @return * @throws InvalidAlgorithmParameterException * @throws NoSuchProviderException */ public byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException { initialize(); try { Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC"); Key sKeySpec = new SecretKeySpec(keyByte, "AES"); cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化 byte[] result = cipher.doFinal(content); return result; } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (NoSuchProviderException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } public static void initialize() { if (initialized) return; Security.addProvider(new BouncyCastleProvider()); initialized = true; } // 生成iv public static AlgorithmParameters generateIV(byte[] iv) throws Exception { AlgorithmParameters params = AlgorithmParameters.getInstance("AES"); params.init(new IvParameterSpec(iv)); return params; } }

WxPKCS7EncoderUtil.java

package com.ebuy.football.util;

import java.nio.charset.Charset;
import java.util.Arrays;


/**
 * 微信小程式加解密
 *
 */
public class WxPKCS7EncoderUtil {
    private static final Charset CHARSET = Charset.forName("utf-8");
    private static final int BLOCK_SIZE = 32;

    /**
     * 獲得對明文進行補位填充的位元組.
     *
     * @param count
     *            需要進行填充補位操作的明文位元組個數
     * @return 補齊用的位元組陣列
     */
    public static byte[] encode(int count) {
        // 計算需要填充的位數
        int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);
        if (amountToPad == 0) {
            amountToPad = BLOCK_SIZE;
        }
        // 獲得補位所用的字元
        char padChr = chr(amountToPad);
        String tmp = new String();
        for (int index = 0; index < amountToPad; index++) {
            tmp += padChr;
        }
        return tmp.getBytes(CHARSET);
    }

    /**
     * 刪除解密後明文的補位字元
     *
     * @param decrypted
     *            解密後的明文
     * @return 刪除補位字元後的明文
     */
    public static byte[] decode(byte[] decrypted) {
        int pad = decrypted[decrypted.length - 1];
        if (pad < 1 || pad > 32) {
            pad = 0;
        }
        return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
    }

    /**
     * 將數字轉化成ASCII碼對應的字元,用於對明文進行補碼
     *
     * @param a
     *            需要轉化的數字
     * @return 轉化得到的字元
     */
    public static char chr(int a) {
        byte target = (byte) (a & 0xFF);
        return (char) target;
    }
}

WXCoreUtil.java

package com.ebuy.football.util;


import org.apache.commons.codec.binary.Base64;
import org.json.JSONObject;

public class WXCoreUtil {
    private static final String WATERMARK = "watermark";
    private static final String APPID = "appid";
    /**
     * @return
     * @throws Exception
     */
    public static String decrypt(String appId, String encryptedData, String sessionKey, String iv){
        String result = "";
        try {
            AESUtil aes = new AESUtil();  
            byte[] resultByte = aes.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(sessionKey), Base64.decodeBase64(iv));  
            if(null != resultByte && resultByte.length > 0){  
                result = new String(WxPKCS7EncoderUtil.decode(resultByte));  
//              JSONObject jsonObject = JSONObject.fromObject(result);
                JSONObject jsonObject = new JSONObject(result);
                String decryptAppid = jsonObject.getJSONObject(WATERMARK).getString(APPID);
                if(!appId.equals(decryptAppid)){
                    result = "";
                }
            }  
        } catch (Exception e) {
            result = "";
            e.printStackTrace();
        }
        return result;
    }

}

執行程式碼:WXCoreUtil.decrypt(appid, encryptedData, sessionKey, iv);

以上問題我遇到了一個大坑:Cipher cipher = Cipher.getInstance(“AES/CBC/PKCS7Padding”,”BC”);
後面要加”BC”,就是這個原因了。太坑了。希望能解決你的問題。哪位老哥知道原因為什麼要加BC,能解釋下嗎,lz不知道,歡迎評論!