2

これは、「自己署名証明書とSSLEngine(JSSE)を使用したSSLハンドシェイク」のフォローアップ質問です。

同じポートでSSLメッセージと非SSLメッセージを処理できるNIOWebサーバーを実装しました。SSLメッセージと非SSLメッセージを区別するために、インバウンド要求の最初のバイトをチェックして、SSL/TLSメッセージであるかどうかを確認します。例:

byte a = read(buf);
if (totalBytesRead==1 && (a>19 && a<25)){
    parseTLS(buf);
}

parseTLS()メソッドでは、SSLEngineをインスタンス化し、ハンドシェイクを開始し、メッセージをラップ/アンラップします。ほとんどの最新のWebブラウザー(Firefox 10、IE 9、Safari 5など)ではすべてが正常に機能しているようです。

問題は、IE6のような古いWebブラウザとJavaのURLConnectionクラスのようなライブラリがSSL/TLSハンドシェイクを異なる方法で開始するように見えることです。たとえば、IE 6の最初の数バイトは次のようになります(16進値)。

80 4F 01 03 00 ...

メッセージをSSLEngineに渡すと、メッセージを認識していないようで、例外がスローされます。

javax.net.ssl.SSLException: Unsupported record version Unknown-0.0

では、IE 6とJavaのURLConnectionクラスは正確には何を送信しているのでしょうか?これは、JSSESSLEngineがサポートできる有効なSSL/ TLSメッセージですか?別のメッセージを送信するには、前処理を行う必要がありますか、それともクライアントと交渉する必要がありますか?

前もって感謝します!

アップデート

ブルーノとEJP、そしてさらにいくつかのデバッグのおかげで、私は何が起こっているのかをはるかによく理解できました。ブルーノが正しく指摘したように、IE6およびJava6クライアントはSSLv2ClientHelloを介して送信しています。以前のコメントの1つとは異なり、Java 1.6のSSLEngineは、実際にはSSLv2メッセージをアンラップし、クライアントに送り返すための有効な応答を生成できます。以前に報告したSSLExceptionは私の側のエラーであり、SSLEngineとは関係ありません(クライアントがデータの送信を完了したと誤って想定し、SSLEngineがより多くのデータのラップ解除を期待していたときに空のByteBufferになってしまいました)。

4

1 に答える 1

4

これはSSLv2クライアントHelloのように見えます(TLS仕様を参照)

SSLバージョン2.0サーバーをサポートするTLS1.1クライアントは、SSLバージョン2.0クライアントのhelloメッセージ[SSL2]を送信する必要があります。TLSサーバーは、同じ接続ポートでSSL 2.0クライアントをサポートする場合は、いずれかのクライアントhello形式を受け入れる必要があります。バージョン2.0仕様からの唯一の逸脱は、値が3のバージョンを指定する機能と、CipherSpecでより多くの暗号化タイプをサポートすることです。

  • 80 4Fは長さであり、上位ビットは1に設定する必要があります(msg_length説明を参照)。
  • 01メッセージタイプです(Client Hello)
  • 03 00サポートされている最高のバージョンです(ここではSSLv3)

Java 7以降、これはデフォルトで無効になっています

編集:

明確にするために、これは実際にはSSLv2クライアントハローではありません。これはSSLv2形式のSSLv3用クライアントハローです。この場合、サーバーは(適切な)SSLv3 Server Hello(03 00要求されたバージョン番号に対応)で応答します。同じことがTLS1.0、1.1、および1.2でも機能しますが、この形式の使用は徐々に非推奨になります。

JSSE 7SSLServerSocketは、このようなClient Helloを引き続き理解し、SSLv3 / TLS1.xServerHelloで適切に応答します。

于 2012-04-17T20:01:38.480 に答える