JavaTM 暗号化拡張機能 (JCE) は、暗号化、鍵生成と鍵協定、およびメッセージ認証コード (MAC) アルゴリズム用のフレームワークおよび実装を提供します。暗号化サポートには、対称、非対称、ブロック、およびストリーム暗号が含まれます。このソフトウェアは、セキュリティ保護されたストリームおよびシールされたオブジェクトもサポートします。
JavaTM 2 SDK, Standard Edition (Java 2 SDK) バージョン 1.2.x および 1.3.x では、JCE はオプションパッケージ (拡張機能) でした。Java 2 SDK, v 1.4 には JCE が統合されています。
JCE の設計方針は、実装非依存および可能な場合には常にアルゴリズム非依存です。これは、Java 2 プラットフォームの暗号化関連セキュリティコンポーネントすべてで利用されている Java 暗号化アーキテクチャフレームワーク内の設計方針と同じです。これは、暗号化サービスプロバイダ (略して「プロバイダ」) という概念を使用する、同一の「プロバイダ」アーキテクチャを使用します。これは、Java Security API の暗号化に関するサブセットの固定実装を提供するパッケージ (またはパッケージセット) です。
JCE は、プロバイダが実装を提供可能な暗号化サービスのリストを拡張します。このため、たとえば、1 つ以上のデジタル署名アルゴリズムの実装、および 1 つ以上の暗号化アルゴリズムをプロバイダに含めることができます。
暗号化機能を使用しようとするプログラムは、単に特定のアルゴリズム (DES など) を実装する特定型のオブジェクト (Cipher オブジェクトなど) を要求するだけで、インストールされているプロバイダの 1 つから実装を取得できます。特定のプロバイダからの実装が望ましい場合、プログラムはそのプロバイダを名前で要求し、同時に目的のアルゴリズムを要求することができます。
Java 2 SDK では 1 つ以上のプロバイダパッケージがインストールされます。各プロバイダパッケージは、Java 2 SDK の 1 つ以上のセキュリティコンポーネント (JCE を含む) で定義された暗号化サービスの実装を提供します。
クライアントは異なるプロバイダを用いて実行環境を構成し、各プロバイダの「優先順位」を指定できます。優先順位とは、特定プロバイダの指定がないときに、要求アルゴリズムについてプロバイダを検索する順序です。
Java 2 SDK, v 1.4 リリースでは、「SunJCE」という名前の標準 JCE プロバイダがあらかじめインストールおよび登録されています。SunJCE は、次の暗号化サービスを提供します。
- Electronic Code Book (ECB)、Cipher Block Chaining (CBC)、Cipher Feedback (CFB)、Output Feedback (OFB)、および Propagating Cipher Block Chaining (PCBC) モードの DES (FIPS PUB 46-1)、トリプル DES、および Blowfish 暗号化アルゴリズムの実装(注: このドキュメントでは、「トリプル DES」と「DES-EDE」を同じものとする)
- DES、トリプル DES、Blowfish、HMAC-MD5、および HMAC-SHA1 アルゴリズムに適した鍵を生成する鍵ジェネレータ
- PKCS #5 で定義された DES-CBC パスワードベース暗号化 (PBE) アルゴリズムを使用する MD5 の実装
- 不透明な DES、トリプル DES、PBE 鍵オブジェクトと、背後の鍵データの透明な表現との双方向変換を提供する「秘密鍵ファクトリ」
- 複数のパーティ間での Diffie-Hellman 鍵協定アルゴリズムの実装
- Diffie-Hellman アルゴリズムに適した公開値および非公開値のペアの生成に必要な Diffie-Hellman 鍵ペアジェネレータ
- Diffie-Hellman アルゴリズムのパラメータジェネレータ
- 不透明な Diffie-Hellman 鍵オブジェクトと背後の鍵データの透明な表現との間の双方向変換を提供する Diffie-Hellman「鍵ファクトリ」
- Diffie-Hellman、DES、トリプル DES、Blowfish、および PBE パラメータ用のアルゴリズムパラメータマネージャ
- RFC 2104 に定義されている、HMAC-MD5 および HMAC-SHA1 キーハッシュアルゴリズムの実装
- PKCS#5 に記載されているパディング方式の実装
- JCEKS という独自のキーストア型のためのキーストアの実装
新たなプロバイダは、静的にも動的にも追加できます。クライアントは、現在どのプロバイダがインストールされているかを問い合わせることができます。
実装が違うと、特徴も違ってくる場合があります。ソフトウェアベースのものもあれば、ハードウェアベースのものもあります。プラットフォーム独立のものもあれば、プラットフォーム固有のものもあります。また、レビューや評価用に使えるプロバイダコードもあれば、使えないものもあります。
このドキュメントの対象読者
Java Security API を使って既存の暗号化アルゴリズムや他のサービスにアクセスするだけであれば、このドキュメントを読む必要はありません。
このドキュメントは、暗号化サービスプロバイダの開発者を対象としています。ここでは、Java Security API クライアントが、作成されたアルゴリズムや他のサービスを要求する際にそれらを検出できるよう、プロバイダを Java Security に統合するための方法がドキュメント化されています。
JCE フレームワークにプラグインできるのは、信頼できるエンティティにより署名されたプロバイダだけです。
関連ドキュメント
このドキュメントでは、読者がすでに次のドキュメントを読んでいることを前提としています。
- 「Java 暗号化アーキテクチャ API の仕様およびリファレンス」
- 「Java 暗号化アーキテクチャ用プロバイダの実装方法」
- 「JavaTM 暗号化拡張機能 (JCE) リファレンスガイド JavaTM 2 SDK, Standard Edition, v 1.4」
Java Security API のさまざまなクラスおよびインタフェースについての説明も含まれます。これらのパッケージの完全なリファレンスドキュメントを以下に示します。
java.security
java.security.spec
java.security.interfaces
javax.crypto
javax.crypto.spec
javax.crypto.interfaces
用語に関する注記
Java 2 SDK, v 1.4 の JCE には、次の 2 つのソフトウェアコンポーネントが含まれます。
このドキュメントでは、「JCE」という語は、Java 2 SDK, v 1.4 の JCE フレームワークを指して使われています。Java 2 SDK, v 1.4 とともに提供される JCE プロバイダに言及する場合、常に「SunJCE」プロバイダのことを明示的に指しています。
- プロバイダが実装を提供可能な暗号化サービスを定義および提供するフレームワーク。このフレームワークには、
javax.crypto
パッケージ内のすべてが含まれる
- 「SunJCE」という名前のプロバイダ
v1.4 と 5.0 の違いについては、「Java 暗号化拡張機能 (JCE) リファレンスガイド」の「JDK 5.0 における JCE の新機能」 を参照してください。プロバイダに影響を及ぼす、JCE 1.2.1 の JCE と Java 2 SDK, v 1.4 の JCE の相違点を次に示します。
Java 2 SDK に含まれる新しい JCE
JavaTM 2 SDK, Standard Edition (Java 2 SDK) バージョン 1.2.x および 1.3.x では、JCE はオプションパッケージ (拡張機能) でした。Java 2 SDK, v 1.4 には JCE が統合されています。SunJCE プロバイダは、Java 2 SDK, v 1.4 に含まれる セキュリティプロパティファイル
java.security
にも含まれ、自動的に登録されます。強力な暗号化機能をデフォルトで装備し、無制限に利用可能
輸入管理制限があるため、Java 2 SDK, v 1.4 に同梱された管轄ポリシーファイルは「強固」ですが、暗号化の使用には制限があります。適格国 (大半の国が該当) の在住者は、暗号化機能に制限のない「無制限」のバージョンを利用できます。このバージョンをダウンロードして、Java 2 SDK, v 1.4 に含まれる暗号化の強力なバージョンと置き換えることができます。無制限のバージョンのダウンロード方法の詳細は、以下を参照してください。
http://java.sun.com/products/jce/index-14.html管轄ポリシーファイルは、次の場所に移されました。
ここで、<java-home> は、ランタイムソフトウェアのインストール先ディレクトリ (JavaTM 2 Runtime Environment (JRE) のトップレベルディレクトリまたは JavaTM 2 SDK (Java 2 SDK) ソフトウェアの jre ディレクトリ) を指します。Java 2 SDK, v 1.4 に含まれる強力な暗号化機能のバージョンを機能無制限のバージョンと簡単に置き換えることができるように、これらのファイルは標準的な位置に移動されました。<java-home>\lib\security [Windows]
<java-home>/lib/security [Solaris]不要になった JCE フレームワークのプロバイダ認証
JCE 1.2.1 では、プラグインする JCE の完全性および信頼性を保証するため、JCE フレームワークの認証用コードをプロバイダに含める必要がありました。JCE が Java 2 SDK, v 1.4 に統合されることにより、この操作は不要になりました。
「How to Implement a Provider for the Java Cryptography Extension 1.2.1」のガイダンスに従う JCE 1.2.1 プロバイダは、Java 2 SDK, v 1.4 の JCE フレームワークでも引き続き使用できます。
しかし、JCE 1.2.1 の JCE プロバイダドキュメント (前述) の推奨条件に従わず、保護ドメインから JCE フレームワークを特定するようなフレームワーク認証コードを持つプロバイダは、Java 2 SDK, v 1.4 では使用できません。JCE が Java 2 SDK, v 1.4 に統合されたため、JCE フレームワークは、Java 2 SDK, v 1.4 のその他のクラスと同様に null コードのソースを持つようになりました。推奨条件に従ってフレームワークの認証を実施できるように、プロバイダを変更できます。また、条件式を挿入して、プロバイダを JCE 1.2.1 で使用する場合以外はフレームワーク認証コードが実行されないようにすることもできます。
「エンジンクラス」は、具体的な実装のない抽象的な方法で暗号化サービスを定義します。
暗号化サービスは、常に特定のアルゴリズムに関連付けられています。このサービスにより、暗号化操作 (暗号または鍵協定プロトコル用の操作) の提供、または暗号化操作に必要な暗号化データ (鍵またはパラメータ) の生成や提供が行われます。たとえば、
Cipher
クラスおよびKeyAgreement
クラスは、エンジンクラスです。Cipher
クラスは暗号化アルゴリズム機能 (DES など) へのアクセスを提供し、KeyAgreement
クラスは鍵協定プロトコル機能 (Diffie-Hellman など) へのアクセスを提供します。Java 暗号化アーキテクチャには、エンジンクラスなどの、暗号化に関連する J2SE Java Security パッケージが含まれています。API のユーザは、エンジンクラスを要求および利用して対応する処理を実行します。
JavaTM 2 SDK, Standard Edition (Java 2 SDK) バージョン 1.2.x および 1.3.x では、JCE はオプションパッケージ (拡張機能) でした。Java 2 SDK, v 1.4 には JCE が統合されています。
JCE では、次のエンジンクラスを定義しています。
Cipher
- 指定されたデータの暗号化または復号化に使用するKeyAgreement
- 複数のパーティ間の鍵協定 (鍵交換) プロトコルの実行に使用するKeyGenerator
- 指定のアルゴリズムに適合した、非公開 (対称) 鍵の生成に使用するMac
- 指定されたデータのメッセージ認証コードの計算に使用するSecretKeyFactory
-SecretKey
型の不透明な暗号化鍵を鍵仕様 (背後の鍵データの透明な表現) に変換したり、その逆の変換を行うために使用するExemptionMechanism
- 鍵復元、鍵弱化、鍵エスクローなどの免責機構、または他の (カスタム) 免責機構の機能を提供するために使用する。免責機構を使用するアプリケーションまたはアプレットは、使用しないアプリケーションまたはアプレットに比べて強力な暗号化機能が付与される。大半の国では暗号化制限はもはや適用されていないため、免責機構が有用なのは政府により制限が要求されているいくつかの国だけであるエンジンクラスは、(特定の暗号化アルゴリズムに依存しない) 特定の型の暗号化サービス機能へのインタフェースを提供します。これにより、Application Programming Interface (API) メソッドが定義され、API が提供する特定の種類の暗号化サービスにアプリケーションがアクセスできるようになります。実際の実装 (1 つ以上のプロバイダから) は特定アルゴリズムのためのものです。たとえば
Cipher
エンジンクラスは、暗号アルゴリズムの機能へのアクセスを提供します。CipherSpi
サブクラスで提供される実際の実装 (次の段落を参照) は、DES や トリプル DES など、特定の種類の暗号化アルゴリズム用です。エンジンクラスが提供するアプリケーションインタフェースは、Service Provider Interface (SPI) として実装されます。つまり、各エンジンクラスに対応する抽象 SPI クラスが存在し、抽象 SPI クラスによって暗号化サービスプロバイダが実装しなければならない Service Provider Interface のメソッドが定義されます。
エンジンクラスのインスタンスである「API オブジェクト」は、対応する SPI クラスのインスタンス「SPI オブジェクト」を private フィールドとしてカプセル化します。API オブジェクトのすべての API メソッドは、final として宣言されます。これらを実装することによって、カプセル化された SPI オブジェクトの対応する SPI メソッドが呼び出されます。エンジンクラス (およびそれに対応する SPI クラス) のインスタンスは、エンジンクラスの
getInstance
ファクトリメソッドへの呼び出しによって作成されます。SPI クラスの名前は、対応するエンジンクラス名のあとに
Spi
を追加した名前になります。たとえば、Cipher
エンジンクラスに対応する SPI クラスは、CipherSpi
クラスです。各 SPI クラスは、抽象クラスです。指定したアルゴリズムに対する特定の型のサービスの実装を提供するには、プロバイダは、対応する SPI クラスをサブクラス化して、すべての抽象メソッドの実装を提供する必要があります。
エンジンクラスのもう 1 つの例として、鍵協定 (鍵交換) アルゴリズムへのアクセスを提供する
KeyAgreement
クラスを紹介します。KeyAgreementSpi
サブクラス内では、Diffie-Hellman などのさまざまな鍵協定アルゴリズムを実装することが可能です。最後に紹介するのは、
SecretKeyFactory
エンジンクラスです。このエンジンクラスは、不透明な非公開鍵から透明な鍵仕様への変換、またはその逆の変換をサポートします(「鍵ファクトリにより要求される鍵仕様のクラス」を参照)。SecretKeyFactorySpi
サブクラスで提供される現実の実装は、DES 鍵などの特定の非公開鍵用の実装です。
プロバイダの実装および JCE への統合までのステップは、次のとおりです。
- ステップ 1: サービス実装コードの記述
- ステップ 2: プロバイダの命名
- ステップ 3: プロバイダのサブクラスである「マスタークラス」の記述
- ステップ 4: コードのコンパイル
- ステップ 5: テストの準備
- ステップ 5a: コード署名証明書の取得
- ステップ 5b: JAR ファイルへのプロバイダの記述
- ステップ 5c: プロバイダの署名
- ステップ 5d: プロバイダのインストール
- ステップ 5e: プロバイダアクセス権の設定
- ステップ 6: テストプログラムの記述とコンパイル
- ステップ 7: テストプログラムの実行
- ステップ 8: 米国政府による輸出承認の申請 (必要な場合)
- ステップ 9: プロバイダおよびそのサポート対象サービスのドキュメント化
- ステップ 10: プロバイダソフトウェアおよびドキュメントをクライアントから利用可能にする
ステップ 1: サービス実装コードの記述
最初に行うべきことは、サポートする暗号化サービスのアルゴリズム固有の実装を提供するコードを記述することです。プロバイダは、Java 2 SDK v 1.4 の 1 つ以上のセキュリティコンポーネント (JCE を含む) で定義された暗号化サービス実装を提供できます。
Java 2 SDK, v 1.4 の JCE では、以前の JCE 1.2.1 リリースと同様、非公開鍵ファクトリ、非公開鍵生成サービス、免責機構の実装だけでなく、暗号、鍵協定、MAC アルゴリズムを提供できます。
JCE には定義されていない暗号化サービス (署名やメッセージダイジェストなど) に関しては、「Java 暗号化アーキテクチャ API の仕様およびリファレンス」を参照してください。
Java 2 SDK の暗号化サービスごとに (JCE で定義されている暗号化サービスを含む)、以下のような適切な SPI クラスのサブクラスを作成する必要があります。JCE では、エンジンクラス
CipherSpi
、KeyAgreementSpi
、KeyGeneratorSpi
、MacSpi
、SecretKeyFactorySpi
、ExemptionMechanismSpi
が定義されています (「エンジンクラスと対応する SPI クラス」を参照)。サブクラスで、以下を実行する必要があります。
- 通常
engine
で始まる名前を持つ抽象メソッド用の実装を提供します。詳細は、「実装の詳細および要件」を参照してください。- 引数を持たない public コンストラクタの存在を確認します。 これが必要な理由は、サービスの要求時に、Java Security が、マスタークラス内のプロパティによる指定に従って、そのサービスを実装するサブクラスをルックアップするためです (ステップ 3 を参照)。その後、Java Security は、サブクラスに関連付けられた
Class
オブジェクトを作成し、そのClass
オブジェクトに対してnewInstance
メソッドを呼び出すことにより、サブクラスのインスタンスを作成します。newInstance
はサブクラスがパラメータを持たない public コンストラクタを保持することを要求します。サブクラスがコンストラクタを持たない場合、引数を持たないデフォルトのコンストラクタが自動的に生成されます。ただし、サブクラスがコンストラクタを定義する場合、引数を持たない public コンストラクタを明示的に定義する必要があります。
JCE プロバイダの追加要件および推奨事項
プロバイダによる JCE サービス実装 (クラス) をインスタンス化する際、JCE フレームワークはプロバイダのコードベース (JAR ファイル) を判定し、その署名を検証します。このようにして、JCE はプロバイダを認証して、信頼されたエンティティにより署名されたプロバイダだけが JCE にプラグインできるようにします。このため、JCE プロバイダは署名付きでなければなりません。詳細はあとのステップで説明します。
また、各プロバイダは自己完全性チェックを実行して、プロバイダメソッドを JCE を介さずに直接呼び出そうとして、コードを含む JAR ファイルが操作されていないことを保証する必要があります。詳細は、「プロバイダによる自己完全性チェックの実行方法」を参照してください。
JCE を介さずに直接アプリケーションからインスタンス化が行われた場合に、プロバイダクラスを使用不可にするため、プロバイダは以下を実装する必要があります。
- プロバイダパッケージ内のすべての SPI 実装クラスを final として宣言し (サブクラス化できないように)、SPI 実装メソッドを protected として宣言する
- プロバイダパッケージ内の暗号化関連ヘルパークラスはすべて、プロバイダパッケージ外からアクセスできないように、パッケージ独自のスコープを保持する
プロバイダを米国以外に輸出する場合、
CipherSpi
実装に、Key
を指定すると鍵のサイズを返すengineGetKeySize
メソッドの実装を含める必要があります。管轄ポリシーファイルで指定された利用可能な暗号化強度に制限が設定されている場合、Cipher
初期化メソッドはengineGetKeySize
を呼び出して、実行中のアプレットまたはアプリケーションの特定位置および状況での鍵の最大有効サイズと結果を比較します。鍵のサイズが大きすぎる場合には、初期化メソッドにより例外がスローされます。プロバイダが実装可能な「オプション」機能を、次に示します。
CipherSpi
のengineWrap
メソッドとengineUnwrap
メソッド。鍵をラッピングすると、ある場所から別の場所へ安全に転送できる。鍵のラップおよびラップ解除の詳細は、「Java 暗号化拡張機能 (JCE) リファレンスガイド」の「鍵のラッピングとアンラッピング」を参照- 1 つ以上の「免責機構」。免責機構には、鍵復元、鍵エスクロー、鍵弱化などが含まれる。この機構を実装および実行すると、これを利用するアプリケーション (またはアプレット) に対する暗号化の制限を緩めることができる。免責機構を利用するアプリケーションの要件に関する詳細は、「Java 暗号化拡張機能 (JCE) リファレンスガイド」の「アプリケーションの暗号化制限の「免責」を取得する方法」を参照
ステップ 2: プロバイダの命名
使用するプロバイダの名前を特定します。これは、クライアントアプリケーションがプロバイダを参照する際に使用する名前です。ステップ 3: プロバイダのサブクラスである「マスタークラス」の記述
3 番目のステップは、java.security.Provider
クラスのサブクラスを作成することです。このサブクラスは
final
にする必要があり、そのコンストラクタは以下を実行する必要があります。
super
を呼び出して、プロバイダ名 (ステップ 2 を参照)、バージョン番号、およびプロバイダおよびプロバイダがサポートするアルゴリズムに関する情報を指定する。以下に例を示すsuper("CryptoX", 1.0, "CryptoX provider v1.0, implementing " +
"RSA encryption and key pair generation, and DES encryption.");- Java Security API がプロバイダにより実装された暗号化サービスを探すために必要とされる、さまざまなプロパティの値を設定する。プロバイダによるサービス実装ごとに、サービスの型 (
Cipher
、KeyAgreement
、KeyGenerator
、Mac
、SecretKeyFactory
、ExemptionMechanism
など) とピリオド、さらにサービスが適用されるアルゴリズム名で構成される名前のプロパティが存在する必要がある。プロパティの値には、サービスを実装するクラスの完全修飾名を指定する必要がある次のリストに、JCE サービスの型に合わせて定義する必要のあるさまざまなプロパティの型を示します。algName は、実際のアルゴリズム名に置き換えてください。
Cipher.
algNameKeyAgreement.
algNameKeyGenerator.
algNameMac.
algNameSecretKeyFactory.
algNameExemptionMechanism.
algName
ExemptionMechanism
とCipher
以外のすべてで、algName はアルゴリズムの標準名になります。
ExemptionMechanism
の場合、algName は例外機構の名前を参照します。たとえば、KeyRecovery
、KeyEscrow
、KeyWeakening
などです。大文字と小文字は区別されません。
Cipher
の場合、algName は実際には変換を表します。これは、アルゴリズム名、指定されたモード、およびパディング方式で構成されます。使用すべき標準アルゴリズム名については、「Java 暗号化拡張機能 (JCE) リファレンスガイド」の「付録 A」を参照してください。各プロパティの値は、指定されたアルゴリズムを実装するクラスの完全修飾名である必要があります。つまり、クラス名のあとにピリオドとパッケージ名が記述されていなければなりません。
たとえば、「SunJCE」プロバイダ実装は、
com.sun.crypto.provider
パッケージのDHKeyAgreement
クラス内で Diffie-Hellman 鍵協定アルゴリズムを実装します。Provider
のサブクラス (com.sun.crypto.provider
パッケージのSunJCE
クラス) は、KeyAgreement.DiffieHellman
プロパティの値をcom.sun.crypto.provider.DHKeyAgreement
に設定します。次にそのコードを示します。put("KeyAgreement.DiffieHellman",
"com.sun.crypto.provider.DHKeyAgreement")
マスタークラスプロパティの設定例の詳細は、「付録 A」を参照して、現在の
SunJCE.java
のソースファイルを閲覧してください。そこでは、SunJCE
クラスのコンストラクタにより、「SunJCE」プロバイダ用のプロパティすべてがどのように設定されるかが示されています。すでに説明したように、
Cipher
プロパティの場合、algName は実際には「変換」を表します。「変換」は、指定された入力に対してCipher
オブジェクトによって実行される操作 (または操作のセット) を説明する文字列です。変換には、暗号化アルゴリズム (DES など) の名前が必ず含まれます。それにモードおよびパディング方式が続く場合もあります。変換は、次の書式で記述されます。
- algorithm/mode/padding または
- algorithm
後者の場合、モードおよびパディング方式には、プロバイダ固有のデフォルト値が使用されます。たとえば、以下は有効な変換です。
Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding");ストリーム暗号モードでブロック暗号を要求する (たとえば
CFB
またはOFB
モードでDES
を要求する) 場合、クライアントは、数値をモード名に追加することにより、一度に処理するビット数をオプションで指定できます。次に変換のサンプルを示します。Cipher c1 = Cipher.getInstance("DES/CFB8/NoPadding");
Cipher c2 = Cipher.getInstance("DES/OFB32/PKCS5Padding");数値がストリーム暗号モードに準拠していない場合、プロバイダ固有のデフォルト値が使用されます。たとえば、「SunJCE」プロバイダはデフォルトの 64 ビットを使用します。
プロバイダは、algorithm/mode/padding の組み合わせごとに別々のクラスを提供できます。または、algorithm、algorithm/mode、algorithm//padding (ダブルスラッシュを使用する点に注意) のいずれかに対応する下位変換を表すより一般的なクラスを提供できます。この場合、要求されたモードやパディングは、
Cipher
のgetInstance
メソッドによって自動的に設定されます。getInstance
メソッドは、プロバイダのCipherSpi
のサブクラスからengineSetMode
メソッドとengineSetPadding
メソッドを呼び出します。つまり、プロバイダマスタークラスの
Cipher
プロパティは、以下の表に示すいずれかの形式になります。
Cipher
プロパティの形式説明 Cipher.
algNameプロバイダの CipherSpi
のサブクラスは、プラグイン可能モードとパディングを利用して algName を実装するCipher.
algName/modeプロバイダの CipherSpi
のサブクラスは、指定されたモードとプラグイン可能なパディングを利用して algName を実装するCipher.
algName//paddingプロバイダの CipherSpi
のサブクラスは、指定されたパディングとプラグイン可能モードを利用して algName を実装するCipher.
algName/mode/paddingプロバイダの CipherSpi
のサブクラスは、指定されたモードとパディングを利用して algName を実装する使用すべき標準アルゴリズム名、モード、およびパディング方式については、「Java 暗号化拡張機能 (JCE) リファレンスガイド」の「付録 A」を参照してください。
たとえば、プロバイダは DES/ECB/PKCS5Padding、DES/CBC/PKCS5Padding、DES/CFB/PKCS5Padding、さらに DES/OFB/PKCS5Padding をそれぞれ実装する
CipherSpi
のサブクラスを提供可能です。このプロバイダは、マスタークラス内に次のCipher
プロパティを保持します。
Cipher.
DES/ECB/PKCS5PaddingCipher.
DES/CBC/PKCS5PaddingCipher.
DES/CFB/PKCS5PaddingCipher.
DES/OFB/PKCS5Padding別のプロバイダは、上記の各モードに対応したクラス (ECB、CBC、CFB、および OFB 用にそれぞれ 1 つのクラス) を実装できます。また、PKCS5Padding に対応する 1 つのクラス、および
CipherSpi
からサブクラス化された汎用の DES クラスも実装できます。このプロバイダは、マスタークラス内に次のCipher
プロパティを保持します。
Cipher.
DES「algorithm」形式の変換の場合、
Cipher
エンジンクラスのgetInstance
ファクトリメソッドは、次の規則に従ってプロバイダのCipherSpi
実装をインスタンス化します。
- プロバイダが、指定された「algorithm」に対応する
CipherSpi
のサブクラスを登録済みかどうかをチェックします。登録済みの場合、このクラスをインスタンス化して、このモードおよびパディング方式のデフォルト値 (プロバイダにより提供) を使用可能にします。
未登録の場合、例外
NoSuchAlgorithmException
をスローします。「algorithm/mode/padding」形式の変換の場合、
Cipher
エンジンクラスのgetInstance
ファクトリメソッドは、次の規則に従ってプロバイダのCipherSpi
実装をインスタンス化します。
- プロバイダが、指定された「algorithm/mode/padding」変換に対応する
CipherSpi
のサブクラスを登録済みかどうかをチェックします。登録済みの場合、このクラスをインスタンス化します。
未登録の場合、次のステップに進みます。
- プロバイダが、サブ変換「algorithm/mode」に対応する
CipherSpi
のサブクラスを登録済みかどうかをチェックします。登録済みの場合、このクラスをインスタンス化してから、新規インスタンスに対し
engineSetPadding(padding)
を呼び出します。未登録の場合、次のステップに進みます。
- プロバイダが、サブ変換「algorithm//padding」 (ダブルスラッシュに注意) に対応する
CipherSpi
のサブクラスを登録済みかどうかをチェックします。登録済みの場合、このクラスをインスタンス化してから、新規インスタンスに対し
engineSetMode(mode)
を呼び出します。未登録の場合、次のステップに進みます。
- プロバイダが、サブ変換「algorithm」に対応する
CipherSpi
のサブクラスを登録済みかどうかをチェックします。登録済みの場合、このクラスをインスタンス化してから、新規インスタンスに対し
engineSetMode(mode)
およびengineSetPadding(padding)
を呼び出します。未登録の場合、例外
NoSuchAlgorithmException
をスローします。ステップ 4: コードのコンパイル
実装コードの作成 (ステップ 1)、プロバイダの命名 (ステップ 2)、およびマスタークラスの作成 (ステップ 3) が完了したら、Java コンパイラを使ってファイルをコンパイルします。ステップ 5: テストの準備
ステップ 5a: コード署名証明書の取得
次のステップは、コード署名証明書の要求です。テストに先立ち、コード署名証明書を使用してプロバイダへの署名を行います。証明書は、テスト環境と製作環境の両方で利用できます。有効期間は 5 年間です。
次に、コード署名証明書の取得方法を示します。keytool ツールの詳細は、keytool (Solaris 用) (Microsoft Windows 用) を参照してください。
- keytool を使用して、DSA 鍵ペアを生成します。
keytool -genkey -alias <alias> -keyalg DSA -keysize 1024
-dname "cn=<Company Name>,ou=Java Software Code Signing,
o=Sun Microsystems Inc"
-keystore <keystore file name>
-storepass <keystore password>(注: このコマンドは 1 行で入力する必要があります。上の例で複数行に分け、インデントを付けて記述してあるのは、読みやすくするためです。)
これにより、DSA 鍵ペア (公開鍵および関連する非公開鍵) が生成され、指定されたキーストアのエントリに格納されます。公開鍵は、自己署名証明書に格納されます。これ以降、キーストアのエントリには、指定された別名を使用してアクセスできます。
角括弧 (「<」 と「>」) 内のオプション値には、実際の値を指定する必要があります。たとえば、
<alias>
は、新しく生成するキーストアのエントリを参照する際に使用する任意の別名で置き換え、<keystore file name>
は、使用するキーストアの名前で置き換えます。注: 実際の値には、角括弧を付けないでください。たとえば、別名をmyTestAlias
にする場合、-alias
オプションを次のように指定します。-alias myTestAliasまだ存在しないキーストアを指定すると、そのキーストアが作成されます。
注: 入力するコマンド行を、実行する
keytool -genkey
コマンドと同じ長さにできない場合 (Microsoft Windows の DOS プロンプトに入力する場合など)、コマンドを含むプレーンテキストのバッチファイルを作成して実行できます。つまり、keytool -genkey
コマンドだけを含むテキストファイルを新規作成します。なお、コマンドは、全体を 1 行に入力してください。拡張子 .bat を付けてファイルを保存します。DOS ウィンドウで、ファイル名を (必要に応じてパスを付けて) 入力します。これで、バッチファイルに記述されたコマンドが実行されます。
- keytool を使用して、証明書署名要求を生成します。
ここで、keytool -certreq -alias <alias> -sigalg DSA
-file <csr file name>
-keystore <keystore file name>
-storepass <keystore password><alias>
には、前のステップで作成した DSA 鍵ペアエントリの別名を指定します。このコマンドにより、証明書署名要求 (CSR) が PKCS#10 形式で生成されます。<csr file name>
で指定した名前のファイルに CSR が格納されます。
- CSR、連絡情報、および他の必須ドキュメントを JCE コード署名証明書発行局に送ります。
CSR および連絡情報 (以下を参照) を、電子メールで javasoft-cert-request@sun.com に送ります。電子メールメッセージの件名行には、以下を入力します。
Request a Certificate for Signing a JCE Providerメッセージの本文に連絡情報を入力し、メッセージに CSR ファイルを添付して送信します。添付に使用するエンコーディングを指定するオプションがメールソフトに存在する場合、「MIME」を選択します。注: CSR ファイルは、Base 64 でエンコーディングされたプレーンテキストです。人間が読むことができるのは、最初と最後の行だけです。
メッセージの本文に次の連絡情報を含めます。
Company Name
Street Address (Not a post office box)
City
State/Province
Country
Company Telephone Number
Company Fax Number
Requester Name
Requester Telephone Number
Requester Email Address
Brief description of your company (size,
line of business, etc.)上記の情報をすべて入力する必要があります。
電子メールメッセージを受信すると、JCE コード署名証明書発行局は、要求番号を電子メールで返信します。この要求番号を受信したら、Certification Form for CSPs を印刷して記入し、送ります。
このフォームは、以下のアドレスに郵送します。フォームに要求番号を記入し、郵送したフォームが電子メールのメッセージに記載した CSR および連絡先情報と一致するようにします。
Sun Microsystems, Inc.JCE コード署名証明書は、電子メールメッセージと必要なフォームの両方を受信後に、要求者の認証を行います。その後、5 年間有効なコード署名証明書を作成および署名します。2 つのプレーンテキストファイルの添付された電子メールメッセージが要求者に送信されます。1 つはこのコード署名証明書を含むファイルで、もう 1 つは独自の CA 証明書を含むファイルで公開鍵の認証に使用します。
International Trade Services/Export Compliance
Attn:Encryption Export
4120 Network Circle MS:USCA12-204
Santa Clara, CA 95054
U.S.A.
- keytool を使用して CA から受信した証明書をインポートします。
JCE コード署名証明書発行局から 2 つの証明書を受信したら、keytool を使用してキーストアにそれらをインポートできます。
最初に、CA の証明書を「信頼できる証明書」としてインポートします。
次に、コード署名証明書をインポートします。keytool -import -alias <alias for the CA cert>
-file <CA cert file name>
-keystore <keystore file name>
-storepass <keystore password>ここで、keytool -import -alias <alias>
-file <code-signing cert file name>
-keystore <keystore file name>
-storepass <keystore password><alias>
にはステップ 1 (DSA 鍵ペアの生成) で作成したのと同じ別名を指定します。このコマンドにより、<alias>
で指定されたキーストアエントリ内の自己署名証明書が、JCE コード署名証明書発行局が署名した証明書で置き換えられます。これで、JCEにより信頼されたエンティティ (JCE コード署名証明書発行局) からの証明書がキーストア内に保存されたので、JAR ファイル内にプロバイダコードを記述し (ステップ 5b)、この証明書を使用して JAR ファイルに署名できます (ステップ 5c)。
ステップ 5b: JAR ファイルへのプロバイダの記述
次のステップ (JAR ファイルへの署名) の準備として、JAR ファイルにプロバイダコードを記載します。jar ツールの詳細については、jar (Solaris 用) (Microsoft Windows 用) を参照してください。
jar cvf <JAR file name> <list of classes, separated by spaces>このコマンドにより、指定されたクラスを含む、指定された名前の JAR ファイルが作成されます。
ステップ 5c: プロバイダの署名
ステップ 5a で取得したコード署名証明書を使用して、前のステップで作成した JAR ファイルに署名します。jarsigner ツールの詳細は、jarsigner (Solaris 用) (Microsoft Windows 用) を参照してください。
jarsigner -keystore <keystore file name>
-storepass <keystore password>
<JAR file name> <alias>ここで、
<alias>
には、JCE コード署名証明書発行局から受け取ったコード署名証明書を含むエントリ用キーストアの別名 (ステップ 5a のコマンドで指定した別名) を指定します。次の方法で、署名を検証できます。
jarsigner -verify <JAR file name>検証が成功すると、「jar verified」というテキストが表示されます。
ステップ 5d: プロバイダのインストール
プロバイダのテスト準備を行うために、プロバイダを使用するクライアントが行うのと同じ方法で、プロバイダをインストールする必要があります。インストールを実行すると、Java Security はクライアントの要求に応じてアルゴリズムの実装を検出できるようになります。プロバイダのインストールには、つまり、プロバイダパッケージクラスのインストールとプロバイダの構成です。
プロバイダクラスのインストール
最初に行う事柄は、作成したクラスを利用可能にして、要求時に検出できるようにすることです。プロバイダクラスは JAR (Java ARchive) ファイルの形式で提供します。プロバイダクラスのインストール方法は 2 種類あります。
- プロバイダクラスを含む JAR ファイルを、「インストール型」または「バンドル型」の拡張機能としてインストールする方法
- プロバイダクラスを含む JAR ファイルを CLASSPATH に含める方法
プロバイダ JAR ファイルは、以下に示すインストール型拡張機能 JAR ファイルの標準位置に配置された場合、インストール型拡張機能と見なされます。
<java-home>/lib/ext [Solaris]
<java-home>\lib\ext [Windows]
ここで、<java-home> は、ランタイムソフトウェアのインストール先ディレクトリ (JavaTM 2 Runtime Environment (JRE) のトップレベルディレクトリまたは JavaTM 2 SDK (Java 2 SDK) ソフトウェアの jre ディレクトリ) を指します。たとえば、Java 2 SDK, v 1.4 を
/home/user1/J2SDK1.4.0
ディレクトリ (Solaris)、またはC:\J2SDK1.4.0
ディレクトリ (Microsoft Windows) にインストールした場合、JAR ファイルを次のディレクトリにインストールする必要があります。/home/user1/J2SDK1.4.0/jre/lib/ext [Solaris]
C:\J2SDK1.4.0\jre\lib\ext [Windows]同様に、JRE, v 1.4 を
/home/user1/j2re1.4.0
ディレクトリ (Solaris)、またはC:\j2re1.4.0
ディレクトリ (Microsoft Windows) にインストールした場合、JAR ファイルを次のディレクトリにインストールする必要があります。/home/user1/j2re1.4.0/lib/ext [Solaris]
C:\j2re1.4.0\lib\ext [Windows]「インストール型」拡張機能の詳細は、「インストール型拡張機能」を参照してください。
「バンドル型」拡張機能の詳細は、「インストール型拡張機能」を参照してください。
プロバイダの構成
次の手順では、認可プロバイダのリストにこのプロバイダを追加します。これは、セキュリティプロパティファイルを編集することにより、静的に行われます。
<java-home>/lib/security/java.security [Solaris]
<java-home>\lib\security\java.security [Windows]ここで、<java-home> は JRE がインストールされているディレクトリを指します。たとえば、Java 2 SDK バージョン 1.4 を
/home/user1/J2SDK1.4.0
(Solaris) またはC:\J2SDK1.4.0
(Microsoft Windows) にインストールしている場合は、次のファイルを編集する必要があります。/home/user1/J2SDK1.4.0/jre/lib/security/java.security [Solaris]
C:\J2SDK1.4.0\jre\lib\security\java.security [Windows]同様に、Java 2 Runtime Environment バージョン 1.4 を Solaris の
/home/user1/j2re1.4.0
ディレクトリにインストールしている場合、または Windows のC:\j2re1.4.0
ディレクトリにインストールしている場合は、次のファイルを編集する必要があります。/home/user1/j2re1.4.0/lib/security/java.security [Solaris]
C:\j2re1.4.0\lib\security\java.security [Windows]プロバイダごとに、このファイルは次の形式の文を保持します。
security.provider.n=masterClassNameこれはプロバイダを宣言し、その優先順位 n を指定します。優先順位とは、特定プロバイダの指定がないときに、要求されたアルゴリズムについてプロバイダを検索する順序です。順位は 1 から始まり、1 が最優先で次に 2、3 ...と続きます。
masterClassName には、ステップ 3 で実装したプロバイダの「マスタークラス」の完全修飾名を指定する必要があります。このクラスは、常に Provider クラスのサブクラスです。
Java 2 SDK, v 1.4 には、「SUN」という名前のプロバイダが標準で搭載されています。このプロバイダは、次に示すように、静的プロバイダとして
java.security
プロパティファイル内で自動的に構成されます。security.provider.1=sun.security.provider.Sun「SUN」プロバイダのマスタークラスは、
sun.security.provider
パッケージ内のSun
クラスです。JCE プロバイダ「SunJCE」および Java 2 プラットフォームに含まれる他のセキュリティ関連プロバイダは、静的プロバイダとして自動的に構成されます。
別の JCE プロバイダを利用する場合、代替プロバイダを登録する行を追加し、優先順位を適切に設定します (必要に応じて他のプロバイダの順序も調整)。
例として、マスタークラスが
com.cryptox.provider
パッケージのCryptoX
クラスで、プロバイダを 2 番目の優先順位とする場合を考えてみましょう。その場合、java.security
ファイルにある「SUN」プロバイダの行の下に次の行を追加して、さらに他のプロバイダの優先順位を 2 より大きくします。security.provider.2=com.cryptox.provider.CryptoX注: プロバイダは動的に登録することもできます。その場合、プログラム (ステップ 6 で記述したテストプログラムなど) は、Security
クラスのaddProvider
メソッドまたはinsertProviderAt
メソッドを呼び出します。こうした登録は持続的なものではありません。また、実行できるのは次の権限を付与されたコードだけです。ここで、java.security.SecurityPermission "insertProvider.{name}"{name}
には実際のプロバイダ名を指定します。たとえば、プロバイダ名が「MyJCE」であり、プロバイダのコードが/localWork
ディレクトリのmyjce_provider.jar
ファイル内に存在する場合、アクセス権を付与するサンプルポリシーファイルのgrant
文は次のようになります。grant codeBase "file:/localWork/myjce_provider.jar" {
permission java.security.SecurityPermission
"insertProvider.MyJCE";
};ステップ 5e: プロバイダアクセス権の設定
JCE プロバイダがインストール型拡張機能ではない場合、セキュリティマネージャがインストール済みの状態で、JCE を使用するアプレットまたはアプリケーションを実行する際、常に JCE プロバイダにアクセス権を付与する必要があります。通常、アプレットの実行時にはセキュリティマネージャが常にインストールされます。アプリケーションの場合でも、アプリケーション自体のコード内またはコマンド行引数で指定することにより、セキュリティマネージャをインストールできます。デフォルトシステムポリシーファイルは、インストール型拡張機能にすべてのアクセス権を付与するため、インストール型拡張機能にはアクセス権を付与する必要はありません。
クライアントがプロバイダをインストール型拡張機能としてインストールしない場合、クライアント環境で次のアクセス権をプロバイダに常に付与する必要があります。
java.lang.RuntimePermission
(クラス保護ドメインを取得するため)。プロバイダは、自己完全性チェックの実行過程で、独自の保護ドメインの取得が必要になる場合があるjava.security.SecurityPermission
(プロバイダプロパティの設定用)セキュリティマネージャがインストールされていて、プロバイダがインストール型拡張機能でない場合は、プロバイダが正しく機能するかどうかを確認するため、インストールおよび実行環境をテストする必要があります。なお、テストを実施する前に、プロバイダとこのプロバイダが使用するすべてのプロバイダに適切なアクセス権を付与しておく必要があります。たとえば、名前が「MyJCE」で、コードが
myjce_provider.jar
内に存在するプロバイダにアクセス権を付与するサンプルコードを次に示します。この種の文は、ポリシーファイルに記述されます。この例では、myjce_provider.jar
ファイルは/localWork
ディレクトリに格納されるものとします。grant codeBase "file:/localWork/myjce_provider.jar" {
permission java.lang.RuntimePermission "getProtectionDomain";
permission java.security.SecurityPermission
"putProviderProperty.MyJCE";
};ステップ 6: テストプログラムの記述とコンパイル
Security API へのプロバイダの統合、およびそのアルゴリズムをテストする 1 つ以上のテストプログラムの記述およびコンパイルを実行します。必要に応じて、暗号化の行われるテストデータ用ファイルなどのサポート用ファイルを作成します。プログラムが実行する最初のテストでは、プロバイダの検出、およびその名前、バージョン番号、追加情報が予期されたとおりかどうかを確認します。このために、次のようなコードを記述できます。
MyPro
部分は、独自のプロバイダ名に置き換えてください。import java.security.*;
Provider p = Security.getProvider("MyPro");
System.out.println("MyPro provider name is " + p.getName());
System.out.println("MyPro provider version # is " + p.getVersion());
System.out.println("MyPro provider info is " + p.getInfo());次に、サービスが検出されることを確認します。たとえば、DES 暗号化アルゴリズムを実装した場合には、要求時にこのアルゴリズムが確実に検出されるかどうかを、次のコードを使ってチェックできます (ここでも「MyPro」は、独自のプロバイダ名に置き換える)。
Cipher c = Cipher.getInstance("DES", "MyPro");
System.out.println("My Cipher algorithm name is " + c.getAlgorithm());
getInstance
への呼び出しでプロバイダ名を指定しない場合、そのアルゴリズムを実装するプロバイダが検出されるまで、登録されたすべてのプロバイダが優先順位に従って検索されます (「プロバイダの構成」を参照)。プロバイダが免責機構を実装している場合、免責機構を使用するテストアプレットまたはアプリケーションを記述する必要があります。この種のアプレット/アプリケーションにも、署名、および「アクセス権ポリシーファイル」のバンドルが必要です。アプリケーションの作成およびテスト方法の詳細は、「Java 暗号化拡張機能 (JCE) リファレンスガイド」の「アプリケーションの暗号化制限の「免責」を取得する方法」を参照してください。
ステップ 7: テストプログラムの実行
テストプログラムを実行します。コードをデバッグし、必要に応じてテストを続行します。Java Security API がアルゴリズムを検出できないようであれば、上記のステップを確認し、すべてのステップが完了していることを確認してください。
複数のインストールオプション (たとえば、プロバイダをインストール型拡張機能にする、またはクラスパス内に配置する) および実行環境 (セキュリティ管理を実行する、または実行しない) を使用して、プログラムを確実にテストしてください。インストールオプションの詳細は、ステップ 5d を参照してください。特に、セキュリティマネージャをインストールし、かつプロバイダがインストール型拡張機能ではない (つまり、プロバイダにアクセス権を付与する必要がある) 場合、プロバイダが正しく機能するかどうかを確認するため、ステップ 5e の手順に従ってプロバイダおよびそのプロバイダが使用する他のプロバイダに必要なアクセス権を付与したあと、インストールおよび実行環境をテストする必要があります。
テストの結果、コードの修正が必要になった場合には、変更および再コンパイル (ステップ 4)、更新したプロバイダコードの JAR ファイルへの配置 (ステップ 5b)、JAR ファイルへの署名 (ステップ 5c)、プロバイダの再インストール (ステップ 5d)、必要に応じたアクセス権の修正または追加 (ステップ 5e) を実行してから、プログラムを再テストします。その後、必要に応じてこれらのステップを繰り返します。
ステップ 8: 米国政府による輸出承認の申請 (必要な場合)
プロバイダを米国外に輸出する可能性のある米国内のベンダーはすべて、米国商務省輸出管理局に輸出承認申請を行う必要があります。詳細は、輸出問題を担当する顧問弁護士に確認してください。
注: プロバイダが
Cipher.getInstance()
を呼び出し、返されるCipher
オブジェクトで、ユーザがダウンロードした管轄ポリシーファイルで許可されている暗号化の強度に関係なく強力な暗号化を実行する必要がある場合は、その暗号化強度に対応したアクセス権が指定されている、JAR ファイルにバンドルする予定のcryptoPerms
アクセス権ポリシーファイルのコピーを含める必要があります。このファイルが必要な理由は、アプレットおよびアプリケーションが暗号化制限を「免除される」ために、JAR ファイルにcryptoPerms
アクセス権ポリシーファイルを含める必要があるのと同じ理由です。こうしたファイルの作成と組み込みの詳細については、「Java 暗号化拡張機能 (JCE) リファレンスガイド」の「アプリケーションの暗号化制限の「免責」を取得する方法」を参照してください。役に立つと思われる URL を 2 つ紹介しておきます。
- 米国商務省: http://www.doc.gov
- 輸出管理局: http://www.bxa.doc.gov
ステップ 9: プロバイダおよびそのサポート対象サービスのドキュメント化
次のステップは、クライアント用のドキュメントを記述することです。少なくとも、次の指定が必要です。さらに、ドキュメント内で、デフォルトのアルゴリズムパラメータなどの、クライアントに関係する他の指定も行う必要があります。
- プロバイダの参照に使用する名前プログラム。注: このドキュメントを執筆している現時点では、プロバイダ名の検索で大文字と小文字が区別される。つまり、マスタークラスがプロバイダ名を「CryptoX」として指定した場合、ユーザが「CRYPTOx」を要求しても、プロバイダは見つからない。この動作は、将来変更される可能性があるが、現時点ではクライアントに対して大文字と小文字を正確に指定するように通知する必要がある
- プロバイダが実装するアルゴリズムおよび他のサービスの種類
- プロバイダのインストール方法に関する指示。これは、情報と例がプロバイダ固有のものになることを除き、ステップ 5d で示した指示と同様
- プロバイダがインストール型拡張機能としてインストールされておらず、セキュリティマネージャが稼動していない場合に必要なアクセス権 (ステップ 5e)
MAC
MAC アルゴリズムごとに、実装が複製可能かどうかを指定します。これは、技術的には必須ではありませんが、複製による中間「「メッセージ認証コード」 (MAC) が可能かどうかを指定することになるため、クライアントの費やす時間およびコードの記述にかかる手間が軽減されます。MAC の実装が複製可能かどうかがわからない場合、クライアントは
Mac
オブジェクトの複製を試みて、発生する可能性のある例外をキャッチすることにより、複製可能かどうかを識別できます。次にその例を示します。try {以下の点に留意してください。
// try and clone it
/* compute the MAC for i1 */
mac.update(i1);
byte[] i1Mac = mac.clone().doFinal();
/* compute the MAC for i1 and i2 */
mac.update(i2);
byte[] i12Mac = mac.clone().doFinal();
/* compute the MAC for i1, i2 and i3 */
mac.update(i3);
byte[] i123Mac = mac.doFinal();
} catch (CloneNotSupportedException cnse) {
// have to use an approach not involving cloning
}
mac
は、Mac.getInstance
への呼び出しを介して要求が行われた場合に、受け取られる MAC オブジェクトi1
、i2
およびi3
は、入力バイト配列- 以下について、別々のハッシュを計算する
i1
i1 および i2
i1、i2、および i3
鍵ペアジェネレータ
鍵ペアジェネレータアルゴリズムでは、クライアントが (
initialize
メソッドの呼び出しを介して) 明示的に鍵ペアジェネレータを初期化しない場合、各プロバイダはデフォルトの初期化を提供およびドキュメント化する必要があります。たとえば、「SunJCE」により提供される Diffie-Hellman 鍵ペアジェネレータは、1024 ビットのデフォルト prime モジュールサイズ (keysize
) を使用します。鍵ファクトリ
プロバイダは、その (非公開) 鍵ファクトリがサポートするすべての鍵仕様をドキュメント化する必要があります。アルゴリズムパラメータジェネレータ
クライアントが AlgorithmParameterGenerator エンジンクラスのinit
メソッドの呼び出しを介してアルゴリズムパラメータジェネレータを明示的に初期化しない場合、各プロバイダはデフォルトの初期化を行い、これをドキュメント化する必要があります。たとえば、「SunJCE」プロバイダは、Diffie-Hellman パラメータの生成に 1024 ビットのデフォルト prime モジュールサイズ (keysize
) を使用します。ステップ 10: プロバイダソフトウェアおよびドキュメントをクライアントから利用可能にする
最後のステップとして、プロバイダソフトウェアおよびドキュメントをカスタマから利用可能にします。
各プロバイダは自己完全性チェックを実行して、プロバイダメソッドを JCE を介さずに直接呼び出すなどの操作により、コードを含む JAR ファイルが改変されていないことを保証する必要があります。JCE サービスの実装を提供するプロバイダは、デジタル署名され、「信頼できる」証明書発行局が発行する証明書で署名されている必要があります。現状では、次の 2 種類の証明書発行局が「信頼できる」とされています。Sun Microsystems の JCE コード署名証明書発行局からコード署名証明書を取得する方法については、ステップ 5b を参照してください。
- Sun Microsystems の JCE コード署名証明書発行局
- IBM の JCE コード署名証明書発行局
署名済み証明書を上記の証明書発行局から入手したあと、プロバイダパッケージに署名する証明書用のバイトを埋め込む必要があります。たとえば、後述する「個々の署名者の識別と信頼できる署名者の特定」で解説する、
bytesOfProviderCert
配列のような配列です。実行時には、埋め込まれた証明書を使用して、プロバイダコードが認証されたものかどうかが判断されます。プロバイダが自らの完全性チェックに使用する基本的な方法を、次に示します。
- プロバイダコードを含む JAR ファイルの URL を特定する
- JAR ファイルのデジタル署名を検証して、JAR ファイルの各エントリの少なくとも 1 つの署名者が信頼できることを確認する
以下のセクションでは、具体的な手順を示します。
- プロバイダ JAR ファイルの検索: 基本
- プロバイダの JAR ファイル URL の確認
- JAR ファイルを参照する JarFile の作成
- プロバイダ JAR ファイルの検証: 基本
- 検証の設定
- JAR ファイル署名のチェック
- 署名の検証
- 署名者の信頼性の確認
- 証明書リストの取得
- 個々の署名者の識別と信頼できる署名者の特定
- サンプルコードについて
注: サンプルコードMyJCE.java
は、これらのステップを実装する完全なコード例です。このコードは参照用としてダウンロードできます。上記の概念がどのようにしてサンプルコードに実装されているかについては、「サンプルコードについて」を参照してください。
重要:JCE 1.2.1 では、プラグインする JCE の完全性および信頼性を保証するため、JCE フレームワークの認証用コードをプロバイダに含める必要がありました。JCE が Java 2 SDK, v 1.4 に統合されることにより、この操作は不要になりました。
JCE フレームワークコードがプロバイダの期待する場所に存在しなくなるため、プロバイダの JCE フレームワーク認証チェックが機能しなくなります。このため、JCE 1.2.1 専用に記述されたプロバイダは、Java 2 SDK, v 1.4 では動作しなくなります。プロバイダを Java 2 SDK, v 1.4 でのみ動作させたい場合は、そのプロバイダから、JCE フレームワークを認証するコードを除外してください。プロバイダを JCE 1.2.1 と Java 2 SDK, v 1.4 の JCE の両方で動作させたい場合は、条件文を追加します。こうしておけば、プロバイダを JCE 1.2.1 で実行する場合にのみ JCE フレームワークを認証するプロバイダコードが実行されるようになります。以下は、サンプルコードです。
Class cipherCls = Class.forName("javax.crypto.Cipher");
CodeSource cs =
cipherCls.getProtectionDomain().getCodeSource();
if (cs != null) {
// Authenticate JCE framework
. . .
}
プロバイダ JAR ファイルの検索: 基本
プロバイダの JAR ファイル URL の確認
プロバイダの JAR ファイルの URL は、プロバイダの
CodeSource
を確認し、CodeSource
に対してgetLocation
メソッドを呼び出すことにより取得できます。URL providerURL = (URL) AccessController.doPrivileged(
new PrivilegedAction) {
public Object run() {
CodeSource cs = MyJCE.class.getProtectionDomain().
getCodeSource();
return cs.getLocation();
}
});JAR ファイルを参照する JarFile の作成
プロバイダの JAR ファイルの URL を取得したら、JAR ファイルを参照する
java.util.jar.JarFile
を作成できます。これは、「プロバイダ JAR ファイルの検証」で必要になります。JAR ファイルを作成するには、まず、
openConnection
メソッドを呼び出し、指定された URL への接続を確立します。URL は JAR URL であるため、java.net.JarURLConnection
型になります。標準的なコードは以下のとおりです。// Prep the url with the appropriate protocol.
jarURL =
url.getProtocol().equalsIgnoreCase("jar") ?
url :
new URL("jar:"+ url.toString() + "!/");
// Retrieve the jar file using JarURLConnection
JarFile jf = (JarFile) AccessController.doPrivileged(
new PrivilegedExceptionAction() {
public Object run() throws Exception {
JarURLConnection conn =
(JarURLConnection) jarURL.openConnection(); ...JarURLConnection
を取得できたら、getJarFile
メソッドを呼び出して JAR ファイルを取得します。// Always get a fresh copy, so we don't have to
// worry about the stale file handle when the
// cached jar is closed by some other application.
conn.setUseCaches(false);
jf = conn.getJarFile();プロバイダ JAR ファイルの検証: 基本
上記のステップに従ってプロバイダ JAR ファイルの URL を確認し、JAR ファイルを参照する
JarFile
を作成したら、ファイルの検証を行います。基本的な方法は以下のとおりです。
- 各エントリの署名者の証明書の少なくとも 1 つが、プロバイダ自身のコード署名証明書と等価であることを確認します。
- JAR ファイルのすべてのエントリを確認して、各エントリの署名が適切であることを検証します。
- 各エントリの署名者の証明書の少なくとも 1 つから、信頼できる証明書発行局までたどれることを確認します。
これらのステップで使用するサンプルコードについては、以下のセクションを参照してください。
- 検証の設定
- JAR ファイル署名のチェック
- 署名の検証
- 署名者の信頼性の確認
- 証明書リストの取得
- 個々の署名者の識別と信頼できる署名者の特定
検証の設定
ここでは、クラス
JarVerifier
を定義して指定された URL からの JAR ファイル取得を処理し、JAR ファイルが指定された証明書で署名されているかどうかを検証します。
JarVerifier
のコンストラクタはプロバイダ URL をパラメータとして取ります。これを使用して、JAR ファイルが取得されます。実際の JAR 検証は、プロバイダコード署名証明書をパラメータとする
verify
メソッドで実装されます。public void verify(X509Certificate targetCert)
throws IOException {
// variable 'jarFile' is a JarFile object created
// from the provider's Jar URL.
...
Vector entriesVec = new Vector();verify
は、基本的に JAR ファイルエントリを 2 回使用します。1 回目は各エントリの署名をチェックし、2 回目は署名者が信頼できることを検証します。注: このコードでは、
jarFile
変数は、プロバイダの jar ファイルのJarFile
オブジェクトです。JAR ファイル署名のチェック
認証されたプロバイダ JAR ファイルが署名されます。このため、署名されない JAR ファイルは、改変されています。
// Ensure the jar file is signed.
Manifest man = jarFile.getManifest();
if (man == null) {
throw new SecurityException("The provider is not signed");
}署名の検証
次のステップでは、JAR ファイルのすべてのエントリを確認して、各エントリの署名が適切であることを検証します。JAR ファイルエントリの署名を検証する 1 つの方法は、単純なファイルの読み取りです。JAR ファイルが署名されていると、
read
メソッドが自動的に署名の検証を実行します。サンプルコードを次に示します。// Ensure all the entries' signatures verify correctly
byte[] buffer = new byte[8192];
Enumeration entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry je = (JarEntry) entries.nextElement();
// Skip directories.
if (je.isDirectory()) continue;
entriesVec.addElement(je);
InputStream is = jarFile.getInputStream(je);
// Read in each jar entry.A security exception will
// be thrown if a signature/digest check fails.
int n;
while ((n = is.read(buffer, 0, buffer.length)) != -1) {
// Don't care
}
is.close();
}署名者の信頼性の確認
前のセクションのコードでは、すべてのプロバイダ JAR ファイルエントリの署名を検証しました。すべてを適正に検証することは必須ですが、JAR ファイルの認証を確認するだけでは十分ではありません。最終的に、署名がこのプロバイダを構築したものと同じエントリから生成されたことを確認する必要があります。署名が信頼できることをテストするために、JAR ファイル内の各エントリをループ処理し (今回は前のステップで作成した
entriesVec
を使用)、署名の必要なエントリ (META-INF ディレクトリ内に存在しないディレクトリ以外のエントリ) ごとに次の操作を実行します。ループの設定方法を、次に示します。
- エントリの署名者証明書のリストを取得します。
- 個々の証明書チェーンを特定し、信頼できる証明書チェーンがあるかどうかを判定します。信頼できる証明書チェーンが 1 つ以上存在しなければなりません。
Enumeration e = entriesVec.elements();
while (e.hasMoreElements()) {
JarEntry je = (JarEntry) e.nextElement();
...
}証明書リストの取得
JAR ファイルエントリ
JarEntry
の署名者の証明書は、JarEntry
のgetCertificates
メソッドを呼び出すだけで取得できます。Certificate[] certs = je.getCertificates();前のループ設定コードに、上記のコードおよび META-INF ディレクトリ内のディレクトリおよびファイルを無視するコードを追加すると、次のようになります。
while (e.hasMoreElements()) {
JarEntry je = (JarEntry) e.nextElement();
// Every file must be signed except files in META-INF.
Certificate[] certs = je.getCertificates();
if ((certs == null) || (certs.length == 0)) {
if (!je.getName().startsWith("META-INF"))
throw new SecurityException("The provider " +
"has unsigned " +
"class files.");
} else {
// Check whether the file is signed by the expected
// signer.The jar may be signed by multiple signers.
// See if one of the signers is 'targetCert'.
...
}
...個々の署名者の識別と信頼できる署名者の特定
JarEntry
のgetCertificates
メソッドが返す証明書配列には、1 つ以上の証明書チェーンが含まれます。エントリの署名者ごとに 1 つのチェーンが存在します。各チェーンには、1 つ以上の証明書が含まれます。チェーン内の各証明書は、前の証明書の公開鍵を認証します。チェーン内の最初の証明書には、エントリの署名に実際に使用される非公開鍵に対応する公開鍵を含む、署名者の証明書です。そのあとに続く証明書は、それぞれ前の証明書の発行者の証明書になります。自己完全性チェックは、JAR ファイルがプロバイダの署名証明書で署名されているかどうかを基準にしているため、信頼性の判断は最初の証明書である署名者の証明書のみで決定されます。
証明書チェーンの配列内で、「信頼できる」エンティティが見つかるまで各チェーンおよび関連する署名者をチェックします。JAR ファイルエントリごとに、信頼できる署名者が少なくとも 1 人必要です。署名者が「信頼できる」と判断されるのは、証明書が、埋め込まれたプロバイダ署名証明書と等価である場合に限ります。
次のサンプルコードでは、すべての証明書チェーンでループ処理を行い、チェーンの最初の証明書と埋め込まれたプロバイダ署名証明書とを比較し、一致した場合に
true
だけを返します。int startIndex = 0;
X509Certificate[] certChain;
boolean signedAsExpected = false;
while ((certChain = getAChain(certs, startIndex)) != null) {
if (certChain[0].equals(targetCert)) {
// Stop since one trusted signer is found.
signedAsExpected = true;
break;
}
// Proceed to the next chain.
startIndex += certChain.length;
}
if (!signedAsExpected) {
throw new SecurityException("The provider " +
"is not signed by a " +
"trusted signer");
}getAChain
メソッドは、次のように定義されます。/**
* Extracts ONE certificate chain from the specified certificate array
* which may contain multiple certificate chains, starting from index
* 'startIndex'.
*/
private static X509Certificate[] getAChain(Certificate[] certs,
int startIndex) {
if (startIndex > certs.length - 1)
return null;
int i;
// Keep going until the next certificate is not the
// issuer of this certificate.
for (i = startIndex; i < certs.length - 1; i++) {
if (!((X509Certificate)certs[i + 1]).getSubjectDN().
equals(((X509Certificate)certs[i]).getIssuerDN())) {
break;
}
}
// Construct and return the found certificate chain.
int certChainSize = (i-startIndex) + 1;
X509Certificate[] ret = new X509Certificate[certChainSize];
for (int j = 0; j < certChainSize; j++ ) {
ret[j] = (X509Certificate) certs[startIndex + j];
}
return ret;
}サンプルコードについて
サンプルコードMyJCE.java
は、自動的に完全性チェックを実行するselfIntegrityChecking
メソッドを備えたサンプルプロバイダです。このコードは、まず固有のプロバイダ JAR ファイルの URL を特定します。次に、このプロバイダ JAR ファイルに、組み込み済みのコード署名証明書による署名があるかどうかを検証します。注:
selfIntegrityChecking
メソッドは、完全性を確保するため、その暗号化エンジンクラスの全コンストラクタによって呼び出されます。プロバイダ
MyJCE
は、次のステップで自動的に完全性チェックを行います。注:
- 固有のクラス
MyJCE.class
を使ってプロバイダ JAR ファイルにアクセスするための URL を特定する- ステップ 1 で特定したプロバイダ URL を使って
JarVerifier
オブジェクトをインスタンス化する- 組み込みバイト配列
bytesOfProviderCert
からX509Certificate
オブジェクトを作成するJarVerifier.verify
メソッドを呼び出し、プロバイダ JAR ファイル内のすべてのエントリに、ステップ 3 でインスタンス化した同じ証明書による署名があることを検証するJarVerifier
クラスは、所定の URL から JAR ファイルを取得し、その JAR ファイルに署名があるか、すべてのエントリに有効な署名があるか、これらのエントリに指定されたX509Certificate
による署名があるかどうかを検証します。場合によっては、
JarVerifier.verify
によってセキュリティ例外がスローされます。
verify
とされた証明書が null (無効) である場合- 所定の URL から JAR ファイルを取得できない場合
- プロバイダに署名がない場合 (jar がマニフェストを持たない)
- プロバイダのクラスファイルの中に未署名のものがある場合
- プロバイダに指定された証明書による署名がない場合
サンプルコード
MyJCE.java
は、上記のコードで構成されます。さらに、エラー処理、サンプルコード署名証明書バイト、埋め込まれたサンプルコード署名証明書バイトからX509Certificate
オブジェクトをインスタンス化するコードが含まれています。
AccessController.doPrivileged
の使用については、「特権ブロックのための API」でdoPrivileged
の使用に関する説明を参照してください。
アルゴリズムの別名
多くの暗号化アルゴリズムでは、公式の「標準名」が 1 つ存在します。Java 2 SDK, v 1.4 の JCE で定義されている標準名のリストは、「Java 暗号化拡張機能 (JCE) リファレンスガイド」の「付録 A」に記載されています。たとえば、
DiffieHellman
は、PKCS #3 で定義された Diffie-Hellman 鍵協定アルゴリズムの標準名です。JCE は、Java 2 SDK, v 1.4 の他のセキュリティ製品と同じ方式で、アルゴリズム名の別名を使用します。この方式では、クライアントは、標準名ではなく別名を使用して、アルゴリズムを参照できます。たとえば、「SunJCE」プロバイダのマスタークラス (
SunJCE.java
) は、標準名DiffieHellman
の鍵協定に対して別名「DH」を定義します。このため、次の文は同じ意味になります。KeyAgreement ka = KeyAgreement.getInstance("DiffieHellman", "SunJCE");別名は、「マスタークラス」内で定義できます (ステップ 3 を参照)。別名を定義するには、次の名前のプロパティを作成します。
KeyAgreement ka = KeyAgreement.getInstance("DH", "SunJCE");Alg.Alias.
engineClassName.aliasNameここで、
engineClassName
はCipher
、KeyAgreement
、KeyGenerator
、Mac
、SecretKeyFactory
、ExemptionMechanism
のいずれかを指します。また、aliasName
は使用する別名を指します。ExemptionMechanism
を除き、プロパティの「値」には、別名の設定されているアルゴリズムの標準アルゴリズム名を指定する必要があります。ExemptionMechanism
の場合、値は免責機構名 (KeyRecovery
、KeyEscrow
、KeyWeakening
のいずれか) になります。たとえば、「SunJCE」プロバイダは、標準名「DiffieHellman」の鍵協定アルゴリズムに対し、別名「DH」を定義します。これは、次に示すように、
Alg.Alias.KeyAgreement.DH
という名前のプロパティに値DiffieHellman
を設定することにより行います。put("Alg.Alias.KeyAgreement.DH", "DiffieHellman");あるプロバイダによって定義された別名は、そのプロバイダのみが使用でき、その他のプロバイダは使用できません。したがって、「SunJCE」プロバイダによって定義された別名は、「SunJCE」プロバイダのみが使用できます。
サービスの相互依存性
アルゴリズムによっては、他の種類のアルゴリズムの使用を要求することがあります。たとえば、通常、PBE アルゴリズムは、メッセージダイジェストアルゴリズムを使用して、パスワードを鍵に変換する必要があります。別のアルゴリズムを要求するアルゴリズムを実装している場合、次のいずれかを実行できます。
- どちらのアルゴリズムにも対応した独自の実装を提供します。
- Java 2 プラットフォームの各インストールに含まれるデフォルトの「SUN」プロバイダにより提供される場合のように、一方のアルゴリズムの実装が他方のアルゴリズムのインスタンスを使用するようにします。たとえば、実装している PBE アルゴリズムがメッセージダイジェストアルゴリズムを要求する場合、次の呼び出しを行うことにより、MD5 メッセージダイジェストアルゴリズムを実装するクラスのインスタンスを取得できます。
MessageDigest.getInstance("MD5", "SUN")- 別の特定のプロバイダにより提供される場合のように、一方のアルゴリズムの実装が他方のアルゴリズムのインスタンスを使用するようにします。これは、プロバイダを使用するすべてのクライアントが、インストールされた他方のプロバイダも保持する場合にだけ有効な方法です。
- 別の (無指定の) プロバイダにより提供される場合のように、一方のアルゴリズムの実装が他方のアルゴリズムのインスタンスを使用するようにします。つまり、アルゴリズムを名前で要求できます。ただし、特定のプロバイダは指定しません。次に例を示します。
MessageDigest.getInstance("MD5")これは、プロバイダが使用される各 Java プラットフォームにインストールされた、要求されたアルゴリズムの実装 (この例では MD5) が少なくとも 1 つ存在することが確実な場合にだけ有効な方法です。デフォルトの初期化
クライアントが明示的に鍵ペアジェネレータまたはアルゴリズムパラメータジェネレータを初期化しない場合、これらサービスの各プロバイダはデフォルトの初期化を提供 (およびドキュメント化) する必要があります。たとえば、「SunJCE」プロバイダは、Diffie-Hellman パラメータの生成に 1024 ビットのデフォルト係数サイズ (キーサイズ) を使用します。
Diffie-Hellman インタフェースおよびその実装要件
Diffie-Hellman サービスを実装するプログラマのために、JCE には次のインタフェースが (javax.crypto.interfaces
パッケージ内に) 用意されています。 以降では、これらのインタフェースの実装要件について取り上げます。
DHPrivateKey
およびDHPublicKey
の実装Diffie-Hellman 鍵ペアジェネレータまたは鍵ファクトリを実装する場合、DHPrivateKey
およびDHPublicKey
インタフェースを実装するクラスを作成する必要があります。Diffie-Hellman 鍵ペアジェネレータを実装する場合、(
KeyPairGeneratorSpi
サブクラスの)generateKeyPair
メソッドはこれらのインタフェース実装のインスタンスを返します。Diffie-Hellman 鍵ファクトリを実装する場合、(
KeyFactorySpi
サブクラスの)engineGeneratePrivate
メソッドはDHPrivateKey
実装のインスタンスを返し、engineGeneratePublic
メソッドはDHPublicKey
実装のインスタンスを返します。また、
engineGetKeySpec
およびengineTranslateKey
メソッドは、引き渡される鍵がDHPrivateKey
またはDHPublicKey
実装のインスタンスであることを求めます。インタフェース実装によって提供されたgetParams
メソッドは、鍵からパラメータを取得および抽出する場合に便利です。その後、これらのパラメータを、パラメータ値からパラメータ仕様を作成するために呼び出されるDHParameterSpec
コンストラクタのパラメータとして利用することにより、KeyPairGenerator
オブジェクトを Diffie-Hellman 用として初期化できます。Diffie-Hellman 鍵協定アルゴリズムを実装する場合、
KeyAgreementSpi
サブクラスのengineInit
メソッドはDHPrivateKey
が渡されることを求めます。また、engineDoPhase
メソッドはDHPublicKey
が渡されることを求めます。注:
DHPublicKey
およびDHPrivateKey
インタフェースはそれぞれ、Diffie-Hellman 公開鍵および非公開鍵に対する非常に一般的なプロバイダ非依存のインタフェースを定義します。KeyFactorySpi
サブクラスのengineGetKeySpec
メソッドとengineTranslateKey
メソッドは、プロバイダ固有の実装の詳細を利用するなどの目的で、引き渡される鍵が実際にプロバイダ独自のDHPrivateKey
またはDHPublicKey
実装のインスタンスであるかどうかをチェックすることもできます。KeyAgreementSpi
サブクラスに含まれている Diffie-Hellman アルゴリズムのengineInit
メソッドとengineDoPhase
メソッドについても同じことが言えます。
DHPublicKey
およびDHPrivateKey
インタフェースを実装するクラスを使ってどんなメソッドを実装する必要があるかについては、次のインタフェース署名に注目してください。
javax.crypto.interfaces
パッケージ内:public interface DHPrivateKey extends DHKey,
java.security.PrivateKey
public interface DHPublicKey extends DHKey,
java.security.PublicKey
public interface DHKey
java.security
パッケージ内:public interface PrivateKey extends Key
public interface PublicKey extends Key
public interface Key extends java.io.SerializableDHPrivateKey
インタフェースとDHPublicKey
インタフェースを実装するには、これらによって定義されるメソッドと、これらによって拡張されるインタフェースによって定義されたメソッドを実装する必要があります。このため、非公開鍵の場合、以下を実装するクラスを提供する必要があります。
同様に、公開 Diffie-Hellman 鍵の場合、以下を実装するクラスを提供する必要があります。
DHPrivateKey
インタフェースのgetX
メソッド- javax.crypto.interfaces.DHKey インタフェースの
getParams
メソッド (DHPrivateKey
がDHKey
を拡張するため)- java.security.Key インタフェースの
getAlgorithm
、getEncoded
、およびgetFormat
メソッド (DHPrivateKey
がjava.security.PrivateKey
を拡張し、PrivateKey
がKey
を拡張するため)
DHPublicKey
インタフェースのgetY
メソッドjavax.crypto.interfaces.DHKey
インタフェースのgetParams
メソッド (DHPublicKey
がDHKey
を拡張するため)- java.security.Key インタフェースの
getAlgorithm
、getEncoded
、およびgetFormat
メソッド (DHPublicKey
がjava.security.PublicKey
を拡張し、PublicKey
がKey
を拡張するため)アルゴリズムパラメータ仕様クラス
アルゴリズムパラメータの仕様は、アルゴリズムとともに使われるパラメータのセットの透明な表現です。
パラメータのセットの「透明な」表現とは、対応する仕様クラスに定義された get メソッドの 1 つを使って、各値に個々にアクセスできるということです。 たとえば、
DHParameterSpec
は、getP
、getG
、getL
メソッドを定義して、パラメータ p、g、l にアクセスします。これと対照的なのが、
AlgorithmParameters
エンジンクラスが提供するような「不透明な」表現です。この場合、鍵データ値に直接アクセスすることはできません。getAlgorithm
を使ってパラメータセットに関連付けられたアルゴリズム名を取得するか、getEncoded
を使ってパラメータセットの符号化方式の一部を取得することしかできません。
AlgorithmParametersSpi
、AlgorithmParameterGeneratorSpi
、KeyPairGeneratorSpi
のいずれかの実装を提供する場合、AlgorithmParameterSpec
インタフェースを利用する必要があります。理由は、これらの各クラスに、AlgorithmParameterSpec
パラメータをとるメソッドが含まれるからです。この種のメソッドは、インタフェースのどの実装が実際に引き渡されるかを判定し、それに応じて動作する必要があります。JCE には、よく使用される暗号化および鍵協定アルゴリズムパラメータの
AlgorithmParameterSpec
実装が多数含まれています。JCE から提供されない、種類の異なるアルゴリズムに対応したアルゴリズムパラメータを操作する場合は、その種類に適した独自のAlgorithmParameterSpec
実装を提供する必要があります。JCE は、
javax.crypto.spec
パッケージ内で次のアルゴリズムパラメータ仕様クラスを定義します。
IvParameterSpec
クラスこのクラス (AlgorithmParameterSpec
インタフェースを実装) は、フィードバックモードでの暗号化に使用される初期化ベクトル (IV) を指定します。
IvParameterSpec
のメソッドメソッド 説明 byte[] getIV()
初期化ベクトル (IV) を返す
PBEParameterSpec
クラスこのクラス (AlgorithmParameterSpec
インタフェースを実装) は、パスワードベースの暗号化 (PBE) アルゴリズムで使用されるパラメータのセットを指定します。
PBEParameterSpec
のメソッドメソッド 説明 int getIterationCount()
繰り返し処理の回数を返す byte[] getSalt()
salt を返す
RC2ParameterSpec
クラスこのクラス (AlgorithmParameterSpec
インタフェースを実装) は、RC2 アルゴリズムで使われるパラメータのセットを指定します。
RC2ParameterSpec
のメソッドメソッド 説明 boolean equals (Object obj)
指定されたオブジェクトと現在のオブジェクトが等価であるかどうかをテストする int getEffectiveKeyBits()
有効なキーサイズをビット単位で返す byte[] getIV()
IV を返す。このパラメータセットに IV が含まれない場合は null を返す int hashCode()
オブジェクトのハッシュコード値を計算する
RC5ParameterSpec
クラスこのクラス (AlgorithmParameterSpec
インタフェースを実装) は、RC5 アルゴリズムで使われるパラメータのセットを指定します。
RC5ParameterSpec
のメソッドメソッド 説明 boolean equals (Object obj)
指定されたオブジェクトと現在のオブジェクトが等価であるかどうかをテストする byte[] getIV()
IV を返す。このパラメータセットに IV が含まれない場合は null を返す int getRounds()
ラウンド回数を返す int getVersion()
バージョンを返す int getWordSize()
ワードサイズをビット単位で返す int hashCode()
オブジェクトのハッシュコード値を計算する
DHParameterSpec
クラスこのクラス (AlgorithmParameterSpec
インタフェースを実装) は、Diffie-Hellman アルゴリズムで使われるパラメータのセットを指定します。
DHParameterSpec
のメソッドメソッド 説明 BigInteger getG()
ベースジェネレータ g
を返すint getL()
ランダム指数 (非公開の値) のサイズ l
をビット単位で返すBigInteger getP()
prime モジュール p
を返すこのクラスは、多くの Diffie-Hellman サービス型にとって有用です。たとえば、このクラスは、「SunJCE」プロバイダが実装する Diffie-Hellman 鍵協定、鍵ペアジェネレータ、アルゴリズムパラメータジェネレータ、およびアルゴリズムパラメータクラスにより利用されます。具体例を挙げると、アルゴリズムパラメータ実装は、
AlgorithmParameterSpec
を返すgetParameterSpec
メソッド用の実装を含む必要があります。「SunJCE」により提供される Diffie-Hellman アルゴリズムパラメータ実装は、DHParameterSpec
クラスのインスタンスを返します。鍵ファクトリにより要求される鍵仕様クラス
鍵仕様は、鍵を構成する鍵データの透明な表現です。JCE は、
javax.crypto.spec
パッケージ内で、鍵仕様クラスDHPrivateKeySpec
、DHPublicKeySpec
、DESKeySpec
、DESedeKeySpec
、PBEKeySpec
、SecretKeySpec
を定義します。
DHPrivateKeySpec
クラスこのクラス (KeySpec
インタフェースを実装) は、関連付けられたパラメータを使って Diffie-Hellman 非公開鍵を指定します。
DHPrivateKeySpec
のメソッドメソッド 説明 BigInteger getG()
ベースジェネレータ g
を返すBigInteger getP()
prime モジュール p
を返すBigInteger getX()
非公開の値 x
を返す
DHPublicKeySpec
クラスこのクラス (KeySpec
インタフェースを実装) は、関連付けられたパラメータを使って Diffie-Hellman 公開鍵を指定します。
DHPublicKeySpec
のメソッドメソッド 説明 BigInteger getG()
ベースジェネレータ g
を返すBigInteger getP()
prime モジュール p
を返すBigInteger getY()
公開の値 y
を返す
DESKeySpec
クラスこのクラス (KeySpec
インタフェースを実装) は、DES 鍵を指定します。
DESKeySpec
のメソッドメソッド 説明 byte[] getKey()
DES 鍵のバイト数を返す static boolean isParityAdjusted(byte[] key, int offset)
所定の DES 鍵データがパリティ対応であるかどうかをチェックする static boolean isWeak(byte[] key, int offset)
所定の DES 鍵データが脆弱 (weak) または準脆弱 (semi-weak) のどちらであるかをチェックする
DESedeKeySpec
クラスこのクラス (KeySpec
インタフェースを実装) は、DES-EDE (トリプル DES) 鍵を指定します。
DESedeKeySpec
のメソッドメソッド 説明 byte[] getKey()
DES-EDE 鍵を返す static boolean isParityAdjusted(byte[] key, int offset)
所定の DES-EDE 鍵がパリティ対応であるかどうかをチェックする
PBEKeySpec
クラスこのクラスは、KeySpec
インタフェースを実装します。パスワードベースの暗号化 (PBE) で使用するパスワードは、ユーザが選択できます。このパスワードは、生の鍵データの型として参照されます。このクラスを使用する暗号化機構は、生の鍵データから暗号鍵を引き出すことができます。
PBEKeySpec
のメソッドメソッド 説明 void clearPassword
パスワードの内部コピーを消去する int getIterationCount
繰り返し処理の回数を返する。指定がない場合は 0 を返す int getKeyLength
引き出される鍵の長さを返す。指定がない場合は 0 を返す char[] getPassword
パスワードのコピーを返す byte[] getSalt
salt のコピーを返す。指定がない場合は null を返す
SecretKeySpec
クラスこのクラスは、KeySpec
インタフェースを実装します。このクラスはSecretKey
インタフェースも実装するため、このクラスを使用するなら、SecretKey
オブジェクトをプロバイダに依存しない方法で (プロバイダベースのSecretKeyFactory
を使用せずに) 構築できます。
SecretKeySpec
のメソッドメソッド 説明 boolean equals (Object obj)
このオブジェクトと「等価」になるオブジェクトがあるかどうかを示す String getAlgorithm()
この秘密鍵に関連付けられているアルゴリズム名を返す byte[] getEncoded()
この秘密鍵の鍵データを返す String getFormat()
この秘密鍵の符号化方式の名前を返す int hashCode()
オブジェクトのハッシュコード値を計算する 非公開鍵の生成
特定の非公開鍵アルゴリズムに対して非公開鍵ジェネレータ (javax.crypto.KeyGeneratorSpi
のサブクラス) を提供する場合、生成された非公開鍵オブジェクト (javax.crypto.SecretKey
のインスタンスであることが必要。engineGenerateKey
を参照) を次のいずれかの方法で返すことができます。
- 鍵ジェネレータと関連付けられたアルゴリズムの非公開鍵を表すインスタンスを保持するクラスを実装する。鍵ジェネレータ実装により、そのクラスのインスタンスが返される。鍵ジェネレータにより生成された鍵がプロバイダ固有のプロパティを保持する場合、この方法は有用である
- 鍵ジェネレータは、
javax.crypto.SecretKey
インタフェースをすでに実装しているSecretKeySpec
のインスタンスを返す。未加工の鍵のバイトおよび鍵ジェネレータに関連付けられた非公開鍵アルゴリズムの名前を、SecretKeySpec
コンストラクタに渡す。基盤となる未加工の鍵のバイトをバイト配列で表すことができ、関連付けられた鍵パラメータが存在しない場合、この方法は有用であるエクスポート機能の保証
JCE では、特定の条件が満たされる場合に、JCE フレームワークおよびプロバイダ暗号化実装をエクスポート可能になります。これは JCE の重要な機能です。
輸入管理制限があるため、Java 2 SDK, v 1.4 に同梱された管轄ポリシーファイルは「強固」ですが、暗号化の使用には制限があります。適格国 (大半の国が該当) の在住者は、暗号化機能に制限のない「無制限」のバージョンを利用できます。ただし、政府が制限を課しているこれらの国が輸入できるのは「強力な」バージョンだけです。JCE フレームワークでは、インストール済みの管轄ポリシーファイルで指定された制限が施行されます。
他の部分で説明したように、もっとも強力な暗号化を実装する、1 つのバージョンのプロバイダソフトウェアだけを実装できます。位置の異なるアプレット/アプリケーションから、利用可能な暗号化アルゴリズムおよび暗号化の最大強度に関して管轄ポリシーファイルに規定された制限を施行するのは、プロバイダではなく、JCE です。
Java 2 SDK, v 1.4 を JCE にプラグインできるようにするため、プロバイダは、以下の条件を満たしていなければなりません。
- 「プロバイダによる自己完全性チェックの実行方法」で説明したように、各 SPI 実装クラスのコンストラクタが、自己完全性チェックを実行する必要がある
- プロバイダコードを、JCE をバイパスして、アプリケーションから直接インスタンス化する場合には、プロバイダクラスが無効になるようにプロバイダコードを記述する必要がある。「プロバイダの実装および統合までのステップ」セクションの「ステップ 1: サービス実装コードの記述」を参照
- プロバイダパッケージは、JCE フレームワークにより信頼されたエンティティを使って署名する必要がある(ステップ 5a から ステップ 5c を参照)。プロバイダを米国外に輸出する可能性のある米国内のベンダーは、輸出承認を米国政府に申請する必要がある(ステップ 8 を参照)
以下に示すのは、編集済みのSunJCE.java
ファイルです。このファイルには、「SunJCE」という名前のプロバイダ用の マスタークラスであるSunJCE
というクラスが含まれます。すべてのマスタークラスの場合と同様、このクラスは
Provider
のサブクラスです。これは、「SunJCE」プロバイダが提供するすべての暗号化サービス実装のクラス名およびパッケージ位置を指定します。さまざまなアルゴリズムおよび他のサービスが要求された場合、エンジンクラスのgetInstance
メソッドはこの情報を使用して検索を行います。以下に示すコードは、プロバイダマスタークラスの例です。
/*
* Copyright 2002 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL.Use is subject to license terms.
*/
package com.sun.crypto.provider;
import java.security.AccessController;
import java.security.Provider;
.. .
/**
* The "SunJCE" Cryptographic Service Provider.
*
* @author Jan Luehe
* @author Sharon Liu
*
* @version 1.42, 01/08/01
*/
/**
* Defines the "SunJCE" provider.
*
* Supported algorithms and their names:
*
* - DES (ECB, CBC, CFB, OFB, PCBC)
*
* - DES-EDE (ECB, CBC, CFB, OFB, PCBC)
*
* - Password-based Encryption (PBE)
*
* - Blowfish
*
* - Diffie-Hellman Key Agreement
*
* - HMAC-MD5, HMAC-SHA1
*
* - PKCS5Padding
*/
public final class SunJCE extends Provider {
private static String info = "SunJCE Provider " +
"(implements DES, Triple DES, Blowfish, PBE, Diffie-Hellman, HMAC-MD5, "
+ "HMAC-SHA1)";
public SunJCE() {
/* We are the "SunJCE" provider */
super("SunJCE", 1.4, info);
AccessController.doPrivileged(new java.security.PrivilegedAction() {
public Object run() {
/*
* Cipher engines
*/
put("Cipher.DES", "com.sun.crypto.provider.DESCipher");
put("Cipher.DESede", "com.sun.crypto.provider.DESedeCipher");
put("Alg.Alias.Cipher.TripleDES", "DESede");
put("Cipher.PBEWithMD5AndDES",
"com.sun.crypto.provider.PBEWithMD5AndDESCipher");
put("Cipher.PBEWithMD5AndTripleDES",
"com.sun.crypto.provider.PBEWithMD5AndTripleDESCipher");
put("Cipher.Blowfish",
"com.sun.crypto.provider.BlowfishCipher");
/*
* Key(pair) Generator engines
*/
put("KeyGenerator.DES",
"com.sun.crypto.provider.DESKeyGenerator");
put("KeyGenerator.DESede",
"com.sun.crypto.provider.DESedeKeyGenerator");
put("Alg.Alias.KeyGenerator.TripleDES", "DESede");
put("KeyGenerator.Blowfish",
"com.sun.crypto.provider.BlowfishKeyGenerator");
put("KeyGenerator.HmacMD5",
"com.sun.crypto.provider.HmacMD5KeyGenerator");
put("KeyGenerator.HmacSHA1",
"com.sun.crypto.provider.HmacSHA1KeyGenerator");
put("KeyPairGenerator.DiffieHellman",
"com.sun.crypto.provider.DHKeyPairGenerator");
put("Alg.Alias.KeyPairGenerator.DH", "DiffieHellman");
/*
* Algorithm parameter generation engines
*/
put("AlgorithmParameterGenerator.DiffieHellman",
"com.sun.crypto.provider.DHParameterGenerator");
put("Alg.Alias.AlgorithmParameterGenerator.DH",
"DiffieHellman");
/*
* Key Agreement engines
*/
put("KeyAgreement.DiffieHellman",
"com.sun.crypto.provider.DHKeyAgreement");
put("Alg.Alias.KeyAgreement.DH", "DiffieHellman");
/*
* Algorithm Parameter engines
*/
put("AlgorithmParameters.DiffieHellman",
"com.sun.crypto.provider.DHParameters");
put("Alg.Alias.AlgorithmParameters.DH", "DiffieHellman");
put("AlgorithmParameters.DES",
"com.sun.crypto.provider.DESParameters");
put("AlgorithmParameters.DESede",
"com.sun.crypto.provider.DESedeParameters");
put("Alg.Alias.AlgorithmParameters.TripleDES", "DESede");
put("AlgorithmParameters.PBE",
"com.sun.crypto.provider.PBEParameters");
put("Alg.Alias.AlgorithmParameters.PBEWithMD5AndDES", "PBE");
put("AlgorithmParameters.Blowfish",
"com.sun.crypto.provider.BlowfishParameters");
/*
* Key factories
*/
put("KeyFactory.DiffieHellman",
"com.sun.crypto.provider.DHKeyFactory");
put("Alg.Alias.KeyFactory.DH", "DiffieHellman");
/*
* Secret-key factories
*/
put("SecretKeyFactory.DES",
"com.sun.crypto.provider.DESKeyFactory");
put("SecretKeyFactory.DESede",
"com.sun.crypto.provider.DESedeKeyFactory");
put("Alg.Alias.SecretKeyFactory.TripleDES", "DESede");
put("SecretKeyFactory.PBEWithMD5AndDES",
"com.sun.crypto.provider.PBEKeyFactory");
/*
* MAC
*/
put("Mac.HmacMD5", "com.sun.crypto.provider.HmacMD5");
put("Mac.HmacSHA1", "com.sun.crypto.provider.HmacSHA1");
/*
* KeyStore
*/
put("KeyStore.JCEKS", "com.sun.crypto.provider.JceKeyStore");
return null;
}
});
}
}
次に、EMProvider.java
ファイルの例を示します。このファイルには、「EMProvider」という名前のプロバイダのマスタークラスである、EMProvider
という名前のクラスが含まれます。すべてのマスタークラスの場合と同様、このクラスは
Provider
のサブクラスです。これは、「EMProvider」プロバイダが提供するすべての暗号化サービス実装のクラス名およびパッケージ位置を指定します。さまざまなアルゴリズムおよび他のサービスが要求された場合、エンジンクラスのgetInstance
メソッドはこの情報を使用して検索を行います。このコードは、免責機構を実装するプロバイダのマスタークラスの例として提供されています。「SunJCE」プロバイダには免責機構が実装されていないため、このコードは、「SunJCE」プロバイダのマスタークラスを示し、「付録 A」を補うものです。注: プロバイダは、暗号化サービスと免責機構サービスの両方を実装できます。
package com.abc.crypto.provider;
import java.security.AccessController;
import java.security.Provider;
/**
* The "EMProvider" Cryptographic Service Provider.
*
* @version 1.00, 03/15/2000
*/
/**
* Defines the "EMProvider" provider.
*
* Supported algorithm(s) and their name(s):
*
* - Key Recovery
*/
public final class EMProvider extends Provider {
private static String info = "EMProvider Exemption Mechanism Provider " +
"(implements KeyRecovery)";
public EMProvider() {
/* We are the "EMProvider" provider */
super("EMProvider", 1.2, info);
AccessController.doPrivileged(new java.security.PrivilegedAction() {
public Object run() {
/*
* Algorithm Parameter engines
*/
put("AlgorithmParameters.KeyRecovery",
"com.abc.crypto.provider.KeyRecoveryParameters");
put("Alg.Alias.AlgorithmParameters.KR", "KeyRecovery");
/*
* ExemptionMechanism
*/
put("ExemptionMechanism.KeyRecovery",
"com.abc.crypto.provider.KeyRecovery");
put("Alg.Alias.ExemptionMechanism.KR", "KeyRecovery");
return null;
}
});
}
}
次に示すのは、java.security
ファイルのコピーで、JRE の各インストールに含まれます。このファイルは次の場所にあります。ここで、<java-home> は JRE がインストールされているディレクトリを指します。したがって、Solaris の<java-home>/lib/security/java.security [Solaris]
<java-home>\lib\security\java.security [Windows]/home/user1/J2SDK1.4.0
ディレクトリまたは Microsoft Windows のC:\J2SDK1.4.0
ディレクトリに Java 2 SDK v 1.4 をインストールしている場合、ファイルは次の場所にあることになります。同様に、Java 2 Runtime Environment バージョン 1.4 を Solaris の/home/user1/J2SDK1.4.0/jre/lib/security/java.security [Solaris]
C:\J2SDK1.4.0\jre\lib\security\java.security [Windows]/home/user1/j2re1.4.0
ディレクトリにインストールしている場合、または Windows のC:\j2re1.4.0
ディレクトリにインストールしている場合は、ファイルは次の場所にあることになります。このファイルにプロバイダに関する情報を追加する例については、ステップ 5d を参照してください。/home/user1/j2re1.4.0/lib/security/java.security [Solaris]
C:\j2re1.4.0\lib\security\java.security [Windows]#
# This is the "master security properties file".
#
# In this file, various security properties are set for use by
# java.security classes.This is where users can statically register
# Cryptography Package Providers ("providers" for short).The term
# "provider" refers to a package or set of packages that supply a
# concrete implementation of a subset of the cryptography aspects of
# the Java Security API.A provider may, for example, implement one or
# more digital signature algorithms or message digest algorithms.
#
# Each provider must implement a subclass of the Provider class.
# To register a provider in this master security properties file,
# specify the Provider subclass name and priority in the format
#
# security.provider.<n>=<className>
#
# This declares a provider, and specifies its preference
# order n. The preference order is the order in which providers are
# searched for requested algorithms (when no specific provider is
# requested).The order is 1-based; 1 is the most preferred, followed
# by 2, and so on.
#
# <className> must specify the subclass of the Provider class whose
# constructor sets the values of various properties that are required
# for the Java Security API to look up the algorithms or other
# facilities implemented by the provider.
#
# There must be at least one provider specification in java.security.
# There is a default provider that comes standard with the JDK.It
# is called the "SUN" provider, and its Provider subclass
# named Sun appears in the sun.security.provider package.Thus, the
# "SUN" provider is registered via the following:
#
# security.provider.1=sun.security.provider.Sun
#
# (The number 1 is used for the default provider.)
#
# Note:Statically registered Provider subclasses are instantiated
# when the system is initialized.Providers can be dynamically
# registered instead by calls to either the addProvider or
# insertProviderAt method in the Security class.
#
# List of providers and their preference orders (see above):
#
security.provider.1=sun.security.provider.Sun
security.provider.2=com.sun.net.ssl.internal.ssl.Provider
security.provider.3=com.sun.rsajca.Provider
security.provider.4=com.sun.crypto.provider.SunJCE
security.provider.5=sun.security.jgss.SunProvider
#
# Select the source of seed data for SecureRandom.By default an
# attempt is made to use the entropy gathering device specified by
# the securerandom.source property.If an exception occurs when
# accessing the URL then the traditional system/thread activity
# algorithm is used.
#
securerandom.source=file:/dev/random
#
# The entropy gathering device is described as a URL and can
# also be specified with the property "java.security.egd".For example,
# -Djava.security.egd=file:/dev/urandom
# Specifying this property will override the securerandom.source setting.
#
# Class to instantiate as the javax.security.auth.login.Configuration
# provider.
#
login.configuration.provider=com.sun.security.auth.login.ConfigFile
#
# Default login configuration file
#
#login.config.url.1=file:${user.home}/.java.login.config
#
# Class to instantiate as the system Policy.This is the name of the class
# that will be used as the Policy object.
#
policy.provider=sun.security.provider.PolicyFile
# The default is to have a single system-wide policy file,
# and a policy file in the user's home directory.
policy.url.1=file:${java.home}/lib/security/java.policy
policy.url.2=file:${user.home}/.java.policy
# whether or not we expand properties in the policy file
# if this is set to false, properties (${...}) will not be expanded in policy
# files.
policy.expandProperties=true
# whether or not we allow an extra policy to be passed on the command line
# with -Djava.security.policy=somefile.Comment out this line to disable
# this feature.
policy.allowSystemProperty=true
# whether or not we look into the IdentityScope for trusted Identities
# when encountering a 1.1 signed JAR file.If the identity is found
# and is trusted, we grant it AllPermission.
policy.ignoreIdentityScope=false
#
# Default keystore type.
#
keystore.type=jks
#
# Class to instantiate as the system scope:
#
system.scope=sun.security.provider.IdentityDatabase
#
# List of comma-separated packages that start with or equal this string
# will cause a security exception to be thrown when
# passed to checkPackageAccess unless the
# corresponding RuntimePermission ("accessClassInPackage."+package) has
# been granted.
package.access=sun.
#
# List of comma-separated packages that start with or equal this string
# will cause a security exception to be thrown when
# passed to checkPackageDefinition unless the
# corresponding RuntimePermission ("defineClassInPackage."+package) has
# been granted.
#
# by default, no packages are restricted for definition, and none of
# the class loaders supplied with the JDK call checkPackageDefinition.
#
#package.definition=
#
# Determines whether this properties file can be appended to
# or overridden on the command line via -Djava.security.properties
#
security.overridePropertiesFile=true
#
# Determines the default key and trust manager factory algorithms for
# the javax.net.ssl package.
#
ssl.KeyManagerFactory.algorithm=SunX509
ssl.TrustManagerFactory.algorithm=SunX509
#
# Determines the default SSLSocketFactory and SSLServerSocketFactory
# provider implementations for the javax.net.ssl package.If, due to
# export and/or import regulations, the providers are not allowed to be
# replaced, changing these values will produce non-functional
# SocketFactory or ServerSocketFactory implementations.
#
#ssl.SocketFactory.provider=
#ssl.ServerSocketFactory.provider=
#
# The Java-level namelookup cache policy for successful lookups:
#
# any negative value:caching forever
# any positive value:the number of seconds to cache an address for
# zero:do not cache
#
# default value is forever (FOREVER).For security reasons, this
# caching is made forever when a security manager is set.
#
# NOTE:Setting this value to anything other than the default value
# can have serious security implications.Do not set it unless
# you are sure you are not exposed to DNS spoofing attack.
#
#networkaddress.cache.ttl=-1
# The Java-level namelookup cache policy for failed lookups:
#
# any negative value:cache forever
# any positive value:the number of seconds to cache negative lookup results
# zero:do not cache
#
# In some Microsoft Windows networking environments that employ
# the WINS name service in addition to DNS, name service lookups
# that fail may take a noticeably long time to return (approx. 5 seconds).
# For this reason the default caching policy is to maintain these
# results for 10 seconds.
#
#
networkaddress.cache.negative.ttl=10
Copyright © 1996-2002 Sun Microsystems, Inc.All Rights Reserved. コメントの送付先: java-security@java.sun.com. |
Java ソフトウェア |