3

コード全体がかなり複雑なので、私は直接要点に来ています。コードは次のとおりです

SSLContext ctx = SSLContext.getInstance("TLS");

getInstance(String protocol) メソッドのドキュメントを読むと、

This method traverses the list of registered security Providers, starting
with the most preferred Provider. A new SSLContext object encapsulating
the SSLContextSpi implementation from the first Provider that supports the
specified protocol is returned.

Note that the list of registered providers may be retrieved via the
Security.getProviders() method.

私にとって Security.getProviders() メソッドは次のプロバイダーを提供します

ここに画像の説明を入力

「TLS」プロトコルがcom.sun.net.ssl.internal.ssl.Provider(インデックス 2 ) にあり、常に選択されていることを確認しました。

しかし、対応する SSLContextSpi オブジェクトは Java 6 と Java 7 で異なってきます。Java 6 では取得com.sun.net.ssl.internal.ssl.SSLContextImpl@7bbf68a9し、Java 7 では取得してsun.security.ssl.SSLContextImpl$TLS10Context@615ece16います。後でSSLソケットを作成するときに、それらが異なるクラスであるため、これは非常に悪い影響を及ぼしています。

では、なぜこれが起こっているのですか?回避策はありますか?コンテキストにカプセル化された同じcom.sun.net.ssl.internal.ssl.SSLContextImpl@7bbf68a9SSLContextSpi オブジェクトが必要ですcom.sun.net.ssl.internal.ssl.Provider(どちらの場合も同じです)。

4

1 に答える 1

5

後でSSLソケットを作成するときに、それらが異なるクラスであるため、これは非常に悪い影響を及ぼしています。

これは悪い影響ではありません。パブリック API のファクトリから取得する実際のクラスは、JRE 実装の裁量に任されています。これらの具体的なクラスは、パブリック API の一部ではありません。

Java 6 と Java 7 で異なるクラスを取得するという事実は、実際には問題ではありません。同じ名前だったとしても、比較する意味がありません。

編集:

public int read(byte[] b)関数は、長さ 4 のバイト配列を指定すると 1 バイトしか読み取らず、ストリームに 4 バイトがあることも確認しました。

SSLSocketJava 7 では、これを取得すると正しく動作します。実際、この最初の 1 バイトの読み取りはBEAST 防止策によるものであるため、おそらく動作は改善されています。あなたはまったく同じ間違いを犯しているので、その質問に対する私自身の答えをコピーして貼り付けます。


byte[]相手側で書いたのとまったく同じように読んでいると仮定するのは、古典的な TCP の間違いです。実際には SSL/TLS に固有のものではありませんが、TCP 接続でも発生する可能性があります。

TCP (および SSL/TLS) では、リーダーのバッファーがライターのバッファー内のパケットとまったく同じパケット長で満たされるという保証はありません。すべての TCP 保証は順序どおりの配信であるため、最終的にはすべてのデータを取得できますが、ストリームとして扱う必要があります。

これが、TCP を使用するプロトコルがインジケーターと区切り文字に依存して、特定のメッセージの読み取りを停止するタイミングを相手に伝える理由です。

たとえば、HTTP 1.1 は空白行を使用してヘッダーの終了を示し、Content-Length ヘッダーを使用して受信者に予想されるエンティティの長さ (またはチャンク転送エンコーディング) を伝えます。SMTP はまた.、メッセージの最後に改行を使用します。

独自のプロトコルを設計している場合は、データの意味のある単位として定義したものがいつ区切られるかを受信者が知る方法を定義する必要があります。データを読み取るときは、そのようなインジケーターを読み取り、期待するバイト数を取得するか、定義した区切り文字が見つかるまで、読み取りバッファーに入力します。

于 2013-09-17T18:35:53.077 に答える