2012-03-30 6 views
6

私が取り組んでいるアプリケーションのTLS上でTCPソケットを使って作業する必要があります。私は数十の例を見てきましたが、私はハンドシェイクをうまくやっても問題はありませんが、何らかの方法で入力ストリームを読むことはできません(readline()、文字配列への読み込みなど)。試してみるたびに、その場所でアプリがフリーズします。私がデバッグした場合、次のコード行には決して行きません。Android SSLEngineの例

試行された解決策では、SSLEngineを使用するように移行しました.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()); 
+0

アップデートとして、(rslt.getStatus()!= SSLEngineResult.Status.OK)の間にアンラップコールでループ処理を試みましたが、決してデータが入力されず、ステータスがOKになりませんでした。 – Paul

+0

このコードを通常のJavaアプリケーションで実行しようとしましたか?それは少なくともAndroidに固有の問題かどうかを判断するのに役立ちます。 – elevine

+0

ええ、私はそれがアンドロイドに固有だとは思わない、私はちょうどアンドロイドプロジェクトでそれをやっていることが起こる。 – Paul

答えて

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; 
     } 
    } 

A full working example of Java SSL and NIO

あなたはAndroid is brokenにSSLEngineの認識すべきである、と述べた今。そのスレッドに応じてスレッドとブロッキングソケットを使用することをおすすめします。

0

unwrap()は何が開封された場合は、空のバッファを得ることができることは、SSLハンドシェイクメッセージや警告ではなく、アプリケーションデータでした。もっと多くのことを言うには十分な情報がありません。後でエンジンの状態はどうでしたか?

0

beginHandshakeハンドシェイクを続行しません。次回のラップ/ラップ解除コールでハンドシェイクを実行することをSSLEngineに通知するために使用されます。 別のハンドシェイクをしたいときに便利です。最初の呼び出しでは、折り返しの最初の呼び出しがハンドシェイクを開始するため、必要ありません。

さらに、すべてのデータが正しくエンコードされているかどうかを調べるには、ラップアンドラッピングの結果を確認する必要があります。すべてのデータを処理するには、メソッドを何回か呼び出さなければならない場合があります。

次のリンクは役立つかもしれない: http://onjava.com/onjava/2004/11/03/ssl-nio.html

それとも、この質問: SSL Handshaking Using Self-Signed Certs and SSLEngine (JSSE)

0

私はSSLEngineを使用して簡単にするために何かを書いています。 NIOやその他のユースケースで使用できます。 Available here SSLFacade