Java SSL连接出现NoClassDefFoundError错误

3
我们有一个应用程序,使用JAX-RPC客户端库,并在旧版本的Java(1.4.2)上运行,出现以下SSL错误:
java.lang.NoClassDefFoundError
    javax.crypto.Cipher.a(DashoA6275)
    javax.crypto.Cipher.getInstance(DashoA6275)
    com.sun.net.ssl.internal.ssl.SunJSSE_i.a(DashoA12275)
    com.sun.net.ssl.internal.ssl.CipherBox$JCECipherBox.<init>(DashoA12275)
    com.sun.net.ssl.internal.ssl.CipherRC4.a(DashoA12275)
    com.sun.net.ssl.internal.ssl.SunJSSE_h.a(DashoA12275)
    com.sun.net.ssl.internal.ssl.CipherSuite$BulkCipher.a(DashoA12275)
    com.sun.net.ssl.internal.ssl.SunJSSE_ax.c(DashoA12275)
    com.sun.net.ssl.internal.ssl.SSLSocketImpl.f(DashoA12275)
    com.sun.net.ssl.internal.ssl.SunJSSE_ax.a(DashoA12275)
    com.sun.net.ssl.internal.ssl.SunJSSE_az.j(DashoA12275)
    com.sun.net.ssl.internal.ssl.SunJSSE_az.a(DashoA12275)
    com.sun.net.ssl.internal.ssl.SunJSSE_az.a(DashoA12275)
    com.sun.net.ssl.internal.ssl.SunJSSE_ax.a(DashoA12275)
    com.sun.net.ssl.internal.ssl.SSLSocketImpl.a(DashoA12275)
    com.sun.net.ssl.internal.ssl.SSLSocketImpl.j(DashoA12275)
    com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(DashoA12275)
    sun.net.www.protocol.https.HttpsClient.afterConnect(DashoA12275)
    sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(DashoA12275)
    sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:569)
    sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(DashoA12275)
    com.sun.xml.rpc.client.http.HttpClientTransport.writeMessageToConnection(HttpClientTransport.java:278)
    com.sun.xml.rpc.client.http.HttpClientTransport.invoke(HttpClientTransport.java:64)
    com.sun.xml.rpc.client.StreamingSender._send(StreamingSender.java:69)
    [ ... trace continues into internal application code ... ]

这在我们之前起过作用,客户端库的唯一更改涉及身份验证协议,并需要更新到最新版本的BouncyCastle。这些更改都在比SSL协议更高的层面上进行,而此错误似乎甚至与BouncyCastle无关。
有人以前看到过这样的错误吗?或许有什么想法或建议?我尝试将证书添加到cacerts。如果对Java 1.6运行,则可以正常工作,但是不幸的是,目前正在运行它的生产系统仍然与Java 1.4绑定。
此外,我们的JAX-RPC代码及其执行的身份验证一直可以正确地工作,如果没有SSL连接到我们的开发系统。
[编辑 - 额外信息] 现在我可以看到较新版本的BouncyCastle存在冲突导致该问题。我尝试使用古老的(1.18)版本,似乎没有收到SSL错误,但是因为应用程序需要更新的算法而得到了错误结果。

您可能需要查看JRE安全策略文件(%JAVA_HOME%/jre/lib/security/java.security和java.policy),以查看Java 1.4使用的类...也许SSL证书使用了一些新的加密算法,这些算法在Java 1.4中不可用,您可以通过查看Java正在使用的类之间的差异来找到它们。 - Renato
你确定你在使用适用于Java 1.4的BouncyCastle库吗?(它有多个版本与同一库的版本相匹配) - Bruno
1
我认为这与SSL证书使用的密码无关。如果我从BouncyCastle 1.46回退到我们以前使用的古老版本1.18,SSL连接就可以正常工作。(在这种情况下,我们的应用程序本身会出现问题,因为我们升级了使用更新的密码) - Michael
1
@nalroff 哦,我很想这样做。不幸的是,正如你所看到的,我对此没有控制力。 :-/ - Michael
所以,看起来如果我使用BC 1.26,它会给出关于我们应用程序使用的“SHA256withRSA”密码错误,但不是SSL错误。如果我切换到BC 1.27,我会得到上面提到的SSL错误。捂脸 - Michael
显示剩余2条评论
2个回答

1

经过大量的研究,我终于发现在我们的代码中将BC提供程序插入为1号提供程序。

Security.insertProviderAt(prov, 1);

不是改变,而是添加提供程序才解决了问题。

Security.addProvider(prov);

0

javax.crypto.Cipher位于一个名为jce.jar的单独JAR文件中(不在rt.jar中)。也许类加载器无法找到此文件,或者在您的生产应用程序服务器上未设置对此文件的读取权限。


2
NoClassDefFoundError 表示它可以找到类,但是找不到该类导入的类。因此,它找到了 Cipher 类。你错了。 - gigadot
好的观点。我以为Cipher是异常消息中的一部分。无论如何,问题可能是由其他与安全相关的jar文件引起的。 - Wojciech Owczarczyk
1
经过更多尝试,我发现这肯定与我们的BouncyCastle库有关。我切换回了以前使用的(非常)旧版本,不再收到那个错误,但是收到了我期望从旧库中获得的应用程序错误。至少有一些进展! - Michael

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接