6

我需要为我正在开发的应用程序使用基于 TLS 的 TCP 套接字。我已经经历了几十个例子,虽然我通过握手没有问题,但我似乎无法通过任何方式读取输入流(尝试了很多,包括 readline()、读取字符数组等)。每次我尝试时,应用程序都会在该位置冻结。如果我调试,它永远不会进入下一行代码。

在一个尝试的解决方案中,我决定转而使用 SSLEngine,因为这应该是 Java 1.5 对 java.nio 的 SSL 答案。但是,我发现了一个示例(此处:http ://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/samples/sslengine/SSLEngineSimpleDemo.java ),这有点令人困惑我,我还没有成功地实施它。当我尝试时, unwrap() 调用产生一个空缓冲区,我知道(通过在命令行上使用 OpenSSL)有问题的服务将数据推回管道。

欢迎提出建议,我已经在这方面花费了太多时间。以下是相关代码:

SSLEngine engine = sslContext.createSSLEngine(uri.getHost(), uri.getPort());
            engine.setUseClientMode(true);
            engine.beginHandshake();
            SSLSession session = engine.getSession();
            int bufferMax = session.getPacketBufferSize();
            int appBufferMax = session.getApplicationBufferSize() + 50;
            ByteBuffer cTo = ByteBuffer.allocateDirect(bufferMax);
            ByteBuffer sTo = ByteBuffer.allocateDirect(bufferMax);

            ByteBuffer out = ByteBuffer.wrap(sessionId.getBytes());
            ByteBuffer in = ByteBuffer.allocate(appBufferMax);


            debug("sending secret");
            SSLEngineResult rslt = engine.wrap(out, cTo);
            debug("first result: " + rslt.toString());
            sTo.flip();
            rslt = engine.unwrap(sTo, in);
            debug("next result" + rslt.toString());
4

4 回答 4

1

此实现缺少一些关键部分。即握手可以在几个状态 NEED_WRAP、NEED_UNWRAP、NEED_TASK 之间反弹来协商连接。这意味着您不能只调用一个然后再调用另一个。您将需要遍历状态,直到握手完成。

   while (handshaking) {
      switch (state) {
          case NEED_WRAP:
              doWrap();
              break;
          case NEED_UNWRAP:
              doUnwrap();
              break;
          case NEED_TASK:
              doTask();
              break;
        }
    }

Java SSL 和 NIO 的完整工作示例

话虽如此,您应该知道Android 上的 SSLEngine 已损坏。Google 建议根据该线程使用线程并阻塞套接字。

于 2012-10-31T16:32:28.097 回答
1

我写了一些东西来让使用 SSLEngine 更容易。它可以与 NIO 或其他用例一起使用。在这里可用 SSLFacade

于 2013-06-25T17:51:37.400 回答
0

unwrap()如果解包的是 SSL 握手消息或警报,而不是应用程序数据,则可以产生一个空缓冲区。这里没有足够的信息可以说更多。之后发动机状态如何?

于 2012-04-02T03:56:14.867 回答
0

beginHandshake不进行握手,它只是用于通知 SSLEngine 您要为下一次调用 wrap/unwrap 执行握手。当您想再次握手时,它很有用。对于第一个,不需要它,因为第一次调用 wrap 将启动握手。

此外,您必须检查 wrap 和 unwrap 方法的结果,以了解所有数据是否已正确编码。您可能必须多次调用这些方法来处理所有数据。

以下链接可能会有所帮助: http: //onjava.com/onjava/2004/11/03/ssl-nio.html

或者这个问题: SSL Handshaking Using Self-Signed Certs and SSLEngine (JSSE)

于 2012-07-20T12:48:12.353 回答