SSL握手异常

20

我使用SSL连接将Web客户端连接到服务器。长期以来一直没有问题。但是从昨天开始出现以下错误,有人能告诉我原因吗?

javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.checkEOF(SSLSocketImpl.java:1172)
        at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:65)
        at net.schubart.fixme.internal.MessageInput.readExactly(MessageInput.java:166)
        at net.schubart.fixme.internal.MessageInput.readMessage(MessageInput.java:78)
        at cc.aot.itsWeb.ClientWriterThread.run(ClientWriterThread.java:241)
        at java.lang.Thread.run(Thread.java:619)
clientWriter.ready
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
        at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
        at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1586)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:865)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1029)
        at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:621)
        at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59)
        at java.io.OutputStream.write(OutputStream.java:58)
        at net.schubart.fixme.internal.Message.write(Message.java:267)
        at net.schubart.fixme.internal.MessageOutput.writeMessage(MessageOutput.java:53)

你有服务器日志吗?它是“单向SSL”(没有用户证书)还是你验证客户端?你能用Web浏览器连接到这个服务器吗?服务器证书有效吗? - Michał Niklas
11个回答

14
您遇到的问题与证书有关。在使用安全的SSL程序之前,您可能需要熟悉以下事项:必须有一个信任存储(truststore)、密钥库(keystore),并且必须添加证书。 要将密钥添加到cacerts文件,就像第6步一样,计算机可能会要求您输入一个您不知道的密码。它很可能是"changeit"。 1)创建新的密钥库和相应的自签名证书以及对应的公共/私有密钥:
 keytool -genkeypair -alias "username" -keyalg RSA -validity 7 -keystore keystore

2) 检查keystore:

keytool -list -v -keystore keystore

3)导出并检查自签名证书:

keytool -export -alias "username" -keystore keystore -rfc -file "username".cer

4) 将证书导入新信任库:

keytool -import -alias "username" -file "username".cer -keystore truststore

5) 检查信任证书库:

keytool -list -v -keystore truststore

6) 添加到密钥库(这就是你要找的):

sudo keytool -import -file "username".cer -alias "username" -keystore "path-to-keystore"

在一些系统中,这个可以在以下位置找到:

/usr/lib/jvm/<java version folder>/jre/lib/security/cacerts

在其他系统上,它类似于

/etc/ssl/certs/java/cacerts

如果您需要更多的澄清,请查看这个 Git-Hub 项目: https://github.com/rabbitfighter81/JSSLInfoCollectionServer 以下是一个有助于密钥管理的 shell 脚本。 https://github.com/rabbitfighter81/SSLKeytool


12

我花了超过12个小时解决这个问题。创建自签名证书后,需要将证书导出到cacert文件中。在我的情况下,它位于/usr/lib/java/jre/lib/security/cacert。您可以使用keytool导出证书(可能需要root访问权限):

$ sudo keytool -exportcert -alias keyStoreAlias -keystore \
       keyStoreKeys.keys -file /usr/local/java/jre/lib/security/cacerts

9

服务器提供的证书不被信任。这可能是由于证书已过期,或者信任管理器无法建立与您信任存储中任何证书的信任链。


7
这个“certificate_unknown”错误信息非常误导人。即使证书在信任库中,当证书已过期时,也会抛出相同的错误信息。我建议在处理其他问题之前,先检查证书的过期日期。

对我来说也是一个过期的证书! - Arthur

2

如果你真的非常需要的话,可以接受所有证书。但请记住,这样做非常丑陋。

请看这里


2

检查证书是否有效,您可以使用浏览器进行操作。


2

我首先会检查一下相关证书是否已过期。在与供应商合作时,我经常遇到这种情况。他们可以更新证书而不通知我们。


0
您可以通过浏览器检查证书。
在Internet Explorer中。
Right Click >> Properties >> Certificates

在证书窗口中,您可以查看整个证书树。

如果您有一个无效的证书,您可能需要使用keytool命令来寻找解决方案。

Keytool命令


0

我认为您需要在jre1.6 cacert中添加密钥库。然后再次部署您的服务器。顺便提一下,您可以使用PORTECLE程序来添加keystore,它非常有用。


0
当我收到这个错误时,问题是服务器证书使用的签名算法是SHA1withRSA和Android 8.0客户端不兼容。切换到基于SHA256withRSA的服务器证书解决了这个问题。

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