zl程序教程

您现在的位置是:首页 >  后端

当前栏目

解决java rsa的错误:javax.crypto.IllegalBlockSizeException: Data must not be longer than 256 bytes

JAVA错误 解决 not Data be must rsa
2023-09-14 09:07:25 时间

这里写目录标题

复现问题

之前在对接第三方连连支付的接口时,报出如下错误:

Exception in thread "main" javax.crypto.IllegalBlockSizeException: Data must not be longer than 256 bytes
    at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:344)
    at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:389)
    at javax.crypto.Cipher.doFinal(Cipher.java:2165)
    at com.asymmetric.rsa.TestRSA.testDecrypt(TestRSA.java:82)
    at com.asymmetric.rsa.TestRSA.main(TestRSA.java:33)

非法字符长度的问题。

分析问题

因为RSA加密算法的默认公私钥的字节长度是256字节,但我通过Linux生成的字节数为2048字节,显然超过的RSA默认的字节长度,如下代码:

/**
 * 签名处理
 *
 * @param prikeyvalue:私钥
 * @param sign_str:签名源内容
 * @return
 */
public static String sign(String prikeyvalue, String sign_str) {
    try {
        //【1】获取私钥
        KeyFactory keyFactory = KeyFactory.getInstance(PaymentConstant.SIGN_TYPE);
        //将BASE64编码的私钥字符串进行解码
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] encodeByte = decoder.decodeBuffer(prikeyvalue);
        //生成私钥对象
        PrivateKey privatekey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodeByte));
        //【2】使用私钥
        // 获取Signature实例,指定签名算法(本例使用SHA1WithRSA)
        Signature signature = Signature.getInstance(PaymentConstant.MD5_WITH_RSA);
        //加载私钥
        signature.initSign(privatekey);
        //更新待签名的数据
        signature.update(sign_str.getBytes(BaseConstant.CHARSET));
        //进行签名
        byte[] signed = signature.sign();
        //将加密后的字节数组,转换成BASE64编码的字符串,作为最终的签名数据
        return new String(org.apache.commons.codec.binary.Base64.encodeBase64(signed));
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}

/**
 * 签名验证
 *
 * @param lianPubkey  下载好的连连公钥
 * @param lianSignSrc 连连的签名原串,也就是将返回串封装成jsonObject
 * @param lianSigned  连连加密签名签名,包括签名原串+私钥
 * @return
 */
public static boolean checksign(String lianPubkey, String lianSigned,
                                String lianSignSrc) {
    try {
        //【1】获取公钥
        //获取KeyFactory,指定RSA算法
        KeyFactory keyFactory = KeyFactory.getInstance(PaymentConstant.SIGN_TYPE);
        //将BASE64编码的公钥字符串进行解码
        BASE64Decoder decoder = new BASE64Decoder();
        //将BASE64解码后的字节数组,构造成X509EncodedKeySpec对象,生成公钥对象
        PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(decoder.decodeBuffer(lianPubkey)));
        byte[] signed = decoder.decodeBuffer(lianSigned);
        //【2】使用公钥,进行验签
        //获取Signature实例,指定签名算法(与之前一致)
        Signature signature = Signature.getInstance(PaymentConstant.MD5_WITH_RSA);
        //加载公钥
        signature.initVerify(publicKey);
        //更新原数据
        signature.update(lianSignSrc.getBytes(BaseConstant.CHARSET));
        //公钥验签(true-验签通过;false-验签失败)
        return signature.verify(signed);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return false;
}

解决问题

于是,和连连那边协商,其提供一个新的jar包,替换jdk安装目录下的两个jar包和JRE目录下的两个jar包,如图所示:

jdk替换位置
JRE替换位置
这样,就完美解决问题了,下载地址:jar包下载地址