有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java SSL:客户端握手失败,服务器没有常见的密码套件

我正在尝试通过Java中的SSLsocket从客户端连接到服务器。 客户端接收握手失败,服务器端(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在客户端导入。 所以,在客户端和服务器端,我们导入了服务器。cer。 Tomcat从端口8443启动,socket使用端口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协议,但仍然没有成功

我想成功地从客户端连接到服务器,但不知道下一步该怎么做,因为在internet上找不到任何建议

我读过一些关于连接所需的私钥的内容。它在哪里? 我猜,那个服务器。cer只有公钥

当tomcat在8443上运行时,使用端口443作为socket是否合适?也许我应该在某个地方指定那些端口


共 (1) 个答案

  1. # 1 楼答案

    你问题的一部分是关于“证书”,我想它代表证书

    您是对的,证书只包含由证书颁发机构(CA)签名的公钥。公钥只是非对称密钥对(例如RSA)的公共部分。服务器需要有私钥。否则,它无法解密使用公钥加密的内容,也无法对发送到客户端的内容进行签名

    也就是说,您需要创建一个RSA密钥对,并将其提供给tomcat。要么让它由一个著名的CA签名(生成证书),要么使用密钥工具生成一个自签名证书。在第一种情况下,客户端不需要特殊操作,因为java(或浏览器)已经知道验证服务器交付的证书所需的众所周知的CA公钥。对于自签名证书,您必须在客户端将其作为受信任证书导入