OpenJDK 11 问题 - 客户端在上次 UNWRAP 之前完成握手

2024-05-22

我正在将代码库从 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 的自定义握手逻辑有任何问题吗?


The Java文档的SSLEngine https://docs.oracle.com/en/java/javase/11/docs/api/java.base/javax/net/ssl/SSLEngine.html在类描述的末尾有一个关于并发的注释。

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

如果将两个函数调用与共享对象同步,则每次握手都应在最后一次解包后完成。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenJDK 11 问题 - 客户端在上次 UNWRAP 之前完成握手 的相关文章

  • 我在使用 JavaFX 绘制十字时遇到问题

    我正在尝试编写代码 在网格上对角绘制 3 个形状 前两个形状是正方形和圆形 我能做到 然而 第三种形状让我有些悲伤 我应该画一个十字 T 版本 而不是 X 每次我写出代码时 它看起来就像一个侧面 我知道我只是错过了一些简单的东西 但我真的很
  • 使用 JavaScript 与 Web 服务器通信的 Applet 是否可以迁移到 JWS?

    只是分享一些信息 希望对社区有用 由于各种浏览器停止支持插件 Applet 的可用性已经下降 Google 已决定停止对 NPAPI 插件的支持 EDGE 不支持插件 Firefox 也不鼓励使用插件 Mozilla 可能会跟进该套件 我们
  • Java:while循环冻结程序

    我正在制作一个游戏 我需要每 3 秒更新一次 JProgressBar 为此 我使用 while 循环 问题是我的程序由于 while 循环而冻结 我在其他问题中读到它 他们没有帮助我解决这个问题 我不知道如何解决 这是我的代码 publi
  • 解析 (yyyy-MM-dd) 格式的字符串日期

    我有一个 2013 09 18 形式的字符串 我想将其转换为 java util Date 我正在做这个 SimpleDateFormat sdf new SimpleDateFormat yyyy MM dd Date converted
  • 像 Google Play 商店一样在垂直 RecyclerView 中动态不同图像水平 RecyclerView

    我一直在关注这个教程 http android pratap blogspot co za 2015 12 horizo ntal recyclerview in vertical html http android pratap blog
  • 如何将完整的日期格式拆分为日期和时间?

    我有很多格式为我的示例所示的字符串 我必须解析它们 我正在尝试确定今天是哪根弦 我的问题是 时间快到了 我只需要比较那个日期 接下来我想检查时间是否在 after 和 before 的两个时间戳 HH mm ss 之间 但存在问题 日期几乎
  • 模式更新后 jOOQ 生成的类的运行时验证?

    我用org jooq util DefaultGenerator在构建过程中生成 jOOQ 类来表示我的数据库模式 当应用程序运行时 架构预计会在应用程序不知情的情况下发生更改 此类更改可能与已生成的代码兼容 也可能不兼容 如何在运行时检测
  • Java - 调整图像大小而不损失质量

    我有 10 000 张照片需要调整大小 因此我有一个 Java 程序来执行此操作 不幸的是 图像的质量损失很大 而且我无法访问未压缩的图像 import java awt Graphics import java awt AlphaComp
  • Java 声音可视化器

    我正在尝试制作一个java声音可视化工具 但我完全不知道如何在实时处理音频后立即从提取的音频中获取字节 我可以将程序与 wav 文件同步 但这不是我想要做的 我想用程序生成声音 然后播放它 而不将其保存在任何地方 谢谢您的帮助 本文可以帮助
  • 使用 VirtualDocumentRoot 的 SSL 虚拟主机

    我在 ubuntu 16 04 VM 上进行开发工作 当我处理多个项目时 为了让我的生活更轻松 我使用 VirtualDocumentRoot 和主机文件使用 dev 域从我的主文件夹中服务器站点 在 000 default conf 我有
  • Jersey 和 Spring 中的全局异常处理?

    我正在使用 Jersey 和 Spring 3 2 以及 Open CMIS 开发 RESTful Web 服务 我没有使用 Spring 的 MVC 模式 它只是 Spring IOC 和 Jersey SpringServlet 控制器
  • 为什么replaceAll在这行代码中不起作用? [复制]

    这个问题在这里已经有答案了 String weatherLocation weatherLoc 1 toString weatherLocation replaceAll how weatherLocation replaceAll wea
  • SQlite 获取最近的位置(带有纬度和经度)

    我的 SQLite 数据库中存储有纬度和经度的数据 我想获取距我输入的参数最近的位置 例如我当前的位置 纬度 经度等 我知道这在 MySQL 中是可能的 并且我已经做了相当多的研究 SQLite 需要一个自定义外部函数来实现半正弦公式 计算
  • Eclipse Juno 指标插件

    Eclipse JUNO 版本有哪些 Eclipse 指标插件 我尝试了一些通用指标插件 但没有一个能够在 Eclipse 的 JUNO 版本中正常运行 差点忘了 我们正在使用 Java 作为编程语言 我想要诸如圈复杂度 代码行数 方法长度
  • gwt 文本框添加更改处理程序

    我有一个从设计师那里收到的文本框 但是我在 GWT 中编写了操作 问题是文本框为空 但是当通过按下按钮用值填充文本框时 将显示警报框 通知值已更改 但没有成功 帮助我 TextBox zip1 null function onModuleL
  • “强制更新快照/版本” - 这是什么意思

    在 Maven 项目中 选择 更新项目 时 有一个名为 强制更新快照 版本 的选项 它有什么作用 强制更新快照 版本 就像运行以下命令 mvn U install U 也可以用作 update snapshot 看here http boo
  • 在Java内存管理中,“PS”代表什么?

    每当我看到 Java 中对内存的引用时 各种空格总是以 PS 为前缀 PS 是什么意思 它开始困扰我 到目前为止我唯一的猜测是 泳池空间 但这将是多余的 例子 PS伊甸园空间 PS 幸存者空间 PS 终身空间 老一代 PS Perm Gen
  • Android - 从渲染线程内结束活动

    下午好 我不熟悉 android 中的活动生命周期 并且一直在尽可能地阅读 但我不知道如何以良好的方式解决以下问题 我有一个使用 GLSurfaceView 的活动来在屏幕上绘制各种内容 在这个 GLSurfaceView 的渲染线程中 我
  • Java有没有类似微软CHESS的工具?

    是否有类似于 Microsoft 的现有 Java 工具CHESS http research microsoft com chess 或者 CHESS 源代码是否开放 以便我可以尝试将其转换为 Java 谷歌的织线工 http code
  • removeall 和removeif 的用例

    我找到了这个 fun main val list MutableList

随机推荐