モジュール java.base
パッケージ javax.net.ssl

クラスSSLSocket

java.lang.Object
java.net.Socket
javax.net.ssl.SSLSocket
すべての実装されたインタフェース:
Closeable, AutoCloseable

public abstract class SSLSocket extends Socket
このクラスはSocketを拡張し、"セキュア・ソケット・レイヤー" (SSL)やIETF "トランスポート層のセキュリティ" (TLS)プロトコルのようなプロトコルを使って安全なソケットを提供します。

これらのソケットは、通常のストリーム・ソケットですが、TCPなどのベースとなるネットワーク・トランスポート・プロトコル上にセキュリティ保護層を追加します。 次のセキュリティ保護が行われます。

  • 整合性の保護 SSLがメッセージを盗聴による改ざんから保護する。
  • 認証 ほとんどのモードでは、SSLによりピア認証が提供される。 通常は、サーバー認証が行われる。サーバーからの要求に応じて、クライアント認証も行われる。
  • 機密性(プライバシの保護) ほとんどのSSLモードでは、クライアントとサーバー間で送信されるデータが暗号化され、データの機密性が保護される。 この結果、受動的な盗聴によって、金融情報や個人情報などの機密性の高いデータが盗聴されることがない。

これらのセキュリティ保護は、「暗号化方式群」を使用して指定します。暗号化方式群は、指定されたSSL接続で使用される暗号化アルゴリズムの組合せです。 ネゴシエーション処理時には、2つの終端が同じ暗号化方式群を選択し、その暗号化方式群が両方の環境で使用可能である必要があります。 共通の暗号化方式群がない場合は、SSL接続を確立できず、データを交換できません。

使用される暗号化方式群は、「ハンドシェーク」と呼ばれるネゴシエーション・プロセスによって確立されます。 ハンドシェークでは、セッションの作成またはセッションへの参加が行われます。このセッションは、時間の経過とともにさまざまな接続を保護します。 ハンドシェークが完了すると、getSessionメソッドを使用してセッション属性にアクセスできます。 この接続の最初のハンドシェークは、次の3つのうちいずれかの方法で開始できます。

  • startHandshakeを呼び出し、ハンドシェークを明示的に開始する。
  • このソケットに対してアプリケーション・データの読み込みまたは書込みを行うと、ハンドシェークが暗黙的に開始される。
  • getSessionを呼び出すと、有効なセッションが現在存在しない場合はセッションが設定され、ハンドシェークが暗黙的に開始される。

なんらかの理由でハンドシェークが失敗した場合、SSLSocketが閉じ、通信できなくなります。

暗号化方式群を使用するときは、2つのグループについて理解する必要があります。

  • サポートされる暗号化方式群: SSL実装でサポートされるすべての暗号化方式群。 このリストは、getSupportedCipherSuitesを使用して報告される。
  • 有効になっている暗号化方式群。サポートされる暗号化方式群の完全なセットより少ないことがある。 このグループは、setEnabledCipherSuitesメソッドを使用して設定し、getEnabledCipherSuitesメソッドを使用して照会する。 新しいソケットでは、最小限の推奨構成を表すデフォルトの暗号化方式群が、初期状態で使用可能になっている。

デフォルトの実装で使用可能にする暗号化方式群では、サーバーを認証し、機密性が保証されなければいけません。 サーバー認証が行われず機密性が保証されない暗号化方式群を選択する場合は、サーバー認証が行われず非公開性が保証されない(暗号化されない)通信が使用されることに2つの終端が明示的に同意する必要があります。

SSLSocketが最初に作成されるとき、ハンドシェイクは行われないので、アプリケーションは最初に通信プリファレンスを設定することができます: どの暗号スイートを使用するか、ソケットをクライアント・モードにするべきか、サーバー・モードにするべきかなどです。しかし、セキュリティは常に、アプリケーション・データが接続を介して送信されるまでに提供されます。

ハンドシェークの完了を伝えるイベント通知を受信するように設定できます。 この場合、2つの追加クラスを利用する必要があります。 HandshakeCompletedEventオブジェクトは、このAPIのユーザーによって登録されたHandshakeCompletedListenerインスタンスに渡されます。 SSLSocketは、SSLSocketFactoryによって、またはSSLServerSocketからの接続をacceptによって作成されます。

SSLソケットの動作には、クライアント・モードまたはサーバー・モードがあります。 ハンドシェーク・プロセスを開始するピア、および各ピアから送信されるメッセージは、モードによって決まります。 接続には、クライアントとサーバーが1つずつ必要です。この要件を満たしていない場合、ハンドシェークは正しく行われません。 最初のハンドシェークが開始されてからは、ネゴシエーションをやり直す場合であっても、ソケットはクライアント・モードとサーバー・モードを切り替えられません。

このクラスのメソッドによって返されるApplicationProtocol String値は、ピアによって送信されるネットワーク・バイト表現内にあります。 バイトは、比較のために直接比較するか、UnicodeのString形式に変換できます。

     String networkString = sslSocket.getHandshakeApplicationProtocol();
     byte[] bytes = networkString.getBytes(StandardCharsets.ISO_8859_1);

     //
     // Match using bytes:
     //
     //   "http/1.1"                       (7-bit ASCII values same in UTF-8)
     //   MEETEI MAYEK LETTERS "HUK UN I"  (Unicode 0xabcd->0xabcf)
     //
     String HTTP1_1 = "http/1.1";
     byte[] HTTP1_1_BYTES = HTTP1_1.getBytes(StandardCharsets.UTF_8);

     byte[] HUK_UN_I_BYTES = new byte[] {
         (byte) 0xab, (byte) 0xcd,
         (byte) 0xab, (byte) 0xce,
         (byte) 0xab, (byte) 0xcf};

     if ((Arrays.compare(bytes, HTTP1_1_BYTES) == 0 )
             || Arrays.compare(bytes, HUK_UN_I_BYTES) == 0) {
        ...
     }

     //
     // Alternatively match using string.equals() if we know the ALPN value
     // was encoded from a String using a certain character set,
     // for example UTF-8.  The ALPN value must first be properly
     // decoded to a Unicode String before use.
     //
     String unicodeString = new String(bytes, StandardCharsets.UTF_8);
     if (unicodeString.equals(HTTP1_1)
             || unicodeString.equals("\uabcd\uabce\uabcf")) {
         ...
     }
 

APIのノート:
接続が不要になった場合、クライアント・アプリケーションとサーバー・アプリケーションは、それぞれの接続の両側を閉じる必要があります。 これは、Socket.close()を呼び出すことによって1つのショットで行うか、またはハーフ・クローズ接続をサポートできるプロトコル・バージョンで役立つSocket.shutdownOutput() / Socket.shutdownInput()を使用して各サイドを個別に閉じることによって行うことができます。

入力ストリームのクローズは、最初にクローズされるピア出力ストリームに依存する場合があります。 適切な方法で(たとえば、ピア書込みクローズ通知を受信する前にSocket.shutdownInput()がコールされます)に接続がクローズされない場合、エラーが発生したことを示す例外が発生する可能性があります。

SSLSocketが閉じられると、再利用できなくなります: 新しいSSLSocketを作成する必要があります。

導入されたバージョン:
1.4
関連項目: