首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >OpenJDK 11问题-客户端在上次解包之前已完成握手

OpenJDK 11问题-客户端在上次解包之前已完成握手
EN

Stack Overflow用户
提问于 2018-12-21 06:15:35
回答 2查看 420关注 0票数 6

我正在将我们的代码库从Oracle Java 1.8.0_131迁移到OpenJDK 11.0.1。我们有实现nio-ssl套接字通道的代码。在Java8中,客户端/服务器握手工作得很好。在Java11中,客户端在从服务器解开最后一个握手消息之前完成握手。

为了产生这个问题,我只是在客户端和服务器之间建立了一个连接,并让它们执行SSL握手。我不会通过发送任何额外的数据。

我使用java8建立连接,并得到下面的输出。然后,我使用java11编译、构建和运行相同的代码,并得到下面的其他输出。我没有更改我的任何代码。

我在客户端和服务器上都有一些日志记录,以显示它们在握手中的哪一步。

日志输出Java 8-客户端

代码语言:javascript
运行
复制
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-服务器

代码语言:javascript
运行
复制
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 -客户端

代码语言:javascript
运行
复制
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 -服务器

代码语言:javascript
运行
复制
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

握手代码

代码语言:javascript
运行
复制
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
  }
}

不幸的是,我的代码驻留在一个有空隙的环境中,所以将它粘贴到这里并不容易。我是手工输入的,所以括号和制表符可能不会对齐。

要点是,在2067字节的包装之后,hs = res.getHandshakeStatus(...)在客户机上返回FINISHED,而实际上它似乎应该返回NEED_UNWRAP。如果我将其更改为hs = engine.getHandshakeStatus(),它将返回NOT_HANDSHAKING

在服务器机器上,hs = engine.getHandshakeStatus()在运行最后一个任务后返回NEED_WRAP,导致它包装最后72个字节。

为什么我的客户端机器上的SSLEngine给我一个“完成”的握手状态,而仍然有72个字节的数据需要从服务器上解开?还有没有人对Java11的自定义握手逻辑有任何问题?

EN

回答 2

Stack Overflow用户

发布于 2018-12-21 08:08:24

JavaDoc of SSLEngine在类描述的末尾有一个关于并发性的注释。

因此,我假设您的问题看起来像是基于竞争条件的并发问题。在从JDK8迁移到JDK11之后,同时调用wrapunwrap函数的方式可能会有所不同。您提供的示例代码没有任何同步语句。

如果将两个函数调用与一个共享对象同步,那么每次在最后一次展开之后握手都应该完成。

票数 3
EN

Stack Overflow用户

发布于 2021-04-11 19:28:25

对于任何想用SSLEngine解决这个问题的人来说,这个问题的原因是在TLS1.3中定义的握手后消息:https://www.rfc-editor.org/rfc/rfc8446#section-4.6要在你的应用程序中正确处理这样的消息,你必须检查unwrap调用的握手状态,如果状态是完成,但握手已经完成,它很可能是由握手后消息和数据引起的,必须再次读取和解包。另请参阅:https://stackoverflow.com/a/57409789/6561198

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53876788

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档