Android SSLEngine的例子

Pau*_*aul 6 android sslengine

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

在尝试的解决方案中,我决定转而使用SSLEngine,因为这应该是针对SSL的java.nio的Java 1.5答案.但是,我找到了一个例子(这里: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());
Run Code Online (Sandbox Code Playgroud)

Cam*_*mer 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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

Java SSL 和 NIO 的完整工作示例

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