![](/img/trans.png)
[英]Android Client -> SSL --> Java Server Error: no cipher suites in common
[英]Java SSL: client handshake failure and server no cipher suites in common
我正在尝试通过 Java 中的 SSL 套接字从客户端连接到服务器。 在客户端接收handshake_failure,在服务器端(www)没有共同的密码套件。
服务器配置为 SSL Tomcat 9,这是连接器:
<Connector SSLEnabled="true" acceptCount="100" clientAuth="false"
disableUploadTimeout="true" enableLookups="false" maxThreads="25"
port="8443" keystoreFile="C:/Users/xxx/.keystore" keystorePass="xxx"
keystoreType="PKCS12"
protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="https"
secure="true" sslProtocol="TLS" />
客户为 Java 项目。 双方在keytool中都有证书。 证书已从 keytool 导出,并由 keytool 在客户端导入。 因此,在客户端和服务器端,我们导入了 server.cer。 Tomcat 从端口 8443 开始,sockets 使用端口 443。
我有什么尝试? - 在代码中设置协议 - 设置密码套件 - 更改端口 - 从 8080 和 8443 端口开始 tomcat
服务器:
void mySSLServerSocket(int port) throws IOException {
SSLServerSocketFactory sslServerSocketFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(port);
sslServerSocket.setEnabledProtocols(new String[] {"TLSv1.2"});
sslServerSocket.setEnabledCipherSuites(new String[] {"TLS_RSA_WITH_AES_256_CBC_SHA"});
SSLSocket socket = (SSLSocket) sslServerSocket.accept();
OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream();
while(true) {
int orderNumber = in.read();
System.out.println("order number readed: " + orderNumber);
}
}
客户:
void mySocket(String ip, int port) throws IOException {
SSLSocketFactory sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(ip, port);
sslSocket.setEnabledProtocols(new String[] {"TLSv1.2"});
sslSocket.setEnabledCipherSuites( new String[] {"TLS_RSA_WITH_AES_256_CBC_SHA"});
sslSocket.startHandshake();
InputStream in = sslSocket.getInputStream();
OutputStream out = sslSocket.getOutputStream();
out.write(1);
while (in.available() > 0) {
System.out.print(in.read());
}
}
客户端错误:
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2020)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1127)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379)
at com.company.SocketUtil.mySocket(SocketUtil.java:31)
at com.company.Main.main(Main.java:15)
服务器(错误来自 web - JSP 页面):
Type Exception Report
Message no cipher suites in common
Description The server encountered an unexpected condition that prevented it from fulfilling the request.
Exception
javax.net.ssl.SSLHandshakeException: no cipher suites in common
java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:307)
java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:263)
java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:254)
java.base/sun.security.ssl.ServerHello$T12ServerHelloProducer.chooseCipherSuite(ServerHello.java:460)
java.base/sun.security.ssl.ServerHello$T12ServerHelloProducer.produce(ServerHello.java:295)
java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:436)
java.base/sun.security.ssl.ClientHello$T12ClientHelloConsumer.consume(ClientHello.java:1102)
java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.onClientHello(ClientHello.java:854)
java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.consume(ClientHello.java:813)
java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:443)
java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:421)
java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:177)
java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:164)
java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1180)
java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1091)
java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:402)
java.base/sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:721)
java.base/sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:804)
java.base/sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:763)
ServerSocketUtils.mySSLServerSocket(ServerSocketUtils.java:38)
MusicControl.doPost(MusicControl.java:24)
javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
Note The full stack trace of the root cause is available in the server logs.
错误说没有密码套件,但我检查了支持的密码并选择了一个,双方都可用。 声明了 TSL 协议,但仍然没有成功。
我想从客户端连接到服务器成功,但不知道下一步我能做什么,因为在互联网上找不到任何建议。
我已经阅读了一些关于进行连接所需的私钥的内容。 它在哪里? 我假设 server.cer 只有公钥。
当 tomcat 在 8443 上运行时,为 sockets 使用端口 443 是否合适? 也许我应该在某处指定这些端口?
您的问题的一部分是关于“证书”,我假设它代表证书。
你是对的,证书只包含一个由证书颁发机构 (CA) 签名的公钥。 公钥只是非对称密钥对(例如 RSA)的公共部分。 服务器需要有私钥。 否则它不能解密用公钥加密的内容,也不能对发送给客户端的内容进行签名。
也就是说,您需要创建一个 RSA 密钥对,并将其提供给 tomcat。 要么让它由知名 CA 签名(制作证书),要么使用密钥工具生成自签名证书。 在第一种情况下,客户端不需要特殊操作,因为 java(或浏览器)已经知道众所周知的 CA 的公钥,这些公钥是验证服务器提供的证书所需的。 如果是自签名证书,您必须在客户端将其作为受信任的证书导入。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.