java.security.NoSuchAlgorithmException: Cannot find any provider supporting DESede/CBC/PKCS5Padding

在从Windows环境迁移到Linux环境时,遇到Java程序中使用DESede加密时出现无法找到支持DESede/CBC/PKCS5Padding提供者的错误。通过检查Security.getProviders()发现,虽然Linux环境下似乎缺少SunJCE提供者,但在类路径中加入sunjce_provider.jar文件成功解决了问题。

最近在做3DES加密,在本地window下面运行ok的程序,放到linux环境上竟然报错:

java.security.NoSuchAlgorithmException: Cannot find any provider supporting DESede/CBC/PKCS5Padding
        at javax.crypto.Cipher.getInstance(Cipher.java:524)
        at com.haha.encrypt.ThreeDES.encryptMode(ThreeDES.java:30)
        at com.haha.encrypt.ThreeDES.encryptString(ThreeDES.java:101)
        at com.haha.mina.MinaServerHandler.sessionIdle(MinaServerHandler.java:91)
        at org.apache.mina.core.filterchain.DefaultIoFilterChain$TailFilter.sessionIdle(DefaultIoFilterChain.java:665)
        at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextSessionIdle(DefaultIoFilterChain.java:398)
        at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1000(DefaultIoFilterChain.java:47)
        at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.sessionIdle(DefaultIoFilterChain.java:755)
        at org.apache.mina.core.filterchain.IoFilterAdapter.sessionIdle(IoFilterAdapter.java:95)
        at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextSessionIdle(DefaultIoFilterChain.java:398)
        at org.apache.mina.core.filterchain.DefaultIoFilterChain.access$1000(DefaultIoFilterChain.java:47)
        at org.apache.mina.core.filterchain.DefaultIoFilterChain$EntryImpl$1.sessionIdle(DefaultIoFilterChain.java:755)
        at org.apache.mina.core.filterchain.IoFilterAdapter.sessionIdle(IoFilterAdapter.java:95)
        at org.apache.mina.core.filterchain.DefaultIoFilterChain.callNextSessionIdle(DefaultIoFilterChain.java:398)
        at org.apache.mina.core.filterchain.DefaultIoFilterChain.fireSessionIdle(DefaultIoFilterChain.java:391)
        at org.apache.mina.core.session.AbstractIoSession.notifyIdleSession0(AbstractIoSession.java:1303)
        at org.apache.mina.core.session.AbstractIoSession.notifyIdleSession(AbstractIoSession.java:1289)
        at org.apache.mina.core.session.AbstractIoSession.notifyIdleness(AbstractIoSession.java:1274)
        at org.apache.mina.core.polling.AbstractPollingIoProcessor.notifyIdleSessions(AbstractPollingIoProcessor.java:760)
        at org.apache.mina.core.polling.AbstractPollingIoProcessor.access$900(AbstractPollingIoProcessor.java:67)
        at org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.run(AbstractPollingIoProcessor.java:1135)
        at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:64)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:744)


对比了下Security.getProviders()

window下:

INFO  2014-04-30 10:32:12   ServerStarter:67 - 0[SUN]
INFO  2014-04-30 10:32:12   ServerStarter:67 - 1[SunRsaSign]
INFO  2014-04-30 10:32:12   ServerStarter:67 - 2[SunEC]
INFO  2014-04-30 10:32:12   ServerStarter:67 - 3[SunJSSE]
INFO  2014-04-30 10:32:12   ServerStarter:67 - 4[SunJCE]
INFO  2014-04-30 10:32:12   ServerStarter:67 - 5[SunJGSS]
INFO  2014-04-30 10:32:12  ServerStarter:67 - 6[SunSASL]
INFO  2014-04-30 10:32:12   ServerStarter:67 - 7[XMLDSig]
INFO  2014-04-30 10:32:12   ServerStarter:67 - 8[SunPCSC]
INFO  2014-04-30 10:32:12   ServerStarter:67 - 9[SunMSCAPI]

linux下:

INFO  2014-04-30 10:33:55   ServerStarter:66 - 0[SUN]
INFO  2014-04-30 10:33:55   ServerStarter:66 - 1[SunRsaSign]
INFO  2014-04-30 10:33:55   ServerStarter:66 - 2[SunJSSE]
INFO  2014-04-30 10:33:55   ServerStarter:66 - 3[SunJGSS]
INFO  2014-04-30 10:33:55   ServerStarter:66 - 4[SunSASL]
INFO  2014-04-30 10:33:55   ServerStarter:66 - 5[XMLDSig]
INFO  2014-04-30 10:33:56   ServerStarter:66 - 6[SunPCSC]


怀疑是缺少SunJCE造成的,但是在linux的JAVA_HOME/jre/lib/ext目录下,有sunjce_provider.jar包,所以很奇怪。

百思不得其姐,最后在一篇文章里,找到一句话,“找到一个 sunjce_provider.jar 的文件扔到你类路径里”,结果,ok了。。。。

<think> 首先,用户的问题是基于提供的引用信息,解决一个具体的错误:"java.security.NoSuchAlgorithmException: Cannot find any provider supporting SM4/ECB/PKCS5Padding"。用户参考了多个引用[1]到[5],这些引用描述了类似的错误和解决方案。 我需要回顾引用中的关键点: - [1]和[2]提到SM4和DES的类似错误,但没有直接给出解决方案。 - [3]和[4]涉及AES/CBC/PKCS7Padding的错误,解决方案是将PKCS7Padding改为PKCS5Padding。 - [5]提供了添加Bouncy Castle provider的解决方案。 用户的错误是特定的:SM4/ECB/PKCS5Padding。从引用中可以看出: - SM4是一种加密算法,类似于AES或DES。 - 错误表明Java无法找到支持该算法的provider。 在Java中,加密算法需要通过provider实现。标准JDK可能不支持某些算法,如SM4(这是一种中国国家标准的算法)。 关键解决方案从引用中提取: - 引用[4]建议更改padding方案(如从PKCS7到PKCS5),但用户的问题已经是PKCS5Padding。 - 引用[5]建议添加Bouncy Castle provider,这是一个常见的第三方加密库。 所以,核心解决方案应该是引入Bouncy Castle provider,因为它支持SM4算法。 步骤: 1. 添加Bouncy Castle库到项目中。 2. 在代码中注册provider。 引用[5]具体说: - 在jre/lib/ext下放一个jar包(如bcprov-jdk15on-1.66.jar)。 - 在jre/lib/security下的java.security文件中添加security.provider.10=org.bouncycastle.jce.provider.BouncyCastleProvider。 但更现代的实践是动态注册在代码中。 回答结构: - 解释错误原因:Java标准provider不支持SM4算法。 - 提供解决方案: - 添加Bouncy Castle依赖。 - 注册provider。 - 代码示例。 - 确保回答真实可靠,基于引用。 - 使用中文。 - 结尾添加相关问题,这是系统指令的一部分。 系统指令要求: - 行内数学表达式用$...$(但这里可能不适用)。 - 独立公式用$$...$$(不适用)。 - LaTeX语法正确(不适用)。 - 使用中文回答。 - 生成相关问题。 - 引用末尾自然地添加引用标识。 在回答中,引用用户提供的引用[^1]到[^5]。 用户引用是基于站内的,所以我在回答中要引用它们。 用户问题:"我想查找解决Java中出现 'java.security.NoSuchAlgorithmException: Cannot find any provider supporting SM4/ECB/PKCS5Padding' 错误的方案" 所以,回答应聚焦于此。 步骤解决方案: 1. 添加Bouncy Castle库到classpath。 - 可以通过Maven或下载jar。 - 例如,对于Maven:添加依赖。 2. 在代码中注册provider: - Security.addProvider(new BouncyCastleProvider()); 3. 然后使用Cipher.getInstance("SM4/ECB/PKCS5Padding"); 参考引用[5],它提供了类似方案。 为什么错误发生:JDK默认的providers(如SunJCE)不一定支持SM4。Bouncy Castle提供支持。 在代码示例中,确保正确。 相关问题生成: - 根据系统指令,在结尾添加相关问题。 - 例如: 1. 如何添加Bouncy Castle providerJava项目? 2. SM4加密与其他加密算法(如AES)有何区别? 3.Java中使用自定义加密provider的最佳实践? 确保回答清晰、结构良好。 最终回答结构: 1. 解释错误。 2. 提供解决方案步骤。 3. 代码示例。 4. 相关问题。 </think> ### 解决 Java 中出现 `java.security.NoSuchAlgorithmException: Cannot find any provider supporting SM4/ECB/PKCS5Padding` 错误的方法 这个错误通常发生在 Java 应用程序中尝试使用 SM4 加密算法(一种中国国家标准的对称加密算法)时,但 Java 标准加密提供者(如 SunJCE)不支持该算法。从您提供的引用(如引用[^5])来看,核心问题是 JDK 默认的加密服务提供者缺乏对 SM4 的支持。以下我将逐步解释原因并提供可靠解决方案,确保操作简单且有效。 #### 错误原因分析 - **算法支持不足**:SM4/ECB/PKCS5Padding 是一个特定算法模式组合(SM4 算法 + ECB 模式 + PKCS5Padding 填充)。Java 标准库(如 JDK 8 或更高版本)默认不包含 SM4 的实现,导致 `Cipher.getInstance("SM4/ECB/PKCS5Padding")` 调用失败(类似引用[^3]和[^4]中 AES 的错误)。 - **Provider 缺失**:Java 加密框架依赖注册的"provider"(加密服务提供者)来支持算法。如果无 provider 支持 SM4,就会抛出此异常(引用[^1]和[^2])。 - **PKCS5Padding 已正确使用**:您的错误中指定了 PKCS5Padding,这与引用[^4]中 AES 的解决方案不同(PKCS7Padding 改为 PKCS5Padding)。因此,这里不需要修改 padding 方案。 #### 解决方案:添加 Bouncy Castle Provider Bouncy Castle 是一个广泛使用的第三方加密库,支持 SM4 算法。以下是完整解决步骤,基于引用[^5]的方案并优化为现代 Java 项目的最佳实践。 ##### 步骤 1: 添加 Bouncy Castle 依赖 首先,将 Bouncy Castle 库添加到您的项目中。推荐使用 Maven 或 Gradle 管理依赖(避免手动修改 JRE 目录,以提高可移植性)。 - **Maven 依赖**:在 `pom.xml` 中添加: ```xml <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.70</version> <!-- 使用最新版本,如 1.70+ --> </dependency> ``` - **Gradle 依赖**:在 `build.gradle` 中添加: ```gradle dependencies { implementation 'org.bouncycastle:bcprov-jdk15on:1.70' } ``` - **手动添加 JAR**:如果不使用构建工具,下载 [bcprov-jdk15on-xxx.jar](https://www.bouncycastle.org/latest_releases.html) 并添加到项目的 classpath 中(例如,放在 `lib` 目录并配置构建路径)。 ##### 步骤 2: 在代码中注册 Bouncy Castle Provider 在初始化加密操作前,动态注册 Bouncy Castle provider。这比修改 `java.security` 文件更安全(引用[^5]建议修改文件,但动态注册更适合现代应用)。 - **代码示例**: ```java import org.bouncycastle.jce.provider.BouncyCastleProvider; import java.security.Security; import javax.crypto.Cipher; public class SM4Encryption { public static void main(String[] args) { // 注册 Bouncy Castle provider Security.addProvider(new BouncyCastleProvider()); try { // 现在可以正常初始化 SM4 算法 Cipher cipher = Cipher.getInstance("SM4/ECB/PKCS5Padding"); System.out.println("Provider: " + cipher.getProvider()); // 验证 provider // 后续加密/解密逻辑... } catch (Exception e) { e.printStackTrace(); } } } ``` - **关键点**: - `Security.addProvider(new BouncyCastleProvider())`:在调用 `Cipher.getInstance` 前注册 provider(只需执行一次,通常放在应用启动时)。 - 如果打包为 JAR 后运行(如引用[^2]场景),确保依赖 JAR 包含在 classpath 中(例如,命令行使用 `java -cp yourApp.jar:lib/* your.MainClass`)。 ##### 步骤 3: 验证解决方案 - **测试运行**:执行代码后,输出应显示 provider 为 `BC`(Bouncy Castle),无异常抛出。 - **常见问题处理**: - 如果仍报错,检查依赖版本是否兼容(如 JDK 11+ 使用 bcprov-jdk15on 1.68+)。 - 确保无多个 provider 冲突:避免重复注册或修改 `java.security` 文件(除非必需),动态注册更可靠。 #### 解决方法原理 - Bouncy Castle 实现了 SM4 算法,注册后扩展了 Java 的加密能力(引用[^5])。 - 此方案避免了修改算法字符串(如引用[^4]的 PKCS7 到 PKCS5),因为您的错误中 PKCS5Padding 已正确使用。 - 性能稳定,适用于各种 Java 环境(开发工具、打包 JAR 等)。 通过以上步骤,您可以彻底解决此错误。如果问题持续,请检查项目依赖或 Java 版本兼容性[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

linyu19872008

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值