我想从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,它为解决您的问题提供了开始。