侧边栏壁纸
  • 累计撰写 14 篇文章
  • 累计创建 22 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

SecurityException: JCE cannot authenticate the provider BC bug问题解决

Administrator
2024-03-15 / 0 评论 / 0 点赞 / 117 阅读 / 6110 字

SecurityException: JCE cannot authenticate the provider BC 问题

hutool.crypto.CryptoException: SecurityException: JCE cannot authenticate the provider BC

    • 先分析异常描述
    • 解决方案

先分析异常的描述
JCE cannot authenticate the provider BC:在使用带签名的jar包时,java会对jar包的签名进行验证,以确认jar包是不是合法的。
SecurityException:加密异常。
总结:在使用加密的第三方类时,验证签名不过关。

然后分析异常的具体位置:

1710472670893.png

找到具体抛异常的位置

image-gyuy.png

然后往上翻可以看到这个类具体是什么作用

image-gpyg.png

BouncyCastle类是一个加密的第三方类,jdk本身是有一些加密的方法的,如果需要额外的一些加密方法的话需要用到BouncyCastle类。但我不记得加过这个类啊,我们先看看到底有没有这个类

image-mbah.png

搜了一下发现有,我们在看看这是在哪里加进来的。

image-terf.png

通过全局搜索没有发现,说明这个类不是我们自己主动通过maven加进来的,是在加别的类的时候,依赖加进来的。

image-ugwe.png

选定模块以后,点击上面的那个图标,然后通过ctrl+f快速搜索这个jar包

image-wuku.png

这里我们这可以知道,是在引入支付宝支付的时候引入了bcprov这个jar包,然后初始化的时候就使用了这个jar包,但是这个版本的jar包签名太旧了(jdk8的时候没有问题),所有报了个签名未通过的错。

解决方法

  • 1.既然是jar包版本太旧了,那是不是升级一下就好了。单独引入新版本的jar包。(怕有影响的可以把sdk那边的手动排除掉)
<!-- 这是maven目前最新的版本 -->
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk16</artifactId>
    <version>1.46</version>
</dependency>

<!-- 网上搜到有人用这个,上面没用的话试试这个 -->
<dependency>
	<groupId>org.bouncycastle</groupId>
	<artifactId>bcprov-jdk15to18</artifactId>
	<version>1.64</version>
</dependency>
  

ps:这个方法没有尝试过,是后面补充的,可以试试。

  • 2.使用openjdk。open jdk是不会去验签的,所以直接把oracle jdk改成open jdk。
  • 3.直接强制关闭Bouncy Castle

image-pstq.png

import cn.hutool.crypto.SecureUtil;

public class Example {
    public static void main(String[] args) {
        // Disable Bouncy Castle
        SecureUtil.disableBouncyCastle();
  
        // Your code here
        // ...
    }
}

4.既然是hutool框架里的类初始化的时候默认去使用Bouncy Castle,那直接不用hutool是不是也能行🤔。当然了 我来提供一个 就可以了

package cn.cws.fulimall.util;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class HmacSHA256Util {
    /**
     * HmacSHA256算法,返回的结果始终是32位
     * @param key 加密的键,可以是任何数据
     * @param content 待加密的内容
     * @return 加密后的内容
     * @throws Exception
     */
    public static byte[] hmacSHA256(byte[] key,byte[] content) throws Exception {
        Mac hmacSha256 = Mac.getInstance("HmacSHA256");
        hmacSha256.init(new SecretKeySpec(key, 0, key.length, "HmacSHA256"));
        return hmacSha256.doFinal(content);
    }
    /**
     * 将加密后的字节数组转换成字符串
     *
     * @param b 字节数组
     * @return 字符串
     */
    public  static String byteArrayToHexString(byte[] b) {
        StringBuilder hs = new StringBuilder();
        String stmp;
        for (int n = 0; b!=null && n < b.length; n++) {
            stmp = Integer.toHexString(b[n] & 0XFF);
            if (stmp.length() == 1)
                hs.append('0');
            hs.append(stmp);
        }
        return hs.toString().toLowerCase();
    }
    /**
     * sha256_HMAC加密
     * @param message 消息
     * @param secret  秘钥
     * @return 加密后字符串
     */
    public static String hmacSHA256(String secret, String message) throws Exception {
        String hash = "";
        Mac hmacSha256 = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
        hmacSha256.init(secret_key);
        byte[] bytes = hmacSha256.doFinal(message.getBytes());
        hash = byteArrayToHexString(bytes);
        return hash;
    }

    public static String signByHmacSHA256AndBase64(String str, String secret) throws Exception {
        String bStr = hmacSHA256(secret, str);
        Base64.Encoder encoder = Base64.getEncoder();
        return encoder.encodeToString(bStr.getBytes());
    }
}


本人在自己系统当中用第四种 测试后发现就可以解决了

0
广告 广告

评论区