小程序对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不知道,欢迎评论!

### 解决 `javax.crypto.IllegalBlockSizeException` 异常 当遇到 `javax.crypto.IllegalBlockSizeException: last block incomplete in decryption` 错误时,通常是因为数据在网络传输过程中被篡改或丢失部分信息所致。具体原因可能涉及以下几个方面: #### 数据编码与解码不一致 如果加密后的数据包含了特殊字符(如 `+`),这些字符在通过 URL 或其他形式的网络请求传递时可能会被转义成不同的符号(如空格)。这会导致接收方接收到的数据与发送方发出的数据不符,在尝试解密时引发异常[^3]。 ```python import base64 def fix_plus_signs(encoded_data): """修复因URL编码导致的加号变为空格问题""" corrected_data = encoded_data.replace(' ', '+') try: decoded_bytes = base64.urlsafe_b64decode(corrected_data) return decoded_bytes.decode() except Exception as e: raise ValueError(f"Failed to decode data after fixing plus signs: {e}") ``` #### 填充模式设置不当 对于分组密码算法(如 AES/DES),若未正确配置填充模式,则可能导致最后一块无法完成解密操作。确保使用的 Cipher 实例初始化时指定了合适的填充方案,例如 PKCS7Padding 或 NoPadding 取决于实际需求[^2]。 ```java Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); SecretKeySpec secretKey = new SecretKeySpec(aesKey.getBytes(StandardCharsets.UTF_8), "AES"); IvParameterSpec ivspec = new IvParameterSpec(iv); cipher.init(Cipher.DECRYPT_MODE, secretKey, ivspec); // 使用正确的填充方式进行解密 byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedData)); String result = new String(decryptedBytes, StandardCharsets.UTF_8); System.out.println(result); ``` #### 输入数据长度不符合要求 某些情况下,输入给解密函数的数据长度不是有效区块大小的整数倍也会触发此异常。检查并确认待处理的数据量满足所选加密标准的要求[^4]。 ---
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值