前提

项目使用 maven-assembly-plugin​ 进行打包,将所有依赖的 jar 都打成一个 jar

业务场景需要用 AES/CBC/PKCS7Padding,但是 java 默认并不支持 PKCS7Padding,所以引入了 bcprov-jdk18on​ 这个第三方库,写代码时没什么问题,打包也没报错,然而真正运行跑到使用加密算法那个位置时报错 JCE cannot authenticate the provider BC

Caused by: java.lang.SecurityException: JCE cannot authenticate the provider BC
        at javax.crypto.Cipher.getInstance(Cipher.java:656)

原因

jvm 在执行 JCE 的算法时,只允许 ExtClassLoader 加载器加载的 jar 里面的算法被执行,而使用 maven-assembly-plugin​ ​打出来的 jar,不属于 ExtClassLoader 负责的范围,所以报 JCE cannot authenticate the provider BC

解决方法

要解决这个问题,有两个方法

方法一

可以将 bcprov-jdk18on​ 的 jar 放到 $JAVA_HOME/jre/lib/ext/

然后在 $JAVA_HOME/jre/lib/security/java.security 注册对应的算法提供类:org.bouncycastle.jce.provider.BouncyCastleProvider

比如:

security.provider.1=sun.security.provider.Sun
security.provider.2=org.bouncycastle.jce.provider.BouncyCastleProvider
security.provider.3=sun.security.rsa.SunRsaSign
security.provider.4=sun.security.ec.SunEC
security.provider.5=com.sun.net.ssl.internal.ssl.Provider
security.provider.6=com.sun.crypto.provider.SunJCE
security.provider.7=sun.security.jgss.SunProvider
security.provider.8=com.sun.security.sasl.Provider
security.provider.9=org.jcp.xml.dsig.internal.dom.XMLDSigRI
security.provider.10=sun.security.smartcardio.SunPCSC

方法二

使用 spring-boot-maven-plugin​ ​打包,可以将依赖的 jar 一起打入一个 jar 里面,插件内置了自己的类加载方式,可以加载到 jar 里面嵌套的 jar

比如:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>2.6.14</version>
    <configuration>
        <mainClass>com.kk.tools.media.video.app.VideoCliApplication</mainClass>
        <finalName>${artifactId}</finalName>
    </configuration>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>

方法三(推荐)

使用 openjdk,openjdk 不会校验加密库的签名,没这些琐事