【问题标题】:SSL Handshake failure JavaSSL 握手失败 Java
【发布时间】:2017-06-04 23:37:45
【问题描述】:

我在学习 SSL 通信时遇到了这个问题。我正在编写一个简单的客户端,它试图与本地 apache 服务器握手。服务器已启用 https。我将服务器证书添加到所有可能的信任库(jdk 中的一个和程序使用的那个)。但是握手状态永远不会达到 FINISHED。一直卡在 NEED_TASK 状态 我在第一次进入循环时得到一个 sun.security.ssl.Handshaker$DelegatedTask。此后状态为 NEED_TASK 并且任务为空。 .下面的代码我的理解错误\缺陷在哪里?

注意:我从以下教程中获取代码:

http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html#KRB

卡在NEED_TASK状态的握手代码如下:

void doHandshake(SocketChannel socketChannel, SSLEngine engine,
            ByteBuffer myNetData, ByteBuffer peerNetData) throws Exception {

        // Create byte buffers to use for holding application data
        int appBufferSize = engine.getSession().getApplicationBufferSize();
        ByteBuffer myAppData = ByteBuffer.allocate(appBufferSize);
        ByteBuffer peerAppData = ByteBuffer.allocate(appBufferSize);
        // Begin handshake
        engine.beginHandshake();
        SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus();
        int i=0;
        // Process handshaking message
        while (hs != SSLEngineResult.HandshakeStatus.FINISHED &&
            hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
            i++;
            switch (hs) {

            case NEED_UNWRAP:
                // Receive handshaking data from peer
                if (socketChannel.read(peerNetData) < 0) {
                    // The channel has reached end-of-stream
                }

                // Process incoming handshaking data
                peerNetData.flip();
                SSLEngineResult res = engine.unwrap(peerNetData, peerAppData);
                peerNetData.compact();
                hs = res.getHandshakeStatus();

                // Check status
                switch (res.getStatus()) {
                case OK :
                    // Handle OK status
                    break;

                // Handle other status: BUFFER_UNDERFLOW, BUFFER_OVERFLOW, CLOSED

                }
                break;

            case NEED_WRAP :
                // Empty the local network packet buffer.
                myNetData.clear();

                // Generate handshaking data
                res = engine.wrap(myAppData, myNetData);
                hs = res.getHandshakeStatus();

                // Check status
                switch (res.getStatus()) {
                case OK :
                    myNetData.flip();

                    // Send the handshaking data to peer
                    while (myNetData.hasRemaining()) {
                        socketChannel.write(myNetData);
                    }
                    break;

                // Handle other status:  BUFFER_OVERFLOW, BUFFER_UNDERFLOW, CLOSED

                }
                break;

            case NEED_TASK :
                Runnable task =engine.getDelegatedTask();
                if(task!= null) {
                    //task.run();
                    new Thread(task).start();
                }// Handle blocking tasks

                break;

            // Handle other status:  // FINISHED or NOT_HANDSHAKING

            }
        }
        // Processes after handshaking

    }

任何帮助将不胜感激。

【问题讨论】:

  • 您需要在循环内获取握手状态,否则在 NEED_TASK 情况下它永远不会改变,也许其他情况也是如此。状态将保持在 NEED_TASK 直到任务完成。在单独的线程中处理任务确实非常复杂。你可能最好内联运行它,直到你至少让它工作。通过循环写入,您正在做类似的事情。解决这两个问题需要与 Selector 集成,这也非常重要。
  • @EJP 这个任务应该做什么?这个任务卡住是因为我没有将服务器证书添加到任何信任库吗?我只想达到握手的 FINISHED 状态。那是我现在唯一的目标。这个选择器概念是否有一些教程或起始页?
  • 跟信任库有关,不知道是什么。

标签: java ssl https jsse sslengine


【解决方案1】:

问题是我对 engine.getHandShakeStatus() 方法的理解不完整。

我把上面的代码改成

 case NEED_TASK :
            Runnable task =engine.getDelegatedTask();
            if(task!= null) {
                //task.run();
               new Thread(task).start();
            }
            hs = engine.getHandshakeStatus();
            break;

现在它完成了握手

【讨论】:

  • 您需要在每次循环时都这样做,而不仅仅是这里。
  • @EJP ...是的。现在我明白你的意思了。我想如果你能把它和回复一样,我可以把它标记为答案。
猜你喜欢
  • 1970-01-01
  • 2016-09-27
  • 2018-03-31
  • 1970-01-01
  • 2018-07-28
  • 2012-10-11
  • 2015-03-16
  • 2021-12-28
相关资源
最近更新 更多