我正在将代码库从 Oracle Java 1.8.0_131 迁移到 OpenJDK 11.0.1。我们有实现 nio-ssl 套接字通道的代码。在 Java 8 中,客户端/服务器握手工作正常。在 Java 11 中,客户端在解包来自服务器的最后一个握手消息之前完成握手。
为了产生这个问题,我只是在客户端和服务器之间建立连接并让它们执行 SSL 握手。我不会发送任何额外的数据。
我使用 java 8 建立连接并得到以下输出。
然后,我使用 java 11 编译、构建并运行相同的代码,并获得下面的其他输出。我不会更改我的任何代码。
我在客户端和服务器上都有一些日志记录,以显示它们在握手中的哪一步。
日志输出Java 8 - 客户端
SSL Handshake Started
WRAP:OK - BytesProduced=172 BytesConsumed=0
UNWRAP:OK - BytesProduced=0 BytesConsumed=2295
TASK
WRAP:OK - BytesProduced=1815 BytesConsumed=0
WRAP:OK - BytesProduced=269 BytesConsumed=0
WRAP:OK - BytesProduced=6 BytesConsumed=0
WRAP:OK - BytesProduced=85 BytesConsumed=0
UNWRAP:OK - BytesProduced=0 BytesConsumed=6
UNWRAP:OK - BytesProduced=0 BytesConsumed=85
SSL Handshake complete
日志输出 Java 8 - 服务器
SSL Handshake Started
UNWRAP:OK - BytesProduced=0 BytesConsumed=172
TASK
WRAP:OK - BytesProduced=2295 BytesConsumed=0
UNWRAP:OK - BytesProduced=0 BytesConsumed=1815
TASK
UNWRAP:OK - BytesProduced=0 BytesConsumed=269
TASK
UNWRAP:OK - BytesProduced=0 BytesConsumed=6
UNWRAP:OK - BytesProduced=0 BytesConsumed=85
WRAP:OK - BytesProduced=6 BytesConsumed=6
WRAP:OK - BytesProduced=85 BytesConsumed=0
SSL Handshake complete
日志输出 Java 11 - 客户端
SSL Handshake Started
WRAP:OK - BytesProduced=422 BytesConsumed=0
UNWRAP:OK - BytesProduced=0 BytesConsumed=160
TASK
WRAP:OK - BytesProduced=6 BytesConsumed=0
UNWRAP:OK - BytesProduced=0 BytesConsumed=6
UNWRAP:OK - BytesProduced=0 BytesConsumed=2204
TASK
WRAP:OK - BytesProduced=2067 BytesConsumed=0
SSL Handshake complete
UNWRAP:OK - BytesProduced=0 BytesConsumed=72
日志输出 Java 11 - 服务器
SSL Handshake Started
UNWRAP:OK - BytesProduced=0 BytesConsumed=422
TASK
WRAP:OK - BytesProduced=160 BytesConsumed=0
WRAP:OK - BytesProduced=6 BytesConsumed=0
WRAP:OK - BytesProduced=2204 BytesConsumed=0
UNWRAP:OK - BytesProduced=0 BytesConsumed=6
UNWRAP:OK - BytesProduced=0 BytesConsumed=2067
TASK
WRAP:OK - BytesProduced=72 BytesConsumed=0
SSL Handshake complete
握手代码
engine.beginHandshake();
HandshakeStatus hs = engine.getHandshakeStatus();
while(hs != HandshakeStatus.FINISHED && hs != HandshakeStatus.NOT_HANDSHAKING){
switch(hs){
case NEED_WRAP:
SSLEngineResult res = engine.wrap(myAppData, myNetData)
hs = res.getHandshakeStatus();
switch(res.getStatus()){
case OK:
// write myNetData
case BUFFER_OVERFLOW:
// increase size of myNetData
case BUFFER_UNDERFLOW:
// throw exception
case CLOSED:
// clean up
default:
// throw illegal state exception
}
break;
case NEED_UNWRAP:
boolean complete = false;
while(!complete){
/*
* First handle any encrypted data left on buffer
* If there is none, read in more
*/
if(peerNetData.position() > 0 || channel.read(peerNetData) > 0){
peerNetData.flip();
res = engine.unwrap(peerNetData, peerAppData);
hs = res.getHandshakeStatus();
switch(res.getStatus()){
case OK:
complete = true;
peerNetData.compact();
break;
case BUFFER_UNDERFLOW:
// if buffer is full, increase size
// if buffer isn't full, compact and read
case BUFFER_OVERFLOW:
// increase size of peerAppData
case CLOSED:
// cleanup
default:
// throw illegal state exception
}
}
}
break;
case NEED_TASK:
// Run task
hs = engine.getHandshakeStatus();
break;
case FINISHED:
break;
case NOT_HANDSHAKING:
break;
default:
// illegal state
}
}
不幸的是,我的代码驻留在气隙环境中,因此将其粘贴到此处并不容易。我是手写的,所以括号和制表符可能不会对齐。
要点是hs = res.getHandshakeStatus(...)
回报FINISHED
在客户端计算机上,在 2067 字节换行之后,看起来应该返回NEED_UNWRAP
。如果我把它改成hs = engine.getHandshakeStatus()
,它返回NOT_HANDSHAKING
.
在服务器机器上,hs = engine.getHandshakeStatus()
回报NEED_WRAP
运行最后一个任务后,导致它 WRAP 最后 72 个字节。
当服务器仍有 72 字节数据需要 UNWRAP 时,为什么我的客户端计算机上的 SSLEngine 会给出“FINISHED”握手状态?还有其他人对 Java 11 的自定义握手逻辑有任何问题吗?