小程序对encryptedData进行解密之javax.crypto.BadPaddingException: pad block corrupted

  代码参考链接:http://blog.youkuaiyun.com/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不知道,欢迎评论!

### 微信登录 `PAD BLOCK CORRUPTED` 错误解决方案 #### 问题分析 当微信小程序进行手机号授权登录时,如果后台解密过程中出现 `javax.crypto.BadPaddingException: pad block corrupted` 的错误提示,则表明加密数据在传输或处理过程中可能出现了损坏或不一致的情况[^1]。 #### 解决方案概述 为了有效解决此问题并提高解密成功率,建议从以下几个方面入手: #### 确保参数最新性和一致性 确保每次请求使用的 `code` 是最新的,并且只使用一次。重复使用同一个 `code` 可能导致验证失败。此外,在从前端传递给后端的数据包中(如 `encryptedData`, `ivStr`),应保持其原始状态不变,任何修改都可能导致校验位的变化从而引发异常[^2]。 #### 验证前后端环境配置匹配度 确认前后端所采用的安全算法版本相同,特别是对于加/解密操作而言非常重要。不同平台间可能存在细微差异,这会影响最终的结果准确性。例如,Java 和 Node.js 对 AES 加密的支持就有所区别,因此需仔细核对文档说明以保证双方设置的一致性。 #### 更新与优化现有逻辑流程 针对原有实现方式存在的潜在缺陷作出调整改进。具体措施可以包括但不限于增加必要的日志记录以便于调试追踪;简化不必要的中间环节减少出错几率;以及考虑引入重试机制应对网络波动等因素造成的临时性故障等问题。 ```java // Java 后端示例代码片段用于正确接收和解析来自前端的信息 public String decrypt(String sessionKey, String iv, String encryptedData){ try { // 将Base64编码后的字符串转换成字节数组 byte[] resultByte = Base64.decode(encryptedData); byte[] keyBytes = new BASE64Decoder().decodeBuffer(sessionKey); byte[] ivBytes = new BASE64Decoder().decodeBuffer(iv); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); SecretKeySpec spec = new SecretKeySpec(keyBytes,"AES"); AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES"); parameters.init(new IvParameterSpec(ivBytes)); cipher.init(Cipher.DECRYPT_MODE,spec,parameters); byte[] decodeFormat = cipher.doFinal(resultByte); return new String(decodeFormat,"UTF-8"); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } } ``` #### 测试与部署前充分准备 完成上述更改之后,务必进行全面的功能测试,模拟各种可能出现的真实场景来检验系统的稳定性和可靠性。只有经过严格的质量控制过程才能确保上线后的用户体验不受影响。
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值