用語と定義
- はじめに
- 特長と利点
- JSSE 標準 API
- SunJSSE プロバイダ
- 新機能
- 関連ドキュメント
- Secure Sockets Layer (SSL) プロトコルの概要
- SSL を使用することの利点
- SSL のしくみ
- 主要なクラス
- クラスの関係
- コアクラスとインタフェース
- SocketFactory および ServerSocketFactory クラス
- SSLSocketFactory および SSLServerSocketFactory クラス
- SSLSocket および SSLServerSocket クラス
SSLEngine
による非ブロック入出力- SSLSession インタフェース
- HttpsURLConnection クラス
- サポートクラスとインタフェース
- SSLContext クラス
- TrustManager インタフェース
- TrustManagerFactory クラス
- X509TrustManager インタフェース
- KeyManager インタフェース
- KeyManagerFactory クラス
- X509KeyManager インタフェース
- TrustManager と KeyManager の関連性
- 二次サポートクラスおよびインタフェース
- SSLSessionContext インタフェース
- SSLSessionBindingListener インタフェース
- SSLSessionBindingEvent クラス
- HandShakeCompletedListener インタフェース
- HandShakeCompletedEvent クラス
- HostnameVerifier インタフェース
- X509Certificate クラス
- 旧バージョン (JSSE 1.0.x) の実装クラスおよびインタフェース
- JSSE のカスタマイズ
- インストールディレクトリ<java-home>
- カスタマイズ
- JCE およびハードウェア高速化/スマートカードのサポート
- JCE の使用法
- ハードウェアアクセラレータ
- スマートカードをキーストアおよびトラストストアとして使用するための JSSE の構成
- 複数の動的キーストア
- Kerberos 符号化方式
- Kerberos 要件
- ピアのアイデンティティ情報
- セキュリティマネージャ
- トラブルシューティング
- 構成上の問題点
- デバッグユーティリティ
付録 A: 標準名
- コード例
- 安全でないソケットから安全なソケットへの変換
- JSSE サンプルコードの実行
- JSSE で使用するキーストアの作成
ネットワークを通じてやり取りされるデータには、意図された受信者以外の人も、簡単にアクセスできます。データにパスワードやクレジットカード番号などの個人情報が含まれる場合、権限のない者がデータを理解できないよう、手段を講じる必要があります。また、意図的であるかどうかにかかわらず、通信中にデータが変更されないようにすることも重要です。Secure Sockets Layer (SSL) および Transport Layer Security (TLS) は、ネットワークを通じたデータの送信時に、データの機密性および整合性を保護するために設計されたプロトコルです。Java Secure Socket Extension (JSSE) により、安全なインターネット通信が可能になります。JSSE では、Java バージョンの SSL および TLS プロトコルのフレームワークおよび実装が提供されます。また、データ暗号化、サーバ認証、メッセージの整合性のほか、オプションでクライアント認証の機能が含まれます。JSSE を使うと、開発者は Hypertext Transfer Protocol (HTTP)、Telnet、FTP など、TCP/IP のアプリケーションプロトコルを実行するクライアントとサーバの間で、安全なデータのやり取りを実現できます(SSL の概要については、「Secure Sockets Layer (SSL) プロトコルの概要」を参照)。
JSSE は、基盤となる複雑なセキュリティアルゴリズムや「ハンドシェーク」機構を抽象化することにより、識別するのが難しく、しかし危険なセキュリティ上の弱点が生まれるリスクを最小限に抑えます。また、JSSE を開発者がアプリケーションに直接統合できる構築ブロックとして使うと、アプリケーション開発が簡単になります。
従来の JSSE は、JavaTM 2 SDK, Standard Edition (J2SDK) バージョン 1.2 と 1.3 のオプションパッケージ (標準拡張) でした。v 1.4 以降の J2SDK には、JSSE が統合されています。
JSSE は、アプリケーションプログラミングインタフェース (API) フレームワークと、その API の実装を提供します。JSSE API は、Java 2 SDK v 1.4 以降の
java.security
パッケージおよびjava.net
パッケージで定義されたコアネットワークと暗号化サービスを補い、拡張されたネットワークソケットクラス、トラストマネージャ、キーマネージャ、SSLContext、およびソケット作成動作をカプセル化するソケットファクトリのフレームワークを提供します。また、Java Development Kit (JDK) 1.1 ベースのプラットフォームと互換性がある公開鍵証明書 API も制限付きで提供します。ただし、この制限付きのjavax.security.cert
証明書 API は JSSE 1.0.x との下位互換のためだけに提供されるので、使用しないようにしてください。標準のjava.security.cert
証明書 API を使用してください。ソケット API は J2SE 5 のブロック化入出力モデルを基にしているため、実装段階で固有の入出力メソッドを選択できるようにするために非ブロックSSLEngine
API が導入されました。JSSE API では、SSL バージョン 2.0 および 3.0 のほか、Transport Layer Security (TLS) 1.0 をサポートします。これらのセキュリティプロトコルは、通常の双方向のストリームソケットをカプセル化し、JSSE API は認証、暗号化、および整合性保護の透過的なサポートを追加します。J2SDK v 1.4 以降の JSSE 実装では、SSL 3.0 と TLS 1.0 が実装されます。SSL 2.0 は実装しません。
すでに説明したように、JSSE は Java 2 プラットフォームのセキュリティコンポーネントで、Java Cryptography Architecture (JCA) フレームワーク上の別の場所にあるものと同じ設計方針に基づいています。暗号化に関するセキュリティコンポーネントのこのフレームワークにより、実装の独立性と、可能な場合にはアルゴリズムの独立性を実現できます。JSSE は、JCA で定義されたのと同じプロバイダアーキテクチャを使用します。
Java 2 プラットフォームの他のセキュリティコンポーネントには、Java 暗号化拡張機能 (JCE)、Java 認証・承認サービス (JAAS)、および Java セキュリティツール があります。JSSE は JCE と同じ概念およびアルゴリズムを多数含んでいますが、単純なストリームソケット API の下でこれらを自動的に適用します。
JSSE API は、その他の SSL/TLS プロトコルと公開鍵インフラストラクチャ (PKI) 実装をシームレスにプラグインできる設計になっています。開発者が、リモートホストの信頼性やリモートホストに送信する認証鍵データを決定するロジックを提供することもできます。
注: JSSE API では基盤となる実装 (プラグイン可能性) を交換できますが、米国の輸出制限により、1.4.x のリリースでは SSL/TLS アルゴリズムを置き換えることは許可されませんでした。その後、最新の米国政府の輸出制限事項では、付録の「プロバイダプラグイン可能性」リストにある符号化方式をサポートしているかぎり、J2SE 5 の JSSE で任意の JSSE プロバイダを使用できるようになっています。なお、TrustManagerFactory
およびKeyManagerFactory
は完全にプラグイン可能です。特長と利点
JSSE には次のような重要な特長があります。
- 100% Pure Java に実装される
- ほとんどの国に輸出できる
- SSL バージョン 2.0 と 3.0 の API をサポートし、SSL バージョン 3.0 を実装する
- TLS バージョン 1.0 に API サポートと実装を提供する
- 安全なチャネルを作成するためにインスタンス化可能なクラスを含む (
SSLSocket
、SSLServerSocket
、およびSSLEngine
)- 安全な通信を開始し、検証するのに使用される SSL ハンドシェーク機能の一部として、符号化方式ネゴシエーションをサポートする
- 通常の SSL ハンドシェーク機能の一部として、クライアントとサーバの認証をサポートする
- SSL プロトコル (HTTPS) でカプセル化された Hypertext Transfer Protocol (HTTP) をサポートする。これにより、HTTPS を使用する Web ページなどのデータにアクセスできる
- メモリ常駐型の SSL セッションを管理するためのサーバセッション管理 API を提供する
- 符号化方式で一般的に使用される複数の暗号化アルゴリズムをサポートする。次の表に示すアルゴリズムが含まれる
JSSE で利用できる暗号化機能
暗号化アルゴリズム *
暗号化処理
鍵の長さ (ビット)
RSA
認証と鍵交換
2048 (認証)
2048 (鍵の交換)
512 (鍵の交換)RC4
バルク暗号化
128
128 (40 が有効)DES
バルク暗号化
64 (56 が有効)
64 (40 が有効)Triple DES
バルク暗号化
192 (112 が有効)
AES
バルク暗号化
256
128Diffie-Hellman
鍵の承認
1024
512DSA
認証
1024
* 注: SunJSSE 実装では、暗号化アルゴリズムのすべてにおいて JavaTM 暗号化拡張機能 (JCE) を使用します。
JSSE 標準 API
JSSE 標準 API は、
javax.net
、javax.net.ssl
、およびjavax.security.cert
パッケージで利用できる API で、次の点をカバーします。
- 安全なソケット (SSL) およびサーバソケット
- SSL/TLS データを生成および消費する非ブロックエンジン (SSLEngine)
- ソケット、サーバソケット、SSL ソケット、および SSL サーバソケットを作成するファクトリ。ソケットの作成および構成をカプセル化できるソケットファクトリの使用
- 安全なソケットファクトリとエンジンのファクトリとして動作する安全なソケットコンテキストを表すクラス
- X.509 固有のキーマネージャやトラストマネージャなどの鍵およびトラストマネージャインタフェース、およびそれらのインタフェースを作成するために使用可能なファクトリ
- 安全な HTTP URL 接続用のクラス (HTTPS)
- JDK 1.1 ベースのプラットフォームと互換性がある公開鍵証明書 API
SunJSSE
プロバイダバージョン 1.4 以降の J2SDK には、「
SunJSSE
」という名前の JSSE プロバイダが付属しています。このプロバイダはあらかじめインストールされ、JCA に登録されています。このプロバイダが提供する暗号化サービスは次のとおりです。SunJSSE がサポートする符号化方式の表、および予約された名前のすべてについては、「付録 A」 に掲載しています。
- Java 2 プラットフォームの、署名に関連した JCA 機能の RSA サポート
- SSL 3.0 および TLS 1.0 セキュリティプロトコルの実装
- もっとも一般的な SSL および TLS 符号化方式の実装。一組の認証、鍵の承認、暗号化、および整合性保護を含む
- X.509 ベースのキーマネージャの実装。標準的な JCA KeyStore から適切な認証キーを選択する
- 証明書チェーンパスを検証する規則を実装する、X.509 ベースのトラストマネージャの実装
- JCA キーストア型「pkcs12」として PKCS12 を実装。PKCS12 の信頼できるアンカーの格納は未サポート。ユーザは、JKS 形式で信頼できるアンカーを格納し、PKCK12 形式で非公開鍵を保存する
新機能
J2SE 5 の JSSE の新機能
Java 2 Platform Standard Edition 5 では、以下の機能が拡張されています。
- SunJSSE 実装では、暗号化アルゴリズムのすべてにおいて Java 暗号化拡張機能 (JCE) を使用。詳細については、「暗号化アルゴリズムプロバイダのカスタマイズ」を参照してください。
SSLEngine
(非ブロック入出力) により、SSL/TLS アプリケーションで固有の入出力と計算モデルを選択可能- 基盤となる OS がサポートしていれば、Kerberos 符号化方式を使用可能
- パフォーマンスを高め、個人データを安全に格納する、JCE とハードウェアアクセラレータ/スマートカードをサポート
- SunJSSE PLCS#12 実装の拡張
- 拡張された TrustManager のサポート
- プロバイダプラグイン可能性
- AES 256 符号化方式をデフォルトで使用可能
- HTTP/HTTPS の拡張機能
- 新規または更新されたメソッドとクラス
拡張された PKCS#12 実装
J2SE 1.4.x は、PKCS#12 キーストアを読み取り専用でサポートし、少数の保護アルゴリズムを提供しました。J2SE 5 の拡張された PKCS#12 キーストアは、PKCS#12 キーストアの読み取りと書き込みをサポートし、一般的なブラウザでサポートされているアルゴリズムなどの多くの保護アルゴリズムを提供します。これにより、J2SE、ブラウザ、および他のセキュリティアプリケーションによってインポート/エクスポートされる PKCS#12 キーストアの相互運用性が向上しています。AES 256 符号化方式
1.4.2 の SunJSSE プロバイダは多くの AES_256 符号化方式 (RFC 3268) をサポートしていましたが、強度が無制限の JCE 管轄ポリシーファイルがインストールされていても、それらの符号化方式を使用することはできませんでした。J2SE 5 では、強度が無制限の JCE 管轄ポリシーファイルがインストールされていれば、AES_256 符号化方式を自動的に使用できます。JCE 管轄ポリシーファイルの詳細については、「JCE リファレンスガイド」を参照してください。
HTTP/HTTPS の拡張機能
J2SE 5 では、HTTPS に影響を与える多くのネットワーク機能の拡張が行われました。概要を以下に示します。これらの拡張機能の詳細については、「J2SE 5.0 リリースノート」を参照してください。
- 接続および読み取りタイムアウト。J2SE 1.4.x では、実装に特定のいくつかのプロパティを使用しなければ、プロトコルハンドラ用の接続および読み取りタイムアウトを設定できませんでした。J2SE 5 では、URLConnection にメソッドを追加し、タイムアウトを設定できるようにしています。
- 動的プロキシサーバの構成と選択。J2SE 5 より前のプロキシサーバ構成は、静的かつグローバルにシステムのプロパティを介して構成されました。J2SE 5 では新規クラスが導入されたので、URI を基本にしてプロキシを動的に構成することができます。
- プラグイン可能クッキーのサポート。J2SE 5 より前のアプリケーションは、HTTP ヘッダの読み取りと設定を行うことによってクッキーを管理していました。5.0 には新規クラスが導入されているため、アプリケーションは独自のクッキーハンドラをインストールすることができ、HTTP 要求があった場合にクッキーキャッシュからクッキーを検索し、HTTP 応答のクッキーをクッキーキャッシュに保存することが可能です。
- プラグイン可能キャッシュのサポート。J2SE 5 にはいくつかのクラスが新たに導入されており、アプリケーションは URL 応答をキャッシュすることが可能なハンドラをインストールできます。
J2SE 5 の新規または更新されたメソッドとクラス
非ブロック入出力をサポートするSSLEngine
とSSLEngineResult
が追加されています。SSLContext
とSSLContextSpi
は、SSLEngine
を生成するために更新されています。
HandshakeCompleteEvent、HttpsURLConnection
、およびSSLSession
に新規メソッドのセットが導入され、セッションで使用される主体を検索することができるようになりました。たとえば、X509 ベース暗号群のX500Principal
や Kerberos 符号化方式のKerberosPrincipal
などです。証明書 (Kerberos 符号化方式) を確実に使用するセッションの証明書チェーンを取得しようとする動作が行われると、SSLPeerUnverifiedException
が発生します。
SSLException
には、例外チェーン機能をサポートする新規コンストラクタが追加されました。
SSLSession
には、セッションが有効で、再開または参加できるかどうかを判断するための新規メソッドが追加されました。セッションのポート情報が入手可能であれば、ポートを判断する別のメソッドも追加されています。また、SSLEngine
を使用する場合に必要な最大バッファサイズを判断する 2 つのメソッドも追加されました。
X509KeyManager
インタフェースのSSLEngine
拡張機能を提供する、新規抽象クラスX509ExtendedKeyManager
が追加されました。SSLContext
は、SSLEngine
を使用する前にX509ExtendedKeyManager
によって初期化する必要があります。2 つの
ManagerFactoryParameters
ファクトリクラスが追加されています。CertPathTrustManagerParameters
により、検証設定をCerPath
ベースのTrustManager
に渡すことができます。KeyStoreBuilderParameter
は動的キーストアをサポートするために追加されました。動的キーストア
の詳細については、KesStore.Builder
クラスまたは「複数および動的なキーストア」セクションを参照してください。この節の残りの部分では、Java 2 プラットフォームのリリース 1.4.2 および 1.4 の JSSE とそれ以前のリリースの JSSE の相違点について説明します。
J2SDK v 1.4.2 の JSSE の新機能
バージョン 1.4.2 の Java 2 プラットフォームの JSSE には、次の変更が加えられています。
- SunJSSE 実装は、現在多くの追加暗号群をサポートしています。たとえば、対称暗号としての AES と、RSA 認証による一時的な Diffie-Hellman (DHE_RSA) を使用する暗号群などがあります。詳細については、
「SunJSSE
プロバイダ」の「サポートされる符号化方式」の表を参照してください。
- SunJSSE プロバイダで以前使用できた単純な X.509 ベースのトラストマネージャの他に、2 番目の PKIX 準拠トラストマネージャもサポートしています。PKIX 準拠トラストマネージャは、デフォルトの CertPath PKIX 実装を使用して実装されました。詳細については、「
TrustManagerFactory
クラス」を参照してください。J2SDK v 1.4 の JSSE の新機能
JSSE 1.0.2 と J2SDK v 1.4 の JSSE の相違点は次のとおりです。
- JSSE が J2SDK に含まれる
javax.security.cert
は使用できない- SunJSSE プロバイダは JCE プロバイダを使って暗号化を行うことができる
- 以前
com.sun.net.ssl
にあったクラスは javax.net.ssl に移動- 新規メソッドとインタフェース
- クラスとメソッドの変更
- ドキュメントの変更
JSSE が J2SDK に含まれる
これまでの JSSE は、JavaTM 2 SDK Standard Edition (J2SDK) のバージョン 1.2 と 1.3 のオプションパッケージ拡張機能でした。今回の JSSE は、J2SDK v 1.4 に統合されています。SunJSSE プロバイダも組み込まれており、J2SDK v 1.4 の
java.security
セキュリティプロパティファイルにあらかじめ登録されています。
javax.security.cert
は使用しないJSSE は
java.security.cert
パッケージが広く利用される前に開発されたものなので、JSSE の初期バージョンjavax.security.cert
では補完的な証明書パッケージが導入されていました。現在、JSSE は J2SDK に付属しており、java.security.cert
パッケージにあるさらに完成度の高い証明書 API を利用しています。新しいアプリケーションはすべてjava.security.cert
を使用することになっています。javax.security.cert
パッケージは以前のリリースの JSSE との後方互換性を確保するために含められているだけです。このパッケージの使用は避けてください。SunJSSE プロバイダは JCE プロバイダを使って暗号化を行うことができる
SunJSSE プロバイダは、暗号化アルゴリズムとして JCE プロバイダを利用できるようになりました。以前は、暗号化アルゴリズムとして、もっぱら内部実装が利用されていました。現在では、SunJSSE よりも優先順位の高いプロバイダの実装を利用できます。詳細については、「暗号化アルゴリズムプロバイダのカスタマイズ」を参照してください。
注: J2SE 5 Development Kit の SunJSSE では、暗号化アルゴリズムとして JCE を排他的に使用します。したがって SunJSSE には、内部暗号化ルーチンが組み込まれていません。
com.sun.net.ssl のクラスは javax.net.ssl に移動
JSSE 1.0.x で
com.sun.net.ssl
パッケージにあったクラスとインタフェースは、すべてjavax.net.ssl
パッケージに移動しました。これまでのcom.sun.net.ssl
とインタフェースもそのままの状態で SunJSSE プロバイダに含まれていますが、これは後方互換性を確保するためにすぎません。実際には、新しいjavax.net.ssl
クラスとインタフェースを参照する「ラッパー」が提供されます。実装で使用されるのは
javax.net.ssl.SSLPermissions
であり、com.sun.net.ssl.SSLPermission
は使用されません。com.sun.net.ssl.SSLPermission
を示すために使用されたポリシーファイルでは、今後はjavax.net.ssl.SSLPermissions
を使用する必要があります。新規メソッドとインタフェース
新規メソッドsetWantClientAuth
およびgetWantClientAuth
がjavax.net.ssl
のSSLSocket
およびSSLServerSocket
に追加され、任意のクライアント認証ができるようになりました。
SSLContext.getInstance(protocol)
メソッドは、少なくとも指定されたプロトコルをサポートするソケットファクトリを返します。SSLSocket
とSSLServerSocket
に新しくsetEnabledProtocols
とgetEnabledProtocols
が追加されました。その結果、現在の接続で利用できるプロトコルが増えました。SSLSocket
とSSLServerSocket
には、もう 1 つの新しいメソッドgetSupportedProtocols
も追加されています。getSupportedProtocols
を使って、SSL 接続で利用できるプロトコルのバージョンを取得することができます。SSLSession
に、セッションで使用するプロトコルの標準名を取得するための新しいメソッドgetProtocol
が追加されました。
SocketFactory
およびServerSocketFactory
には新規メソッドcreateSocket
およびcreateServerSocket
がそれぞれ追加され、接続されていないソケットが作成できるようになりました。
SSLContext
に新しいメソッドgetServerSessionContext
とgetClientSessionContext
が追加されました。開発者は、これらのメソッドを使って、ハンドシェーク中に繰り返し利用できる SSL クライアントのセットまたはサーバセッションを取得できます。
SSLSessionContext
に新しいメソッドsetSessionTimeout
とgetSessionTimeout
が追加されました。開発者は、これらのメソッドを使って、セッションがタイムアウトし、無効になるタイミングを制御できます。次回以降の接続で再利用するためにセッションをいくつまでキャッシュできるかを制御する新しいメソッドsetSessionCacheSize
とgetSessionCacheSize
が追加されました。
javax.net.ssl
内のHttpsURLConnection
、SSLSession
、およびHandshakeCompletedEvent
に新しいメソッドが追加されました。これらのメソッドを利用して、既存のメソッドから返されるjavax.security.cert.X509Certificate
証明書のほかに、汎用の Java 2java.security.cert.Certificate
証明書を取得できます。新しいメソッドは次の 3 つです。SSLSession.getPeerCertificates
HandshakeCompletedEvent.getPeerCertificates
HttpsURLConnection.getServerCertificates
getLocalCertificates
メソッドがSSLSession
、HandshakeCompletedEvent
、およびHttpsURLConnection
に追加されました。このメソッドは、ハンドシェーク中に相手に送信された証明書を返します。これにより、任意の SSL セッションのローカルサイドを認証するため、どの証明書チェーンを実際に使ったかを判断できます。プロバイダが拡張できる基本インタフェースとして新規インタフェース
ManagerFactoryParameters
が追加されました。プロバイダが初期化パラメータKeyManagerFactory
およびTrustManagerFactory
を必要とする場合には拡張でき、これらのクラスの KeyStore ベースのinit
メソッドにパラメータを渡すことができる場合は拡張されません。KeyManagerFactory
およびTrustManagerFactory
クラスはそれぞれ、ManagerFactoryParameters
を引数に取る新規メソッドinit
を持ちます。特定のプロバイダの利用者は、プロバイダによる定義に従って、適切なManagerFactoryParameters
の実装を渡す必要があります。クラスとメソッドの変更
javax
名前空間にcom.sun
API を追加する準備を行なっている間に、このバージョンのjavax
で API の制限事項の一部が修正されました。以前の JSSE オプションパッケージ内の古いcom.sun.*
API はそのままの状態になっています。次に説明する変更点は、同じ名前の新規javax.*
クラスにだけ適用されます。
HttpsURLConnection
コンストラクタが変更され、保護されるようになりました。これにより、java.net
パッケージのURLConnection
、JarURLConnection
、HttpURLConnection
など、類似した他のクラスとの一貫性が確保されます。また、javax.security.cert
証明書を返すメソッドは削除されました。汎用性を高めるため、ホスト名の再検証を行うようになりました。検証先の
verify
メソッドには、受け取った証明書に含まれているホスト名の代わりに、ネゴシエーション済みのSSLSession
が渡されるようになりました。このため、新しいSSLSession
では、ネゴシエーション済みの暗号群、交換済みの証明書などを照会できます。
X509TrustManager isClientTrusted
はcheckClientTrusted
、isServerTrusted
はcheckServerTrusted
に名称変更されました。証明書チェーンがこのTrustManager
によって信頼されない場合、checkClientTrusted
メソッドとcheckServerTrusted
メソッドは例外をスローします (以前のメソッドはboolean
を返していた)。これを利用して、実装は、信頼が得られなかった原因を突き止めることができます。checkClientTrusted
とcheckServerTrusted
により、証明書が鍵使用拡張に対応した操作で使用されているかどうかの検証を含むチェックが行われます。このチェックを正しく実行するためには、両メソッドに認証のタイプを指定し、String authType
引数を追加する必要があります。1 つのパラメータが追加され、
X509KeyManager chooseClientAlias
およびchooseServerAlias
メソッドの 1 つのパラメータが変更されました。両メソッドには、接続に使用するソケットを指定するSocket socket
パラメータが追加されています。chooseClientAlias
メソッドのkeytype
パラメータが、単一の文字列から鍵のアルゴリズムの型名を指定する文字列の配列に変更され、最優先の型が最初に来るようになりました。たとえば、chooseClientAlias
メソッドのシグニチャーはこれまで、次のような形式でした。これは、次のような形式になります。chooseClientAlias(String keyType, Principal[] issuers)パラメータを使うと、リモートホストへの接続時にどの証明書を使用するかを決めることができます。chooseClientAlias(String[] keyType, Principal[] issuers,
Socket socket)デフォルトのキーマネージャファクトリのアルゴリズム名が、
sun.ssl.keymanager.type
からssl.KeyManagerFactory.algorithm
に変更されました。同様に、デフォルトのトラストマネージャファクトリのアルゴリズム名が、sun.ssl.trustmanager.type
からssl.TrustManagerFactory.algorithm
に変更されました。ドキュメントの変更
このドキュメント自体も更新され、内容が増補されました。
JSSE javadoc には、主として不正な引数と明示的には記述されていない動作について、細かな改良が多数加えられました。
関連ドキュメント
Java Secure Socket Extension 関連ドキュメント
- JSSE ホームページ。JavaOneSM カンファレンスのスライドへのリンク、JSSE FAQ、法律上の問題など:
http://java.sun.com/products/jsse/- Sun の Java セキュリティチーム ( java-security@sun.com) に寄せられた API に関する質問と回答:
http://archives.java.sun.com/archives/java-security.html注: 上記のメーリングリストは、購読リストやサポート機構ではありません。これは、Java 2 Standard Edition セキュリティチームへのコメントの送付のみを目的としています。
- JSSE API 関連ドキュメント:
Java 2 プラットフォームのセキュリティ関連ドキュメント
- Java 2 セキュリティホームページ:
http://java.sun.com/security/- JavaTM Certification Path API プログラマーズガイド:
http://java.sun.com/j2se/1.5.0/ja/docs/ja/guide/security/certpath/CertPathProgGuide.html
- その他の Java 2 プラットフォームセキュリティドキュメント:
http://java.sun.com/j2se/1.5.0/ja/docs/ja/guide/security/
- Java 2 プラットフォームセキュリティのチュートリアル:
http://java.sun.com/docs/books/tutorial/security1.2/- Java 2 プラットフォームセキュリティに関する文書:
『Inside Java 2 Platform Security: Architecture, API Design, and Implementation』、Li Gong 著、Addison Wesley Longman, Inc. 発行、1999。ISBN: 0201310007 http://java.sun.com/docs/books/security/index.html暗号化に関する輸出上の問題
米国の暗号政策については、次のサイトを参照してください。
- 米国商務省:
http://www.commerce.gov- 輸出規制に関するページ:
http://www.crypto.com/- Computer Systems Public Policy (CSPP):
http://www.cspp.org/- 連邦情報処理標準出版物 (FIPS PUBS) のホームページ。データ暗号化規格 (DES) へのリンクあり:
http://www.itl.nist.gov/fipspubs/- 米国暗号化輸出規制 (改訂版):
http://www.epic.org/crypto/export_controls/regs_1_00.html暗号化に関するドキュメント
オンラインリソース
- Rivest 博士の暗号化とセキュリティのページ:
http://theory.lcs.mit.edu/~rivest/crypto-security.html書籍:
- 『Applied Cryptography, Second Edition』、Bruce Scheneier 著、John Wiley and Sons, Inc. 発行、1996
- 『Cryptography Theory and Practice』、Doug Stinson 著、CRC Press, Inc. 発行、1995
- 『Cryptography & Network Security: Principles & Practice』、William Stallings 著、Prentice Hall 発行、1998
Secure Sockets Layer 関連ドキュメント
オンラインリソース
- Netscape による SSL に関するドキュメント:
http://developer.netscape.com/docs/manuals/security.html#SSL- Sun™ ONE ソフトウェアからの SSL の導入:
http://docs.sun.com/source/816-6156-10/contents.htm- SSL プロトコルバージョン 3.0 インターネットドラフト:
http://wp.netscape.com/eng/ssl3/ssl-toc.html- TLS プロトコルバージョン 1.0 RFC:
http://www.ietf.org/rfc/rfc2246.txt- 「HTTP Over TLS」 の RFC 情報:
http://www.ietf.org/rfc/rfc2818.txt書籍:
- 『SSL and TLS: Designing and Building Secure Systems』、Eric Rescorla 著、Addison Wesley Professional 発行、2000
- 『SSL and TLS Essentials: Securing the Web』、Stephen Thomas 著、John Wiley and Sons, Inc. 発行、2000
- 『Java 2 Network Security, Second Edition』、Marco Pistoia、Duane F Reller、Deepak Gupta、Milind Nagnur、Ashok K Ramani 著、Prentice Hall 発行、1999。Copyright 1999 International Business Machines
このドキュメントでは、暗号化に関する用語が使用されます。この節では、こうした用語を定義します。
認証
認証とは、通信相手の識別情報を確認するプロセスです。符号化方式
符号化方式とは、暗号化パラメータの組み合わせで、認証、鍵の承認、暗号化、および整合性保護に使用するセキュリティアルゴリズムおよび鍵のサイズを定義します。証明書
証明書とは、デジタル署名付きの文で、あるエンティティ (人や会社など) の識別情報および公開鍵の内容を保証します。証明書には、自己署名付き証明書と証明書発行局 (CA) から発行された証明書があります。証明書発行局とは、ほかのエンティティのために有効な証明書を発行する信頼のおけるエンティティです。よく知られている CA には VeriSign、Entrust、および GTE CyberTrust があります。X509 は証明書の一般的な形式で、JDK の keytool で管理することができます。暗号化ハッシュ関数
暗号化ハッシュ関数はチェックサムと似ています。データは、ハッシュと呼ばれる、比較的小さなビット文字列を生成するアルゴリズムで処理されます。暗号化ハッシュ関数には、次のような 3 つの主な特徴があります。(1) 一方向の関数であるため、ハッシュからオリジナルデータを生成することはできません。(2) オリジナルデータをわずかに変更しても、ハッシュでは大きな変更になります。(3) 暗号化鍵は必要ありません。暗号化サービスプロバイダ
JCA では、さまざまな暗号化アルゴリズムの実装が、暗号化サービスプロバイダ (略称は「プロバイダ」) によって提供されます。プロバイダは、基本的には、特定のアルゴリズムのエンジンクラスを実装するパッケージです。エンジンクラスは、具体的な実装のない抽象的な方法で暗号化サービスを定義します。デジタル署名
デジタル署名とは、手書きの署名のデジタル版です。これは、ネットワークで伝送されるデータが、それを送信したと主張する人物からのものであり、送信中にデータが変更されていないことを保証するものです。たとえば、RSA ベースのデジタル署名を計算するには、まずデータの暗号化ハッシュを計算し、次に送信者の非公開鍵でハッシュを暗号化します。暗号化および暗号解読
暗号化とは、複雑なアルゴリズムを使用して、元のメッセージ (クリアテキスト) を符号化されたメッセージ (暗号テキスト) に変換するプロセスです。暗号テキストは、復号化しないかぎり、その内容を理解できません。復号化とは、クリアテキストから暗号テキストを作成するのとは逆のプロセスです。通常、データの暗号化および復号化に使用するアルゴリズムには、次の 2 つのカテゴリがあります。それは、秘密鍵 (対称型) 暗号と公開鍵 (非対称型) 暗号です。ハンドシェークプロトコル
2 つのソケット同士が新しいセッションや既存のセッションの使用に同意するネゴシエーションのフェーズです。ハンドシェークプロトコルは、レコードプロトコルを介して交換される一連のメッセージです。ハンドシェークの終了時に、セッションの接続に固有の暗号化鍵や、整合性を保護するための鍵が、鍵の承認による秘密に基づいて新たに生成されます。鍵協定
鍵協定は、2 つのパーティが協力して共通鍵を確立するための方法です。それぞれの側が一定のデータを生成して交換します。その後、2 つのデータが組み合わされて、1 つの鍵が生成されます。適正な非公開初期化データを保持しているユーザだけが、最終的な鍵を取得することができます。Diffie-Hellman (DH) は、一般的な鍵協定アルゴリズムの一例です。鍵交換
一方の側が対称鍵を生成し、標準的には RSA により、ピアの公開鍵を使用して暗号化します。それからデータがピアに送信され、ピアは対応する非公開鍵を使用して対称鍵を復号化します。キーマネージャとトラストマネージャ
キーマネージャとトラストマネージャは、それぞれの鍵データにキーストアを使用します。キーマネージャはキーストアを管理し、ユーザ承認時など必要に応じて公開鍵を提供します。トラストマネージャは、管理するトラストストアの情報に基づいて、トラストの対象者を決定します。
キーストアとトラストストア
キーストアは、鍵データのデータベースです。鍵データにはさまざまな用途があり、それには認証やデータ整合性も含まれます。利用できるキーストアにはさまざまな型があり、その中には「PKCS12」や Sun の「JKS」も含まれます。
一般に、キーストア情報は次の 2 つのカテゴリに分類できます。それは、鍵のエントリと、信頼される証明書のエントリです。鍵のエントリはエンティティの識別情報とその非公開鍵から構成されており、さまざまな暗号化の用途に使用できます。これとは対照的に、信頼される証明書のエントリには、公開鍵とそのエンティティの識別情報しか含まれていません。したがって、
javax.net.ssl.KeyManager
の場合など、非公開鍵が必要な場合は、信頼される証明書のエントリを使用することはできません。JKS の J2SDK 実装では、キーストアに鍵のエントリと、信頼される証明書のエントリの両方を含めることができます。トラストストアとは、トラストの対象を決めるときに使用するキーストアです。すでに信頼しているエンティティからデータを受け取る場合、およびそのエンティティが発信元を名乗るエンティティであることを検証できる場合は、データは実際にそのエンティティから届いたものであると仮定できます。
ユーザがそのエンティティを信頼すると決定した場合に限り、トラストストアにエントリが追加されます。ユーザは、鍵のペアを生成するか、証明書をインポートすることにより、そのエントリにトラストを与えます。これにより、キーストアのエントリは信頼されたエントリと見なされます。
次のような 2 つのキーストアファイルがあると便利です。1 つは鍵のエントリだけのファイル、もう 1 つは信頼された証明書のエントリを含むファイルです。これには、証明書発行局 (CA) が発行する証明書が含まれます。前者には機密性のある情報が含まれますが、後者には機密性のある情報は含まれません。単独のキーストアファイルではなく、異なる 2 つのキーストアファイルを使用すると、独自の証明書 (および対応する非公開鍵) と他の証明書を論理的に区別した明確な区分が提供されます。アクセス制限があるキーストアに非公開鍵を保存すると、非公開鍵をさらに保護することができます。一方、必要であれば、より自由にアクセスできるキーストアで信頼される証明書を提供することもできます。
メッセージ認証コード
メッセージ認証コード (MAC) は、送信された情報や、信頼できないメディアに保存されている情報の整合性を、秘密鍵に基づいてチェックする方法を提供します。通常、MAC は秘密鍵を共有する 2 つの当事者間で、お互いが送信する情報を検証するために使用されます。暗号化ハッシュ機能に基づくMAC 機構は、HMAC と呼ばれます。HMAC は、共有する秘密鍵と組み合わせて、Message Digest 5 (MD5) や Secure Hash Algorithm (SHA) などの暗号化ハッシュ関数とともに使用できます。HMAC については、RFC 2104 で規定されています。
公開鍵暗号方式
公開鍵暗号化では、2 つの鍵を生成する暗号化アルゴリズムを使用します。一方の鍵は公開されますが、他方は非公開のままです。公開鍵と非公開鍵では、逆の暗号化処理がなされ、一方の鍵で暗号化したものを他方の鍵で復号化します。公開鍵暗号化は、非対称暗号化とも呼ばれます。レコードプロトコル
レコードプロトコルは、アプリケーションレベルのデータやハンドシェークプロセスの一部であるデータをすべて、独立したデータレコードにパッケージ化します。これは、TCP ストリームソケットでアプリケーションバイトストリームをネットワークパケットに変換する場合によく似ています。個々のレコードは、使用している暗号化鍵および整合性保護鍵によって保護されます。秘密鍵暗号方式
秘密鍵暗号方式では、データの暗号化と復号化に同じ鍵を使用する暗号化アルゴリズムを使用します。秘密鍵暗号方式は対称暗号方式とも呼ばれます。セッション
セッションとは、名前付きの状態の情報のコレクションで、認証されたピア識別情報、符号化方式、鍵の承認の秘密を含みます。セッションでは、安全なソケットハンドシェークを通じてネゴシエーションが行われます。セッションは、複数の安全なソケットインスタンスで共有することができます。トラストマネージャ
「キーマネージャとトラストマネージャ」を参照してください。トラストストア
「キーストアとトラストストア」を参照してください。
Secure Sockets Layer (SSL) は、Web で暗号化を実装する場合にもっともよく使用されるプロトコルです。SSL は、ネットワークで安全な通信を行うために暗号化プロセスを組み合わせて使用します。この節では、SSL および SSL が使用する暗号化プロセスについて簡単に説明します。
SSL は、インターネットで使用される標準的な TCP/IP ソケットプロトコルの機能を安全に拡張します。次の図「SSL を使用する TCP/IP プロトコル」で示すように、Secure Sockets Layer は標準的な TCP/IP プロトコルのトランスポート層とアプリケーション層の間に追加されます。SSL とともにもっともよく使用されるアプリケーションは Hypertext Transfer Protocol (HTTP) です。これはインターネットの Web ページ用のプロトコルです。このほかにも、Net News Transfer Protocol (NNTP)、Telnet、Lightweight Directory Access Protocol (LDAP)、Interactive Message Access Protocol (IMAP)、File Transfer Protocol (FTP) などのアプリケーションがあり、やはり SSL とともに使用します。
注: 現在のところ、安全な FTP の標準規格は存在しません。
SSL を使用する TCP/IP プロトコル
TCP/IP の層
プロトコル
アプリケーション層
HTTP、NNTP、Telnet、FTP など
Secure Sockets Layer
SSL
トランスポート層
TCP
インターネット層
IP
SSL は 1994 年に Netscape 社によって開発され、インターネットの世界で使用されるようになると、標準的な存在になりました。現在では、国際的な標準化機構である Internet Engineering Task Force (IETF) が管理しています。IETF は SSL の名称を Transport Layer Security (TLS) に変更し、1999 年 1 月にバージョン 1.0 を初めて発表しました。TLS 1.0 は、SSL の最新バージョン 3.0 を少しだけ変更したものです。SSL 3.0 と TLS 1.0 にはほとんど違いがありません。
SSL を使用することの利点
次の 3 つの理由から、機密情報をネットワークで送信する際に危険が伴う場合があります。
- 通信相手のエンティティが、実際には必ずしも想定する相手とは限らない
- ネットワーク上のデータは傍受されることがあり、権限のない第三者 (場合によっては攻撃者) にデータを読み取られてしまうことがある
- 攻撃者がデータを傍受できる場合、攻撃者はデータが受信者に届く前に内容を変更できる
SSL はこれらの問題に対応しています。最初の問題には、認証と呼ばれるプロセスを通じ、通信の当事者双方に互いの識別情報を任意に確認させることで対応しています。両者が認証されると、SSL は両者を暗号化接続して安全な通信を行います。両者の通信を暗号化することで 2 番目の問題に対応し、機密性が保持されます。SSL で使用する暗号化アルゴリズムには、安全なハッシュ関数が含まれています。これはチェックサムに似ています。これにより、送信中にデータが変更されていないことが保証されます。安全なハッシュ関数により、3 番目の問題に対応し、データの整合性を確保します。
認証も暗号化もオプションであり、当事者間でネゴシエーションが行われた符号化方式に基づいていることに注意してください。
もっとも端的な SSL の使用例は電子商取引です。電子商取引では、通信するサーバの識別情報は保証されていると考えるべきではありません。クレジットカードの番号を入力するだけですばらしいサービスが受けられるという偽の Web サイトを作成するのは簡単なことです。SSL を使うと、クライアントがサーバの識別情報を認証することができます。また、サーバもクライアントの情報を認証できますが、インターネット上の取引では、この方法はあまり使われていません。
クライアントとサーバが互いの情報を認証すると、SSL は暗号化アルゴリズムを使って機密性とデータの整合性を提供します。これにより、クレジットカード番号のような機密情報をインターネット上で安全に送信することができます。
SSL は認証、機密性、およびデータの整合性を提供しますが、非拒否サービスは提供しません。非拒否性とは、メッセージを送信したエンティティは、あとになって送信を拒否することができないということを意味します。メッセージとデジタル署名が関連付けられていると、あとになって通信内容を証明することができます。SSL 単独では、非拒否性を提供しません。
SSL のしくみ
SSL が有効な理由の 1 つに、複数の暗号化プロセスを使用していることがあります。SSL は、公開鍵暗号で認証を行い、秘密鍵暗号とデジタル署名で機密性とデータの整合性を提供します。SSL について理解する前に、暗号化の処理方法を理解しておくと役立ちます。暗号化処理
暗号化の主な目的は、権限のない第三者が非公開の通信にアクセスしたり、その内容を理解するのを困難にすることです。暗号化では、データに対する権限のないすべてのアクセスを必ずしも制限できるわけではありませんが、権限のない第三者が非公開のデータを読み取れないようにすることができます。暗号化では、複雑なアルゴリズムを使用して、元のメッセージ (クリアテキスト) を符号化されたメッセージ (暗号テキスト) に変更します。通常、ネットワークで送信されるデータの暗号化および復号化に使用するアルゴリズムには 2 つのカテゴリがあります。秘密鍵暗号方式と公開鍵暗号方式です。これらの暗号方式については、以下の節で説明します。秘密鍵暗号方式も公開鍵暗号方式も、合意に基づく暗号鍵または暗号鍵のペアを使用します。鍵は、データの暗号化プロセスおよび復号化プロセスで暗号化アルゴリズムが使用するビット文字列です。暗号化鍵は錠の鍵に似ています。錠を開けることができるのは、正しい鍵だけです。
通信の当事者が互いに鍵を安全に送信するのは、些細な問題ではありません。公開鍵証明書を使うと、公開鍵を安全に送信し、受信者に公開鍵の信頼性を保証することができます。公開鍵証明書については、あとの節で説明します。
以下で説明する暗号化プロセスでは、セキュリティコミュニティで使用する名称を使います。通信の当事者をそれぞれ Alice と Bob とし、権限のない第三者を Charlie とします。Charlie は攻撃者にもなります。
秘密鍵暗号方式
秘密鍵暗号方式では、通信する Alice と Bob はメッセージの暗号化と復号化に同じ鍵を使います。暗号化されたデータをネットワークで送信する前に、Alice と Bob は鍵を持っていることが必要で、暗号化と復号化に使用する暗号化アルゴリズムに同意している必要があります。
秘密鍵暗号方式で大きな問題になるのは、攻撃者にアクセスされずに一方から他方に鍵を渡す方法です。Alice と Bob が秘密鍵暗号方式でデータを暗号化しても、Charlie がその鍵にアクセスできれば Alice と Bob の非公開メッセージを傍受することができます。Charlie は Alice と Bob のメッセージを復号化できるだけではなく、Alice になりすまして暗号化データを Bob に送信することもできるのです。Bob には、メッセージが Charlie から届いたものか Alice から届いたものかはわかりません。
秘密鍵の配布方法の問題が解決すれば、秘密鍵暗号はたいへん貴重なツールになります。そのアルゴリズムにより、優れたセキュリティと暗号化データが比較的迅速に提供できるからです。SSL セッションで送信される機密性の高いデータの多くは、秘密鍵暗号方式で送信されます。
秘密鍵暗号方式は、データの暗号化と復号化に同じ鍵を使用するので、対称暗号化方式とも呼ばれます。よく知られている秘密鍵暗号化アルゴリズムには、Data Encryption Standard (DES)、トリプル DES (3DES)、Rivest Cipher 2 (RC2)、および Rivest Cipher 4 (RC4) があります。
公開鍵暗号方式
公開鍵暗号化方式は、公開鍵と非公開鍵を使うことで鍵の配布方法を解決しました。公開鍵はネットワークを通じて公開し、送信できますが、非公開鍵は通信の 1 人の当事者にしか公開されません。公開鍵と非公開鍵は暗号化方式が逆で、一方の鍵で暗号化したものをもう一方の鍵で復号化します。
ここで、Bob が Alice に公開鍵暗号方式で秘密のメッセージを送信する場合を考えてみましょう。Alice は公開鍵と非公開鍵をどちらも持っているので、非公開鍵は安全な場所に保管しておき、公開鍵を Bob に送信します。Bob は Alice の公開鍵を使って Alice への秘密のメッセージを暗号化します。Alice は非公開鍵を使ってメッセージを復号化します。
Alice が非公開鍵を使ってメッセージを暗号化し、そのメッセージを Bob に送信すれば、Bob が受信するデータは Alice から届いたものだと考えることができます。Bob が Alice の公開鍵でデータを復号化できれば、そのメッセージは Alice が自分の非公開鍵で暗号化したものに間違いありません。Alice の非公開鍵を持っているのは Alice だけだからです。問題は、Alice の公開鍵が公開されているために、だれもがメッセージを読めてしまうことです。このシナリオは、安全なデータ通信を考慮に入れていませんが、デジタル署名の基本には触れています。デジタル署名とは公開鍵証明書のコンポーネントの 1 つで、SSL でクライアントやサーバを認証するために使用します。公開鍵証明書とデジタル署名については、あとの項で説明します。
公開鍵暗号方式は、データの暗号化と復号化に同じ鍵を使用するので、非対称暗号化方式とも呼ばれます。SSL を使用することが多い、よく知られている公開鍵暗号化アルゴリズムには、Rivest Shamir Adleman があります。このほかにも、秘密鍵を交換するために設計された SSL を使う公開鍵暗号化アルゴリズムには、Diffie-Hellman (DH) があります。公開鍵暗号方式には膨大な計算が必要なため、速度が遅くなります。そこで、この方式は暗号化データ通信全体に使用するよりもむしろ、秘密鍵など少量のデータを暗号化する場合にだけ使用します。
秘密鍵暗号方式と公開鍵暗号方式の比較
秘密鍵暗号方式と公開鍵暗号方式のどちらにも、長所と弱点があります。秘密鍵暗号方式では、データの暗号化や復号化に時間はかかりませんが、通信者同士が同じ秘密鍵情報を持つ必要があり、鍵の交換方法が問題になります。公開鍵暗号方式では、鍵を秘密にする必要がないので交換方法は問題になりません。しかしデータの暗号化と復号化に使用するアルゴリズムには膨大な計算が必要で、速度が遅くなります。
公開鍵証明書
公開鍵証明書を使うと、エンティティは非対称暗号方式で使用する公開鍵を安全に配布できます。公開鍵証明書は次のような状況を回避します。Charlie が自分の公開鍵と非公開鍵を作成すれば、自分は Alice だと名乗って Bob に公開鍵を送信できます。Bob は Charlie と通信できますが、データを Alice に送信していると思い込んでしまいます。
公開鍵証明書は電子的なパスポートだと考えることができます。これは、信頼できる組織によって発行され、所有者に識別情報を提供します。公開鍵証明書を発行する信頼できる組織を、証明書発行局 (CA) と呼びます。CA は公証人に例えることができます。CA から証明書を取得するには、識別情報の証拠となるものを提供する必要があります。CA は、申請者が申し立てる組織の代表であるとの確証が得られたら、証明書に含まれる情報の妥当性を証明する証明書に署名します。
公開鍵証明書には、次のようなフィールドがあります。
- 発行者 - 証明書を発行した CA です。証明書を発行する CA が信頼でき、証明書が有効であれば、証明書は信頼できます。
- 有効期間 - 証明書には期日があります。証明書の妥当性を検証する場合は、この日付は確認すべき情報の 1 つになります。
- 被認証者 - 被認証者フィールドには、証明書が表すエンティティの情報が含まれます。
- 被認証者の公開鍵 - 証明書が提供する主な情報に、被認証者の公開鍵があります。その他のフィールドは、この鍵の妥当性を確認するためのものです。
- 署名 - 証明書は、証明書を発行した CA によって電子的に署名されます。署名は CA の非公開鍵を使って作成され、証明書の妥当性を保証するものです。証明書にだけ署名され、SSL トランザクション送信されるデータには署名されないので、SSL には非拒否性がありません。
Alice が Bob に公開鍵証明書で自分の公開鍵を送信するとき、Bob が Alice の公開鍵を有効であると認める以外のことを行わない場合、Charlie が Alice になりすましたとしても、Bob が Charlie に秘密情報を送信することはありません。
複数の証明書を証明書チェーンでリンクすることもできます。証明書チェーンを使用する場合、最初の証明書は必ず送信者の証明書です。次は送信者の証明書を発行したエンティティの証明書です。チェーン内にさらに証明書がある場合、直前の証明書を発行した証明書発行局の証明書が続きます。チェーンの最後の証明書は、ルート CA の証明書です。ルート CA は、広く信頼されている公開証明書発行局です。複数のルート CA の情報は、通常、クライアントのインターネットブラウザに保存されています。この情報には、CA の公開鍵が含まれています。よく知られている CA には VeriSign、Entrust、および GTE CyberTrust があります。
暗号化ハッシュ関数
暗号化されたデータを送信する場合、SSL は通常、暗号化ハッシュ関数を使ってデータの整合性を保証します。ハッシュ関数を使って、Alice が Bob に送ったデータを Charlie が改ざんできないようにします。
暗号化ハッシュ関数はチェックサムに似ています。主な違いは、チェックサムがデータの偶発的変化を検出するのに対し、暗号化ハッシュ関数は故意による変更を検出するということです。データが暗号化ハッシュ関数で処理されると、ハッシュと呼ばれる小さなビット文字列が生成されます。メッセージがごくわずかだけ変更された場合も、結果として生成されるハッシュは大きく変更されます。暗号化ハッシュ関数には、暗号化鍵が必要ありません。SSL とともに使用されることが多いハッシュ関数には、Message Digest 5 (MD5) と Secure Hash Algorithm (SHA) の 2 つがあります。SHA は、U.S. National Institute of Science and Technology (NIST) によって提案されました。
メッセージ認証コード
メッセージ認証コード (MAC) は暗号化ハッシュに似ていますが、秘密鍵をベースにしている点が異なります。秘密鍵情報が暗号化ハッシュ関数で処理したデータに含まれている場合、その結果生成されるハッシュは HMAC と呼ばれます。Alice は、Bob へのメッセージを Charlie が傍受していないことを確認したい場合、メッセージの HMAC を計算して元のメッセージに HMAC を追加できます。次に、Bob と共有している秘密鍵を使ってメッセージと HMAC を暗号化します。Bob は、メッセージを復号化して HMAC を計算すれば、送信中にメッセージが変更されたかどうかを知ることができます。SSL では、HMAC を使って安全なデータを送信します。
デジタル署名
メッセージに暗号化ハッシュが作成されると、ハッシュは送信者の非公開鍵で暗号化されます。このような暗号化ハッシュをデジタル署名と呼びます。
SSL 処理
SSL を使った通信は、クライアントとサーバ間の情報交換から始まります。この情報交換を SSL ハンドシェークと呼びます。
SSL には、主に次のような 3 つの目的があります。
- 符号化方式のネゴシエーション
- 情報の認証 (オプション)
- 暗号化機構の同意による情報セキュリティの確立
符号化方式のネゴシエーション
SSL セッションは、どの符号化方式を使用するかについて、クライアントとサーバがネゴシエーションを行うことから始まります。符号化方式とは、コンピュータがデータを暗号化するために使用する暗号化アルゴリズムと鍵のサイズです。符号化方式には、公開鍵交換アルゴリズムまたは鍵協定アルゴリズム、およびおよび暗号化ハッシュ関数に関する情報が含まれます。クライアントは利用できる符号化方式をサーバに伝え、サーバは、どちらにも適用できる符号化方式を選択します。
サーバの認証
SSL の認証ステップは省略できます。しかし、Web 上の電子商取引では、一般的にクライアントがサーバを認証します。サーバの認証により、サーバが表すとクライアントが信じているエンティティを、そのサーバが実際に表していることをクライアントが確認できます。
サーバは、自らが表すと唱える組織に属していることを証明するため、クライアントに公開鍵証明書を提示します。この証明書が有効であれば、クライアントはサーバの識別情報について確信できます。
クライアントとサーバは、同じ秘密鍵について同意できる情報を交換します。たとえば、RSA を使う場合、クライアントは公開鍵証明書で取得したサーバの公開鍵を使用して、秘密鍵情報を暗号化します。クライアントは暗号化された秘密鍵情報をサーバに送信します。復号化にはサーバの非公開鍵が必要なので、サーバでだけ、このメッセージを復号化できます。
暗号化されたデータの送信
クライアントとサーバは、同じ秘密鍵にアクセスします。それぞれのメッセージでは、この処理の最初の段階で選択した、秘密情報を共有する暗号化ハッシュ関数を使って、メッセージに添付される HMAC を計算します。次に、秘密鍵と、この処理の最初の段階で設定した秘密鍵アルゴリズムを使い、安全なデータと HMAC を暗号化します。その後、クライアントとサーバは、暗号化されハッシュ化されたデータを使って安全に通信することができます。
SSL プロトコル
前の節では、SSL ハンドシェークを上位レベルで説明しました。つまり、暗号化されたメッセージを送信する前にクライアントとサーバで行われる情報交換について説明しました。この節では、さらに詳しく説明します。
次の「SSL メッセージ」には、SSL ハンドシェークで交換される一連のメッセージが示されています。特定の状況下でだけ送信されるメッセージには (Optional) と記されています。SSL メッセージの説明は次のとおりです。
SSL メッセージは、次の順序で送信されます。
- Client hello - クライアントはサーバ情報を送信します。この情報には、自分がサポートする最上位バージョンの SSL と符号化方式のリストが含まれます。TLS 1.0 は SSL 3.1 と表示されます。符号化方式の情報には、暗号化アルゴリズムと鍵のサイズが含まれます。
- Server hello - サーバは、クライアントとサーバの両方がサポートする最上位バージョンの SSL と最適な符号化方式を選択し、この情報をクライアントに送信します。
- Certificate - サーバはクライアントに証明書または証明書チェーンを送信します。証明書チェーンは通常、サーバの公開鍵証明書で始まり、認証局のルート証明書で終わります。このメッセージはオプションで、サーバ認証を求められた場合に使用します。
- Certificate request - サーバがクライアントを認証する必要がある場合、クライアントに証明書要求を送信します。インターネットアプリケーションでは、このメッセージが使われることはほとんどありません。
- Server key exchange - 上記の 3 で送信した公開鍵情報が鍵交換を行うのに不十分な場合、サーバはクライアントにサーバ鍵交換メッセージを送信します。
- Server hello done - サーバは、最初のネゴシエーションメッセージを終了したことをクライアントに伝えます。
- Certificate - メッセージ 4 でサーバがクライアントに証明書を要求すると、クライアントはメッセージ 3 でサーバが行なったようにして、証明書チェーンを送信します。
注: クライアントに証明書を要求するのは、ごく一部のインターネットサーバアプリケーションだけです。
- Client key exchange - クライアントは、対称暗号方式で使用する鍵を作成する情報を生成します。RSA では、クライアントはサーバの公開鍵でこの鍵情報を暗号化してサーバに送信します。
- Certificate verify - このメッセージは、上述のとおりクライアントが証明書を提示する場合に送信されます。このメッセージは、サーバにクライアントの認証処理を完了させるためのものです。このメッセージが使用されると、クライアントは暗号化ハッシュ関数で電子的に署名した情報を送信します。サーバがクライアントの公開鍵でこの情報を復号化すれば、サーバはクライアントを認証できます。
- Change cipher spec - クライアントはメッセージを送信し、暗号化モードを変更するようサーバに伝えます。
- Finished - クライアントはサーバに、安全なデータ通信を開始する準備ができたことを伝えます。
- Change cipher spec - サーバはメッセージを送信し、暗号化モードを変更するようクライアントに伝えます。
- Finished - サーバはクライアントに、安全なデータ通信を開始する準備ができたことを伝えます。SSL ハンドシェークが終了します。
- Encrypted data - クライアントとサーバは、メッセージ 1 と 2 で取り決めた対称暗号化アルゴリズムと暗号化ハッシュ関数、およびメッセージ 8 でクライアントがサーバに送信した秘密鍵を使って通信します。
- Close Messages - 接続の終わりに、それぞれの側が close_notify メッセージを送信し、接続が終了したことをピアに伝えます。
SSL セッションで生成したパラメータを保存しておけば、それ以降も SSL セッションで利用することができます。SSL セッションのパラメータを保存しておけば、暗号化通信をすばやく開始できます。
符号化方式の選択とリモートエンティティの検証
SSL/TLS プロトコルでは、保護された接続を確保するための一連の具体的な手順を定義しています。ただし、選択する符号化方式により、接続で確保するセキュリティの種類が決まります。たとえば、匿名符号化方式を選択した場合、アプリケーションにはリモートピアの識別情報を検証する手段がありません。暗号化なしの符号化方式が選択された場合は、データの機密性を保護できません。また SSL/TLS プロトコルでは、受信した資格と、ピアから送信されることが予期される資格が一致するようにとは規定していません。接続が何らかの理由で悪意のあるピアにリダイレクトされたときに、悪意のあるピアの資格が現在のトラストデータに基づいて受け入れられた場合、その接続は有効と見なされてしまいます。raw
SSLSockets/SSLEngines
を使用する場合は、データの送信前に必ずピアの資格をチェックしてください。SSLSocket
クラスとSSLEngine
クラスは、URL のホスト名がピアの資格にあるホスト名と一致するかどうかを自動的に検証しません。ホスト名が検証されなければ、URL 不正行為によって被害を受ける可能性があります。https などのプロトコルは、ホスト名の検証処理が不要です。アプリケーションは、
HostnameVerifier
を使用してデフォルトの HTTPS ホスト名規則を上書きできます。詳細については、「HttpsURLConnection
」 を参照してください。
SSL と TLS に関する参照資料
SSL についての参考資料は、「Secure Sockets Layer の関連ドキュメント」を参照してください。
クラスの関係
安全な通信を行うには、接続の両方の側で SSL が使用できることが必要です。JSSE API の接続のエンドポイントクラスは、
SSLSocket
およびSSLEngine
です。次の図では、SSLSocket/SSLEngine
の作成に使用される主なクラスを論理的な順序で並べています。
SSLSocket
はSSLSocketFactory
またはインバウンド接続を受け取るSSLServerSocket
によって作成されます。SSLServerSocket
はSSLServerSocketFactory
で作成されます。SSLSocketFactory
およびSSLServerSocketFactory
オブジェクトはどちらもSSLContext
で作成されます。SSLEngine
は、SSLContext によって直接作成され、アプリケーションに依存してすべての入出力を処理します。
重要: rawSSLSockets/SSLEngines
を使用する場合は、データの送信前に必ずピアの資格をチェックしてください。たとえばSSLSocket/SSLEngine
クラスは、URL のホスト名がピアの資格にあるホスト名と一致するかどうかを自動的に検証しません。ホスト名が検証されなければ、URL 不正行為によって被害を受ける可能性があります。
SSLContext
を取得して初期化するには、次の 2 通りの方法があります。
- もっとも簡単な方法は、
SSLSocketFactory
またはSSLServerSocketFactory
クラスでgetDefault
static メソッドを呼び出すことです。これらのメソッドは、デフォルトのKeyManager
、TrustManager
、および安全な乱数発生関数を使ってデフォルトのSSLContext
を作成します。デフォルトのKeyManagerFactory
およびTrustManagerFactory
を使うと、KeyManager
およびTrustManager
がそれぞれ作成されます。使用する鍵データはデフォルトのキーストアおよびトラストストアにあり、「デフォルトの鍵とトラストストア、ストア型、およびストアパスワードのカスタマイズ」で説明するシステムプロパティで設定します。- 作成したコンテキストの動作を呼び出し側でもっともよく管理できる方法は、
SSLContext
クラスでgetInstance
static メソッドを呼び出し、さらにそのインスタンスの適切なinit
メソッドを呼び出してコンテキストを初期化することです。init
メソッドの派生関数は、次の 3 つの引数をとります。KeyManager
オブジェクトの配列、TrustManager
オブジェクトの配列、およびSecureRandom
乱数発生関数です。適切なインタフェースを実装するか、KeyManagerFactory
クラスとTrustManagerFactory
クラスを使って実装を生成することにより、KeyManager
オブジェクトとTrustManager
オブジェクトが作成されます。次に、KeyManagerFactory
およびTrustManagerFactory
クラスを、TrustManagerFactory/KeyManagerFactory
のinit
メソッドで引数として渡されたKeyStore
に含まれる鍵データで初期化します。最後に、TrustManagerFactory
のgetTrustManagers
メソッドとKeyManagerFactory
のgetKeyManagers
メソッドを呼び出して、トラストマネージャまたはキーマネージャの配列を取得します。どちらもトラストデータや鍵データの型の 1 つです。SSL 接続が確立されると、
SSLSession
が作成されます。これには設定した識別情報、使用する符号化方式などの情報が含まれます。次に、SSLSession
を使って両方のエンティティの現在の関係と状態を表します。各 SSL 接続には、一度に 1 つのセッションが含まれますが、そのセッションがエンティティ間の接続に、同時に、または連続して何度も使用されることがあります。コアクラスとインタフェース
コア JSSE クラスは、
java.net
およびjavax.net.ssl
パッケージの一部です。
SocketFactory
およびServerSocketFactory
クラス抽象クラス
javax.net.SocketFactory
は、ソケットの作成に使われます。このクラスは、他のファクトリでサブクラス化する必要があります。ファクトリは、ソケットの特定のサブクラスを作成し、一般的なソケットレベルの機能を追加するフレームワークを提供します。たとえば、「SSLSocketFactory」
を参照してください。
javax.net.ServerSocketFactory
クラスは、SocketFactory
クラスに似ていますが、サーバソケットの作成に特に使われます。ソケットファクトリを使うと、構築するソケットに関する一連のポリシーを簡単に取得し、ソケットを要求する特別なコード設定を必要としない方法でソケットを作成できます。
- ファクトリとソケットに多相性があるため、種類が異なるファクトリを渡すだけで、種類が異なるソケットに同じアプリケーションコードを使用できます。
- ソケット構築時に使用するパラメータを使って、ファクトリ自身をカスタマイズできます。たとえば、ファクトリをカスタマイズして、異なるネットワークタイムアウトのソケットや、設定済みのセキュリティパラメータを返すことができます。
- アプリケーションに返されるソケットは
java.net.Socket
(またはjavax.net.ssl.SSLSocket
) のサブクラスにすることができます。そうすれば、圧縮、セキュリティ、レコード宣言、統計情報収集、ファイアウォールトンネリングなどの機能の新しい API を直接公開できます。
SSLSocketFactory
およびSSLServerSocketFactory
クラス
javax.net.ssl.SSLSocketFactory
は、安全なソケットを作成するファクトリとして動作します。このクラスは、javax.net.SocketFactory
の抽象サブクラスです。安全なソケットファクトリは、安全なソケットの作成と初期設定の詳細情報をカプセル化します。これには、認証鍵、ピア証明書の検証、使用できる符号化方式などが含まれます。
javax.net.ssl.SSLServerSocketFactory
クラスはSSLSocketFactory
クラスに似ていますが、サーバソケットの作成に特化して使われます。
SSLSocketFactory
の取得
SSLSocketFactory
を取得するには、次の 3 つの方法があります。
SSLSocketFactory.getDefault
static メソッドを呼び出してデフォルトのファクトリを取得する
- API パラメータとしてファクトリを受信する。つまり、ソケットを作成する必要があるものの、そのソケットの設定内容の詳細に関与しないコードには、
SSLSocketFactory
パラメータでメソッドを含めることができる。これは、クライアントによって呼び出され、ソケットの作成時に使用するSSLSocketFactory
を指定するパラメータである。(例: javax.net.ssl.HttpsURLConnection)
- 動作を指定した新規ファクトリを構築する
通常、デフォルトのファクトリはサーバ認証だけをサポートするように設定されています。このため、デフォルトのファクトリで作成されたソケットは、一般的な TCP ソケット以上にクライアントの情報を漏らすことはありません。
ソケットを作成して使用するクラスの多くは、ソケットの作成方法を詳しく知る必要はありません。パラメータとして渡されたソケットファクトリを介してソケットを作成するのは、ソケット設定の詳細を分離し、ソケットを作成して使用するクラスの再利用性を高めるよい方法です。
新しいソケットファクトリインスタンスを作成するには、独自のソケットファクトリサブクラスを実装するか、ソケットファクトリのファクトリとして動作するクラスを別に使用します。そのようなクラスの 1 つに、
SSLContext
があります。このクラスは、プロバイダベースの構成クラスとして JSSE 実装に提供されています。
SSLSocket
およびSSLServerSocket
クラス
javax.net.ssl.SSLSocket
は、標準的な Java のjava.net.Socket
クラスのサブクラスです。標準的なソケットメソッドをすべてサポートし、安全なソケットに固有のメソッドを追加します。このクラスのインスタンスは、作成されたときにベースとなったSSLContext
をカプセル化します。ソケットインスタンスの安全なソケットセッションの作成を管理する API もありますが、トラストマネージャおよびキーマネージャは直接公開されません。
javax.net.ssl.SSLServerSocket
クラスはSSLSocket
クラスに似ていますが、サーバソケットの作成に特化して使われます。
ピアの不正行為を防止するには、常に SSLSocket に示される資格を検証してください。
実装にあたっての注意: SSL と TLS プロトコルは複雑なので、接続時の入力バイトがハンドシェークのデータとアプリケーションデータのどちらなのかを予測し、現在の接続状態にどのような影響を与えるか (処理を中断させることもある) を予測するのは困難です。Sun JSSE の実装では、
SSLSocket.getInputStream()
によって取得されたオブジェクトのavailable()
メソッドは、SSL 接続で正常に復号化されても、アプリケーションではまだ読み込まれていないデータのバイト数を返します。
SSLSocket
の取得SSLSocket
のインスタンスは、次の 2 つの方法で取得できます。1 つ目は、そのクラスに複数存在するcreateSocket
メソッドの 1 つを介して、SSLSocketFactory
のインスタンスでSSLSocket
を作成する方法です。2 つ目は、SSLServerSocket
クラスのaccept
メソッドを介してSSLSocket
を取得する方法です。
SSLEngine
による非ブロック入出力SSL/TLS が利用される機会はますます増えており、広範な計算プラットフォームやデバイスを包含するさまざまなアプリケーションで使用されています。こうした技術の普及に伴い、アプリケーションのパフォーマンス、拡張性、サイズその他の要件を満たすため、異なる入出力モデルやスレッドモデルにおいても使用可能にする必要が生じています。たとえば、ブロックおよび非ブロック入出力チャネル、非同期入出力、任意の入力ストリームと出力ストリーム、およびバイトバッファでの使用が求められています。また、数千のネットワーク接続を管理することが必要な、非常に拡張性の高いパフォーマンス重視の環境で使用することも求められています。J2SE 5 以前の JSSE API は、SSLSocket によるストリームベースソケットという 1 つのトランスポート抽象化のみをサポートしていました。ストリームベースソケットは多くのアプリケーションに適切でしたが、異なる入出力モデルやスレッドモデルを使用する必要があるアプリケーションの要求は満たせませんでした。5.0 では、新しい抽象化手法が導入され、トランスポートに依存せずに SSL/TLS プロトコルをアプリケーションで使用できるようになりました。これによりアプリケーションでは、アプリケーションの必要を満たす最善のトランスポートモデルや計算モデルを自由に選択することができます。この新しい抽象化により、非ブロック入出力チャネルや他の入出力モデルをアプリケーションで使用できるだけでなく、異なるスレッドモデルにも対応することができます。事実上これは、入出力とスレッドの決定がアプリケーションに委ねられることになります。こうした柔軟性に対応するため、これからのアプリケーションは、それ自体が複雑な問題でもある入出力とスレッドを管理するとともに、SSL/TLS プロトコルをある程度理解する能力を持つ必要があります。このように、新しい抽象化は高度な API なので、初心者は引き続き SSLSocket を使用してください。
API を初めて使用する人は、「
java.nio.channels.SocketChannel
を拡張するSSLSocketChannel
だけにしたらどうか」と考えることもあるでしょう そうしない主な理由は 2 つあります。入出力を抽象化し、データをバイトのストリームとして処理することによってこれらの問題を解決した結果、新しい API は既存または将来のどんな入出力モデルでも使用できるようになりました。このソリューションでは、入出力と CPU の処理が開発者に任されますが、構成不能または変更不能な内部の詳細設定によって JSSE 実装を使用できなくなるような状況を防止しています。
- クラス階層、および
Selector
や他のタイプのSocketChannel
との相互動作方法など、SSLSocketChannel
をどのような API にすべきかということに関して、難問が数多くありました。SSL/TLS に対応するために拡張された新しい API 抽象化は、どれも同じほど重要な分析が必要となり、大規模で複雑な API になる可能性のあることが判明しました。
- 新しい API のすべての JSSE 実装では、最善の入出力および計算戦略を自由に選択することになりましたが、これらの詳細事項を隠すことは、全面的な制御権を必要とするアプリケーションにとっては不適切です。どんな固有の実装方法も、アプリケーションセグメントによっては適さない場合があります。
JGSS や SASL など、他の Java プログラミング言語 API のユーザは、アプリケーションがデータをトランスポートする機能を果たすという類似点があることに気付くでしょう。
SSLEngine
この新しい抽象化方法のコアクラスは、javax.net.ssl.SSLEngine です。このコアクラスは、SSL/TLS 状態マシンをカプセル化し、SSLEngine のユーザによって供給されるインバウンドとアウトバウンドのバイトバッファ上で動作します。次の図は、アプリケーションから送り出され、SSLEngine とトランスポート機構を経て再び戻ってくるデータフローの様子を示しています。 左側に示されるアプリケーションは、アプリケーションのプレーンテキストデータをアプリケーションバッファに供給し、SSLEngine に渡します。SSLEngine は、バッファに格納されているデータまたはハンドシェークデータを処理して SSL/TLS 符号化データを生成し、アプリケーションによって提供されるネットワークバッファに格納します。次にアプリケーションは、右側に示されている適切なトランスポートを使用して、ネットワークバッファの内容をピアに送信する役割を実行します。トランスポートを介してピアから SSL/TLS 符号化データを受け取ると、アプリケーションはそのデータをネットワークバッファに格納し、SSLEngine に渡します。SSLEngine は、ネットワークバッファの内容を処理し、ハンドシェークデータまたはアプリケーションデータを生成します。SSLEngine は、全体として次に示す 5 つの状態のいずれかの状態を示します。
これらの 5 つの状態の詳細については、SSLEngine クラスの資料を参照してください。
- 作成 - 設定準備完了
- 初期ハンドシェーク - 認証の実行と通信パラメータのネゴシエーション
- アプリケーションデータ - アプリケーションの交換準備完了
- 再ハンドシェーク - 通信パラメータ/認証情報の再ネゴシエーション。ハンドシェーク情報はアプリケーションデータと混合可能
- 閉鎖 - 接続のシャットダウン準備完了
入門
SSLEngine を作成するには、SSLContext.createSSLEngine() メソッドを使用します。次に、クライアントまたはサーバとして動作するようにエンジンを設定し、使用する符号化方式やクライアント認証が必要かどうかなどの他の設定パラメータも設定します。次に SSLEngine の作成例を示します。サーバ名とポート番号は、サーバとの通信には使用されません。すべてのトランスポートはアプリケーションによって実行されます。以下の作成例は、SSL セッションキャッシングの場合、および取得するサーバ資格を決定する Kerberos ベースの符号化方式が実装されている場合に使用する、JSSE プロバイダへのヒントです。
import javax.net.ssl.*; import java.security.*; // Create/initialize the SSLContext with key material char[] passphrase = "passphrase".toCharArray(); // First initialize the key and trust material. KeyStore ksKeys = KeyStore.getInstance("JKS"); ks.load(new FileInputStream("testKeys"), passphrase); KeyStore ksTrust = KeyStore.getInstance("JKS"); ks.load(new FileInputStream("testTrust"), passphrase); // KeyManager's decide which key material to use. KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ksKeys, passphrase); // TrustManager's decide whether to allow connections. TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(ksTrust); sslContext = SSLContext.getInstance("TLS"); sslContext.init( kmf.getKeyManagers(), tmf.getTrustManagers(), null); // We're ready for the engine. SSLEngine engine = sslContext.createSSLengine(hostname, port); // Use as client engine.setUseClientMode(true);SSL/TLS データの生成と処理
SSLEngine の主要な 2 つのメソッドである wrap() と unwrap() により、それぞれネットワークデータが生成および消費されます。SSLEngine の状態に応じて、このデータはハンドシェークデータかアプリケーションデータになります。それぞれの SSLEngine には、ライフタイムを通じて数種類の段階があります。アプリケーションデータを送信/受信できるようにするには、SSL/TLS プロトコルに従ってハンドシェークを実行し、暗号化パラメータを確定する必要があります。このハンドシェークでは、SSLEngine による一連のデータやり取り手順が必要です。ハンドシェーク自体の詳細については、「SSL プロセス」を参照してください。
初期ハンドシェーク時に、wrap() と unwrap() はハンドシェークデータを生成および消費し、アプリケーションはデータをトランスポートする役割を担います。wrap()/unwrap() シーケンスは、ハンドシェークが終了するまで繰り返されます。それぞれの SSLEngine 動作により SSLEngineResult が生成され、SSLEngineResult の SSLEngineResult.HandshakeStatus フィールドは、ハンドシェークを続行するために実行する必要のある以下の動作を決定するために使用されます。
標準的なハンドシェークでは次のような動作が行われます。
これでハンドシェークが完了します。さらに wrap() への別の呼び出しがあると、アプリケーションデータおよびパッケージを消費してトランスポートしようとします。unwrap() は反対の動作を試みます。
クライアント
SSL/TLS メッセージ
HSStatus
wrap()
ClientHello
NEED_UNWRAP
unwrap()
ServerHello/Cert/ServerHelloDone
NEED_WRAP
wrap()
ClientKeyExchange
NEED_WRAP
wrap()
ChangeCipherSpec
NEED_WRAP
wrap()
Finished
NEED_UNWRAP
unwrap()
ChangeCipherSpec
NEED_UNWRAP
unwrap()
Finished
FINISHED
ピアにデータを送信するには、まずアプリケーションが送信するデータを SSLEngine.wrap() を介して SSLEngine に送信し、対応する SSL/TLS 符号化データを取得します。次にアプリケーションは、選択したトランスポート機構を使用して符号化データをピアに送信します。アプリケーションは、トランスポート機構を介してピアから SSL/TLS 符号化データを受け取ると、SSLEngine.unwrap() を介してそのデータを SSLEngine に送り、ピアによって送信されたプレーンテキストデータを取得します。
非ブロック SocketChannel を使用してピアと通信する SSL アプリケーションの例を次に示します。SSL アプリケーションは、非ブロック SocketChannel を組み込んだ Selector を使用することにより、堅牢性と拡張性を高めることができます。以下のサンプルコードは、前の例で作成した SSLEngine を使用して符号化することにより、ピアに文字列 「hello」 を送信します。バイトバッファのサイズは、SSLSession からの情報を使用して決定されます。
以下のコードは、非ブロック SocketChannel からデータを読み取り、前に作成した SSLEngine を使用して、そのデータからプレーンテキストを抽象化します。このコードが反復されるごとに、ハンドシェーク処理が進行しているかどうかに応じて、プレーンテキストが生成されたり、生成されなかったりします。// Create a non-blocking socket channel SocketChannel socketChannel = SocketChannel.open(); socketChannel.configureBlocking(false); socketChannel.connect(new InetSocketAddress(hostname, port)); // Complete connection while (!socketChannel.finishedConnect()) { // do something until connect completed } // Create byte buffers to use for holding application and encoded data SSLSession session = engine.getSession(); ByteBuffer myAppData = ByteBuffer.allocate(session.getApplicationBufferSize()); ByteBuffer myNetData = ByteBuffer.allocate(session.getPacketBufferSize()); ByteBuffer peerAppData = ByteBuffer.allocate(session.getApplicationBufferSize()); ByteBuffer peerNetData = ByteBuffer.allocate(session.getPacketBufferSize()); // Do initial handshake doHandshake(socketChannel, engine, myNetData, peerNetData); myAppData.put("hello".getBytes()); myAppData.flip(); while (myAppData.hasRemaining()) { // Generate SSL/TLS encoded data (handshake or application data) SSLEngineResult res = engine.wrap(myAppData, myNetData); // Process status of call if (res.getStatus() == SSLEngineResult.Status.OK) { myAppData.compact(); // Send SSL/TLS encoded data to peer while(myNetData.hasRemaining()) { int num = socketChannel.write(myNetData); if (num == -1) { // handle closed channel } else if (num == 0) { // no bytes written; try again later } } } // Handle other status: BUFFER_OVERFLOW, CLOSED ... }// Read SSL/TLS encoded data from peer int num = socketChannel.read(peerNetData); if (num == -1) { // Handle closed channel } else if (num == 0) { // No bytes read; try again ... } else { // Process incoming data peerNetData.flip(); res = engine.unwrap(peerNetData, peerAppData); if (res.getStatus() == SSLEngineResult.Status.OK) { peerNetData.compact(); if (peerAppData.hasRemaining()) { // Use peerAppData } } // Handle other status: BUFFER_OVERFLOW, BUFFER_UNDERFLOW, CLOSED ... }動作のステータス
エンジンのステータスとアプリケーションに求められる動作の種類を示すため、SSLEngine.wrap() メソッドと SSLEngine.unwrap() メソッドは、前の例に示されるような SSLEngineResult インスタンスを返します。SSLEngineResult には、エンジンの全体的なステータスとハンドシェークのステータスで構成される 2 つのステータス情報があります。全体的なステータスは、SSLEngineResult.Status enum によって表されます。たとえばこのステータスには、エラーがないことを意味する OK や、入力バッファのデータが不足しているために、アプリケーションはネットワークからデータを読み込むなどしてピアからもっとデータを取得する必要があることを示す BUFFER_UNDERFLOW などがあります。
ハンドシェークのステータスは、SSLEngineResult.HandshakeStatus enum によって表されます。このステータスにより、ハンドシェークが完了しているかどうか、発信側はピアからさらにハンドシェークデータを取得する必要があるかどうか、またピアにもっとハンドシェークデータを送信する必要があるかどうかなどの状態を表します。
動作結果ごとに 2 種類のステータスを示すことにより、エンジンはアプリケーションで実行することが必要な 2 つの動作、つまりハンドシェークへの応答における動作と wrap()/unwrap() メソッドの全体的なステータスを表す動作を示すことができます。たとえばエンジンは、1 回の SSLEngine.unwrap() 呼び出しの結果として、SSLEngineResult.Status.OK を返して入力データが正常に処理されたことを示し、SSLEngineResult.HandshakeStatus.NEED_UNWRAP を返すことにより、ハンドシェークを継続するためにアプリケーションがピアからさらに SSL/TLS 符号化データを取得し、もう一度 SSLEngine.unwrap() に供給すべきことを示します。お気付きのとおり、先の例はかなり単純化されていますが、これらすべてのステータスを適正に処理するにはコードをかなり拡張する必要があります。
ブロックタスク
ハンドシェーク動作の間に、SSLEngine はブロックしたり処理に長い時間がかかったりするタスクに直面することがあります。たとえば、TrustManager はリモートの証明書検証サービスに接続する必要があり、KeyManager は、プロンプトを表示して、クライアント認証の一部として使用する証明書をユーザに決定してもらう必要があります。SSLEngine は、エンジンの非ブロック性を回避するため、それらのタスクに直面した場合に SSLEngineResult.HandshakeStatus.NEED_TASK を返します。このステータスを受け取ると、アプリケーションは SSLEngine.getDelegatedTask() を呼び出してタスクを取得し、その要件に適したスレッドモデルを使用してタスクを処理します。アプリケーションは、たとえばスレッドプールからスレッドを入手してタスクを処理し、メインスレッドは他の入出力の処理に取りかかります。新しく作成されたスレッドでそれぞれのタスクを実行する例を以下に示します。
エンジンは、未処理のタスクすべてが完了するまで、if (res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK) { Runnable task; while ((task=engine.getDelegatedTask()) != null) { new Thread(task).start(); } }wrap/unwrap
呼び出しをブロックします。シャットダウン
SSL/TLS 接続を正しい順序でシャットダウンするため、SSL/TLS プロトコルではクローズメッセージを送信する必要があります。したがって、アプリケーションが SSL/TLS 接続を終了する場合は、最初に SSLEngine からクローズメッセージを取得し、トランスポート機構を使用してそれらのメッセージをピアに送信して、最後にトランスポート機構をシャットダウンします。次に例を示します。SSLEngine を明示的にクローズするアプリケーションに加え、SSLEngine は、ハンドシェークデータを処理している間にクローズメッセージを受け取ることにより、ピアによってクローズされます。または、アプリケーションデータまたはハンドシェークデータを処理している間にエラーが発生した SSLEngine によってクローズされます。そのエラーは、SSLException がスローされることによって示されます。そのような場合アプリケーションは、SSLEngine.wrap() を呼び出してクローズメッセージを取得し、前の例に示されるように SSLEngine.isOutboundDone() が true 値を返すまで、または SSLEngineResult.getStatus() が CLOSED を返すまでそのメッセージをピアに送信します。// Indicate that application is done with engine engine.closeOutbound(); while (!engine.isOutboundDone()) { // Get close message SSLEngineResult res = engine.wrap(empty, myNetData); // Check res statuses // Send close message to peer while(myNetData().hasRemaining()) { int num = socketChannel.write(myNetData); if (num == -1) { // handle closed channel } else if (num == 0) { // no bytes written; try again later } myNetData().compact(); } } // Close transport socketChannel.close();正常なシャットダウンに加え、クローズメッセージが交換される前にトランスポートリンクを切断する非常シャットダウン方法があります。前の例では、非ブロック SocketChannel からの読み取りまたは書き込みを実行しようとすると、アプリケーションは -1 を受け取ります。最後の入力データになったら、engine.closeInbound() を呼び出し、SSL/TLS の観点からはリモートのペアによって正常にクローズされた SSLEngine を検証してください。その後アプリケーションは、上述の手順に従って正常なシャットダウンを試みます。SSLSocket とは異なり、SSLEngine を使用するアプリケーションは、SSLEngine を使用する場合よりも明らかに多くの状態移行、ステータス、およびプログラミングに対処する必要があります。
SSLEngine
ベースアプリケーションの作成方法については、「NIO ベースの HTTPS サーバ」を参照してください。
SSLSession
インタフェース
javax.net.ssl.SSLSession
は、SSLSocket/SSLEngine
接続の 2 つのピアの間で取り決めたセキュリティコンテキストを表します。一度確立されたセッションは、同じ 2 つのピアの間で接続されるその後のSSLSocket/Engine
によっても共有できます。セッションには符号化方式が含まれます。これは、リモートピアのネットワークアドレスに関する権限のないヒントと同様、安全なソケットの通信でも使用され、作成や最後の使用の時点などで、管理情報としても使用されます。セッションには、SSLSocket/SSLEngine
による通信を暗号化して整合性を保証する暗号鍵を作成するために使用される、ピア間で取り決めた共用マスターとなる秘密も含まれます。このマスターとなる秘密の値は、基盤となるセキュリティソケット実装にだけ伝えられ、SSLSession
API では公開されません。
HttpsURLConnection
クラスhttps プロトコルは http プロトコルに似ていますが、データを要求または受信する前に、まず SSL/TLS ソケットを利用して安全なチャネルを確立してピアの識別情報を検証します。javax.net.ssl.HttpsURLConnection
はjava.net.HttpsURLConnection
クラスを拡張し、https に固有の機能をサポートします。https URL の構造と使用法の詳細については、java.net.URL
,java.net.URLConnection
、java.net.HttpURLConnection
、およびjavax.net.ssl.HttpURLConnection
クラスを参照してください。
HttpsURLConnection
を取得する際、URLConnection.connect
メソッドを使って実際にネットワーク接続を開始する前に、複数の http/https パラメータを構成できます。これらについては、以下を参照してください。割り当て済みの
SSLSocketFactory
の設定状況によっては、
HttpsURLConnection
のインスタンスによって使用されるSSLSocketFactory
を指定したほうがよい場合があります。たとえば、デフォルト実装ではサポートされないプロキシを使ってトンネリングを行う場合がこれに該当します。新しいSSLSocketFactory
は、すでに必要なトンネリングの完了したソケットを返すことができます。このため、HttpsURLConnection
は追加のプロキシを使用することができます。
HttpsURLConnection
クラスには、ロード時に割り当てられたデフォルトのSSLSocketFactory
があります(特にSSLSocketFactory.getDefault
によって返されたファクトリの場合)。以降、HttpsURLConnection
のインスタンスは、static メソッドHttpsURLConnection.setDefaultSSLSocketFactory
によってクラスに新しいデフォルトのSSLSocketFactory
が割り当てられるまで、現在のデフォルトのSSLSocketFactory
を継承します。HttpsURLConnection
のインスタンスが作成されたあと、setSSLSocketFactory
メソッドへの呼び出しにより、このインスタンス上の継承されたSSLSocketFactory
を上書きできます。デフォルトの static メソッド
SSLSocketFactory
を変更しても、既存のHttpsURLConnections
のインスタンスには何の影響もありません。既存のインスタンスを変更するには、setSSLSocketFactory
メソッドを呼び出す必要があります。
getSSLSocketFactory
メソッドまたはgetDefaultSSLSocketFactory
メソッドを呼び出すことにより、インスタンスごと、またはクラスごとにSSLSocketFactory
を取得できます。割り当て済みの
HostnameVerifier
の設定URL のホスト名が SSL/TLS ハンドシェーク時に受け取った資格のホスト名と一致しない場合、URL 不正行為が発生している可能性があります。ホスト名の確実性に疑いが持たれる場合、SSL 実装は、インスタンスの割り当て済みHostnameVerifier
のコールバックを実行します。こうすることで、より詳しいチェックを行うことができます。ホスト名識別子は、判定を下すために必要な処理を行います。その一環として、たとえばその他のホスト名パターンマッチングを実行したり、対話式のダイアログボックスを表示したりします。ホスト名ベリファイアによる検証に失敗した場合は、接続が切断されます。ホスト名の検証については、RFC 2818 を参照してください。
setHostnameVerifier
メソッドおよびsetDefaultHostnameVerifier
メソッドは、setSSLSocketFactory
メソッドおよびsetDefaultSSLSocketFactory
メソッドとよく似ています。これらの共通点は、インスタンスごと、またはクラスごとにHostnameVerifiers
が割り当てられ、現在の値がgetHostnameVerifier
メソッドまたはgetDefaultHostnameVerifier
メソッドによって取得されるという点です。サポートクラスとインタフェース
この節で説明するクラスとインタフェースは、
SSLContext
オブジェクトの作成と初期化をサポートし、SSLSocketFactory、SSLServerSocketFactory
オブジェクトとSSLEngine
オブジェクトを作成するために提供されます。サポートクラスとインタフェースはjavax.net.ssl
パッケージに含まれています。この節で説明するクラスは
SSLContext
、KeyManagerFactory
、およびTrustManagerFactory
の 3 つで、いずれもエンジンクラスです。エンジンクラスとは、特定のアルゴリズムの API クラス (SSLContext
の場合はプロトコル) です。1 つまたは複数の暗号化サービスプロバイダ (プロバイダ) パッケージで実装が提供されることがあります。プロバイダとエンジンクラスの詳細については、「JavaTM 暗号化アーキテクチャ API の仕様およびリファレンス」の「設計方針」と「概念」の節を参照してください。JSSE に標準で付属する
SunJSSE
プロバイダは、SSLContext
、KeyManagerFactory
、およびTrustManagerFactory
実装を提供し、標準の Java セキュリティ (java.security
) API ではエンジンクラスの実装も提供します。SunJSSE
が提供する実装は次のとおりです。エンジンクラス アルゴリズムまたは 実装 プロトコル KeyFactory "RSA" KeyPairGenerator "RSA" KeyStore "PKCS12" Signature "MD2withRSA"、 "MD5withRSA"、 "SHA1withRSA" KeyManagerFactory "SunX509"、 "NewSunX509" TrustManagerFactory "SunPKIX" (aka "X509"/"PKIX")、 "SunX509" SSLContext "SSLv3" (aka "SSL")、 "TLSv1" (aka "TLS")
SSLContext
クラス
javax.net.ssl.SSLContext
は、安全なソケットプロトコルの実装のエンジンクラスです。このクラスのインスタンスは、SSL ソケットファクトリおよび SSL エンジンのファクトリとして動作します。SSLContext
は、そのコンテキストの下で作成されたすべてのオブジェクトで共有される状態情報をすべて保持します。たとえば、セッションの状態は、ソケットファクトリにより作成され、コンテキストにより提供されたソケットによってハンドシェークプロトコルが取り決められると、SSLContext
と関連付けられます。キャッシュに書き込まれたこれらのセッションは、同じコンテキストで作成された別のソケットで再利用したり共有することができます。各インスタンスは、認証の実行に必要な鍵、証明書チェーン、および信頼されたルート CA 証明書を使って
init
メソッドで設定されます。この設定は、鍵とトラストマネージャの形で提供されます。これらのマネージャは認証をサポートし、コンテキストによってサポートされる符号化方式の鍵の承認を提供します。現在は、X.509 ベースのマネージャだけがサポートされています。
SSLContext
オブジェクトの作成他の JCA プロバイダベースの「エンジン」クラスと同様に、SSLContext
オブジェクトは、SSLContext
クラスのgetInstance
ファクトリメソッドを使って作成されます。このような static メソッドは、最低限要求された安全なソケットプロトコルを実装するインスタンスを返します。返されるインスタンスも、その他のプロトコルを実装できます。たとえば、getInstance("SSLv3")
から返されるインスタンスは、"SSLv3"
と"TLSv1"
を実装します。getSupportedProtocols
メソッドは、このコンテキストからSSLSocket、SSLServerSocket
またはSSLEngine
が作成されたときに、サポート対象のプロトコルのリストを返します。実際の SSL 接続でどのプロトコルを有効にするかは、setEnabledProtocols(String[] protocols)
メソッドを使って制御できます。注:
SSLSocketFactory.getDefault
を呼び出すと、SSLContext
が自動的に作成され、インスタンス化され、SSLSocketFactory
に静的に割り当てられます。したがって、デフォルト動作をオーバライドする場合を除き、SSLContext
オブジェクトを直接作成したり初期化したりする必要はありません。
getInstance
ファクトリメソッドを呼び出してSSLContext
オブジェクトを作成するには、プロトコル名を指定する必要があります。または、要求されたプロトコルの実装を提供するプロバイダを次のように指定することもできます。public static SSLContext getInstance(String protocol);
public static SSLContext getInstance(String protocol,
String provider);
public static SSLContext getInstance(String protocol,
Provider provider);プロトコル名だけを指定すると、システムは、要求されたプロトコルの実装がその環境で利用できるかどうかを判断します。複数の実装がある場合、より望ましいものがあるかどうかを判断します。
プロトコル名とプロバイダを指定すると、システムは、要求されたプロトコルの実装が要求されたプロバイダで利用できるかどうかを判断し、利用できない場合は例外をスローします。
プロトコルは、希望する安全なソケットプロトコルを記述する文字列 (「SSL」など) です。
SSLContext
オブジェクトの一般的なプロトコル名は、付録 A で定義されています。次に
SSLContext
の取得例を示します。SSLContext sc = SSLContext.getInstance("SSL");新しく作成された
SSLContext
は、init
メソッドを呼び出すことによって初期化する必要があります。public void init(KeyManager[] km, TrustManager[] tm,
SecureRandom random);
KeyManager[]
パラメータが NULL の場合、このコンテキストには空のKeyManager
が定義されます。TrustManager[]
パラメータが NULL の場合、インストールされたセキュリティプロバイダは、TrustManagerFactory
のもっとも優先度の高い実装で検索され、適切なTrustManager
が取得されます。同様に、SecureRandom パラメータも NULL にすることができます。その場合、デフォルト実装が使用されます。内部のデフォルトコンテキストが使用される場合 (たとえば、
SSLContext
はSSLSocketFactory.getDefault()
またはSSLServerSocketFactory.getDefault()
によって作成される) は、デフォルトのKeyManager
とTrustManager
が作成されます。また、デフォルトのSecureRandom
実装も選択されます。
TrustManager
InterfaceTrustManager
は、提示された認証資格の信頼性を判定します。信頼できない資格の場合、接続は切断されます。安全なソケットピアのリモート識別情報を認証するには、1 つまたは複数のTrustManager
でSSLContext
オブジェクトを初期化する必要があります。サポートされる認証機構のそれぞれに対し、TrustManager
を 1 つ渡す必要があります。SSLContext
の初期化中に NULL が渡されると、トラストマネージャが作成されます。通常は、X.509 公開鍵証明書 (X509TrustManager
など) に基づく認証をサポートする単一のトラストマネージャが存在しています。安全なソケット実装には、共有の秘密鍵、Kerberos、またはその他の機構に基づく認証をサポートするものもあります。
TrustManager
はTrustManagerFactory
によって、またはインタフェースの具体的な実装を行うことによって作成されます。
TrustManagerFactory
クラス
javax.net.ssl.TrustManagerFactory
はプロバイダベースのサービスのエンジンクラスで、1 つまたは複数の型のTrustManager
オブジェクトのファクトリとして動作します。これはプロバイダベースなので、さらにファクトリを実装して設定し、より高度なサービスを提供するトラストマネージャや、インストール専用の認証ポリシーを実装するトラストマネージャを追加したり、別に提供することができます。
TrustManagerFactory
の作成このクラスのインスタンスはSSLContext
と同様の方法で作成しますが、getInstance
メソッドにプロトコル名ではなくアルゴリズム名の文字列を渡す点が異なります。public static TrustManagerFactory
getInstance(String algorithm);
public static TrustManagerFactory
getInstance(String algorithm,
String provider);
public static TrustManagerFactory
getInstance(String algorithm,
Provider provider);アルゴリズム名文字列の例を次に示します。
"PKIX"呼び出しの例を次に示します。
TrustManagerFactory tmf =
TrustManagerFactory.getInstance("PKIX", "SunJSSE");上の呼び出しは、
SunJSSE
プロバイダの PKIX トラストマネージャファクトリのインスタンスを作成します。このファクトリを使用して、X.509 PKIX ベースの証明書パス妥当性検査を実行するトラストマネージャを作成できます。
SSLContext
を初期化する場合は、トラストマネージャファクトリから作成したトラストマネージャを使用するか、CertPath
API などを使用して独自のトラストマネージャを記述することができます。詳細については、「JavaTM Certification Path API プログラマーズガイド」を参照してください。X509TrustManager
インタフェースを使用してトラストマネージャを実装する場合は、トラストマネージャが不要です。新しく作成されたファクトリは、
init
メソッドの 1 つを呼び出すことによって初期化する必要があります。public void init(KeyStore ks);
public void init(ManagerFactoryParameters spec);使用する
TrustManagerFactory
に適切なinit
メソッドを呼び出す必要があります。プロバイダのベンダーに問い合わせてください。「SunX509」
TrustManagerFactory
など、SunJSSE
プロバイダが提供するファクトリは多数ありますが、TrustManagerFactory
を初期化するために必要な情報はKeyStore
だけなので、最初にinit
メソッドを呼び出すのが適切です。TrustManagerFactory
はKeyStore
に、認証チェック中に信頼すべきリモート証明書の情報を問い合わせます。場合によっては、
KeyStore
以外の初期化パラメータがプロバイダに必要になります。特定のプロバイダの利用者は、プロバイダによる定義に従って適切なManagerFactoryParameters
の実装を渡す必要があります。その後、プロバイダはManagerFactoryParameters
実装の特定のメソッドを呼び出し、必要な情報を取得できます。たとえば、
TrustManagerFactory
プロバイダが、そのプロバイダを使うアプリケーションの初期化パラメータ B、R、および S を必要としているとします。KeyStore 以外の初期化パラメータを要求するすべてのプロバイダと同様に、プロバイダはアプリケーションがManagerFactoryParameters
の特定のサブインタフェースを実装するクラスのインスタンスを提供することを要求します。たとえば、呼び出し側のアプリケーションがMyTrustManagerFactoryParams
のインスタンスを実装して作成し、2 つ目のinit
に渡すようプロバイダが要求しているとします。この場合のMyTrustManagerFactoryParams
の状態を次に示します。public interface MyTrustManagerFactoryParams extends
ManagerFactoryParameters {
public boolean getBValue();
public float getRValue();
public String getSValue():
}KeyStore オブジェクトやその他のパラメータで明示的に初期化されなくても、トラストが決定できるトラストマネージャもあります。そのようなマネージャは、たとえば、LDAP 経由でローカルディレクトリサービスのトラストデータにアクセスしたり、オンラインの証明書状態チェックサーバをリモートで使用したり、または標準のローカル位置からデフォルトのトラストデータにアクセスすることもできます。
PKIX TrustManager のサポート
Java2 プラットフォームの 1.4.2 リリースから、「SunPKIX」と呼ばれる CertPath ベースの X.509 トラストマネージャファクトリが追加されました。SunPKIX は、デフォルトに加えて使用できましたが、「SunX509」として知られる単純な X.509 トラストマネージャファクトリでした。
J2SE 5 では、SunPKIX が現在のデフォルト X509TrustManagerFactory です。トラストマネージャは、
java.security
ファイルのssl.TrustManagerFactory.algorithm
プロパティによって選択されます。古いトラストマネージャを使用する場合は、「デフォルトのキーマネージャおよびトラストマネージャのカスタマイズ」で説明される手順に従い、プロパティを「PKIX」から「SunX509」に変更してください。この変更によって影響を受けるのはデフォルトのトラストマネージャだけであり、SSLContext.init(..., TrustManager[],...) を介して明示的にトラストマネージャを指定するアプリケーションには影響しません。別の方法として、TrustManagerFactory.getInstance("SunPKIX")
を呼び出すことにより、プログラムから SunPKIX ファクトリにアクセスすることも可能です。PKIX トラストマネージャファクトリは、インストールされたセキュリティプロバイダからの「CertPath PKIX」実装を使用します。「SUN」CerPath プロバイダは J2SE 5 Development Kit に付属しています。トラストマネージャファクトリは、
init(KeyStore ks)
メソッドを使用して、または新しく導入された javax.net.ssl.CertPathTrustManagerParameters クラスを使用して、CertPath パラメータを PKIX トラストマネージャに渡すことにより初期化することができます。トラストマネージャを取得して特定の LDAP 証明書ストアを使用する方法と、取り消し確認を有効にする方法の例を以下に示します。
import javax.net.ssl.*; import java.security.cert.*; import java.security.KeyStore; ... // Create PKIX parameters KeyStore anchors = KeyStore.getInstance("JKS"); anchors.load(new FileInputStream(anchorsFile)); CertPathParameters pkixParams = new PKIXBuilderParameters(anchors, new X509CertSelector()); // Specify LDAP certificate store to use LDAPCertStoreParameters lcsp = new LDAPCertStoreParameters("ldap.imc.org", 389); pkixParams.addCertStore(CertStore.getInstance("LDAP", lcsp)); // Specify that revocation checking is to be enabled pkixParams.setRevocationEnabled(true); // Wrap them as trust manager parameters ManagerFactoryParameters trustParams = new CertPathTrustManagerParameters(pkixParams); // Create TrustManagerFactory for PKIX-compliant trust managers TrustManagerFactory factory = TrustManagerFactory.getInstance("PKIX"); // Pass parameters to factory to be passed to CertPath implementation factory.init(trustParams); // Use factory SSLContext ctx = SSLContext.getInstance("TLS"); ctx.init(null, factory.getTrustManagers(), null);
init (KeyStore ks)
メソッドが使用される場合は、取り消し確認が無効にされる点を除いて、デフォルトの PKIXParameter が使用されます。有効にするには、システムプロパティcom.sun.net.ssl.checkRevocation
をtrue
に設定します。この設定では、CertPath 実装自身が取り消し情報の場所を検出する必要があります。SUN プロバイダの PKIX 実装では多くの場合にこの動作を実行できますが、システムプロパティcom.sun.security.enableCRLDP
をtrue
に設定する必要があります。PKIX および CertPath API の詳細については、「Java Certificate Path API プログラミングガイド」 を参照してください。
X509TrustManager
インタフェース
javax.net.ssl.X509TrustManager
インタフェースは、汎用のTrustManager
インタフェースを拡張したものです。X. 509ベースの認証を行う際、トラストマネージャは必ずこのインタフェースを実装します。JSSE を使ったリモートソケットピアの X.509 認証をサポートするには、このインタフェースのインスタンスを
SSLContext
オブジェクトのinit
メソッドに渡す必要があります。
X509TrustManager
の作成このインタフェースは、自分で直接実装することも、SunJSSE
プロバイダなど、プロバイダベースのTrustManagerFactory
から取得することもできます。また、独自のインタフェースを実装して、ファクトリで生成されたトラストマネージャに委譲することもできます。たとえば、結果として生じたトラストの決定をフィルタにかけ、GUI を使ってエンドユーザに問い合わせる場合に、これを実行します。注: null の KeyStore パラメータが
SunJSSE
の「SunX509」または「SunPKIX」TrustManagerFactory
に渡される場合、ファクトリは次の手順でトラストデータを検索します。
- システムプロパティ
が定義されている場合、javax.net.ssl.trustStoreTrustManagerFactory
は、このシステムプロパティで指定したファイル名を使ってファイルを検索し、このファイルをキーストアで使用します。システムプロパティjavax.net.ssl.trustStorePassword
が同様に定義されている場合は、ファイルを開く前に、その値を使ってトラストストアのデータの整合性をチェックします。
javax.net.ssl.trustStore
が定義されているものの、指定したファイルが存在しない場合、空のキーストアを使用するデフォルトのTrustManager
が作成されます。javax.net.ssl.trustStore
システムプロパティが指定されておらず、さらにファイルが存在すれば、そのファイルを使用します。<java-home>/lib/security/jssecacerts<java-home>
の詳細については、「インストールディレクトリ <java-home>」を参照してください。それ以外の場合、- ファイル
が存在すれば、そのファイルを使用します。<java-home>/lib/security/cacertsどのファイルも存在しない場合、それは匿名の SSL 符号化方式があるためと考えられます。この符号化方式は認証を行わないので、トラストストアは必要ありません。
ファクトリは、セキュリティプロパティ
javax.net.ssl.trustStore
経由で指定したファイル、またはjssecacerts
ファイルを検索してcacerts
ファイルをチェックし、信頼されたルート証明書の JSSE 固有のセットを、コードに署名する目的で、cacerts
にあるものとは別に提供できるようにします。独自の
X509TrustManager
の作成指定したX509TrustManager
の動作がニーズに合わない場合は、独自のX509TrustManager
を作成できます。方法としては、独自のTrustManagerFactory
を作成および登録する方法と、X509TrustManager
インタフェースを直接実装する方法があります。以下の
MyX509TrustManager
クラスは、デフォルトのSunJSSE
X509
TrustManager
が失敗したとき、その他の認証ロジックを提供することによって、デフォルトの動作を拡張します。このようなトラストマネージャを作成できたら、class MyX509TrustManager implements X509TrustManager { /* * The default X509TrustManager returned by SunX509. We'll delegate * decisions to it, and fall back to the logic in this class if the * default X509TrustManager doesn't trust it. */ X509TrustManager sunJSSEX509TrustManager; MyX509TrustManager() throws Exception { // create a "default" JSSE X509TrustManager. KeyStore ks = KeyStore.getInstance("JKS"); ks.load(new FileInputStream("trustedCerts"), "passphrase".toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509", "SunJSSE"); tmf.init(ks); TrustManager tms [] = tmf.getTrustManagers(); /* * Iterate over the returned trustmanagers, look * for an instance of X509TrustManager. If found, * use that as our "default" trust manager. */ for (int i = 0; i < tms.length; i++) { if (tms[i] instanceof X509TrustManager) { sunJSSEX509TrustManager = (X509TrustManager) tms[i]; return; } } /* * Find some other way to initialize, or else we have to fail the * constructor. */ throw new Exception("Couldn't initialize"); } /* * Delegate to the default trust manager. */ public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { try { sunJSSEX509TrustManager.checkClientTrusted(chain, authType); } catch (CertificateException excep) { // do any special handling here, or rethrow exception. } } /* * Delegate to the default trust manager. */ public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { try { sunJSSEX509TrustManager.checkServerTrusted(chain, authType); } catch (CertificateException excep) { /* * Possibly pop up a dialog box asking whether to trust the * cert chain. */ } } /* * Merely pass this through. */ public X509Certificate[] getAcceptedIssuers() { return sunJSSEX509TrustManager.getAcceptedIssuers(); } }init
メソッドを使って、これをSSLContext
に割り当てます。以降、このSSLContext
から作成されたSocketFactories
は、ユーザ独自のTrustManager
を使用して信頼性を判定するようになります。TrustManager[] myTMs = new TrustManager [] { new MyX509TrustManager() }; SSLContext ctx = SSLContext.getInstance("TLS"); ctx.init(null, myTMs, null);
keyStore
の動的更新MyX509TrustManager
を拡張して、キーストアの動的更新処理を行うことができます。checkClientTrusted
またはcheckServerTrusted
のテストに失敗し、信頼できる証明書チェーンを確立できなかった場合、キーストアに対して、要求された信頼できる証明書を追加できます。更新されたキーストアを使って初期化されたTrustManagerFactory
から新しいsunX509TrustManager
を作成する必要があります。以前に初期化したSSLContext
を使って新しい接続を確立すると、新しく追加された証明書が呼び出され、信頼性の判定が行われます。
KeyManager
Interface
KeyManager
は、最終的にリモートホストに送信される認証資格を選択します。自分自身 (ローカルのセキュリティソケットピア) をリモートピアに認証させるには、1 つまたは複数のKeyManager
でSSLContext
オブジェクトを初期化する必要があります。サポートされる各認証機構に、KeyManager
を 1 つ渡す必要があります。SSLContext
の初期化中に NULL が渡されると、空のKeyManager
が作成されます。内部のデフォルトコンテキストが使用される場合 (たとえば、SSLContext
はSSLSocketFactory.getDefault()
またはSSLServerSocketFactory.getDefault()
によって作成される) は、デフォルトのKeyManager
が作成されます。通常は、X.509
公開鍵証明書に基づく認証をサポートするキーマネージャが 1 つあります。安全なソケット実装には、共有の秘密鍵、Kerberos、またはその他の機構に基づく認証をサポートするものもあります。
KeyManager
はKeyManagerFactory
によって、またはインタフェースの具体的な実装を行うことによって作成されます。
KeyManagerFactory
クラス
javax.net.ssl.KeyManagerFactory
はプロバイダベースのサービスのエンジンクラスで、1 つまたは複数の型のKeyManager
オブジェクトのファクトリとして動作します。SunJSSE
プロバイダは、基本となる X.509 キーマネージャを返すことができるファクトリを実装します。これはプロバイダベースであるため、追加のファクトリを実装し、設定することにより、追加の、または代替のキーマネージャを提供できます。
KeyManagerFactory
の作成このクラスのインスタンスはSSLContext
と同様の方法で作成しますが、getInstance
メソッドにプロトコル名ではなくアルゴリズム名の文字列を渡す点が異なります。public static KeyManagerFactory
getInstance(String algorithm);
public static KeyManagerFactory
getInstance(String algorithm,
String provider);
public static KeyManagerFactory
getInstance(String algorithm,
Provider provider);アルゴリズム名文字列の例を次に示します。
"SunX509"呼び出しの例を次に示します。
KeyManagerFactory kmf =
KeyManagerFactory.getInstance("SunX509", "SunJSSE");上記の呼び出しで
SunJSSE
プロバイダのデフォルトのキーマネージャファクトリのインスタンスが作成されます。キーマネージャファクトリは、基本となる X.509 ベースの認証キーを提供します。新しく作成されたファクトリは、
init
メソッドの 1 つを呼び出すことによって初期化する必要があります。public void init(KeyStore ks, char[] password);
public void init(ManagerFactoryParameters spec);使用する
KeyManagerFactory
に適切なinit
メソッドを呼び出します。プロバイダのベンダーに問い合わせてください。デフォルトの「SunX509」
KeyManagerFactory
など、SunJSSE
プロバイダが提供するファクトリは多数ありますが、KeyManagerFactory
を初期化するために必要な情報はKeyStore
とパスワードだけなので、最初にinit
メソッドを呼び出すのが適切です。KeyManagerFactory
はKeyStore
に、リモートのソケットピアを認証するために使用する非公開鍵、および対応する公開鍵証明書について問い合わせます。パスワードパラメータは、KeyStore
の鍵にアクセスするメソッドで使用するパスワードを指定します。KeyStore
の鍵はすべて、同じパスワードで保護する必要があります。プロバイダには、
KeyStore
とパスワード以外の初期化パラメータが必要な場合もあります。そのような特定のプロバイダの利用者は、プロバイダによる定義に従って、適切なManagerFactoryParameters
の実装を渡す必要があります。その後、プロバイダはManagerFactoryParameters
実装の特定のメソッドを呼び出し、必要な情報を取得できます。ある種のファクトリでは、KeyStore オブジェクトやその他のパラメータで初期化されなくても、認証データにアクセスできます。たとえば、Java 認証・承認サービス (JAAS) などのログイン機構の一部として鍵データにアクセスできる場合があります。
上で述べたように、
SunJSSE
プロバイダは「SunX509」ファクトリをサポートします。ファクトリは、KeyStore パラメータで初期化する必要があります。
X509KeyManager
インタフェースjavax.net.ssl.X509KeyManager
インタフェースは、汎用のKeyManager
インタフェースを拡張したものです。X.509 ベースの認証を行うキーマネージャで実装します。JSSE を使ったリモートソケットピアの X.509 認証をサポートするには、このインタフェースのインスタンスをSSLContext
オブジェクトのinit
メソッドに渡す必要があります。
X509KeyManager
の作成このインタフェースは、自分で直接実装することも、SunJSSE
プロバイダなど、プロバイダベースのKeyManagerFactory
から取得することもできます。また、独自のインタフェースを実装して、ファクトリで生成されたキーマネージャに委譲することもできます。たとえば、生成される鍵をフィルタにかけ、GUI を使ってエンドユーザに問い合わせる場合に、これを実行します。注: KeyStore パラメータを
SunJSSE
のデフォルトの「SunX509」KeyManagerFactory
に渡さない場合、ファクトリは次のシステムプロパティに問い合わせて、鍵データを検索します。これらのプロパティが適切なパスワードを持つファイルを指定すれば、ファクトリはこのファイルを KeyStore で使用します。そのファイルが存在しない場合、空のキーストアを使用するデフォルトのjavax.net.ssl.keyStore
javax.net.ssl.keyStorePasswordKeyManager
が作成されます。一般に、ハンドシェークでサーバとして動作するプロセスには、クライアントへの認証資格を取得するため、KeyManager のキーストアが必要です。ただし、匿名の符号化方式を選択する場合、サーバの
KeyManager
キーストアは必要ありません。また、サーバがクライアント認証を要求しないかぎり、クライアントとして動作するプロセスには、KeyManager
キーストアは必要ありません。したがって、このような状況では、javax.net.ssl.keyStore
のシステムプロパティ値が定義されていない場合もあります。独自の
X509KeyManager
の作成X509KeyManager
のデフォルトの動作がニーズに合わない場合は、「独自のX509TrustManager
の作成」と同様の手順で独自のX509KeyManager
を作成できます。
TrustManager
とKeyManager
の関連性これまでは、TrustManager
とKeyManager
の機能がしばしば混同されてきました。ここでは、各マネージャ型の主な機能を要約します。
型 機能 TrustManager
リモート認証資格の信頼性 (すなわち接続の信頼性) を判定します。 KeyManager
リモートホストに送信される認証資格を決定します。 二次サポートクラスおよびインタフェース
二次サポートクラスは、安全なソケットの作成、使用、および管理をサポートする JSSE API の一部として提供されます。このクラスは、セキュリティソケットアプリケーションでは、コアクラスやサポートクラスほどには使用されません。二次サポートクラスおよびインタフェースは
javax.net.ssl
およびjavax.security.cert
パッケージに含まれています。
SSLSessionContext
インタフェース
javax.net.ssl.SSLSessionContext
は、単一のエンティティに関連付けられたSSLSession
をグループ化したものです。たとえば、多数のセッションに同時に参加するサーバやクライアントに関連付けることができます。このインタフェースのメソッドを使うと、コンテキストの全セッションを列挙したり、セッション ID で特定のセッションを検索することができます。
SSLSessionContext
は、SSLSession のgetSessionContext
メソッドを呼び出してSSLSession
から任意に取得することもできます。一部の環境では、コンテキストが利用できません。それは、getSessionContext
メソッドが NULL を返す場合です。
SSLSessionBindingListener
インタフェース
javax.net.ssl.SSLSessionBindingListener
は、SSLSession
からバインドまたはアンバインドされるときに通知を受けるオブジェクトによって実装されます。
SSLSessionBindingEvent
クラス
javax.net.ssl.SSLSessionBindingEvent
は、SSLSession
からバインドまたはアンバインドされるときに、SSLSessionBindingListener
と通信するイベントです。
HandShakeCompletedListener
インタフェース
javax.net.ssl.HandShakeCompletedListener
は、SSLSocket
接続時に SSL プロトコルハンドシェークの完了通知を受け取る任意のクラスに実装されるインタフェースです。
HandShakeCompletedEvent
クラス
javax.net.ssl.HandShakeCompletedEvent
は、SSLSocket
接続の SSL プロトコルハンドシェークが終了したときにHandShakeCompletedListener
と通信するイベントです。
HostnameVerifier
インタフェースSSL/TLS 実装の標準ホスト名検証ロジックが失敗した場合、実装は、このインタフェースを実装し、このHttpsURLConnection
インスタンスに割り当てられたクラスのverify
メソッドを呼び出します。所定のパラメータがホスト名を受け付けることが明らかな場合、コールバッククラスは、接続が許可されることを報告する必要があります。応答が受け付けられない場合、接続は切断されます。次に例を示します。
public class MyHostnameVerifier implements HostnameVerifier {
public boolean verify(String hostname, SSLSession session) {
// pop up an interactive dialog box
// or insert additional matching logic
if (good_address) {
return true;
} else {
return false;
}
}
}
//...deleted...
HttpsURLConnection urlc = (HttpsURLConnection)
(new URL("https://www.sun.com/")).openConnection();
urlc.setHostnameVerifier(new MyHostnameVerifier());HostnameVerifier
をHttpsURLConnection
に割り当てる方法については、「HttpsURLConnection
クラス」を参照してください。
X509Certificate
クラス安全なソケットプロトコルの多くは、X.509 証明書という公開鍵証明書を使って認証を行います。これは、SSL および TLS プロトコルのデフォルト認証機構です。
java.security.cert.X509Certificate
抽象クラスは、X.509 証明書の属性にアクセスする標準的な方法を提供します。注:
javax.security.cert.X509Certificate
クラスは、以前のバージョンの JSSE (1.0.x、1.1.x) との後方互換性を確保するためのものです。新しいアプリケーションではjava.security.cert.X509Certificate
を使用し、javax.security.cert.X509Certificate
は使用しません。旧バージョン (JSSE 1.0.x) の実装クラスおよびインタフェース
JSSE の旧バージョン (1.0.x) にはリファレンス実装があり、その実装では、クラスおよびインタフェースが
com.sun.net.ssl
パッケージで提供されました。v 1.4 の時点で、JSSE は J2SDK に統合されています。従来
com.sun.net.ssl
パッケージにあったクラスは、javax.net.ssl
パッケージに移動し、現在では標準の JSSE API に含まれています。
com.sun.net.ssl
のクラスとインタフェースは下位互換のために存在しているので、使用しないようお勧めします。これらのクラスとインタフェースを使って記述したアプリケーションは、再コンパイルせずに v 1.4 以降の J2SDK で実行することができます。今後のリリースでは、このクラスとインタフェースは削除される可能性があります。そのため、新しいアプリケーションはすべてjavax
のクラスとインタフェースを使って書くほうがよいでしょう。現在のところ、
com.sun.net.ssl
API を使用して作成したアプリケーションは、com.sun.net.ssl
を使用する JSSE 1.0.2 プロバイダ、またはjavax
API を使用する v 1.4 以降の J2SDK 用に記述された JSSE プロバイダのどちらでも利用できます。ただし、J2SDK v 1.4 以降の JSSE API を使って作成したアプリケーションは、v 1.4 以降の J2SDK 用に記述された JSSE プロバイダしか利用できません。新しいリリースには何らかの新機能が含まれるので、対応していないプロバイダではそうした新機能は利用できません。SunJSSE
は Sun Microsystems の J2SDK で提供されるプロバイダで、javax
API で作成されています。JSSE 1.0.2 を使用している場合のように
java.protocol.handler.pkgs
System
プロパティを設定して URL 検索パスを更新すれば、引き続きcom.sun.net.ssl.HttpsURLConnection
を取得できます。詳細については、トラブルシューティングの「HttpsURLConnection
クラスを使用するコード」を参照してください。
インストールディレクトリ<java-home>
このマニュアルでは、
<java-home>
は、Java 2 Runtime Environment (JRE) がインストールされているディレクトリを表します。ディレクトリは、JSSE を実行しているのが、JavaTM 2 SDK をインストールした JRE か、インストールしていない JRE かによって異なります。Java 2 SDK には JRE が含まれていますが、ファイル階層のレベルは異なります。
<java-home>
が表すディレクトリの例を、次に示します。
- Solaris で、Java 2 SDK のインストール先が
/home/user1/jdk1.5.0
の場合、<java-home>
は次の場所です。/home/user1/jdk1.5.0/jre
- Solaris で、JRE が
/home/user1/jre1.5.0
にインストールされており Java 2 SDK がインストールされていない場合、<java-home>
は次の場所です。/home/user1/jre1.5.0
- Microsoft Windows で、Java 2 SDK のインストール先が
C:\jdk1.5.0
の場合、<java-home>
は次の場所です。C:\j2k1.5.0\jre
- Microsoft Windows で、JRE が
C:\jre1.5.0
にインストールされており、Java 2 SDK がインストールされていない場合、、<java-home>
は次の場所です。C:\jre1.5.0カスタマイズ
JSSE には、すべてのユーザが使用できる実装が含まれています。必要であれば、JSSE のさまざまな機能を変更して異なる実装を追加したり、デフォルトのキーストアを指定することもできます。次の表は、カスタマイズできる機能、デフォルト設定、およびカスタマイズの提供に使用する機構をまとめたものです。表の最初の列には、指定した機能と、カスタマイズ方法の詳細が説明されているサイトへのリンクが設定してあります。
一部の機能は、システムプロパティやセキュリティプロパティの値を設定してカスタマイズできます。表に続く節では、プロパティ値の設定方法について説明します。
重要: この表に示すプロパティの多くは、現在 JSSE 実装で使用されていますが、それらの名前や型 (システムまたはセキュリティ) が今後も変更されないという保証はなく、それが将来のリリースに存在するという保証もありません。変更や廃止の可能性があるプロパティには「*」が付いています。ここでは、JSSE 実装で使用する場合の参考として、それらに言及しています。
JSSE のカスタマイズ
カスタマイズ項目
デフォルト設定
カスタマイズ方法
X509Certificate 実装 Sun Microsystems の X509Certificate 実装
cert.provider.x509v1セキュリティプロパティ
HTTPS プロトコル実装 Sun Microsystems の実装
java.protocol.handler.pkgs システムプロパティ
プロバイダ実装 SunJSSE
セキュリティプロパティファイルの security.provider.n= 行。説明を参照
デフォルトの SSLSocketFactory 実装 Sun Microsystems からの SSLSocketFactory 実装
** ssl.SocketFactory.provider セキュリティプロパティ
デフォルトの SSLServerSocketFactory 実装 Sun Microsystems からの SSLServerSocketFactory 実装
** ssl.ServerSocketFactory.provider セキュリティプロパティ
デフォルトのキーストア デフォルトは存在しない
* javax.net.ssl.keyStore システムプロパティ。
値NONE
を指定可能。この設定は、ハードウェアトークンに存在する場合など、キーストアがファイルベースでない場合に適切デフォルトのキーストアパスワード デフォルトは存在しない
* javax.net.ssl.keyStorePassword システムプロパティ
デフォルトのキーストアプロバイダ デフォルトは存在しない
* javax.net.ssl.keyStoreProvider システムプロパティ
デフォルトのキーストア型 KeyStore.getDefaultType()
* javax.net.ssl.keyStoreType システムプロパティ
デフォルトのトラストストア 存在する場合は
jssecacerts
。存在しない場合はcacerts
*
javax.net.ssl.trustStore
システムプロパティデフォルトのトラストストアパスワード デフォルトは存在しない
* javax.net.ssl.trustStorePassword システムプロパティ
デフォルトのトラストストアプロバイダ デフォルトは存在しない
* javax.net.ssl.trustStoreProvider システムプロパティ
デフォルトのトラストストア型 KeyStore.getDefaultType()
* javax.net.ssl.trustStoreType システムプロパティ。
値NONE
を指定可能。この設定は、ハードウェアトークンに存在する場合など、トラストストアがファイルベースでない場合に適切デフォルトのキーマネージャファクトリのアルゴリズム名
SunX509
ssl.KeyManagerFactory.algorithm セキュリティプロパティ デフォルトのトラストマネージャファクトリのアルゴリズム名
PKIX
ssl.TrustManagerFactory.algorithm セキュリティプロパティ デフォルトのプロキシホスト デフォルトは存在しない
* https.proxyHost システムプロパティ デフォルトのプロキシポート 80
* https.proxyPort システムプロパティ デフォルトの暗号群 ソケットファクトリによって決定
* https.cipherSuites システムプロパティ。 HttpsURLConnection
で使用できる符号化方式を指定する符号化方式名リスト (コンマ区切り形式) を含む。SSLSocket setEnabledCipherSuites(String[])
メソッドを参照デフォルトのハンドシェークプロトコル ソケットファクトリによって決定
* https.protocols システムプロパティ。 HttpsURLConnection
で使用できるプロトコル群を指定するプロトコル群名リスト (コンマ区切り形式) を含む。 SSLSocket setEnabledProtocols(String[]) メソッドを参照デフォルトの https ポート 443
* https URL 内の port
フィールドをカスタマイズSunJSSE プロバイダが使用する JCE 暗号化アルゴリズム SunJCE 実装
代替 JCE アルゴリズムプロバイダに SunJSSE プロバイダより高い優先順位を付与 * このプロパティは現在、JSSE 実装で使用されています。他の実装での検証および使用は保証されていません。他の実装で検証する場合は、その実装でも JSSE 実装と同じ方法でプロパティを処理するものとします。プロパティが今後も存在すること、またはシステム型やセキュリティ型が将来のリリースでも変更されないことの保証はされません。
** 米国輸出規制により、Sun Microsystems の Java 2 SDK, v 1.4 以降の JSSE 実装は完全なプラグイン可能性に対応していないので、デフォルトの
SSLSocketFactory
実装およびSSLServerSocketFactory
実装の交換には制約があります。詳細については 「プラグイン可能性に関する注記」 を参照し、 該当する配備プラットフォームごとに制約事項を確認してください。その他の SSL/TLS 実装を許容する JSSE 実装を使用する場合は、指定されたセキュリティプロパティを設定して使用します。
java.lang.system
プロパティを設定してカスタマイズする項目と、java.security.Security
プロパティを設定してカスタマイズする項目があります。以下の節では、両方のプロパティ型の値を設定する方法を説明します。
java.lang.system
プロパティの設定方法JSSE の機能には、システムプロパティを設定してカスタマイズするものがあります。システムプロパティは静的または動的に設定します。
- システムプロパティを静的に設定するには、
java
コマンドの-D
オプションを使用します。たとえば、アプリケーションMyApp
を実行してシステムプロパティjavax.net.ssl.trustStore
を設定し、「MyCacertsFile
」というトラストストアを指定するには、次のように入力します。java -Djavax.net.ssl.trustStore=MyCacertsFile MyApp
- システムプロパティを動的に設定するには、次のコードで
java.lang.System.setProperty
メソッドを呼び出します。適切なプロパティ名と値を入力してください。たとえば、システムプロパティSystem.setProperty(propertyName,
"propertyValue");javax.net.ssl.trustStore
を設定して「MyCacertsFile
」というトラストストアを指定する、上記の例に対応したsetProperty
呼び出しでは、次のように入力します。System.setProperty("javax.net.ssl.trustStore",
"MyCacertsFile");
java.security.Security
プロパティの設定JSSE の機能には、セキュリティプロパティを設定してカスタマイズするものがあります。セキュリティプロパティは静的または動的に設定します。
- セキュリティプロパティを静的に設定するには、セキュリティプロパティファイルに 1 行追加します。セキュリティプロパティファイルは次のディレクトリにあります。
ここで、<java-home> は、JRE ランタイムソフトウェアのインストールディレクトリです。インストールディレクトリ <java-home> を参照してください。<java-home>/lib/security/java.securityセキュリティプロパティファイルでセキュリティプロパティ値を指定するには、次の行を追加します。
propertyName=propertyValueたとえば、デフォルトの「SunX509」以外のキーマネージャファクトリのアルゴリズム名を指定するとします。
ssl.KeyManagerFactory.algorithm
のセキュリティプロパティ値をアルゴリズム名に指定します。たとえば、値を「MyX509」に設定するには、セキュリティプロパティファイルを次のように変更します。ssl.KeyManagerFactory.algorithm=MyX509
- セキュリティプロパティを動的に設定するには、次のコードで
java.security.Security.setProperty
メソッドを呼び出します。適切なプロパティ名と値を入力してください。たとえば、キーマネージャファクトリのアルゴリズム名を指定する、上記の例に対応したSecurity.setProperty(propertyName,
"propertyValue");setProperty
呼び出しでは、次のように入力します。Security.setProperty("ssl.KeyManagerFactory.algorithm",
"MyX509");X509 証明書実装のカスタマイズ
X509Certificate.getInstance
メソッドで返された X509 証明書実装は、デフォルトでは JSSE 実装の実装です。任意で、別の実装を返すようにすることもできます。その場合は、新しい実装クラスの名前 (およびパッケージ) を、
cert.provider.x509v1
というセキュリティプロパティ値に設定します。たとえば、MyX509CertificateImpl
というクラスがcom.cryptox
パッケージにある場合、セキュリティプロパティファイルに次の行を追加します。cert.provider.x509v1=com.cryptox.MyX509CertificateImplHTTPS プロトコルの代替実装
java.net.URL
クラスに https で始まる URL を使えば、SSL が利用できる Web サーバで安全に通信できます。J2SDK では、https の URL 実装をデフォルトで提供します。別の https プロトコル実装を使用する場合は、
java.protocol.handler.pkgs
のシステムプロパティに新しいクラス名を追加します。その結果、J2SDK のデフォルトクラスより前に、指定したクラスが検索され、ロードされます。詳細については、java.net.URL
クラスを参照してください。旧バージョンの JSSE ユーザへの注記: 旧バージョンの JSSE では、JSSE のインストール中に
java.protocol.handler.pkgs
システムプロパティを設定する必要がありました。このステップは、com.sun.net.ssl.HttpsURLConnection
のインスタンスを取得する場合以外は不要になりました。詳細については、「トラブルシューティング」の「HttpsURLConnection
クラスを使用するコード」を参照してください。プロバイダ実装のカスタマイズ
v 1.4 以降の J2SDK リリースには、「
SunJSSE
」という JSSE 暗号化サービスプロバイダ (プロバイダ) が標準で付属しています。基本的に、プロバイダは特定の暗号化アルゴリズムのエンジンクラスを実装するパッケージです。JSSE のエンジンクラスはSSLContext
、KeyManagerFactory
、およびTrustManagerFactory
です。プロバイダとエンジンクラスの詳細については、「JavaTM 暗号化アーキテクチャ APIの仕様およびリファレンス」の「設計方針」と「概念」の節を参照してください。プロバイダを使用するには、そのプロバイダを静的または動的に登録する必要があります。「SunJSSE」プロバイダは登録済みなので、新しく登録する必要はありません。他のプロバイダを使用する場合は、後述のセクションでプロバイダの登録方法を確認してください。
暗号化サービスプロバイダを静的に登録する
プロバイダを静的に登録するには、セキュリティプロパティファイルに次の行を追加します。security.provider.n=providerClassNameこれはプロバイダを宣言し、優先順位「n」を指定するものです。優先順位とは、特定プロバイダの指定がない場合に、要求されたサービスに関して検索されるプロバイダの順位です。順位は 1 から始まり、1 が最優先で次に 2、3 ...と続きます。
providerClassName は、プロバイダクラスの完全修飾名です。この名前は、プロバイダベンダーから取得します。
プロバイダを登録するには、セキュリティプロパティに上記の行を追加して、providerClassName をプロバイダクラスの完全な修飾名、n をプロバイダに割り当てる優先順位にします。
標準のセキュリティプロバイダ、および Java 2 プラットフォームに付属する SunJSSE が自動的に登録されます。
java.security
セキュリティプロパティファイルに次の行が追加され、SunJCE セキュリティプロバイダの優先順位が 5、SunJSSE プロバイダの優先順位が 4 として登録されます。security.provider.1=sun.security.pkcs11.SunPKCS11 \ ${java.home}/lib/security/sunpkcs11-solaris.cfg security.provider.2=sun.security.provider.Sun security.provider.3=sun.security.rsa.SunRsaSign security.provider.4=com.sun.net.ssl.internal.ssl.Provider security.provider.5=com.sun.crypto.provider.SunJCE security.provider.6=sun.security.jgss.SunProvider security.provider.7=com.sun.security.sasl.Provider他の JSSE プロバイダを使う場合は、行を追加してプロバイダを登録し、優先順位を設定します。
複数の JSSE プロバイダを同時に登録できます。プロバイダには、異なるエンジンクラスの、異なるアルゴリズムの異なる実装が含まれる場合があり、同じ型のアルゴリズムおよびエンジンクラスの一部または全部をサポートする場合もあります。特定のアルゴリズムの特定のエンジンクラス実装を検索するとき、その条件に該当する特定のプロバイダが指定されていない場合、プロバイダは優先順位付きで検索され、指定したアルゴリズムを実装する最初のプロバイダの実装が使用されます。
暗号化サービスプロバイダを動的に登録する
プロバイダを静的に登録する代わりに、プログラム開始時に
Security.addProvider
メソッドを呼び出して、実行時に動的に追加することができます。たとえば、プロバイダのクラス名がMyProvider
で、com.ABC
パッケージにMyProvider
クラスがある場合、次のようなメソッドを呼び出してプロバイダを動的に追加します。Security.addProvider(
new com.ABC.MyProvider());
Security.addProvider
メソッドは、次に利用できる優先順位で、指定したプロバイダを追加します。この登録は恒久的ではなく、十分なアクセス権があるプログラムでしか実行できません。
デフォルトの鍵とトラストストア、ストア型、およびストアパスワードのカスタマイズ
SSLSocketFactory.getDefault
やSSLServerSocketFactory.getDefault
を呼び出すことでデフォルトのSSLSocketFactory
やSSLServerSocketFactory
が作成され、このデフォルトのSSLSocketFactory
(またはSSLServerSocketFactory
) が JSSE リファレンス実装に由来するものであれば、デフォルトのSSLContext
は必ずソケットファクトリに関連付けられます。デフォルトのソケットファクトリは、JSSE 実装に由来します。デフォルトの
SSLContext
は、デフォルトのKeyManager
およびTrustManager
で初期化されます。javax.net.ssl.keyStore
システムプロパティによってキーストアが指定されると、デフォルトのSSLContext
によって作成されるKeyManager
は、指定したキーストアを管理するKeyManager
実装になります。実際には「デフォルト鍵とトラストマネージャ」で説明したとおりに実装されます。システムプロパティが指定されない場合は、KeyManager
が管理するキーストアは新しい空のキーストアです。同様に、トラストストアを
javax.net.ssl.trustStore
システムプロパティで指定すると、デフォルトのSSLContext
で作成したTrustManager
が、指定したトラストストアを管理するTrustManager
実装になります。この場合、プロパティが存在しても指定するファイルが存在しなければ、トラストストアは使用されません。javax.net.ssl.trustStore
プロパティが存在しない場合は、デフォルトのトラストストアを検索します。<java-home>/lib/security/jssecacerts
というトラストストアが見つかった場合、これを使用します。このトラストストアが見つからない場合、<java-home>/lib/security/jssecacerts
というトラストストアを検索し、見つかればこれを使用します。<java-home>
については「インストールディレクトリ <java-home>」を参照してください。トラストストアが見つからない場合、TrustManager
は新しい空のトラストストアを管理します。
重要: J2SDK には、少数の信頼されたルート証明書を含む<java-home>/lib/security/cacerts
ファイルが付属しています。「keytool」 に記載したとおり、このファイルをトラストストアとして使用する場合は、このファイルに含まれる証明書の管理 (追加または削除) を行う必要があります。接続先のサーバの証明書構成によっては、ルート証明書を新たに追加しなければならない場合もあります。適切なベンダーから必要なルート証明書を入手してください。
システムプロパティ
javax.net.ssl.keyStoreType
とjavax.net.ssl.keyStorePassword
の両方またはどちらか一方が指定されている場合、それぞれがデフォルトのKeyManager
キーストア型とパスワードとして扱われます。型が指定されていない場合、デフォルトの型はKeyStore.getDefaultType()
が返すkeystore.type
セキュリティプロパティの値です。また、そうしたセキュリティプロパティが指定されていない場合は「jks」になります。キーストアのパスワードが指定されていない場合は "" と見なされます。同様に、システムプロパティ
javax.net.ssl.trustStoreType
とjavax.net.ssl.trustStorePassword
の両方またはどちらか一方が指定されている場合、それぞれがデフォルトのトラストストア型とパスワードとして扱われます。型が指定されていない場合、KeyStore.getDefaultType()
によってデフォルト型が返されます。トラストストアのパスワードが指定されていない場合は "" と見なされます。重要: この節では、現在の JSSE リファレンス実装の動作を説明します。この節で説明するシステムプロパティの名前と型 (システムかセキュリティか) が今後も使用されるという保証はありません。また、今後のリリースで存在するという保証もありせん。また、他の JSSE 実装での検証や使用も保証されていません。他の実装で検証される場合は、その実装がここで説明される JSSE リファレンス実装と同じ方法でプロパティを処理するものとします。
デフォルトのキーマネージャおよびトラストマネージャのカスタマイズ
「デフォルトの鍵とトラストストア、ストア型、およびパスワードのカスタマイズ」で説明したように、デフォルトの
SSLSocketFactory
やSSLServerSocketFactory
が作成され、このデフォルトのSSLSocketFactory
(またはSSLServerSocketFactory
) が JSSE リファレンス実装に由来する場合は、常にデフォルトのSSLContext
はソケットファクトリに関連付けられます。このデフォルトの
SSLContext
は、デフォルトのKeyManager
およびTrustManager
で初期化されます。デフォルトのSSLContext
に提供されたKeyManager
とTrustManager
の両方またはどちらか一方は、指定したキーストアまたはトラストストアを管理するKeyManager
またはTrustManager
の実装になります。これについては、あとの節で説明します。選択される
KeyManager
実装は、まずセキュリティプロパティを確認して決定されます。そのようなプロパティ値が指定されていると、指定したアルゴリズムのssl.KeyManagerFactory.algorithmKeyManagerFactory
実装が検索されます。実装を提供する最初のプロバイダの実装が使用されます。実装のgetKeyManagers
メソッドが呼び出され、デフォルトのSSLContext
に提供するKeyManager
が決定されます。技術的には、getKeyManagers
はKeyManager
の配列を返します。これは鍵データの型ごとのKeyManager
です。そのようなセキュリティプロパティ値が指定されていない場合、「SunX509」のデフォルト値を使って検索します。注: 「SunX509」アルゴリズムのKeyManagerFactory
実装はSunJSSE
プロバイダが提供します。プロバイダが指定するKeyManager
はjavax.net.ssl.X509KeyManager
実装です。同様に、選択される
TrustManager
実装は、まずセキュリティプロパティを確認して決定されます。そのようなプロパティ値が指定されていると、指定したアルゴリズムのssl.TrustManagerFactory.algorithmTrustManagerFactory
実装が検索されます。実装を提供する最初のプロバイダの実装が使用されます。実装のgetTrustManagers
メソッドが呼び出され、デフォルトのSSLContext
に提供するTrustManager
が決定されます。技術的には、getTrustManagers
はTrustManager
の配列を返します。これは鍵データの型ごとのTrustManager
です。そのようなセキュリティプロパティ値が指定されていない場合、「PKIX」のデフォルト値を使って検索します。注: 「PKIX」アルゴリズムのTrustManagerFactory
実装はSunJSSE
プロバイダが提供します。プロバイダが指定するTrustManager
はjavax.net.ssl.X509TrustManager
実装です。重要: この節では、現在の JSSE リファレンス実装の動作を説明します。この節で説明するシステムプロパティの名前と型 (システムかセキュリティか) が今後も使用されるという保証はありません。また、今後のリリースで存在するという保証もありせん。また、他の JSSE 実装での検証や使用も保証されていません。他の実装で検証される場合は、その実装がここで説明される JSSE リファレンス実装と同じ方法でプロパティを処理するものとします。
暗号化アルゴリズムプロバイダのカスタマイズ
J2SE 5 のリリースから、SunJSSE プロバイダは、暗号化の必要すべてを満たすために SunJCE 実装を使用しています。Sun プロバイダは通常の位置に置くことが推奨されていますが、SunJCE プロバイダより前に登録することにより、他の JCA/JCE プロバイダからの実装を使用することもできます。 プロバイダの構成には、標準 JCA 機構を使用できます。まず、以下のセキュリティプロパティファイルを利用して静的に行う方法があります。
次に、<java-home>/lib/security/java.securityjava.security.Security
クラスのaddProvider
メソッドまたはinsertProviderAt
メソッドを利用して動的に行う方法があります。<java-home>
の詳細については、「インストールディレクトリ <java-home>」を参照してください。プロバイダの実装を行うユーザへの注記
SunJSSE が
Cipher.getInstance()
を呼び出すとき、使用される変換文字列は「RSA/ECB/PKCS1Padding」、「RC4」、「DES/CBC/NoPadding」、および「DESede/CBC/NoPadding」になります。Cipher クラスと変換文字列の詳細については、「JCE リファレンスガイド」を参照してください。
JCE の使用法
Java 暗号化拡張機能 (JCE) は、暗号化、鍵生成と鍵協定、およびメッセージ認証コード (MAC) アルゴリズム用のフレームワークおよび実装となるパッケージセットです。J2SE 5 より前の SunJSSE プロバイダは、構成されていれば JCE プロバイダを利用することができましたが、依然として JCE を使用しない内部暗号化コードが含まれていました。J2SE 5 の SunJSSE プロバイダは、すべての暗号化操作のために JCE を排他的に使用するので、JCE に新しく追加された PKCS#11 のサポートを含め、JCE の特長や拡張機能の利点を自動的に活用することができます。これにより J2SE 5 の SunJSSE プロバイダは、ハードウェア暗号化アクセラレータを使用してパフォーマンスを著しく向上させ、キーストアとしてスマートカードを使用し、鍵および信頼性管理の柔軟性を高めることができます。ハードウェアアクセラレータ
基盤となるアクセラレータハードウェアを使用するように SUN PKCS#11 プロバイダが構成され、その PKCS#11 プロバイダを使用するように JCE が構成されていれば、ハードウェア暗号化アクセラレータは自動的に使用されます。PKCS#11 プロバイダは、プロバイダリストにある他の JCE/JCA プロバイダより前に構成する必要があります。Sun PCCS#11 プロバイダの構成方法については、「PKCS#11 リファレンスガイド」を参照してください。
スマートカードをキーストアおよびトラストストアとして使用するための JSSE の構成
JCE での PKCS#11 のサポートにより、キーストアとしてスマートカードにアクセスすることもできます。JSSE によって使用されるキーストアの型と場所の構成方法については、「カスタマイズ」を参照してください。スマートカードをキーストアまたはトラストストアとして使用するには、javax.net.ssl.keyStoreType および javax.net.ssl.trustStoreType システムプロパティをそれぞれ「pkcs11」に設定し、javax.net.ssl.keyStore および javax.net.ssl.trustStore システムプロパティをそれぞれ「NONE」に設定します。特定のプロバイダを使用するように指定するには、javax.net.ssl.keyStoreProvider および javax.net.ssl.trustStoreProvider システムプロパティを使用します (例:「SunPKCS11-joe」)。 これらのプロパティを使用することにより、以前はファイルベースのキーストアにアクセスするためにこれらのプロパティに依存していたアプリケーションを構成して、アプリケーションに変更を加えずにスマートカードのキーストアを使用できます。アプリケーションによっては、キーストアをプログラムで使用する必要があります。こうしたアプリケーションでは、引き続き既存の API を使用して Keystore をインスタンス化し、キーマネージャとトラストマネージャに渡すことができます。Keystore インスタンスがスマートカードによる PKCS#11 キーストアを参照する場合は、JSSE アプリケーションがスマートカードキーにアクセスすることになります。
複数の動的キーストア
スマートカードおよび他の取り外し可能トークンには、X509KeyManager の場合に要件が追加されます。Java アプリケーションが存続する間には、異なるスマートカードがスマートカードリーダーに挿入され、それらのスマートカードは異なるパスワードを使用して保護されます。J2SE 5 以前の API および SunX509 キーマネージャは、これらの要件を十分に満たしていませんでした。 そのため、J2SE 5 には新しい API が組み込まれており、新しい X509KeyManager 実装が SunJSSE プロバイダに追加されました。
java.security.KeyStore.Builder クラスは、KeyStore オブジェクトの構造と初期化データを抽象化します。パスワードのプロンプトに CallbackHandlers を使用でき、サブクラス化してアプリケーションにとって望ましい追加機能をサポートできます。たとえば、ビルダを実装して、個々の KeyStore エントリを異なるパスワードで保護することが可能です。その後、javax.net.ssl.KeyStoreBuilderParameters クラスを使用し、これらのビルダオブジェクトを 1 つ以上使用して KeyManagerFactory を初期化することができます。
「NewSunX509」と呼ばれる、SunJSSE プロバイダの新しい X509KeyManager 実装は、これらのパラメータをサポートしています。複数の証明書が使用可能な場合は、鍵の使用法が適切な証明書を選択し、期限切れの証明書より有効な証明書を優先させます。
スマートカードを使用する PKCS#11 ファイルベースキーストアと PCKS#12 ファイルベースキーストアの両方を使用するよう JSSE に指示する方法の例を以下に示します。
import javax.net.ssl.*; import java.security.KeyStore.*; ... // Specify keystore builder parameters for PKCS#11 keystores Builder scBuilder = Builder.newInstance("PKCS11", null, new CallbackHandlerProtection(myGuiCallbackHandler)); // Specify keystore builder parameters for a specific PKCS#12 keystore Builder fsBuilder = Builder.newInstance("PKCS12", null, new File(pkcsFileName), new PasswordProtection(pkcsKsPassword)); // Wrap them as key manager parameters ManagerFactoryParameters ksParams = new KeyStoreBuilderParameters( Arrays.asList(new Builder[] { scBuilder, fsBuilder })); // Create KeyManagerFactory KeyManagerFactory factory = KeyManagerFactory.getInstance("NewSunX509"); // Pass builder parameters to factory factory.init(ksParams); // Use factory SSLContext ctx = SSLContext.getInstance("TLS"); ctx.init(factory.getKeyManagers(), null, null);
J2SE 5 の SunJSSE プロバイダは、RFC 2712 で規定される Kerberos 符号化方式をサポートします。以下の符号化方式がサポートされていますが、デフォルトでは有効になっていません。これらの符号化方式を使用可能にするには、明示的に指定する必要がります。詳細については、SSLEngine.setEnabledCipherSuites() および SSLSocket.setEnabledCipherSuites() を参照してください。その他のすべての SSL/TLS 符号化方式同様、符号化方式がピアの側でサポートされていない場合は、暗号のネゴシエーション時に選択されません。また、アプリケーションまたはサーバが必要な Kerberos 資格を取得できない場合は、Kerberos 符号化方式も選択されません。TLS_KRB5_WITH_RC4_128_SHA TLS_KRB5_WITH_RC4_128_MD5 TLS_KRB5_WITH_3DES_EDE_CBC_SHA TLS_KRB5_WITH_3DES_EDE_CBC_MD5 TLS_KRB5_WITH_DES_CBC_SHA TLS_KRB5_WITH_DES_CBC_MD5 TLS_KRB5_EXPORT_WITH_RC4_40_SHA TLS_KRB5_EXPORT_WITH_RC4_40_MD5 TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5TLS_KRB5_WITH_DES_CBC_SHA 符号化方式のみを使用する TLS クライアントの例を示します。
// Create socket SSLSocketFactory sslsf = (SSLSocketFactory) SSLSocketFactory.getDefault(); SSLSocket sslSocket = (SSLSocket) sslsf.createSocket(tlsServer, serverPort); // Enable only one cipher suite String enabledSuites[] = { "TLS_KRB5_WITH_DES_CBC_SHA" }; sslSocket.setEnabledCipherSuites(enabledSuites);Kerberos 要件
JSSE で Kerberos 符号化方式を使用する前に、配備されている環境で Kerberos インフラストラクチャを設定しておく必要があります。特に、TLS クライアントとサーバの両方に、Kerberos Key Distribution Center (KDC) によるアカウントが設定されていことが必要です。実行時に Kerberos 符号化方式の 1 つ以上が有効化されると、TLS クライアントとサーバは、それぞれのアカウントに関連付けられている自身の Kerberos 資格を KDC から取得します。たとえば、Keberos 領域 IMC.ORG のマシン mach1.imc.org で動作する TLS サーバは、host/mach1.imc.org@IMC.ORG という名前のアカウントを持ち、IMC.ORG 用の KDC を使用するように構成されている必要があります。J2SE での Kerberos の使用法の詳細については、Java 認証・承認サービス (JAAS) と Kerberos ログインモジュールを使用して、自身の Kerberos 資格を取得できます。J2SE 5 Development Kit は、Kerberos ログインモジュールに付属しています。JSSE での Kerberos 符号化方式は、Java Generic Security Services (Java GSS) の使用法と同様に、JAAS プログラムがある場合とない場合に使用できます。JAAS プログラムなしで Kerberos 符号化方式を使用するには、JAAS 構成入力用に 「com.sun.net.ssl.server」または「other、および TLS クライアント用に「com.sun.net.ssl.client」または「other」というインデックス名を使用し、システムプロパティ javax.security.auth.useSubjectCredsOnly を false に設定する必要があります。たとえば、JAAS プログラムを使用しない TLS サーバには以下の JAAS 構成ファイルがあります。
JAAS プログラムなしの Java GSS と Kerberos の例は、「Java GSS チュートリアル」で説明されています。Java GSS 呼び出しを JSSE 呼び出しに置き換えることにより、JSSE の使用例に適応できます。com.sun.net.ssl.server { com.sun.security.auth.module.Krb5LoginModule required principal="host/mach1.imc.org@IMC.ORG" useKeyTab=true keyTab=mach1.keytab storeKey=true; };JAAS プログラムによって Kerberos 符号化方式を使用するには、任意のインデックス名を使用できます。これは、アプリケーションに、インデックス名を使用して JAAS LoginContext を作成し、JSSE 呼び出しを Subject.doAs() または Subject.doAsPrivileged() 呼び出しの内部にラップする役割があるからです。Java GSS および Kerberos で JAAS を使用する方法の例は、「Java GSS チュートリアル」で説明されています。Java GSS 呼び出しを JSSE 呼び出しに置き換えることにより、JSSE の使用例に適応できます。JSSE アプリケーションで Kerberos を使用する場合の使用法または構成方法に関する問題については、Java GSS チュートリアルの 「トラブルシューティング」を参照してください。
ピアのアイデンティティ情報
SSL 接続のピアのアイデンティティを判別するには、javax.net.ssl.SSLSession、javax.net.ssl.HttpsURLConnection、および javax.net.HandshakeCompletedEvent クラスで getPeerPrincipal() メソッドを使用します。同様に、ローカルエンティティを識別するためにピアに送信されたアイデンティティを取得するには、これらのクラスで getLocalPrincipal() メソッドを使用します。X509 ベースの符号化方式の場合は、これらのメソッドによって javax.security.auth.x500.X500Principal のインスタンスが返され、Kerberos 符号化方式の場合は、これらのメソッドによって javax.security.auth.kerberos.KerberosPrincipal のインスタンスが返されます。J2SE 5 以前の JSSE アプリケーションでは、getPeerCertificates() メソッド、および javax.net.ssl.SSLSession、javax.net.ssl.HttpsURLConnection、および javax.net.HandshakeCompletedEvent の類似のメソッドを使用して、ピアの情報を取得していました。ピアに証明書がない場合は、SSLPeerUnverifiedException がスローされます。こうしたメソッドの振る舞いは J2SE 5 にも継承されているので、Kerberos 符号化方式を使用して接続の安全が確保された場合は、これらのメソッドにより SSLPeerUnverifiedException がスローされます。
アプリケーションで、ピアのアイデンティティまたはピアに送信されたアイデンティティのみを判別する必要がある場合は、それぞれ getPeerPrincipal() メソッドまたは getLocalPrincipal() メソッドを使用してください。getPeerCertificates() メソッドと getLocalCertificates() メソッドは、それらの証明書の内容を調べる必要がある場合にのみ使用してください。また、認証されるピアに証明書が何もない場合に対処する仕組みを用意しておく必要もあります。
セキュリティマネージャ
セキュリティマネージャが使用可能になっている場合は、ピアとの通信に必要な SocketPermission に加えて、Kerberos 符号化方式を使用する TLS クライアントアプリケーションには、以下の権限が必要です。ここで、serverPrincipal は TLS クライアントが通信する TLS サーバの Kerberos 主体名で、host/mach1.imc.org@IMC.ORG のような名前になります。TLS サーバアプリケーションには、以下の権限が必要です。javax.security.auth.kerberos.ServicePermission(serverPrincipal, "initiate");ここで、serverPrincipal は TLS サーバの Kerberos 主体名で、host/mach1.imc.org@IMC.ORG のような名前になります。資格がローカルでキャッシュされないなどのために、サーバまたはクライアントが KDC に問い合わせを行う必要がある場合は、以下の権限も必要になります。javax.security.auth.kerberos.ServicePermission(serverPrincipal, "accept");ここで、tgtPrincipal は KDC の主体名で、krbtgt/IMC.ORG@IMC.ORG のような名前になります。javax.security.auth.kerberos.ServicePermission(tgtPrincipal, "initiate");