我想从ssl握手中获取客户端压缩_方法或客户端支持的密码套件之类的信息
我尝试使用

public static void main(String[] args) throws Exception {
    String serverKeyStoreFile = "D:\\tomcat.keystore";
    String serverKeyStorePwd = "logiscn";
    String catServerKeyPwd = "logiscn";
    String serverTrustKeyStoreFile = "D:\\tomcat.keystore";
    String serverTrustKeyStorePwd = "logiscn";
    //System.setProperty("javax.net.debug", "ssl,handshake");
    KeyStore serverKeyStore = KeyStore.getInstance("JKS");
    serverKeyStore.load(new FileInputStream(serverKeyStoreFile), serverKeyStorePwd.toCharArray());
    KeyStore serverTrustKeyStore = KeyStore.getInstance("JKS");
    serverTrustKeyStore.load(new FileInputStream(serverTrustKeyStoreFile), serverTrustKeyStorePwd.toCharArray());

    KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    kmf.init(serverKeyStore, catServerKeyPwd.toCharArray());

    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(serverTrustKeyStore);
    SSLContext sslContext = SSLContext.getInstance("TLSv1");
    // System.out.println(sslContext.getProvider());
    sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
    SSLServerSocketFactory sslServerSocketFactory = sslContext.getServerSocketFactory();
    SSLServerSocket sslServerSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(SERVER_PORT);
    // sslServerSocket.setNeedClientAuth(true);

    while (true) {
        SSLSocket s = (SSLSocket) sslServerSocket.accept();
    //  System.out.println(s);
        //System.out.println(s.getClass());
        // s.getSupportedProtocols()
        CatServer cs = new CatServer(s);
        //s.addHandshakeCompletedListener(cs);
        s.startHandshake();
        // System.out.println(s.getHandshakeSession().getProtocol());
        new Thread(cs).start();
    }
}


但是SSLSocket不包含获取此类信息的api。
我阅读了有关jsse.jar的源代码,发现
在sslhandshake期间,SSLSocket使用sun.security.ssl.ServerHandshaker完成整个处理,并且ServerHandshaker更新了ClientHello来恢复此操作

    void processMessage(byte paramByte, int paramInt) throws IOException {
    if ((this.state >= paramByte) && (this.state != 16) && (paramByte != 15)) {
        throw new SSLProtocolException("Handshake message sequence violation, state = " + this.state + ", type = " + paramByte);
    }
    switch (paramByte) {
    case 1:
        HandshakeMessage.ClientHello localClientHello = new HandshakeMessage.ClientHello(this.input, paramInt);
        clientHello(localClientHello);
        break;
    case 11:
        if (this.doClientAuth == 0) {
            fatalSE((byte) 10, "client sent unsolicited cert chain");
        }
        clientCertificate(new HandshakeMessage.CertificateMsg(this.input));
        break;
    case 16:
        SecretKey localSecretKey;
        switch (this.keyExchange) {
        case K_RSA:
        case K_RSA_EXPORT:
            RSAClientKeyExchange localRSAClientKeyExchange = new RSAClientKeyExchange(this.protocolVersion, this.clientRequestedVersion,
                    this.sslContext.getSecureRandom(), this.input, paramInt, this.privateKey);

            localSecretKey = clientKeyExchange(localRSAClientKeyExchange);
            break;
        case K_KRB5:
        case K_KRB5_EXPORT:
            localSecretKey = clientKeyExchange(new KerberosClientKeyExchange(this.protocolVersion, this.clientRequestedVersion,
                    this.sslContext

                            .getSecureRandom(),
                    this.input,

                    getAccSE(), this.serviceCreds));

            break;
        case K_DHE_RSA:
        case K_DHE_DSS:
        case K_DH_ANON:
            localSecretKey = clientKeyExchange(new DHClientKeyExchange(this.input));
            break;
        case K_ECDH_RSA:
        case K_ECDH_ECDSA:
        case K_ECDHE_RSA:
        case K_ECDHE_ECDSA:
        case K_ECDH_ANON:
            localSecretKey = clientKeyExchange(new ECDHClientKeyExchange(this.input));
            break;
        default:
            throw new SSLProtocolException("Unrecognized key exchange: " + this.keyExchange);
        }
        calculateKeys(localSecretKey, this.clientRequestedVersion);
        break;
    case 15:
        clientCertificateVerify(new HandshakeMessage.CertificateVerify(this.input, getLocalSupportedSignAlgs(), this.protocolVersion));
        break;
    case 20:
        if (!receivedChangeCipherSpec()) {
            fatalSE((byte) 40, "Received Finished message before ChangeCipherSpec");
        }
        clientFinished(new HandshakeMessage.Finished(this.protocolVersion, this.input, this.cipherSuite));
        break;
    default:
        throw new SSLProtocolException("Illegal server handshake msg, " + paramByte);
    }
    if (this.state < paramByte) {
        if (paramByte == 15) {
            this.state = (paramByte + 2);
        } else {
            this.state = paramByte;
        }
    }
}


问题是我无法从sslsocket对象获取HandshakeMessage.ClientHello。

最佳答案

从理论上讲,这似乎是可能的,但是我还没有看到任何准备使用Java代码的东西。请看“准备ClientHello分析器”部分中的JSSE Reference Guide,它为解决您的问题提供了开始。

08-04 22:04