Java 11解密PGP消息时JCE无法认证BC提供商的替代方案咨询
问题背景
在Java 11环境下解密PGP消息时触发核心异常:
Caused by: java.lang.SecurityException: JCE cannot authenticate the provider BC
项目当前使用的BouncyCastle依赖包:
- bcprov-jdk15-140.jar
- bcpg.jar
曾尝试注释java.security文件中的以下配置项解决问题,但该方案不被管理层接受:
jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ DSA keySize < 1024, include jdk.disabled.namedCurves, \ SHA1 denyAfter 2019-01-01
现寻求无需修改java.security的有效修复方案,相关堆栈跟踪及依赖包清单如下:
完整堆栈跟踪
Exception in thread "main" org.bouncycastle.openpgp.PGPException: Exception creating cipher at org.bouncycastle.openpgp.PGPSecretKey.extractKeyData(Unknown Source) at org.bouncycastle.openpgp.PGPSecretKey.extractPrivateKey(Unknown Source) at org.bouncycastle.openpgp.PGPSecretKey.extractPrivateKey(Unknown Source) at TestPGPUtil.findSecretKey(TestPGPUtil.java:34) at KeyBasedFileProcessor.decryptFile(KeyBasedFileProcessor.java:189) at KeyBasedFileProcessor.decryptFile(KeyBasedFileProcessor.java:149) at KeyBasedFileProcessor.decrypt(KeyBasedFileProcessor.java:552) at KeyBasedFileProcessor.decryptContent(KeyBasedFileProcessor.java:109) at KeyBasedFileProcessor.main(KeyBasedFileProcessor.java:602) Caused by: java.lang.SecurityException: JCE cannot authenticate the provider BC at java.base/javax.crypto.Cipher.getInstance(Cipher.java:692) ... 9 more Caused by: java.util.jar.JarException: file:/C:/project/TEST/java/pgp/Dependency/bcprov-jdk15-140.jar has unsigned entries - org/bouncycastle/LICENSE.class at java.base/javax.crypto.JarVerifier.verifySingleJar(JarVerifier.java:463) at java.base/javax.crypto.JarVerifier.verifyJars(JarVerifier.java:318) at java.base/javax.crypto.JarVerifier.verify(JarVerifier.java:261) at java.base/javax.crypto.ProviderVerifier.verify(ProviderVerifier.java:129) at java.base/javax.crypto.JceSecurity.verifyProvider(JceSecurity.java:191) at java.base/javax.crypto.JceSecurity.getVerificationResult(JceSecurity.java:217) at java.base/javax.crypto.Cipher.getInstance(Cipher.java:688) ... 9 more
依赖包Manifest信息
bcprov-jdk15-140.jar
Manifest-Version: 1.0 Created-By: 1.5.0_08-b03 (Sun Microsystems Inc.) Ant-Version: Apache Ant 1.6.5 Specification-Version: 1.1 Specification-Vendor: BouncyCastle.org Implementation-Vendor-Id: org.bouncycastle Extension-Name: org.bouncycastle.bcprovider Implementation-Version: 1.40.0 Implementation-Vendor: BouncyCastle.org
bcpg.jar
Manifest-Version: 1.0 Implementation-Version: 1.46.0 Specification-Vendor: BouncyCastle.org Tool: Bnd-1.30.0 Bundle-Name: bcpg Created-By: 1.6.0_22 (Sun Microsystems Inc.) Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Ant-Version: Apache Ant 1.6.5 Implementation-Vendor: BouncyCastle.org Trusted-Library: true Implementation-Vendor-Id: org.bouncycastle Bundle-Version: 1.46 Bnd-LastModified: 1298423474896 Bundle-ManifestVersion: 2 Specification-Version: 1.1 Bundle-SymbolicName: bcpg Originally-Created-By: 1.6.0-b105 (Sun Microsystems Inc.) Extension-Name: org.bouncycastle.bcpg
有效修复方案
从堆栈根因可知:bcprov-jdk15-140.jar存在未签名条目org/bouncycastle/LICENSE.class,且该版本是针对JDK 1.5编译的,完全不兼容Java 11的JCE验证机制,这才是问题核心,而非java.security的配置。
修复步骤:
升级BouncyCastle依赖到Java 11兼容版本
弃用老旧的bcprov-jdk15-140.jar和bcpg.jar,改用官方支持JDK 8+的jdk15on系列稳定版(建议1.70及以上版本)。例如Maven依赖配置:<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.70</version> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcpg-jdk15on</artifactId> <version>1.70</version> </dependency>使用官方签名的依赖包
从BouncyCastle官方渠道获取依赖,避免使用第三方修改过的未签名包,确保JCE验证可通过。显式注册BouncyCastle Provider(可选)
在程序启动时主动注册Provider,避免依赖系统自动加载:import org.bouncycastle.jce.provider.BouncyCastleProvider; import java.security.Security; // 注册Provider Security.addProvider(new BouncyCastleProvider()); // 或设置为优先加载 // Security.insertProviderAt(new BouncyCastleProvider(), 1);
临时方案生效的原因
注释jdk.jar.disabledAlgorithms中的SHA1 denyAfter 2019-01-01会放宽JCE签名验证策略,允许SHA1签名的老旧包通过验证,但这会引入安全风险,因此不建议采用。
内容的提问来源于stack exchange,提问作者Chennai Cheetah

