mCertForm.txt
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」という名前のプロバイダ
プロバイダに影響を及ぼす、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, v1.4 に同梱されている強力な暗号化機能を持つバージョンに置き換えることも可能です。無制限のバージョンのダウンロード方法の詳細は、以下を参照してください。
http://java.sun.com/products/jce/index-14.html管轄ポリシーファイルは、次の場所に移されました。
ここで、<java-home> は、ランタイムソフトウェアのインストール先ディレクトリ (JavaTM 2 Runtime Environment<java-home>¥lib¥security [Win32] <java-home>/lib/security [Solaris]のトップレベルディレクトリまたは JavaTM 2 SDK ソフトウェアの jre ディレクトリ) を指します。 Java 2 SDK, v 1.4 に含まれる強力な暗号化機能のバージョンを機能無制限のバージョンと簡単に置き換えることができるように、これらのファイルは標準的な位置に移動されました。 不要になった 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>
は、新しく生成するキーストアのエントリを参照する際に使用する任意の別名で置き換えます。注: 実際の値には、角括弧を付けないでください。たとえば、別名をmyTestAlias
にする場合、-alias
オプションを次のように指定します。-alias myTestAliasまだ存在しないキーストアを指定すると、そのキーストアが作成されます。
注: 入力するコマンド行を、実行する
keytool 鉾enkey
コマンドと同じ長さにできない場合 (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 Domestic CSPs に記入して送付します。
- 米国外のベンダーの場合、次の Certification Form for Domestic CSPs に記入して送付します。
いずれの場合にも、フォームに要求番号を記載して以下の住所に郵送することにより、CSR および連絡情報を含む電子メールメッセージと郵送するハードコピーとを一致させる必要があります。 フォームの郵送先を次に示します。
Corporate Export Attn:Encryption export 901 San Antonio Road, UPAL01-541 Palo Alto, CA 94303JCE コード署名証明書は、電子メールメッセージと必要なフォームの両方を受信後に、要求者の認証を行います。その後、5 年間有効なコード署名証明書を作成および署名します。そして、電子メールメッセージに 2 つのプレーンテキストファイルを添付して要求者に送信します。1 つはこのコード署名証明書を含むファイルで、もう 1 つは独自の CA 証明書を含むファイルで公開鍵の認証に使用します。
注: この住所は変更される可能性があります。フォームを送る前に、「Sun Microsystems International Trade Services Contacts」ページで最新の住所を確認してください。
- 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 [Win32]
ここで、<java-home> は、ランタイムソフトウェアのインストール先ディレクトリ (JavaTM 2 Runtime Environment
のトップレベルディレクトリまたは JavaTM 2 SDK ソフトウェアの jre ディレクトリ) を指します。 たとえば、Java 2 SDK, v 1.4 を /home/user1/J2SDK1.4.0
ディレクトリ (Solaris)、またはC:¥J2SDK1.4.0
ディレクトリ (Win32) にインストールした場合、JAR ファイルを次のディレクトリにインストールする必要があります。/home/user1/J2SDK1.4.0/jre/lib/ext [Solaris] C:¥J2SDK1.4.0¥jre¥lib¥ext [Win32]同様に、JRE, v 1.4 を
/home/user1/j2re1.4.0
ディレクトリ (Solaris)、またはC:¥j2re1.4.0
ディレクトリ (Win32) にインストールした場合、JAR ファイルを次のディレクトリにインストールする必要があります。/home/user1/j2re1.4.0/lib/ext [Solaris] C:¥j2re1.4.0¥lib¥ext [Win32]「インストール型」拡張機能の詳細は、「インストール型拡張機能」を参照してください。
「バンドル型」拡張機能の詳細は、「インストール型拡張機能」を参照してください。
プロバイダの構成
次の手順では、認可プロバイダのリストにこのプロバイダを追加します。これは、セキュリティプロパティファイルを編集することにより、静的に行われます。
<java-home>/lib/security/java.security [Solaris] <java-home>¥lib¥security¥java.security [Win32]ここで、<java-home> は JRE がインストールされているディレクトリを指します。 たとえば、Java 2 SDK バージョン 1.4 を
/home/user1/J2SDK1.4.0
(Solaris) またはC:¥J2SDK1.4.0
(Win32) にインストールしている場合は、次のファイルを編集する必要があります。/home/user1/J2SDK1.4.0/jre/lib/security/java.security [Solaris] C:¥J2SDK1.4.0¥jre¥lib¥security¥java.security [Win32]同様に、Java 2 Runtime Environment バージョン 1.4 を Solaris の
/home/user1/j2re1.4.0
ディレクトリにインストールしている場合、または Win32 のC:¥j2re1.4.0
ディレクトリにインストールしている場合は、次のファイルを編集する必要があります。/home/user1/j2re1.4.0/lib/security/java.security [Solaris] C:¥j2re1.4.0¥lib¥security¥java.security [Win32]プロバイダごとに、このファイルは次の形式の文を保持します。
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 ファイルへの署名 (ステップ 5c)、プロバイダの再インストール (ステップ 5d)、必要に応じたアクセス権の修正または追加 (Step 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 サービスの実装を提供するプロバイダには、デジタル署名を行う必要があります。特定の証明書発行局は「信頼できる」と判断され、信頼される証明書発行局のいずれかの証明書まで証明書チェーンを追跡可能な証明書を使って署名されたコードはすべて、信頼できると判断されます。 プロバイダパッケージには、関連した信頼できる証明書発行局の証明書用のバイトが埋め込まれていなければなりません。後述の「証明書チェーンが信頼できるかどうかの判定」 で解説する
trustedCaCerts
を参照してください。実行時には、埋め込まれた証明書を使用して、プロバイダコードが認証されたものかどうかが判断されます。現在のところ、信頼できる証明書発行局には、Sun Microsystems の JCE コード署名 CA、および IBM JCE コード署名 CA の 2 つがあります。Sun Microsystems の JCE コード署名 CA からコード署名証明書を取得する方法については、ステップ 5b を参照してください。
プロバイダが自らの完全性チェックに使用する基本的な方法を、次に示します。
- プロバイダコードを含む 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 フレームワークを認証するプロバイダコードが実行されるようになります。以下は、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 jf = (JarFile) AccessController.doPrivileged( =new PrivilegedExceptionAction() { public Object run() throws Exception { JarURLConnection conn = (JarURLConnection) jarURL.openConnection(); // 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); ...JarURLConnection
を取得できたら、getJarFile
メソッドを呼び出して JAR ファイルを取得します。JarFile jf = (JarFile)jc.getJarFile();プロバイダ JAR ファイルの検証:基本
上記のステップに従ってプロバイダ JAR ファイルの URL を確認し、JAR ファイルを参照する
JarFile
を作成したら、ファイルの検証を行います。基本的な方法は以下のとおりです。
- JAR ファイルが署名された JAR ファイルであることを確認します。
- JAR ファイルのすべてのエントリを確認して、各エントリの署名が適切であることを検証します。
- 各エントリの署名者の証明書の少なくとも 1 つから、信頼できる証明書発行局までたどれることを確認します。
これらのステップで使用するサンプルコードについては、以下のセクションを参照してください。
- 検証の設定
- JAR ファイル署名のチェック
- 署名の検証
- 署名者の信頼性の確認
- 署名者証明書リストの取得
- 個々の証明書チェーンの特定と信頼できる証明書チェーンの特定
検証の設定
前のステップで作成した
JarFile
をパラメータとしてとるverifySingleJarFile
メソッドを定義します。
verifySingleJarFile
は、基本的に JAR ファイルエントリを 2 回使用します。このメソッドは、効率を上げるため、ベクトルentriesVec
を割り当て、最初にループを通過する際に JAR ファイルのエントリを処理し、各エントリをentriesVec
に追加して 2 回目のループで使用できるようにします。以下に、メソッドの最初の部分を示します。private static void verifySingleJarFile(JarFile jf) throws IOException, CertificateException { Vector entriesVec = new Vector();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 ファイルの認証を確認するだけでは十分ではありません。検証すべき最終要件は、署名が JCE の信頼するエンティティにより生成されたことです。 署名が信頼できることをテストするために、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'. int startIndex = 0; X509Certificate[] certChain; boolean signedAsExpected = false; } ...個々の証明書チェーンの特定と信頼できる証明書チェーンの特定
JarEntry
のgetCertificates
メソッドが返す証明書配列には、1 つ以上の証明書チェーンが含まれます。エントリの署名者ごとに 1 つのチェーンが存在します。各チェーンには、1 つ以上の証明書が含まれます。チェーン内の各証明書は、前の証明書の公開鍵を認証します。チェーン内の最初の証明書には、エントリの署名に実際に使用される非公開鍵に対応する公開鍵が含まれます。その後に続く証明書は、それぞれ前の証明書に署名を行ったエンティティの証明書になります。チェーン内の最後の証明書は、次のいずれかです。証明書チェーンの配列内で、「信頼できる」エンティティが見つかるまで各チェーンと関連証明書をチェックします。 JAR ファイルエントリごとに、信頼できる証明書チェーンが少なくとも 1 つ以上必要です。
- 証明書発行局の証明書、または
- 証明書発行局により発行された証明書
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; }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 がマニフェストを持たない)
- プロバイダのクラスファイルの中に未署名のものがある場合
- プロバイダに指定された証明書による署名がない場合
サンプルコードは、エラー処理を行うという点、必要に応じて
AccessController.doPrivileged
を使用するという点で、上記の抜粋コードとは異なっています。doPrivileged
の使用方法の詳細は、「特権ブロックのための API」を参照してください。
アルゴリズムの別名
多くの暗号化アルゴリズムでは、公式の「標準名」が 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"); KeyAgreement ka = KeyAgreement.getInstance("DH", "SunJCE");別名は、「マスタークラス」内で定義できます (ステップ 3 を参照)。別名を定義するには、次の名前のプロパティを作成します。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」プロバイダにより定義された別名は、クライアントがどのプロバイダを要求するとしても、すべてのクライアントから利用可能です。たとえば、Diffie-Hellman アルゴリズムを実装する「MyPro」という名前のプロバイダを作成すると、その別名を定義しなくても、「SunJCE」により定義された別名「DH」を使用してプロバイダの Diffie-Hellman 実装を参照できます。次にその方法を示します。
KeyAgreement ka = KeyAgreement.getInstance("DH", "MyPro");
サービスの相互依存性
アルゴリズムによっては、他の種類のアルゴリズムの使用を要求することがあります。たとえば、通常、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 [Win32]/home/user1/J2SDK1.4.0
ディレクトリまたは Win32 の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 [Win32]/home/user1/j2re1.4.0
ディレクトリにインストールしている場合、または Win32 のC:¥j2re1.4.0
ディレクトリにインストールしている場合は、ファイルは次の場所にあることになります。このファイルにプロバイダに関する情報を追加する例については、ステップ 5d を参照してください。/home/user1/j2re1.4.0/lib/security/java.security [Solaris] C:¥j2re1.4.0¥lib¥security¥java.security [Win32]# # 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 ソフトウェア |