java.security
プロパティーファイルJava プラットフォームでは、暗号化、公開鍵インフラストラクチャー、認証、安全な通信、アクセス制御など、主要なセキュリティー分野に渡る一連の API が定義されています。これらの API によって、開発者はアプリケーションコードにセキュリティーを簡単に統合できます。これらは、次の方針に基づいて設計されました。
実装の独立性
アプリケーションでセキュリティーを実装する必要はありません。Java プラットフォームからセキュリティーサービスを要求できます。セキュリティーサービスはプロバイダ (次を参照) に実装されています。プロバイダは、標準インタフェースによって Java プラットフォームにプラグインされます。アプリケーションは、複数の独立したプロバイダにセキュリティー機能を依存する場合があります。
実装の相互運用性
プロバイダは、アプリケーション間で相互運用できます。具体的には、アプリケーションは特定のプロバイダにバインドされず、プロバイダは特定のアプリケーションにバインドされません。
アルゴリズムの拡張性
Java プラットフォームには、現在広く使用されている基本的なセキュリティーサービスを実装する多数の組み込みプロバイダが含まれています。ただし、一部のアプリケーションは、まだ実装されていない普及しつつある規格や独自のサービスに依存している場合があります。Java プラットフォームは、そのようなサービスを実装するカスタムプロバイダのインストールをサポートします。
「暗号化サービスプロバイダ」(プロバイダ) は、JDK Security API の暗号化に関するサブセットの固定実装を提供するパッケージ (またはパッケージセット) です。
java.security.Provider
クラスは、セキュリティープロバイダの概念を Java プラットフォームでカプセル化します。プロバイダの名前を指定し、実装するセキュリティーサービスを一覧します。複数のプロバイダが同時に構成される場合があり、それらは優先順に一覧されます。セキュリティーサービスが要求されると、そのサービスを実装する、優先順位がいちばん高いプロバイダが選択されます。
図 1 および図 2 は、MD5 メッセージダイジェスト実装を要求するための、これらのオプションを示しています。どちらの図も、メッセージダイジェストアルゴリズムを実装する 3 つのプロバイダを示しています。プロバイダは、左から右への優先順位 (1 から 3) で並べられています。図 1 では、アプリケーションはプロバイダ名を指定せずに MD5 アルゴリズム実装を要求しています。プロバイダが優先順位に従って検索され、その特定のアルゴリズムを提供する最初のプロバイダである ProviderB から実装が返されます。図 2 では、アプリケーションは特定のプロバイダである ProviderC から MD5 アルゴリズム実装を要求しています。この場合は、優先順位の高いプロバイダである ProviderB も MD5 実装を提供しますが、指定されたプロバイダから実装が返されます。
図 1 (左): プロバイダの検索。図 2 (右): 特定のプロバイダの要求
各インストールでは 1 つ以上のプロバイダパッケージがインストールされます。クライアントは異なるプロバイダを用いて実行環境を構成し、各プロバイダの優先順位を指定できます。優先順位とは、特定プロバイダの指定がないときに、要求アルゴリズムについてプロバイダを検索する順序です。
Sun が提供する Java Runtime Environment には、「SUN」という名前のデフォルトのプロバイダが標準で搭載されています。ほかの Java Runtime Environment には、「SUN」プロバイダが含まれない場合があります。
Java Security API を使って既存の暗号化アルゴリズムやほかのサービスにアクセスするだけであれば、このドキュメントを読む必要はありません。
このドキュメントは、暗号化サービス実装を提供する独自のプロバイダパッケージを作成する上級プログラマを対象としています。ここでは、Java Security API クライアントが、作成されたアルゴリズムやほかのサービスを要求する際にそれらを検出できるよう、プロバイダを Java に統合するための方法がドキュメント化されています。
このドキュメントは、読者がすでに「Java 暗号化アーキテクチャーリファレンスガイド」を読んでいることを前提としています。
Security API のさまざまなクラスおよびインタフェースを含むパッケージについてドキュメント化されています。
java.security
java.security.spec
java.security.interfaces
javax.crypto
javax.crypto.spec
javax.crypto.interfaces
java.security
、javax.crypto
、javax.crypto.spec
、javax.crypto.interfaces
などのパッケージが含まれます。このドキュメントでは、JCA という語は、JCA フレームワークを指して使用されています。このドキュメントで特定の JCA プロバイダを取り上げる場合は、常にプロバイダ名で明示的に指定されます。
エンジンクラスは、固定実装のない抽象的な方法で暗号化サービスを定義します。
暗号化サービスは、常に特定のアルゴリズムまたは型に関連付けられています。このサービスによって、暗号化の操作 (デジタル署名またはメッセージダイジェスト、暗号または鍵協定プロトコルなどのための操作) の提供、暗号化の操作に必要な暗号化データ (鍵またはパラメータ) の生成や提供、あるいは暗号化の操作で使用する暗号化鍵を安全にカプセル化するデータオブジェクト (キーストアまたは証明書) の生成が行われます。
たとえば、次の 4 つのエンジンクラスがあります。
Signature
クラスは、デジタル署名アルゴリズムの機能へのアクセスを提供します。KeyFactory
クラスは、(エンコード形式または透明な仕様から) DSA 非公開鍵または公開鍵を、それぞれ DSA Signature オブジェクトの initSign または initVerify メソッドから利用可能な形式で提供します。Cipher
クラスは、DES などの暗号化アルゴリズムの機能へのアクセスを提供します。KeyAgreement
クラスは、Diffie-Hellman などの鍵協定プロトコルの機能へのアクセスを提供します。Java 暗号化アーキテクチャーには、エンジンクラスなど、暗号化に関連するセキュリティーパッケージを構成するクラスが含まれています。API のユーザーは、エンジンクラスを要求および利用して対応する処理を実行します。JDK は、次のエンジンクラスを定義します。
MessageDigest
- 指定データのメッセージダイジェスト (ハッシュ) の計算に使います。Signature
- デジタル署名の署名および検証に使います。KeyPairGenerator
- 指定のアルゴリズムに適合した、公開鍵、非公開鍵ペアの生成に使います。KeyFactory
- Key
型の不透明な暗号化鍵を鍵仕様 (基本の鍵データの透明な表現) に変換したり、その逆の変換を行うために使用します。KeyStore
- キーストアの作成および管理に使用します。キーストアは、鍵のデータベースです。キーストア内の非公開鍵には、鍵に関連した証明書連鎖があります。証明書連鎖は、対応する公開鍵を認証します。また、キーストアには、信頼できるエンティティーからの証明書も格納されています。CertificateFactory
- 公開鍵の証明書および証明書の取り消しリスト (CRL) の作成に使用します。AlgorithmParameters
- パラメータのエンコードおよびデコードなど、特定のアルゴリズムのパラメータ管理に使います。AlgorithmParameterGenerator
- 特定のアルゴリズムに適したパラメータセットの生成に使います。SecureRandom
- 乱数または擬似乱数の生成に使用します。Cipher
- 指定されたデータの暗号化または復号化に使用します。KeyAgreement
- 複数のパーティー間の鍵協定 (鍵交換) プロトコルの実行に使用します。KeyGenerator
- 指定のアルゴリズムに適合した、秘密 (対称) 鍵の生成に使用します。Mac
- 指定されたデータのメッセージ認証コードの計算に使用します。SecretKeyFactory
- SecretKey
型の不透明な暗号化鍵を鍵仕様 (基本の鍵データの透明な表現) に変換したり、その逆の変換を行うために使用します。ExemptionMechanism
- 鍵復元、鍵弱化、鍵エスクローなどの免責メカニズム、またはほかの (カスタム) 免責メカニズムの機能を提供するために使用します。免責メカニズムを使用するアプリケーションまたはアプレットは、使用しないアプリケーションまたはアプレットに比べて強力な暗号化機能が付与されます。大半の国では暗号化制限はもはや適用されていないため、免責メカニズムが有用なのは政府により制限が要求されているいくつかの国だけです。注:ジェネレータ (generator) は、最新の内容でオブジェクトを作成しますが、ファクトリ (factory) は既存の構成要素 (エンコードなど) からオブジェクトを作成します。
エンジンクラスは、(特定の暗号化アルゴリズムに依存しない) 特定の型の暗号化サービス機能へのインタフェースを提供します。これにより、Application Programming Interface (API) メソッドが定義され、API が提供する特定の種類の暗号化サービスにアプリケーションがアクセスできるようになります。実際の実装 (1 つ以上のプロバイダから) は特定アルゴリズムのためのものです。たとえば Signature エンジンクラスは、デジタル署名アルゴリズムの機能へのアクセスを提供します。SignatureSpi
サブクラス (次の段落を参照) に実際に提供される実装は、DSA を使用する SHA-1、RSA を使用する SHA-1、または RSA を使用する MD5 などの特定の種類の署名アルゴリズムとなります。
エンジンクラスが提供するアプリケーションインタフェースは、Service Provider Interface (SPI) として実装されます。つまり、各エンジンクラスに対応する抽象 SPI クラスが存在し、抽象 SPI クラスによって暗号化サービスプロバイダが実装しなければならない Service Provider Interface のメソッドが定義されます。
エンジンクラスのインスタンスである「API オブジェクト」は、対応する SPI クラスのインスタンスである「SPI オブジェクト」を private フィールドとしてカプセル化します。API オブジェクトのすべての API メソッドは、「final」として宣言し、それらを実装することによって、カプセル化される SPI オブジェクトの対応する SPI メソッドが呼び出されます。エンジンクラス (およびそれに対応する SPI クラス) のインスタンスは、エンジンクラスの getInstance
ファクトリメソッドへの呼び出しによって作成されます。
各 SPI クラスの名前は、対応するエンジンクラス名のあとに「Spi」を追加した名前になります。たとえば、Signature エンジンクラスに対応する SPI クラスは、SignatureSpi クラスです。
各 SPI クラスは、抽象クラスです。指定したアルゴリズムに対する特定の型のサービスの実装を提供するには、プロバイダは、対応する SPI クラスをサブクラス化して、すべての抽象メソッドの実装を提供する必要があります。
エンジンクラスの別の例に MessageDigest クラスがあります。このクラスは、メッセージダイジェストアルゴリズムへのアクセスを提供します。MessageDigestSpi サブクラスでのこのクラスの実装は、SHA-1、MD5、または MD2 などの各種メッセージダイジェストアルゴリズムにできます。
さらに別の例として、KeyFactory エンジンクラスは、不透明な鍵から透明な鍵仕様への変換、またはその逆の変換をサポートします。詳細は、「鍵ファクトリにより要求される鍵仕様のインタフェースおよびクラス」を参照してください。KeyFactorySpi サブクラスで提供される現実の実装は、DSA 公開鍵または非公開鍵などの、特定の種類の鍵のための実装です。
次の手順に従って、プロバイダを実装し JCA フレームワークに統合します。
最初に、サポートする暗号化サービスのアルゴリズム固有の実装を提供するコードを記述する必要があります。
プロバイダは、JDK の 1 つ以上のセキュリティーコンポーネントですでに使用可能になっている暗号化サービス実装を提供できます。
JCA には定義されていない暗号化サービス (署名やメッセージダイジェストなど) に関しては、「Java 暗号化アーキテクチャーリファレンスガイド」を参照してください。
実装する暗号化サービスごとに、適切な SPI クラスのサブクラスを作成します。JCA は、次のエンジンクラスを定義します。
SignatureSpi
MessageDigestSpi
KeyPairGeneratorSpi
SecureRandomSpi
AlgorithmParameterGeneratorSpi
AlgorithmParametersSpi
KeyFactorySpi
CertificateFactorySpi
KeyStoreSpi
CipherSpi
KeyAgreementSpi
KeyGeneratorSpi
MacSpi
SecretKeyFactorySpi
ExemptionMechanismSpi
JCA およびその他の暗号化クラスについては、このドキュメントの「エンジンクラスおよび対応する SPI クラス」を参照してください。
サブクラスで、次を実行する必要があります。
engine
で始まる名前を持つ抽象メソッド用の実装を提供します。詳細は、「実装の詳細および要件」を参照してください。Class
オブジェクトを作成し、その Class
オブジェクトに対して newInstance
メソッドを呼び出すことにより、サブクラスのインスタンスを作成します。newInstance
はサブクラスがパラメータを持たない public コンストラクタを保持することを要求します。プロバイダによる Cipher、KeyAgreement、KeyGenerator、MAC
または SecretKey
ファクトリの実装 (クラス) をインスタンス化する際、フレームワークはプロバイダのコードベース (JAR ファイル) を判定し、その署名を検証します。このようにして、JCA はプロバイダを認証して、信頼されたエンティティーにより署名されたプロバイダだけが JCA にプラグインできるようにします。このため、暗号化プロバイダは署名付きにする必要があります。詳細は後のステップで説明します。
また、各プロバイダは自己整合性チェックを実行して、プロバイダメソッドを JCA を介さずに直接呼び出そうとして、コードを含む JAR ファイルが操作されていないことを保証する必要があります。詳細は、「プロバイダによる自己整合性チェックの実行方法」を参照してください。
JCA を介さずに直接アプリケーションからインスタンス化が行われた場合に、プロバイダクラスを使用不可にするため、プロバイダは次の実装を行う必要があります。
プロバイダを米国以外に輸出する場合、CipherSpi
実装に、Key
を指定すると鍵のサイズを返す engineGetKeySize
メソッドの実装を含める必要があります。管轄ポリシーファイルで指定された利用可能な暗号化強度に制限が設定されている場合、Cipher
初期化メソッドは engineGetKeySize
を呼び出して、実行中のアプレットまたはアプリケーションの特定位置および状況での鍵の最大有効サイズと結果を比較します。鍵のサイズが大きすぎる場合には、初期化メソッドにより例外がスローされます。
プロバイダが実装可能なオプション機能を、次に示します。
CipherSpi
の engineWrap
メソッドおよび engineUnwrap
メソッド。鍵をラッピングすると、ある場所から別の場所へ安全に転送できます。鍵のラップおよびラップの解除の詳細は、「Java 暗号化アーキテクチャーリファレンスガイド」の「鍵のラッピングとアンラッピング」のセクションを参照してください。使用するプロバイダの名前を特定します。これは、クライアントアプリケーションがプロバイダを参照する際に使用する名前です。
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.");
次のリストに、JCA サービスのさまざまな型を示します。algName は、実際のアルゴリズム名に置き換えてください。
Signature.algName
MessageDigest.algName
KeyPairGenerator.algName
SecureRandom.algName
AlgorithmParameterGenerator.algName
AlgorithmParameters.algName
KeyFactory.algName
CertificateFactory.algName
KeyStore.algName
Cipher.algName
KeyAgreement.algName
KeyGenerator.algName
Mac.algName
SecretKeyFactory.algName
ExemptionMechanism.algName
ExemptionMechanism
および Cipher
を除き、これらのどの場合にも algName、certType
、または storeType
は、アルゴリズム、証明書の型、またはキーストアの型の「標準」名です。使用する必要がある標準名については、「Java 暗号化アーキテクチャーリファレンスガイド」の「付録 A」を参照してください。
ExemptionMechanism
の場合、algName は例外メカニズムの名前を指し、KeyRecovery
、KeyEscrow
、または KeyWeakening
。大文字小文字は区別されません。
Cipher
の場合、algName は実際には変換を表します。これは、アルゴリズム名、指定されたモード、およびパディングスキームで構成されます。詳細は、「Java 暗号化アーキテクチャーリファレンスガイド」の「付録 A」を参照してください。
各プロパティーの値は、指定されたアルゴリズム、証明書の型、またはキーストアの型を実装するクラスの完全修飾名である必要があります。つまり、クラス名のあとにピリオドとパッケージ名が記述されていなければなりません。
たとえば、SUN という名前のデフォルトプロバイダは、sun.security.provider
パッケージの DSA
という名前のクラス内のデジタル署名アルゴリズム (その標準名は SHA1withDSA
) を実装します。Provider
のサブクラス (sun.security.provider package
の Sun クラス) は、次のようにして、Signature.SHA1withDSA
プロパティーが値 sun.security.provider.DSA
を保持するよう設定します。
put("Signature.SHA1withDSA", "sun.security.provider.DSA")
次のリストに、さまざまな種類のサービスに合わせて定義可能なその他のプロパティーを示します。実際には、algName はアルゴリズム名に、certType は証明書の型に、storeType はキーストアの型に、attrName は属性名に置き換えられます。
Signature.algName [one or more spaces] attrName
MessageDigest.algName [one or more spaces] attrName
KeyPairGenerator.algName [one or more spaces] attrName
SecureRandom.algName [one or more spaces] attrName
KeyFactory.algName [one or more spaces] attrName
CertificateFactory.certType [one or more spaces] attrName
KeyStore.storeType [one or more spaces] attrName
AlgorithmParameterGenerator.algName [one or more spaces] attrName
AlgorithmParameters.algName [one or more spaces] attrName
Cipher.algName [one or more spaces] attrName
KeyAgreement.algName [one or more spaces] attrName
KeyGenerator.algName [one or more spaces] attrName
Mac.algName [one or more spaces] attrName
SecretKeyFactory.algName [one or more spaces] attrName
ExemptionMechanism.algName [one or more spaces] attrName
これらのどの場合にも、algName、certType、storeType、
または attrName
は、アルゴリズム、証明書の型、キーストアの型、または属性の「標準」名です。使用するべき標準名については、「Java 暗号化アーキテクチャーリファレンスガイド」の「付録 A」を参照してください。
前述の形式のプロパティーの場合、プロパティーの値は、対応する属性に応じた値である必要があります。(各標準属性の定義については、「Java 暗号化アーキテクチャー API 仕様 & リファレンス」の「付録 A」を参照してください。)
たとえば、「SUN」という名前のデフォルトプロバイダは、SHA1withDSA Digital
デジタル署名アルゴリズムをソフトウェア内で実装します。プロバイダ「SUN」のマスタークラスでは、次のようにして、Signature.SHA1withDSA ImplementedIn
が値 Software
を保持するように設定が行われます。
put("Signature.SHA1withDSA ImplementedIn", "Software")
マスタークラスプロパティーの設定例の詳細は、「付録 A」を参照して現在の Sun.java のソースファイルを閲覧するか、「付録 B」を参照して SunJCE プロバイダを参照してください。これらのファイルでは、Sun および SunJCE プロバイダがプロパティーをどのように設定しているかがわかります。
すでに説明したように、Cipher
プロパティーの場合、algName は実際には変換を表します。変換は、指定された入力に対して Cipher
オブジェクトによって実行される操作 (または操作のセット) を説明する文字列です。変換には、暗号化アルゴリズム (DES など) の名前が必ず含まれます。それにモードおよびパディングスキームが続く場合もあります。
変換は、次の書式で記述されます。
後者の場合、モードおよびパディングスキームには、プロバイダ固有のデフォルト値が使用されます。たとえば、次は有効な変換です。
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 のサブクラスは、指定された mode とプラグイン可能なパディングを利用して algName を実装します。 |
Cipher. algName//padding |
プロバイダの CipherSpi のサブクラスは、指定された padding とプラグイン可能なモードを利用して algName を実装します。 |
Cipher. algName/mode/padding |
プロバイダの CipherSpi のサブクラスは、指定された mode と padding を利用して algName を実装します。 |
(使用する必要がある標準アルゴリズム名、モード、およびパディングスキームについては、「Java 暗号化アーキテクチャーリファレンスガイド」の「付録 A」を参照してください。)
たとえば、プロバイダは、DES/ECB/PKCS5Padding、DES/CBC/PKCS5Padding、DES/CFB/PKCS5Padding、さらには DES/OFB/PKCS5Padding をそれぞれ実装する CipherSpi
のサブクラスを提供できます。このプロバイダは、マスタークラス内に次の Cipher
プロパティーを保持します。
Cipher.DES/ECB/PKCS5Padding
Cipher.DES/CBC/PKCS5Padding
Cipher.DES/CFB/PKCS5Padding
Cipher.DES/OFB/PKCS5Padding
別のプロバイダは、前述の各モードのためのクラス (つまり、ECB、CBC、CFB、OFB のためにそれぞれ 1 つのクラス)、PKCS5Padding のための 1 つのクラス、および CipherSpi
からサブクラス化された汎用 DES クラスを実装できます。このプロバイダは、マスタークラス内に次の Cipher
プロパティーを保持します。
Cipher.DES
Cipher.DES SupportedModes
Example: "ECB|CBC|CFB|OFB"
Cipher.DES SupportedPaddings
Example: "NOPADDING|PKCS5Padding"
「algorithm」形式の変換の場合、Cipher
エンジンクラスの getInstance
ファクトリメソッドは、次の規則に従ってプロバイダの CipherSpi
の実装をインスタンス化します。
CipherSpi
のサブクラスを登録済みかどうかをチェックする。NoSuchAlgorithmException
をスローします。「algorithm/mode/padding」形式の変換の場合、Cipher
エンジンクラスの getInstance
ファクトリメソッドは、次の規則に従ってプロバイダの CipherSpi
の実装をインスタンス化します。
CipherSpi
のサブクラスを登録済みかどうかをチェックする。CipherSpi
のサブクラスを登録済みかどうかをチェックする。engineSetPadding(padding)
を呼び出します。CipherSpi
のサブクラスを登録済みかどうかをチェックする。engineSetMode(mode)
を呼び出します。CipherSpi
のサブクラスを登録済みかどうかをチェックする。engineSetMode(mode)
および engineSetPadding(padding)
を呼び出します。NoSuchAlgorithmException
をスローします。実装コードの作成 (ステップ 1)、プロバイダの命名 (ステップ 2)、およびマスタークラスの作成 (ステップ 3) が完了したら、Java コンパイラを使ってファイルをコンパイルします。
次のステップ (JAR ファイルへの署名) の準備として、JAR ファイルにプロバイダコードを記載します。jar ツールの詳細については、jar (Solaris 用) (Microsoft Windows 用) を参照してください。
jar cvf <JAR file name> <list of classes, separated by spaces>
このコマンドにより、指定されたクラスを含む、指定された名前の JAR ファイルが作成されます。
プロバイダが Cipher KeyAgreement、KeyGenerator、Mac、
または SecretKeyFactory
クラスによって暗号化アルゴリズムを提供している場合、実行時に JCA がコードを認証できるように、JAR ファイルに署名する必要があります。詳細は、Step 1a を参照してください。この種類の実装を提供していない場合は、このステップはスキップできます。
次のステップは、コード署名証明書の要求です。テストに先立ち、コード署名証明書を使用してプロバイダへの署名を行います。証明書は、テスト環境と製作環境の両方で利用できます。有効期間は 5 年間です。
次に、コード署名証明書の取得方法を示します。keytool ツールの詳細については、keytool (Solaris 用) (Microsoft Windows 用) を参照してください。
keytool -genkeypair -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>
これにより、DSA 鍵ペア (公開鍵および関連する非公開鍵) が生成され、指定されたキーストアのエントリに格納されます。公開鍵は、自己署名証明書に格納されます。これ以降、キーストアのエントリには、指定された別名を使用してアクセスできます。
角括弧 (「<」と「>」) 内のオプション値には、実際の値を指定する必要があります。たとえば、<alias>
は、新しく生成するキーストアのエントリを参照する際に使用する任意の別名で置き換え、<keystore file name>
は、使用するキーストアの名前で置き換えます。注: 実際の値には、角括弧を付けないでください。たとえば、別名を myTestAlias
にする場合、-alias
オプションを次のように指定します。
-alias myTestAliasまだ存在しないキーストアを指定すると、そのキーストアが作成されます。
注: 入力するコマンド行を、実行する keytool -genkeypair
コマンドと同じ長さにできない場合 (Microsoft Windows の DOS プロンプトに入力する場合など)、コマンドを含むプレーンテキストのバッチファイルを作成して実行できます。つまり、keytool -genkeypair
コマンドだけを含むテキストファイルを新規作成します。なお、コマンドは、全体を 1 行に入力してください。拡張子 .bat を付けてファイルを保存します。DOS ウィンドウで、ファイル名を (必要に応じてパスを付けて) 入力します。これで、バッチファイルに記述されたコマンドが実行されます。
keytool -certreq -alias <alias> \ -file <csr file name> \ -keystore <keystore file name> \ -storepass <keystore password>ここで、
<alias>
には、前のステップで作成した DSA 鍵ペアエントリの別名を指定します。このコマンドにより、証明書署名要求 (CSR) が PKCS#10 形式で生成されます。<csr file name>
で指定した名前のファイルに CSR が格納されます。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>
で指定されたキーストアエントリ内の自己署名証明書が、JCA コード署名証明書発行局が署名した証明書で置き換えられます。これで、JCA により信頼されたエンティティー (JCA コード署名証明書発行局) からの証明書がキーストア内に保存されたため、JAR ファイル内にプロバイダコードを記述し (ステップ 5)、この証明書を使用して JAR ファイルに署名できます (ステップ 6.2)。
ステップ 6 で取得したコード署名証明書を使用して、ステップ 5 で作成した JAR ファイルに署名します。jarsigner ツールの詳細については、jarsigner (Solaris 用) (Microsoft Windows 用) を参照してください。
jarsigner -keystore <keystore file name> \ -storepass <keystore password> \ <JAR file name> <alias>
ここで、<alias>
には、JCA コード署名証明書発行局から受け取ったコード署名証明書を含むエントリ用キーストアの別名 (ステップ 6.1 のコマンドで指定した別名) を指定します。
次の方法で、署名を検証できます。
jarsigner -verify <JAR file name>
検証が成功すると、「jar verified」というテキストが表示されます。
次の手順では、新しいプロバイダを JCA で使用できるようにインストールおよび構成する方法について説明します。
プロバイダのテスト準備を行うために、プロバイダを使用するクライアントが行うのと同じ方法で、プロバイダをインストールする必要があります。インストールを実行すると、Java Security はクライアントの要求に応じてアルゴリズムの実装を検出できるようになります。
プロバイダのインストールには、次の 2 つのステップが含まれます。プロバイダパッケージクラスのインストール、およびプロバイダの構成です。
最初に行う事柄は、作成したクラスを利用可能にして、要求時に検出できるようにすることです。プロバイダクラスは Jar (Java ARchive) ファイルの形式で提供します。
プロバイダクラスのインストール方法は 2 種類あります。
プロバイダ JAR ファイルは、次に示すインストール型拡張機能 JAR ファイルの標準位置に配置された場合、インストール型拡張機能と見なされます。
<java-home>/lib/ext [Solaris] <java-home>\lib\ext [Windows]
ここで、<java-home> は、実行ソフトウェアのインストール先ディレクトリ (Java™ 2 Runtime Environment (JRE) のトップレベルディレクトリまたは Java™ SE (JDK) ソフトウェアの jre ディレクトリ) を指します。たとえば、JDK 6 を /home/user1/jdk1.6.0
ディレクトリ (Solaris)、または C:\jdk1.6.0
ディレクトリ (Microsoft Windows) にインストールした場合、JAR ファイルを次のディレクトリにインストールする必要があります。
/home/user1/jdk1.6.0/jre/lib/ext [Solaris] C:\jdk1.6.0\jre\lib\ext [Windows]
同様に、JRE 6 を /home/user1/jre1.6.0
ディレクトリ (Solaris)、または C:\jre1.6.0
ディレクトリ (Microsoft Windows) にインストールした場合、JAR ファイルを次のディレクトリにインストールする必要があります。
/home/user1/jre1.6.0/lib/ext [Solaris] C:\jre1.6.0\lib\ext [Windows]
「インストール型」拡張機能の詳細は、「インストール型拡張機能」を参照してください。
「バンドル型」拡張機能の詳細は、「バンドル型拡張機能」を参照してください。
次の手順では、認可プロバイダのリストにこのプロバイダを追加します。これは、セキュリティープロパティーファイルを編集することにより、静的に行われます。
<java-home>/lib/security/java.security [Solaris] <java-home>\lib\security\java.security [Windows]
ここで、<java-home> は JRE がインストールされているディレクトリを指します。たとえば、JDK 6 を /home/user1/jdk1.6.0
ディレクトリ (Solaris)、または C:\jdk1.6.0
ディレクトリ (Microsoft Windows) にインストールした場合、次のファイルを編集する必要があります。
/home/user1/jdk1.6.0/jre/lib/security/java.security [Solaris] C:\jdk1.6.0\jre\lib\security\java.security [Windows]
同様に、JRE 6 を Solaris の /home/user1/jre1.6.0
ディレクトリにインストールしている場合、または Windows の C:\jre1.6.0
ディレクトリにインストールしている場合は、次のファイルを編集する必要があります。
/home/user1/jre1.6.0/lib/security/java.security [Solaris] C:\jre1.6.0\lib\security\java.security [Windows]
プロバイダごとに、このファイルは次の形式の文を保持します。
security.provider.n=masterClassName
これはプロバイダを宣言し、その優先順位 n を指定します。優先順位とは、特定プロバイダの指定がないときに、要求されたアルゴリズムについてプロバイダを検索する順序です。順位は 1 から始まり、1 が最優先で次に 2、3...と続きます。
masterClassName には、ステップ 3 で実装したプロバイダの「マスタークラス」の完全修飾名を指定する必要があります。このクラスは、常に Provider クラスのサブクラスです。
security.provider.2=sun.security.provider.Sun security.provider.3=sun.security.rsa.SunRsaSign security.provider.4=sun.security.provider.SunJCE
SUN プロバイダのマスタークラスは、sun.security.provider
パッケージ内の Sun
クラスです。
JCA プロバイダ SunJCE および Java プラットフォームに含まれるほかのセキュリティー関連プロバイダは、静的プロバイダとして自動的に構成されます。
ほかの JCA プロバイダを使用する場合は、行を追加してプロバイダを登録し、SUN および SunRsaSign プロバイダよりも低い優先順位を設定します。
例として、マスタークラスが com.cryptox.provider
パッケージの CryptoX
クラスで、プロバイダを 4 番目の優先順位とする場合を考えてみましょう。そのためには、java.security
ファイルを次のように編集します。
security.provider.2=sun.security.provider.Sun security.provider.3=sun.security.rsa.SunRsaSign security.provider.4=com.cryptox.provider.CryptoX security.provider.5=sun.security.provider.SunJCE
注: プロバイダは動的に登録することもできます。その場合、プログラム (ステップ 8 で記述したテストプログラムなど) は、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"; };
プロバイダがインストール型拡張機能ではない場合、セキュリティーマネージャーがインストール済みの状態で、アプレットまたはアプリケーションを実行する際、常にプロバイダにアクセス権を付与する必要があります。通常、アプレットの実行時にはセキュリティーマネージャーが常にインストールされます。アプリケーションの場合でも、アプリケーション自体のコード内またはコマンド行引数で指定することにより、セキュリティーマネージャーをインストールできます。デフォルトシステムポリシーファイルは、インストール型拡張機能にすべてのアクセス権を付与するため、インストール型拡張機能にはアクセス権を付与する必要はありません。
クライアントがプロバイダをインストール型拡張機能としてインストールしない場合、クライアント環境で次のアクセス権をプロバイダに常に付与する必要があります。
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"; };
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 暗号化アーキテクチャーリファレンスガイド」の「アプリケーションの暗号化制限の「免責」を取得する方法」を参照してください。
テストプログラムを実行します。コードをデバッグし、必要に応じてテストを続行します。Java Security API がアルゴリズムを検出できないようであれば、前述のステップを確認し、すべてのステップが完了していることを確認してください。
複数のインストールオプション (プロバイダをインストール型拡張機能にする、またはクラスパス内に配置するなど) および実行環境 (セキュリティー管理を実行する、または実行しない) を使用して、プログラムを確実にテストしてください。インストールオプションの詳細は、ステップ 7.1 を参照してください。特に、セキュリティーマネージャーをインストールし、かつプロバイダがインストール型拡張機能ではない (つまり、プロバイダにアクセス権を付与する必要がある) 場合、プロバイダが正しく機能するかどうかを確認するため、ステップ 7.2 の手順に従ってプロバイダおよびそのプロバイダが使用するほかのプロバイダに必要なアクセス権を付与したあと、インストールおよび実行環境をテストする必要があります。
テストの結果、コードの修正が必要になった場合には、変更および再コンパイル (ステップ 4)、JAR ファイルへの更新されたプロバイダコードの記載 (ステップ 6)、必要に応じた JAR ファイルへの署名 (ステップ 6.2)、プロバイダの再インストール (ステップ 7.1)、必要に応じたアクセス権の修正または追加 (Step 7.2) を実行してから、プログラムを再テストします。そのあと、必要に応じてこれらのステップを繰り返します。
プロバイダを米国外に輸出する可能性のある米国内のベンダーはすべて、米国商務省産業安全保障局に輸出承認申請を行う必要があります。詳細は、輸出問題を担当する顧問弁護士に確認してください。
注: プロバイダが Cipher.getInstance()
を呼び出し、返される Cipher
オブジェクトで、ユーザーがダウンロードした管轄ポリシーファイルで許可されている暗号化の強度に関係なく強力な暗号化を実行する必要がある場合は、その暗号化強度に対応したアクセス権が指定されている、JAR ファイルにバンドルする予定の cryptoPerms
アクセス権ポリシーファイルのコピーを含める必要があります。このファイルが必要な理由は、アプレットおよびアプリケーションが暗号化制限を「免責」されるために、JAR ファイルに cryptoPerms
アクセス権ポリシーファイルを含める必要があるのと同じ理由です。このようなファイルの作成と組み込みの詳細は、「Java 暗号化アーキテクチャーリファレンスガイド」の「アプリケーションの暗号化制限の「免責」を取得する方法」を参照してください。
役に立つと思われる URL を 2 つ紹介しておきます。
次のステップは、クライアント用のドキュメントを記述することです。少なくとも、次の指定が必要です。
さらに、ドキュメント内で、デフォルトのアルゴリズムパラメータなどの、クライアントに関係するその他の指定も行う必要があります。
メッセージダイジェストおよび MAC アルゴリズムごとに、実装が複製可能かどうかを指定します。これは、技術的には必須ではありませんが、複製による中間メッセージダイジェストまたは MAC が可能かどうかを指定することになるため、クライアントの費やす時間およびコードの記述にかかる手間が軽減されます。MessageDigest
または 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 and i2
i1, i2, and i3
鍵ペアジェネレータアルゴリズムでは、クライアントが (initialize
メソッドの呼び出しを介して) 明示的に鍵ペアジェネレータを初期化しない場合、各プロバイダはデフォルトの初期化を提供およびドキュメント化する必要があります。たとえば、SunJCE プロバイダにより提供される Diffie-Hellman 鍵ペアジェネレータは、1024 ビットのデフォルト素数モジュラスサイズ (keysize
) を使用します。
プロバイダは、その (秘密) 鍵ファクトリがサポートするすべての鍵仕様をドキュメント化する必要があります。
クライアントが AlgorithmParameterGenerator
エンジンクラスの init
メソッドの呼び出しを介してアルゴリズムパラメータジェネレータを明示的に初期化しない場合、各プロバイダはデフォルトの初期化を行い、これをドキュメント化する必要があります。たとえば、SunJCE プロバイダは、Diffie-Hellman パラメータの生成に 1024 ビットのデフォルト素数モジュラスサイズ (keysize
) を使用し、SUN プロバイダは、DSA パラメータの生成に 1024 ビットのデフォルトモジュラス素数サイズを使用します。
署名アルゴリズムを実装する場合、署名 (sign
メソッドの 1 つを使って生成される) をエンコードする形式をドキュメント化する必要があります。たとえば、「SUN」プロバイダにより提供される SHA1withDSA 署名アルゴリズムは、署名を、2 つの整数 r
および s
の標準 ASN.1 SEQUENCE
としてエンコードします。
乱数生成アルゴリズムの場合、生成される数がどのように「ランダム」なのかを示す情報、および乱数ジェネレータの自己シード時のシードの質に関する情報を提供します。同時に、SecureRandom オブジェクト (およびそのカプセル化された SecureRandomSpi 実装オブジェクト) の直列化解除時に、何が発生するかにも留意してください。復元されたオブジェクトの nextBytes
メソッド (カプセル化された SecureRandomSpi オブジェクトの engineNextBytes
メソッドを呼び出す) への続く呼び出しにより、元のオブジェクトが生成するのと正確に同じ (ランダム) バイトが生成される場合、この動作が望ましくないのであれば、setSeed
メソッドを呼び出して復元されたランダムオブジェクトにシードをするよう、ユーザーに通知してください。
プロバイダは、ファクトリが作成可能な証明書の種類 (および必要に応じてそのバージョン番号) をドキュメント化する必要があります。
プロバイダは、キーストアの実装に関するすべての関連情報 (ベースとなるデータ形式など) をドキュメント化する必要があります。
プロバイダソフトウェアの記述、構成、テスト、インストール、およびドキュメント化のあとで、ドキュメントをカスタマから利用可能にします。
各プロバイダは自己整合性チェックを実行して、プロバイダメソッドを JCA を介さずに直接呼び出すなどの操作により、コードを含む JAR ファイルが改変されていないことを保証する必要があります。暗号化サービス (Cipher、KeyAgreement、KeyGenerator、MAC
、または SecretKey
ファクトリ) の実装を提供するプロバイダは、デジタル署名され、「信頼できる」証明書発行局が発行する証明書で署名されている必要があります。現状では、次の 2 種類の証明書発行局が「信頼できる」とされています。
Sun Microsystems の JCA コード署名 CA からコード署名証明書を取得する方法については、ステップ 6.2 を参照してください。
署名済み証明書を上記の証明書発行局から入手したあと、プロバイダパッケージに署名する証明書用のバイトを埋め込む必要があります。たとえば、後述する「個々の署名者の識別と信頼できる署名者の特定」のセクションで解説する、bytesOfProviderCert
配列のような配列です。実行時には、埋め込まれた証明書を使用して、プロバイダコードが認証されたものかどうかが判断されます。
プロバイダが自らの整合性チェックに使用する基本的な方法を、次に示します。
次のセクションでは、具体的な手順を示します。
注: サンプルコード MyJCE.java
は、これらのステップを実装する完全なコード例です。このコードは参照用としてダウンロードできます。前述の概念がどのようにしてサンプルコードに実装されているかについては、「サンプルコードについて」のセクションを参照してください。
重要: JCE 1.2.x (JDK 1.2.x および 1.3.x とともに使用される) のバンドルされていないバージョンでは、プラグインする JCA の整合性および信頼性を保証するため、JCA フレームワークの認証用コードをプロバイダに含める必要がありました。JDK 6 では、これは必要なくなりました。
これにより、JCE フレームワークコードはプロバイダの期待する場所に存在しなくなるため、プロバイダの JCE フレームワーク認証チェックが機能しなくなります。このため、JCE 1.2.2 専用に記述されたプロバイダは、JDK 6 では動作しなくなります。プロバイダが JDK 6 でのみ動作するようにするには、JCE フレームワークを認証するコードをプロバイダに含めないようにしてください。プロバイダを JCE 1.2.2 と JDK 6 の両方で動作させる場合は、条件文を追加します。こうしておけば、プロバイダを JCE 1.2.2 で実行する場合にのみ JCE フレームワークを認証するプロバイダコードが実行されるようになります。次に、サンプルコードを示します。
Class cipherCls = Class.forName("javax.crypto.Cipher"); CodeSource cs = cipherCls.getProtectionDomain().getCodeSource(); if (cs != null) { // Authenticate JCE framework
. . . }
プロバイダの 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 ファイルの 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 ファイルの URL を確認し、JAR ファイルを参照する JarFile
を作成したら、ファイルの検証を行います。
基本的な方法は次のとおりです。
これらのステップで使用するサンプルコードについては、次のセクションを参照してください。
ここでは、クラス 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 ファイルは、改変されています。
// 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 ディレクトリ内に存在しないディレクトリ以外のエントリ) ごとに次の操作を実行します。
ループの設定方法を、次に示します。
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 を特定する。JarVerifier
オブジェクトをインスタンス化する。bytesOfProviderCert
から X509Certificate
オブジェクトを作成する。JarVerifier.verify
メソッドを呼び出し、プロバイダ JAR ファイル内のすべてのエントリに、ステップ 3 でインスタンス化した同じ証明書による署名があることを検証する。注: JarVerifier
クラスは、所定の URL から JAR ファイルを取得し、その JAR ファイルに署名があるか、すべてのエントリに有効な署名があるか、これらのエントリに指定された X509Certificate
による署名があるかどうかを検証します。
場合によっては、JarVerifier.verify
によってセキュリティー例外がスローされます。
verify
とされた証明書が null (無効) である場合。サンプルコード MyJCE.java
は、前述のコードで構成されます。さらに、エラー処理、サンプルコード署名証明書バイト、埋め込まれたサンプルコード署名証明書バイトから X509Certificate
オブジェクトをインスタンス化するコードが含まれています。
AccessController.doPrivileged
の使用については、「特権ブロックのための API」で doPrivileged
の使用に関する情報を参照してください。
多くの暗号化のアルゴリズムおよび型には、「Java 暗号化アーキテクチャーリファレンスガイド」の「付録 A」で定義された公式な「標準名」が 1 つ存在します。
たとえば、「MD5」は、RFC 1321 の RSA DSI で定義された RSA-MD5 メッセージダイジェストアルゴリズムの標準名です。DiffieHellman
は、PKCS3 で定義された Diffie-Hellman 鍵協定アルゴリズムの標準です。
JDK では、アルゴリズムまたは型への参照時に、クライアントが標準名ではなく別名を使用することを可能にするエイリアス化スキームが存在します。たとえば、「SUN」プロバイダのマスタークラス (Sun.java
) は、標準名が「SHA1withDSA」であるアルゴリズムの別名「SHA1/DSA」を定義します。このため、次の文は同じ意味になります。
Signature sig = Signature.getInstance("SHA1withDSA", "SUN"); Signature sig = Signature.getInstance("SHA1/DSA", "SUN");
別名は、「マスタークラス」内で定義できます (ステップ 3 を参照)。別名を定義するには、次の名前のプロパティーを作成します。
Alg.Alias.
engineClassName.aliasName
engineClassName にはエンジンクラス (Signature
など) の名前が、aliasName には設定する別名が当てはまります。プロパティーの値は、別名を設定するアルゴリズム (または型) の標準アルゴリズム (または型) 名でなければなりません。
例として、「SUN」プロバイダが、Alg.Alias.Signature.SHA1/DSA
という名前のプロパティーに値 SHA1withDSA
を設定することにより、標準名が SHA1withDSA である署名アルゴリズムに別名「SHA1/DSA」を定義する場合を考えましょう。次にそのコードを示します。
put("Alg.Alias.Signature.SHA1/DSA", "SHA1withDSA");
あるプロバイダによって定義された別名は、そのプロバイダのみが使用でき、その他のプロバイダは使用できません。したがって、SunJCE プロバイダによって定義された別名は、SunJCE プロバイダのみが使用できます。
アルゴリズムによっては、ほかの種類のアルゴリズムの使用を要求することがあります。たとえば、通常、PBE アルゴリズムは、メッセージダイジェストアルゴリズムを使用して、パスワードを鍵に変換する必要があります。
別のアルゴリズムを要求するアルゴリズムを実装している場合、次のいずれかを実行できます。
MessageDigest.getInstance("MD5", "SUN")
MessageDigest.getInstance("MD5")これは、プロバイダが使用される各 Java プラットフォームにインストールされた、要求されたアルゴリズムの実装 (この例では MD5) が少なくとも 1 つ存在することが確実な場合にだけ有効な方法です。
次に、アルゴリズムの相互依存の一般的な種類を示します。
署名アルゴリズムは、メッセージダイジェストアルゴリズムを必要とすることがあります。たとえば、SHA1withDSA 署名アルゴリズムは、SHA-1 メッセージダイジェストアルゴリズムを必要とします。
署名アルゴリズムは、(擬似) 乱数生成アルゴリズムの使用を必要とすることがあります。たとえば、DSA 署名を生成するためには、対応する乱数生成アルゴリズムが必要です。
鍵のペア生成アルゴリズムは、メッセージダイジェストアルゴリズムの使用を必要とすることがあります。たとえば、DSA 鍵は、SHA-1 メッセージダイジェストアルゴリズムを使って生成されます。
アルゴリズムパラメータジェネレータは、メッセージダイジェストアルゴリズムの使用を必要とすることがあります。たとえば、DSA パラメータは、SHA-1 メッセージダイジェストアルゴリズムを使って生成されます。
キーストア実装は、メッセージダイジェストアルゴリズムを利用して鍵ハッシュ (key
はユーザーが提供するパスワード) を計算し、キーストアの統合性検査、およびキーストアが改変されていないことを確認することがあります。
鍵のペア生成アルゴリズムは、新規アルゴリズムパラメータセットの生成を必要とする場合があります。パラメータは、直接生成するか、アルゴリズムパラメータジェネレータを使用して生成できます。
鍵のペア生成アルゴリズムは、新しい鍵ペアおよび (場合によっては) 鍵に関連付けられた新規パラメータセットの生成に、乱数の発生源を必要とする場合があります。乱数の発生源は、SecureRandom
オブジェクトにより表されます。鍵ペア生成アルゴリズムの実装は、鍵パラメータ自体を生成する場合もあれば、アルゴリズムパラメータジェネレータを使って鍵パラメータを生成する場合もあります。これらの場合、乱数の発生源を使ってアルゴリズムパラメータジェネレータを初期化する場合もあれば、そうでない場合もあります。
アルゴリズムパラメータジェネレータの engineGenerateParameters
メソッドは、AlgorithmParameters
インスタンスを返す必要があります。
署名アルゴリズムを実装している場合、実装の engineInitSign
メソッドおよび engineInitVerify
メソッドは、ベースとなるアルゴリズム (DSS アルゴリズム用の DSA 鍵など) に対して有効な、引き渡しの行われる鍵を必要とします。次のいずれかを実行できます。
java.security.interfaces
パッケージから DSAPrivateKey
および DSAPublicKey
インタフェースを実装するクラスなど) も作成し、独自の鍵ペアのジェネレータとこれらの型の鍵を返す鍵ファクトリのどちらかまたは両方を作成します。engineInitSign
および engineInitVerify
に渡される鍵が、実装した鍵 (つまり、鍵ペアジェネレータまたは鍵ファクトリから生成された鍵) と同じ型である必要があります。または、次の方法も可能です。engineInitSign
メソッドは、java.security.interfaces.DSAPrivateKey
のインスタンスである任意の非公開鍵を受け取ることができます。キーストアの実装は、鍵ファクトリを利用してキーストアに格納された鍵の構文解析を行うことがあります。また、証明書ファクトリを利用してキーストアに格納された証明書の構文解析を行います。
クライアントが明示的に鍵ペアジェネレータまたはアルゴリズムパラメータジェネレータを初期化しない場合、これらサービスの各プロバイダはデフォルトの初期化を提供 (およびドキュメント化) する必要があります。たとえば、Sun プロバイダは、DSA パラメータの生成に 1024 ビットのデフォルトモジュラスサイズ (強度) を使用し、「SunJCE」プロバイダは、Diffie-Hellman パラメータの生成に 1024 ビットのデフォルトモジュラスサイズ (キーサイズ) を使用します。
鍵ペアジェネレータを実装する場合、クライアントがパラメータを指定しない場合は、実装がデフォルトのパラメータを提供する必要があります。提供するドキュメント (ステップ 11) で、デフォルトパラメータを指定する必要があります。
たとえば、SUN プロバイダの DSA 鍵ペアジェネレータは、512、768、および 1024 ビットの鍵ペア生成用に、計算済みの p
、q
、および g
デフォルト値のセットを提供します。次の p
、q
、および g
値は、1024 ビット DSA 鍵ペア生成用のデフォルト値として使用されます。
p = fd7f5381 1d751229 52df4a9c 2eece4e7 f611b752 3cef4400 c31e3f80 b6512669 455d4022 51fb593d 8d58fabf c5f5ba30 f6cb9b55 6cd7813b 801d346f f26660b7 6b9950a5 a49f9fe8 047b1022 c24fbba9 d7feb7c6 1bf83b57 e7c6a8a6 150f04fb 83f6d3c5 1ec30235 54135a16 9132f675 f3ae2b61 d72aeff2 2203199d d14801c7 q = 9760508f 15230bcc b292b982 a2eb840b f0581cf5 g = f7e1a085 d69b3dde cbbcab5c 36b857b9 7994afbb fa3aea82 f9574c0b 3d078267 5159578e bad4594f e6710710 8180b449 167123e8 4c281613 b7cf0932 8cc8a6e1 3c167a8b 547c8d28 e0a3ae1e 2bb3a675 916ea37f 0bfa2135 62f1fb62 7a01243b cca4f1be a8519089 a883dfe1 5ae59f06 928b665e 807b5525 64014c3b fecf492a
(ここで指定された p
および q
値は、素数生成標準により、次の 160 ビットのシードを使って生成されます。
SEED: 8d515589 4229d5e6 89ee01e6 018a237e 2cae64cd
このシードでは、カウンタが 92 の時に p
および q
を検出しました。)
Provider.Service
クラス導入されて以来、セキュリティープロバイダは Hashtable エントリに入力された適切なフォーマットの鍵と値の String ペアを使用して、サービス情報を公開してきました。このメカニズムはシンプルで簡便ですが、カスタマイズの範囲がかぎられています。そのため、JDK 5.0 では、2 番目のオプションとして、Provider.Service
クラスが導入されました。これを利用して、プロバイダはサービスおよびサポートに、次で説明するような追加機能を通知できます。この追加機能は、String 値の HashTable エントリを使用する以前の方法と完全な互換性があることに留意してください。JDK 5.0 では、プロバイダはどちらの方法も選択でき、また同時に両方を使用することもできます。
Provider.Service
オブジェクトは、サービスに関するすべての情報をカプセル化します。このプロバイダは、サービス、型 (MessageDigest
、Signature
など)、アルゴリズム名、およびサービスを実装するクラス名を提供します。また、このサービス (別名) および属性に対する代替アルゴリズム名の一覧を持っています。この一覧は、名前と値の String ペアのマップです。さらに、newInstance()
および supportsParameter()
メソッドを定義します。これらのメソッドはデフォルトで実装されていますが、プロバイダがハードウェアセキュリティートークンとのインタフェースとなる場合は、必要に応じてプロバイダによるオーバーライドが可能です。
newInstance()
メソッドは、新しい実装インスタンスを生成する必要がある場合に、セキュリティーフレームワークによって使用されます。デフォルトの実装では、リフレクションを使用してサービス各種の標準的なコンストラクタが呼び出されます。CertStore
を除くすべての標準サービスで、このコンストラクタは引数をとりません。newInstance()
の constructorParameter は、この場合 null である必要があります。CertStore
型のサービスでは、CertStoreParameters
オブジェクトを使用するコンストラクタが呼び出されます。constructorParameter は、CertStoreParameters.
の null 以外のインスタンスである必要があります。セキュリティープロバイダは、newInstance()
メソッドをオーバーライドして、その実装に適したインスタンス化を実装できます。直接呼び出すことも、Provider インスタンスまたはトークンに固有の追加情報を渡すコンストラクタを呼び出すこともできます。たとえば、システムに複数のスマートカードリーダがある場合、新しく作成されたサービスをどのリーダーに関連付けるかという情報を渡すことができます。ただし、カスタマイズした場合でも、すべての実装は、前述の constructorParameter に関する規約に従わなければなりません。
supportsParameter()
は、Service が指定されたパラメータを使用できるかどうかをテストします。このサービスがパラメータを使用できない場合、false を返します。このサービスがパラメータを使用できる場合、すばやいチェックが実行できない場合、またはステータスが不明な場合、true を返します。これは、ある種のサービスに対してセキュリティーフレームワークにより使用され、一致しない実装が対象からすばやく除外されます。現状では、これは Signature
、Cipher
、Mac
、および KeyAgreement
の標準サービスでのみ定義されています。この場合、parameter は Key のインスタンスである必要があります。たとえば、Signature
サービスの場合、フレームワークはサービスをインスタンス化する前に、サービスが指定された Key を使用できるかどうかをテストします。デフォルトの実装では、前述のように、属性 SupportedKeyFormats
および SupportedKeyClasses
が検査されます。ここでも、プロバイダはこのメソッドをオーバーライドして、追加テストを実装できます。
SupportedKeyFormats
属性は、エンコードされた鍵 (key.getFormat() によって返される) でサポートされる形式の一覧で、「|」(パイプ) 文字で区切られています。たとえば、X.509|PKCS#8
です。SupportedKeyClasses
属性は、インタフェースまたはクラス名の一覧で、「|」文字で区切られています。鍵オブジェクトは、指定されたクラスまたはインタフェースの 1 つ以上に割り当て可能な場合に、受け入れ可能と認識されます。言い換えれば、鍵オブジェクトのクラスがリスト表示されたいずれかのクラスのサブクラス (またはクラス自体) である場合、またはリスト表示されたインタフェースを実装する場合です。たとえば、値 "java.security.interfaces.RSAPrivateKey|java.security.interfaces.RSAPublicKey"
がこれに該当します。
サービスの追加および検索用の 4 つのメソッドが Provider クラスに追加されました。前述のように、これらのメソッドおよび既存の Properties メソッドの実装は、既存の Provider サブクラスとの互換性を保つように特別に設計されています。次のようにして実現されます。
既存の Properties メソッドをエントリの追加に使用する場合、Provider クラスは、プロパティー文字列を解析して等価な Service オブジェクトに変換してから、getService() を使用して検索するようにします。同様に、putService() メソッドを使用する場合、等価なプロパティー文字列がプロバイダのハッシュテーブルに同時に配置されます。プロバイダ実装が Provider クラス内のメソッドをオーバーライドする場合、実装がこの変換に干渉しないようにする必要があります。問題を防止するため、実装によって Provider
クラスのメソッドがオーバーライドされないようにすることをお勧めします。
署名アルゴリズムを実装する場合、提供するドキュメント (ステップ 11) で署名 (sign
メソッドの 1 つを使って生成される) をエンコードする形式を指定する必要があります。
たとえば、SUN プロバイダにより提供される SHA1withDSA 署名アルゴリズムは、署名を 2 つの ASN.1 INTEGER
値、r
および s
をこの順序で、標準 ASN.1 シーケンスとしてエンコードします。
SEQUENCE ::= { r INTEGER, s INTEGER }
Java Security API には、DSA サービスを実装するプログラマが利用しやすいように、(java.security.interfaces
パッケージ内の) 次のインタフェースが含まれます。
以降のセクションでは、これらのインタフェースの実装要件について取り上げます。
DSAKeyPairGenerator
実装このインタフェースは使用されていません。これは、クライアントに対し、実装で提供するデフォルトパラメータの代わりに DSA 固有のパラメータを使用することを可能にする上で必要でした。ただし、AlgorithmParameterSpec
パラメータを取る新規 KeyPairGenerator
initialize
メソッドにより、クライアントがアルゴリズム固有のパラメータを示すことが可能になったため、Java ではこれは必要ではなくなりました。
DSAParams
実装DSA 鍵ペアジェネレータを実装している場合、p
、q
、および g
パラメータを保持したり返したりするために、DSAParams
を実装するクラスを必要とします。
DSAPrivateKey
および DSAPublicKey
インタフェースを実装する場合は、DSAParams
実装も必要です。DSAPublicKey
および DSAPrivateKey
は、どちらも DSAParams
オブジェクトを返す getParams
メソッドを含む DSAKey インタフェースを拡張します。詳細は、「DSAPrivateKey および DSAPublicKey 実装」を参照してください。
注: JDK に組み込み済みの DSAParams
実装である java.security.spec.DSAParameterSpec
クラスが存在します。
DSAPrivateKey
および DSAPublicKey
実装DSA 鍵ペアジェネレータまたは鍵ファクトリを実装する場合、DSAPrivateKey
および DSAPublicKey
インタフェースを実装するクラスを作成する必要があります。
DSA 鍵ペアジェネレータを実装する場合、(KeyPairGeneratorSpi
サブクラスの) generateKeyPair
メソッドはこれらのインタフェース実装のインスタンスを返します。
DSA 鍵ファクトリを実装する場合、(KeyFactorySpi
サブクラスの) engineGeneratePrivate
メソッドは DSAPrivateKey
実装のインスタンスを返し、engineGeneratePublic
メソッドは DSAPublicKey
実装のインスタンスを返します。
また、engineGetKeySpec
および engineTranslateKey
メソッドは、引き渡される鍵が DSAPrivateKey
または DSAPublicKey
実装のインスタンスであることを求めます。インタフェース実装により提供される getParams
メソッドは、鍵からパラメータを取得および抽出し、そのあとパラメータを使用する上で有用です。たとえば、DSAParameterSpec
コンストラクタへのパラメータとして使用して、DSA 用の KeyPairGenerator
オブジェクトの初期化に使用可能なパラメータ値からパラメータ仕様を作成できます。
DSA 署名アルゴリズムを実装する場合、(SignatureSpi
サブクラスの) engineInitSign
メソッドは DSAPrivateKey
が渡されることを期待し、engineInitVerify
メソッドは DSAPublicKey
が渡されることを期待します。
注: DSAPublicKey
および DSAPrivateKey
インタフェースはそれぞれ、DSA 公開鍵および非公開鍵に対するきわめて汎用的なプロバイダ非依存のインタフェースを定義します。KeyFactorySpi
サブクラスの engineGetKeySpec
メソッドと engineTranslateKey
メソッドは、プロバイダ固有の実装の詳細を利用するなどの目的で、引き渡される鍵が実際にプロバイダ独自の DSAPrivateKey
または DSAPublicKey
実装のインスタンスであるかどうかをチェックすることもできます。SignatureSpi
サブクラスの DSA 署名アルゴリズム engineInitSign
および engineInitVerify
メソッドについても、同様のことが当てはまります。
DSAPublicKey
および DSAPrivateKey
インタフェースを実装するクラスを使用してどのようなメソッドを実装する必要があるかについては、次のインタフェース署名に注目してください。
java.security.interfaces
パッケージ内:
public interface DSAPrivateKey extends DSAKey, java.security.PrivateKey public interface DSAPublicKey extends DSAKey, java.security.PublicKey public interface DSAKey
java.security
パッケージ内:
public interface PrivateKey extends Key public interface PublicKey extends Key public interface Key extends java.io.Serializable
DSAPrivateKey
インタフェースと DSAPublicKey
インタフェースを実装するには、これらによって定義されるメソッドと、直接または間接的にこれらによって拡張されるインタフェースによって定義されたメソッドを実装する必要があります。
このため、非公開鍵の場合、次を実装するクラスを提供する必要があります
DSAPrivateKey
インタフェースの getX
メソッド。java.security.interfaces.DSAKey
インタフェースの getParams
メソッド (DSAPrivateKey
が DSAKey
を拡張するため)。注:getParams
メソッドは、DSAParams
オブジェクトを返します。このため、DSAParams
実装も保持する必要があります。java.security.Key
インタフェースの getAlgorithm
、getEncoded
、および getFormat
メソッド (DSAPrivateKey
が java.security.PrivateKey
を拡張し、PrivateKey
が Key
を拡張するため)。
同様に、公開 DSA 鍵の場合、次のものを実装するクラスを提供する必要があります。
getY
メソッド。java.security.interfaces.DSAKey
インタフェースの getParams
メソッド (DSAPublicKey
が DSAKey を拡張するため)。注:getParams
メソッドは、DSAParams
オブジェクトを返します。このため、DSAParams
実装も保持する必要があります。java.security.Key
インタフェースの getAlgorithm
、getEncoded
、および getFormat
メソッド (DSAPublicKey
が java.security.PublicKey
を拡張し、PublicKey
が Key
を拡張するため)。Java Security API には、RSA サービスを実装するプログラマが利用しやすいように、(java.security.interfaces
パッケージ内の) 次のインタフェースが含まれます。
以降のセクションでは、これらのインタフェースの実装要件について取り上げます。
RSAPrivateKey
、 RSAPrivateCrtKey
、および RSAPublicKey
実装RSA 鍵ペアジェネレータまたは鍵ファクトリを実装する場合、RSAPrivateKey
(と RSAPrivateCrtKey
のどちらかまたは両方) および RSAPublicKey
インタフェースを実装するクラスを作成する必要があります。(RSAPrivateCrtKey
は、中国剰余定理 (CRT) 表現を使用した、RSA 非公開鍵へのインタフェースです。
RSA 鍵ペアジェネレータを実装する場合、(KeyPairGeneratorSpi
サブクラスの) generateKeyPair
メソッドはこれらのインタフェース実装のインスタンスを返します。
RSA 鍵ファクトリを実装する場合、(KeyFactorySpi
サブクラスの) engineGeneratePrivate
メソッドは RSAPrivateKey
(または RSAPrivateCrtKey
) 実装のインスタンスを返し、engineGeneratePublic
メソッドは RSAPublicKey
実装のインスタンスを返します。
また、engineGetKeySpec
および engineTranslateKey
メソッドは、引き渡される鍵が RSAPrivateKey
、RSAPrivateCrtKey
、または RSAPublicKey
実装のインスタンスであることを求めます。
RSA 署名アルゴリズムを実装する場合、(SignatureSpi
サブクラスの) engineInitSign
メソッドは RSAPrivateKey
または RSAPrivateCrtKey
が渡されることを期待し、engineInitVerify
メソッドは RSAPublicKey
が渡されることを期待します。
注: RSAPublicKey
、RSAPrivateKey
、および RSAPrivateCrtKey
インタフェースは、RSA 公開鍵および非公開鍵に対するきわめて汎用的なプロバイダ非依存のインタフェースを定義します。KeyFactorySpi
サブクラスの engineGetKeySpec
メソッドと engineTranslateKey
メソッドは、プロバイダ固有の実装の詳細を利用するなどの目的で、引き渡される鍵が実際にプロバイダ独自の RSAPrivateKey
、RSAPrivateCrtKey
、または RSAPublicKey
実装のインスタンスであるかどうかをチェックすることもできます。SignatureSpi
サブクラスの RSA 署名アルゴリズム engineInitSign
および engineInitVerify
メソッドについても、同様のことが当てはまります。
RSAPublicKey
、RSAPrivateKey
、および RSAPrivateCrtKey
インタフェースを実装するクラスを使用してどのようなメソッドを実装する必要があるかについては、次のインタフェース署名に注目してください。
java.security.interfaces
パッケージ内:
public interface RSAPrivateKey extends java.security.PrivateKey public interface RSAPrivateCrtKey extends RSAPrivateKey public interface RSAPublicKey extends java.security.PublicKey
java.security
パッケージ内:
public interface PrivateKey extends Key public interface PublicKey extends Key public interface Key extends java.io.Serializable
RSAPrivateKey
、RSAPrivateCrtKey
、および RSAPublicKey
インタフェースを実装するには、これらによって定義されるメソッドと、直接または間接的にこれらによって拡張されるインタフェースによって定義されたメソッドを実装する必要があります。
このため、RSA 非公開鍵の場合、次のものを実装するクラスを提供する必要があります。
RSAPrivateKey
インタフェースの getModulus
および getPrivateExponent
メソッド。getAlgorithm
、getEncoded
、および getFormat
メソッド (RSAPrivateKey
が java.security.PrivateKey
を拡張し、PrivateKey
が Key
を拡張するため)。同様に、中国剰余定理 (CRT) 表現を使用する RSA 非公開鍵の場合、次のものを実装するクラスを提供する必要があります。
RSAPrivateCrtKey
が java.security.interfaces.RSAPrivateKey
を拡張するためです。 RSAPrivateKey
インタフェースの getPublicExponent
、getPrimeP
、getPrimeQ
、getPrimeExponentP
、getPrimeExponentQ
、および getCrtCoefficient
メソッド。公開 RSA 鍵の場合、次のものを実装するクラスを提供する必要があります。
RSAPublicKey
インタフェースの getModulus
および getPublicExponent
メソッド。getAlgorithm
、getEncoded
、および getFormat
メソッド (RSAPublicKey
が java.security.PublicKey
を拡張し、PublicKey
が Key
を拡張するため)。JCA には、よく使用される暗号化および鍵協定アルゴリズムパラメータの AlgorithmParameterSpec
実装が多数含まれています。JCA から提供されない、種類の異なるアルゴリズムに対応したアルゴリズムパラメータを操作する場合は、その種類に適した独自の AlgorithmParameterSpec
実装を提供する必要があります。
Diffie-Hellman サービスを実装するプログラマのために、JCA には次のインタフェースが (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.Serializable
DHPrivateKey
インタフェースと DHPublicKey
インタフェースを実装するには、これらによって定義されるメソッドと、直接または間接的にこれらによって拡張されるインタフェースによって定義されたメソッドを実装する必要があります。
このため、非公開鍵の場合、次を実装するクラスを提供する必要があります。
DHPrivateKey
インタフェースの getX
メソッド。getParams
メソッド (DHPrivateKey
が DHKey
を拡張するため)。getAlgorithm
、getEncoded
、および getFormat
メソッド (DHPrivateKey
が java.security.PrivateKey
を拡張し、PrivateKey
が Key
を拡張するため)。同様に、公開 Diffie-Hellman 鍵の場合、次を実装するクラスを提供する必要があります。
DHPublicKey
インタフェースの getY
メソッド。javax.crypto.interfaces.DHKey
インタフェースの getParams
メソッド (DHPublicKey
が DHKey
を拡張するため)。getAlgorithm
、getEncoded
、および getFormat
メソッド (DHPublicKey
が java.security.PublicKey
を拡張し、PublicKey
が Key
を拡張するため)。これまでに説明したとおり、Java Security API には、DSA、RSA、ECC などのサービスを実装するプログラマの利用に便利なインタフェースが含まれます。API サポートがないサービスがある場合、独自の API を定義する必要があります。
異なるアルゴリズム用の鍵ペアジェネレータを実装する場合、実装が提供するデフォルトパラメータではなく、アルゴリズム固有のパラメータをクライアントが提供して使用する場合にクライアントが呼び出すことのできる 1 つ以上の initialize
メソッドを使ってインタフェースを作成する必要があります。KeyPairGeneratorSpi
のサブクラスは、このインタフェースを実装する必要があります。
直接の API サポートがないアルゴリズムの場合は、同様のインタフェースを作成して、実装クラスを提供することをお勧めします。公開鍵のインタフェースは、PublicKey
インタフェースを拡張する必要があります。同様に、非公開鍵のインタフェースは、PrivateKey
インタフェースを拡張する必要があります。
アルゴリズムパラメータの仕様は、アルゴリズムとともに使われるパラメータのセットの透明な表現です。
パラメータの「透明な」表現とは、対応する仕様クラスに定義された get メソッドの 1 つを使用して、各値に個々にアクセスできるということです。たとえば、DSAParameterSpec
は、getP
、getQ
、getG
メソッドを定義して、パラメータ p、q、g にアクセスします。
これと対照的なのが、AlgorithmParameters エンジンクラスによって提供される場合のような「不透明な」表現です。この場合は、鍵データ値に直接アクセスすることはできません。パラメータセットに関連付けられたアルゴリズム名の取得 (getAlgorithm
による)、およびそのパラメータセット用のある種のエンコードの取得 (getEncoded
による) しかできません。
AlgorithmParametersSpi
、AlgorithmParameterGeneratorSpi
、KeyPairGeneratorSpi
のいずれかの実装を提供する場合、AlgorithmParameterSpec
インタフェースを利用する必要があります。理由は、これらの各クラスに、AlgorithmParameterSpec
パラメータを取るメソッドが含まれるからです。この種のメソッドは、インタフェースのどの実装が実際に引き渡されるかを判定し、それに応じて動作する必要があります。
JCA には、よく使用される署名、暗号化、および鍵協定アルゴリズムパラメータの AlgorithmParameterSpec
実装が多数含まれています。JCA から提供されない、種類の異なるアルゴリズムに対応したアルゴリズムパラメータを操作する場合は、その種類に適した独自の AlgorithmParameterSpec
実装を提供する必要があります。
Java は、次のアルゴリズムパラメータ仕様インタフェースおよびクラスを、java.security.spec
および javax.crypto.spec
パッケージ内で定義します。
AlgorithmParameterSpec
インタフェースAlgorithmParameterSpec
は、暗号化パラメータの透明な仕様へのインタフェースです。
このインタフェースには、メソッドまたは定数が含まれていません。このインタフェースの唯一の目的は、すべてのパラメータの仕様をグループ化すること (およびそれらのパラメータに安全な型を提供すること) です。すべてのパラメータの仕様で、このインタフェースを実装する必要があります。
DSAParameterSpec
クラスAlgorithmParameterSpec
および DSAParams
インタフェースを実装するこのクラスは、DSA アルゴリズムで使用されるパラメータのセットを指定します。このクラスには、次のメソッドがあります。
public BigInteger getP() public BigInteger getQ() public BigInteger getG()
これらのメソッドは、DSA アルゴリズムパラメータである素数の p
、サブ素数の q
、およびベースの g
を返します。
多くの DSA サービスの型は、このクラスを有用とみなします。たとえば、このクラスは、SUN プロバイダが実装する DSA 署名、鍵ペアジェネレータ、アルゴリズムパラメータジェネレータ、およびアルゴリズムパラメータクラスにより利用されます。具体例を挙げると、アルゴリズムパラメータ実装は、AlgorithmParameterSpec
を返す getParameterSpec
メソッド用の実装を含む必要があります。SUN により提供される DSA アルゴリズムパラメータ実装は、DSAParameterSpec
クラスのインスタンスを返します。
IvParameterSpec
クラスこのクラス (AlgorithmParameterSpec
インタフェースを実装) は、フィードバックモードでの暗号化に使用される初期化ベクトル (IV) を指定します。
メソッド | 説明 |
---|---|
byte[] getIV() |
初期化ベクトル (IV) を返します。 |
OAEPParameterSpec
クラスこのクラスは、PKCS #1 標準で定義されている、OAEP パディングで使用されるパラメータのセットを指定します。
メソッド | 説明 |
---|---|
String getDigestAlgorithm() |
メッセージダイジェストのアルゴリズムの名前を返します。 |
String getMGFAlgorithm() |
マスク生成関数のアルゴリズムの名前を返します。 |
AlgorithmParameterSpec getMGFParameters() |
マスク生成関数のパラメータを返します。 |
PSource getPSource() |
エンコーディング入力 P のソースを返します。 |
PBEParameterSpec
クラスこのクラス (AlgorithmParameterSpec
インタフェースを実装) は、パスワードベースの暗号化 (PBE) アルゴリズムで使用されるパラメータのセットを指定します。
メソッド | 説明 |
---|---|
int getIterationCount() |
繰り返し処理の回数を返します。 |
byte[] getSalt() |
salt を返します。 |
RC2ParameterSpec
クラスこのクラス (AlgorithmParameterSpec
インタフェースを実装) は、RC2 アルゴリズムで使われるパラメータのセットを指定します。
メソッド | 説明 |
---|---|
boolean equals(Object obj) |
指定されたオブジェクトとこのオブジェクトが等価であるかどうかをテストします。 |
int getEffectiveKeyBits() |
有効なキーサイズをビット単位で返します。 |
byte[] getIV() |
IV を返します。このパラメータセットに IV が含まれない場合は null を返します。 |
int hashCode() |
オブジェクトのハッシュコード値を計算します。 |
RC5ParameterSpec
クラスこのクラス (AlgorithmParameterSpec
インタフェースを実装) は、RC5 アルゴリズムで使われるパラメータのセットを指定します。
メソッド | 説明 |
---|---|
boolean equals(Object obj) |
指定されたオブジェクトとこのオブジェクトが等価であるかどうかをテストします。 |
byte[] getIV() |
IV を返します。このパラメータセットに IV が含まれない場合は null を返します。 |
int getRounds() |
ラウンド回数を返します。 |
int getVersion() |
バージョンを返します。 |
int getWordSize() |
ワードサイズをビット単位で返します。 |
int hashCode() |
オブジェクトのハッシュコード値を計算します。 |
DHParameterSpec
クラスこのクラス (AlgorithmParameterSpec
インタフェースを実装) は、Diffie-Hellman アルゴリズムで使われるパラメータのセットを指定します。
メソッド | 説明 |
---|---|
BigInteger getG() |
ベースジェネレータ g を返します。 |
int getL() |
ランダム指数 (非公開値) のビット単位のサイズ l を返します。 |
BigInteger getP() |
素数モジュラス p を返します。 |
このクラスは、多くの Diffie-Hellman サービス型にとって有用です。たとえば、このクラスは、「SunJCE」プロバイダが実装する Diffie-Hellman 鍵協定、鍵ペアジェネレータ、アルゴリズムパラメータジェネレータ、およびアルゴリズムパラメータクラスにより利用されます。具体例を挙げると、アルゴリズムパラメータ実装は、AlgorithmParameterSpec
を返す getParameterSpec
メソッド用の実装を含む必要があります。「SunJCE」により提供される Diffie-Hellman アルゴリズムパラメータ実装は、DHParameterSpec
クラスのインスタンスを返します。
鍵ファクトリは、不透明な鍵 (Key
型) と鍵仕様との間の双方向変換を提供します。このため、鍵ファクトリを実装する場合には、鍵仕様を理解して利用することが必要になります。場合によっては、独自の鍵仕様を実装する必要もあります。
鍵仕様、Java で提供されるインタフェースとクラス、および仕様に関する鍵ファクトリの要件についての詳細は、後述します。
鍵仕様は、鍵を構成する鍵データの透明な表現です。鍵がハードウェアデバイス上に格納されている場合は、その鍵仕様には、デバイス上の鍵の識別を助ける情報が含まれていることがあります。
鍵の「透明な」表現とは、対応する仕様クラスで定義された get メソッドの 1 つを使って、各鍵データ値に個々にアクセスできるということです。たとえば、java.security.spec.
DSAPrivateKeySpec は、getX
、getP
、getQ
、および getG
メソッドを定義し、非公開鍵 x
および鍵の計算に使用する DSA アルゴリズムのパラメータ (素数の p
、サブ素数の q
、およびベースの g
) にアクセスします。
これと対照的なのが、Key インタフェースによって定義されるような、不透明な表現です。「不透明な」表現では、パラメータフィールドに直接アクセスできません。つまり、「不透明」さにより、鍵へのアクセスが、Key インタフェースによって定義されるgetAlgorithm
、getFormat
、および getEncoded
。
鍵は、アルゴリズムに固有の方法か、またはアルゴリズムに依存しない符号化形式 (ASN.1 など) で指定できます。たとえば、DSA 非公開鍵は、非公開鍵のコンポーネント x
、p
、q
、および g
によって指定するか (DSAPrivateKeySpec
を参照)、または、非公開鍵の DER エンコーディングを使って指定することが可能です (PKCS8EncodedKeySpec
を参照)。
Java は、次の鍵仕様インタフェースおよびクラスを、java.security.spec
および javax.crypto.spec
パッケージ内で定義します。
KeySpec
インタフェースこのインタフェースには、メソッドまたは定数が含まれていません。このインタフェースの唯一の目的は、すべての鍵仕様をグループ化すること (およびそれらのグループに安全な型を提供すること) です。すべての鍵仕様で、このインタフェースを実装する必要があります。
Java は、KeySpec
インタフェースである DSAPrivateKeySpec
、DSAPublicKeySpec
、RSAPrivateKeySpec
、RSAPublicKeySpec
、EncodedKeySpec
、PKCS8EncodedKeySpec
、および X509EncodedKeySpec
を実装するいくつかのクラスを提供します。
JDK が対応する KeySpec
クラスを提供していない鍵型 (Your_PublicKey_type
および Your_PrivateKey_type
など) をプロバイダが使用する場合、2 とおりの対処方法が考えられます。1 つは、独自の鍵仕様を実装する方法です。
KeySpec
クラスを提供する必要はありません。KeyPairGenerator
を使用して Your_PublicKey_type
および Your_PrivateKey_type
鍵を作成します。あとで使用するために生成された鍵を格納する場合には、(Key
インタフェースの getEncoded
メソッドを使用して) 鍵のエンコードを取得します。エンコードから Your_PublicKey_type
または Your_PrivateKey_type
鍵を作成する場合 (署名または検証目的で Signature オブジェクトを初期化する場合など) は、エンコードから X509EncodedKeySpec
または PKCS8EncodedKeySpec
のインスタンスを作成して、プロバイダが提供する適切な KeyFactory
に渡します。KeyFactory の generatePublic
および generatePrivate
メソッドは、要求された PublicKey
(Your_PublicKey_type
のインスタンス) または PrivateKey
(Your_PrivateKey_type
のインスタンス) オブジェクトをそれぞれ返します。KeySpec
クラス (KeySpec
インタフェースを実装するクラス) を指定して、自分の鍵型用の鍵データフィールドおよび関連するパラメータ値を返すようにする必要があります。これらのクラスは、JDK 6 で提供される DSAPrivateKeySpec
および DSAPublicKeySpec
クラスが行うのと同様の方法で指定します。これらのクラスは、プロバイダクラスとともに (たとえば、プロバイダ JAR ファイルの一部として) 提供する必要があります。DSAPrivateKeySpec
クラスこのクラス (KeySpec
インタフェースを実装) は、関連付けられたパラメータを使って DSA 非公開鍵を指定します。このクラスには、次のメソッドがあります。
DSAPrivateKeySpec のメソッド |
説明 |
---|---|
public BigInteger getX() |
非公開鍵 x を返します。 |
public BigInteger getP() |
素数 p を返します。 |
public BigInteger getQ() |
サブ素数 q を返します。 |
public BigInteger getG() |
ベース g を返します。 |
これらのメソッドは、非公開鍵 x
、および鍵の計算に使用される DSA アルゴリズムパラメータである素数の p
、サブ素数の q
、およびベースの g
を返します。
このクラス (KeySpec
インタフェースを実装) は、関連付けられたパラメータを使って DSA 公開鍵を指定します。このクラスには、次のメソッドがあります。
DSAPublicKeySpec のメソッド |
説明 |
---|---|
public BigInteger getY() |
公開鍵 y を返します。 |
public BigInteger getP() |
素数 p を返します。 |
public BigInteger getQ() |
サブ素数 q を返します。 |
public BigInteger getG() |
ベース g を返します。 |
これらのメソッドは、公開鍵 y
、および鍵の計算に使用される DSA アルゴリズムパラメータである素数の p
、サブ素数の q
、およびベースの g
を返します。
このクラス (KeySpec
インタフェースを実装) は、RSA 非公開鍵を指定します。このクラスには、次のメソッドがあります。
RSAPrivateKeySpec のメソッド |
説明 |
---|---|
public BigInteger getModulus() |
モジュラスを返します。 |
public BigInteger getPrivateExponent() |
非公開指数を返します。 |
これらのメソッドは、RSA 非公開鍵を構成する RSA モジュラス n
および非公開指数 d
の値を返します。
このクラス (RSAPrivateKeySpec
クラスを拡張) は、PKCS#1 標準で定義されているように、中国剰余定理 (CRT) 情報の値を使って、RSA 非公開鍵を指定します。このクラスには、スーパークラスの RSAPrivateKeySpec
から継承したメソッドのほかに、次のメソッドがあります。
RSAPrivateCrtKeySpec のメソッド |
説明 |
---|---|
public BigInteger getPublicExponent() |
公開指数を返します。 |
public BigInteger getPrimeP() |
素数 P を返します。 |
public BigInteger getPrimeQ() |
素数 Q を返します。 |
public BigInteger getPrimeExponentP() |
primeExponentP を返します。 |
public BigInteger getPrimeExponentQ() |
primeExponentQ を返します。 |
public BigInteger getCrtCoefficient() |
crtCoefficient を返します。 |
これらのメソッドは、公開指数 e
および CRT 情報の整数 (モジュラス n
の素数因数 p
、n
の素数因数 q
、指数 d mod (p-1)
、指数 d mod (q-1)
、および中国剰余定理係数 (inverse of q) mod p
) を返します。
RSA 非公開鍵は、論理的にはモジュラスと非公開の指数だけで構成されます。CRT 値は、効率を向上させる目的で存在します。
このクラス (KeySpec
インタフェースを実装) は、RSA 公開鍵を指定します。このクラスには、次のメソッドがあります。
RSAPublicKeySpec のメソッド |
説明 |
---|---|
public BigInteger getModulus() |
モジュラスを返します。 |
public BigInteger getPublicExponent() |
公開指数を返します。 |
これらのメソッドは、RSA 公開鍵を構成する RSA モジュラス n
および公開指数 e
の値を返します。
この抽象クラス (KeySpec
インタフェースを実装する) は、エンコードされた形式の公開鍵または非公開鍵を表します。
EncodedKeySpec のメソッド |
説明 |
---|---|
public abstract byte[] getEncoded() |
エンコードされた鍵を返します。 |
public abstract String getFormat() |
エンコード形式の名前を返します。 |
JDK 6 は、EncodedKeySpec
インタフェースである PKCS8EncodedKeySpec および X509EncodedKeySpec を実装する 2 つのクラスを提供します。必要に応じて、これらの、またはほかの型の鍵エンコーディング用に独自の EncodedKeySpec
実装を提供することもできます。
PKCS8EncodedKeySpec
クラスこのクラスは、EncodedKeySpec
のサブクラスで、PKCS #8 標準で指定された形式に従って、非公開鍵の DER エンコードを表現します。
このクラスの getEncoded
メソッドは、PKCS #8 標準に従ってエンコードされた鍵のバイトを返します。その getFormat
メソッドは、文字列「PKCS#8」を返します。
このクラスは、EncodedKeySpec
のサブクラスで、X.509 標準で指定された形式に従って、公開鍵または非公開鍵の DER エンコードを表現します。
その getEncoded
メソッドは、X.509 標準に従ってエンコードされた鍵のバイトを返します。その getFormat
メソッドは、文字列「X.509」を返します。 DHPrivateKeySpec
、DHPublicKeySpec
、DESKeySpec
、DESedeKeySpec
、PBEKeySpec
、および SecretKeySpec
。
DHPrivateKeySpec
クラスこのクラス (KeySpec
インタフェースを実装) は、関連付けられたパラメータを使って Diffie-Hellman 非公開鍵を指定します。
DHPrivateKeySpec のメソッド |
説明 |
---|---|
BigInteger getG() |
ベースジェネレータ g を返します。 |
BigInteger getP() |
素数モジュラス p を返します。 |
BigInteger getX() |
非公開値 x を返します。 |
DHPublicKeySpec
クラスこのクラス (KeySpec
インタフェースを実装) は、関連付けられたパラメータを使って Diffie-Hellman 公開鍵を指定します。
DHPublicKeySpec のメソッド |
説明 |
---|---|
BigInteger getG() |
ベースジェネレータ g を返します。 |
BigInteger getP() |
素数モジュラス 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
コンストラクタに渡します。基盤となる未加工の鍵のバイトをバイト配列で表すことができ、関連付けられた鍵パラメータが存在しない場合、この方法は有用です。次の情報は、「Java 暗号化アーキテクチャーリファレンスガイド」の「付録 A」で標準アルゴリズムとして挙げられていないアルゴリズムを提供するプロバイダに当てはまります。
JCA が、暗号化アルゴリズム実装について、アルゴリズム識別子から (たとえば、証明書内でエンコードされたものとして) インスタンスの生成を行う必要がある場合があります。アルゴリズム識別子には、定義上、アルゴリズムのオブジェクト識別子 (OID) が含まれます。たとえば、X.509 証明書の署名を検証するために、JCA は証明書内でエンコードされた署名アルゴリズム識別子から署名アルゴリズムを判別し、そのアルゴリズムの Signature オブジェクトについてインスタンスを生成してから、検証のために初期化します。
JCA でアルゴリズムを検索するには、プロバイダマスターファイルで、アルゴリズムの別名エントリとしてアルゴリズム識別子を指定します。
put("Alg.Alias.<engine_type>.1.2.3.4.5.6.7.8", "<algorithm_alias_name>");
アルゴリズムが複数のオブジェクト識別子で知られている場合、オブジェクト識別子ごとに別名エントリを作成する必要があります。
JCA によるこの種のマッピングの例として、アルゴリズム (Foo
) が署名アルゴリズムで、ユーザーが keytool
コマンドを実行して (署名) アルゴリズムの別名を指定する場合を考えます。
% keytool -genkeypair -sigalg 1.2.3.4.5.6.7.8
この場合、プロバイダのマスターファイルには、次のエントリを含める必要があります。
put("Signature.Foo", "com.xyz.MyFooSignatureImpl"); put("Alg.Alias.Signature.1.2.3.4.5.6.7.8", "Foo");
この種のマッピングの別の例として、(1) アルゴリズムがキータイプアルゴリズムで、プログラムが (SUN プロバイダの X.509 実装を使って) 証明書を構文解析し、証明書から公開鍵を抽出して、Signature オブジェクトを初期化する場合、および (2) keytool
ユーザーが、対応する鍵のペアの生成後に (デジタル署名を実行するために) キータイプの非公開鍵にアクセスしようとする場合、を挙げることができます。これらの場合、プロバイダのマスターファイルには、次のエントリを含める必要があります。
put("KeyFactory.Foo", "com.xyz.MyFooKeyFactoryImpl"); put("Alg.Alias.KeyFactory.1.2.3.4.5.6.7.8", "Foo");
JCA が逆マッピング (つまり、アルゴリズム名からその関連付けられた OID への) を実行する必要がある場合、アルゴリズムと関連付けられた OID の 1 つに対して、次の形式の別名エントリを提供する必要があります。
put("Alg.Alias.Signature.OID.1.2.3.4.5.6.7.8", "MySigAlg");
アルゴリズムが複数のオブジェクト識別子で知られている場合、優先度の高いものに接頭辞「OID」を追加します。
JCA がこの種のマッピングを実行する一例として、ユーザーが keytool
を、-sigalg
オプションを取る任意のモードで実行する場合を挙げることができます。たとえば、-genkeypair
および -certreq
コマンドが呼び出されると、ユーザーは -sigalg
オプションを使用して (署名) アルゴリズムを指定できます。
JCA では、特定の条件が満たされる場合に、JCA フレームワークおよびプロバイダ暗号化実装をエクスポート可能になります。これは JCA の重要な機能です。
輸入管理制限があるため、Java 2 SDK, v 6 に同梱された管轄ポリシーファイルは「強固」ですが、暗号化の使用には制限があります。適格国 (大半の国が該当) の在住者は、暗号化機能に制限のない「無制限」のバージョンを利用できます。ただし、政府が制限を課しているこれらの国が輸入できるのは「強力な」バージョンだけです。JCA フレームワークでは、インストール済みの管轄ポリシーファイルで指定された制限が施行されます。
ほかの部分で説明したように、もっとも強力な暗号化を実装する、1 つのバージョンのプロバイダソフトウェアだけを実装できます。位置の異なるアプレット/アプリケーションから、利用可能な暗号化アルゴリズムおよび暗号化の最大強度に関して管轄ポリシーファイルに規定された制限を施行するのは、プロバイダではなく、JCA です。
JCA へのプラグインを可能にするために、プロバイダが満たす必要がある条件を次に示します。
次に示すのは、編集済みの Sun.java
ファイルです。このファイルには、Sun という名前のプロバイダ用のマスタークラスである Sun
という名前のクラスが含まれます。
すべてのマスタークラスの場合と同様、このクラスは Provider
のサブクラスです。これは、SUN プロバイダが提供するすべてのサービス実装のクラス名およびパッケージ位置を指定します。さまざまなアルゴリズムおよびその他のサービスが要求された場合、エンジンクラスの getInstance
メソッドはこの情報を使用して検索を行います。
次に示すコードは、プロバイダマスタークラスの例です。
/* * @(#)Sun.java 1.28 99/05/27 * * Copyright (c) 1996, 1998, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package sun.security.provider; import java.io.*; import java.util.*; import java.security.*; /** * The SUN Security Provider. * * @author Benjamin Renaud * * @version 1.28, 05/27/99 */ /** * Defines the SUN provider. * * Algorithms supported, and their names: * * - SHA is the message digest scheme described in FIPS 180-1. * Aliases for SHA are SHA-1 and SHA1. * * - SHA1withDSA is the signature scheme described in FIPS 186. * (SHA used in DSA is SHA-1: FIPS 186 with Change No 1.) * Aliases for SHA1withDSA are DSA, DSS, SHA/DSA, SHA-1/DSA, SHA1/DSA, * SHAwithDSA, DSAWithSHA1, and the object * identifier strings "OID.1.3.14.3.2.13", "OID.1.3.14.3.2.27" and * "OID.1.2.840.10040.4.3". * * - DSA is the key generation scheme as described in FIPS 186. * Aliases for DSA include the OID strings "OID.1.3.14.3.2.12" * and "OID.1.2.840.10040.4.1". * * - MD5 is the message digest scheme described in RFC 1321. * There are no aliases for MD5. */ public final class Sun extends Provider { private static final String INFO = "SUN " + "(DSA key/parameter generation; DSA signing; " + "SHA-1, MD5 digests; SecureRandom; X.509 certificates; JKS keystore)"; public Sun() { /* We are the SUN provider */ super("SUN", 1.2, INFO); AccessController.doPrivileged(new java.security.PrivilegedAction() { public Object run() { /* * Signature engines */ put("Signature.SHA1withDSA", "sun.security.provider.DSA"); put("Alg.Alias.Signature.DSA", "SHA1withDSA"); put("Alg.Alias.Signature.DSS", "SHA1withDSA"); put("Alg.Alias.Signature.SHA/DSA", "SHA1withDSA"); put("Alg.Alias.Signature.SHA-1/DSA", "SHA1withDSA"); put("Alg.Alias.Signature.SHA1/DSA", "SHA1withDSA"); put("Alg.Alias.Signature.SHAwithDSA", "SHA1withDSA"); put("Alg.Alias.Signature.DSAWithSHA1", "SHA1withDSA"); put("Alg.Alias.Signature.OID.1.2.840.10040.4.3", "SHA1withDSA"); put("Alg.Alias.Signature.1.2.840.10040.4.3", "SHA1withDSA"); put("Alg.Alias.Signature.1.3.14.3.2.13", "SHA1withDSA"); put("Alg.Alias.Signature.1.3.14.3.2.27", "SHA1withDSA"); /* * Key Pair Generator engines */ put("KeyPairGenerator.DSA", "sun.security.provider.DSAKeyPairGenerator"); put("Alg.Alias.KeyPairGenerator.OID.1.2.840.10040.4.1", "DSA"); put("Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1", "DSA"); put("Alg.Alias.KeyPairGenerator.1.3.14.3.2.12", "DSA"); /* * Digest engines */ put("MessageDigest.MD5", "sun.security.provider.MD5"); put("MessageDigest.SHA", "sun.security.provider.SHA"); put("Alg.Alias.MessageDigest.SHA-1", "SHA"); put("Alg.Alias.MessageDigest.SHA1", "SHA"); /* * Algorithm Parameter Generator engines */ put("AlgorithmParameterGenerator.DSA", "sun.security.provider.DSAParameterGenerator"); /* * Algorithm Parameter engines */ put("AlgorithmParameters.DSA", "sun.security.provider.DSAParameters"); put("Alg.Alias.AlgorithmParameters.1.3.14.3.2.12", "DSA"); put("Alg.Alias.AlgorithmParameters.1.2.840.10040.4.1", "DSA"); /* * Key factories */ put("KeyFactory.DSA", "sun.security.provider.DSAKeyFactory"); put("Alg.Alias.KeyFactory.1.3.14.3.2.12", "DSA"); put("Alg.Alias.KeyFactory.1.2.840.10040.4.1", "DSA"); /* * SecureRandom */ put("SecureRandom.SHA1PRNG", "sun.security.provider.SecureRandom"); /* * Certificates */ put("CertificateFactory.X509", "sun.security.provider.X509Factory"); put("Alg.Alias.CertificateFactory.X.509", "X509"); /* * KeyStore */ put("KeyStore.JKS", "sun.security.provider.JavaKeyStore"); /* * KeySize */ put("Signature.SHA1withDSA KeySize", "1024"); put("KeyPairGenerator.DSA KeySize", "1024"); put("AlgorithmParameterGenerator.DSA KeySize", "1024"); /* * Implementation type: software or hardware */ put("Signature.SHA1withDSA ImplementedIn", "Software"); put("KeyPairGenerator.DSA ImplementedIn", "Software"); put("MessageDigest.MD5 ImplementedIn", "Software"); put("MessageDigest.SHA ImplementedIn", "Software"); put("AlgorithmParameterGenerator.DSA ImplementedIn", "Software"); put("AlgorithmParameters.DSA ImplementedIn", "Software"); put("KeyFactory.DSA ImplementedIn", "Software"); put("SecureRandom.SHA1PRNG ImplementedIn", "Software"); put("CertificateFactory.X509 ImplementedIn", "Software"); put("KeyStore.JKS ImplementedIn", "Software"); return null; } }); } }
次に示すのは、編集済みの SunJCE.java
ファイルです。このファイルには、SunJCE という名前のプロバイダ用のマスタークラスである SunJCE
という名前のクラスが含まれます。
すべてのマスタークラスの場合と同様、このクラスは Provider
のサブクラスです。これは、SunJCE プロバイダが提供するすべての暗号化サービス実装のクラス名およびパッケージ位置を指定します。さまざまなアルゴリズムおよびその他のサービスが要求された場合、エンジンクラスの getInstance
メソッドはこの情報を使用して検索を行います。
次に示すコードは、プロバイダマスタークラスの例です。
/* * @(#)SunJCE.java 1.73 05/12/13 * * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package com.sun.crypto.provider; import java.security.*; import java.security.cert.*; import java.net.URL; import java.io.ByteArrayInputStream; /** * The "SunJCE" Cryptographic Service Provider. * * @author Jan Luehe * @author Sharon Liu * * @version 1.73, 12/13/05 */ /** * Defines the "SunJCE" provider. * * Supported algorithms and their names: * * ...edited for space... * */ public final class SunJCE extends Provider { private static final String info = "SunJCE Provider " + "(implements RSA, DES, Triple DES, AES, Blowfish, ARCFOUR, RC2, PBE, " + "Diffie-Hellman, HMAC)"; private static final String OID_PKCS5_MD5_DES = "1.2.840.113549.1.5.3"; private static final String OID_PKCS3 = "1.2.840.113549.1.3.1"; public SunJCE() { /* We are the "SunJCE" provider */ super("SunJCE", 1.6d, info); final String BLOCK_MODES = "ECB|CBC|PCBC|CTR|CTS|CFB|OFB" + "|CFB8|CFB16|CFB24|CFB32|CFB40|CFB48|CFB56|CFB64" + "|OFB8|OFB16|OFB24|OFB32|OFB40|OFB48|OFB56|OFB64"; final String BLOCK_MODES128 = BLOCK_MODES + "|CFB72|CFB80|CFB88|CFB96|CFB104|CFB112|CFB120|CFB128" + "|OFB72|OFB80|OFB88|OFB96|OFB104|OFB112|OFB120|OFB128"; final String BLOCK_PADS = "NOPADDING|PKCS5PADDING|ISO10126PADDING"; AccessController.doPrivileged(new java.security.PrivilegedAction() { public Object run() { /* * Cipher engines */ put("Cipher.RSA", "com.sun.crypto.provider.RSACipher"); put("Cipher.RSA SupportedModes", "ECB"); put("Cipher.RSA SupportedPaddings", "NOPADDING|PKCS1PADDING|OAEPWITHMD5ANDMGF1PADDING" + "|OAEPWITHSHA1ANDMGF1PADDING" + "|OAEPWITHSHA-1ANDMGF1PADDING" + "|OAEPWITHSHA-256ANDMGF1PADDING" + "|OAEPWITHSHA-384ANDMGF1PADDING" + "|OAEPWITHSHA-512ANDMGF1PADDING"); put("Cipher.RSA SupportedKeyClasses", "java.security.interfaces.RSAPublicKey" + "|java.security.interfaces.RSAPrivateKey"); put("Cipher.PBEWithMD5AndDES", "com.sun.crypto.provider.PBEWithMD5AndDESCipher"); put("Alg.Alias.Cipher.OID."+OID_PKCS5_MD5_DES, "PBEWithMD5AndDES"); put("Alg.Alias.Cipher."+OID_PKCS5_MD5_DES, "PBEWithMD5AndDES"); put("Cipher.AES", "com.sun.crypto.provider.AESCipher"); put("Alg.Alias.Cipher.Rijndael", "AES"); put("Cipher.AES SupportedModes", BLOCK_MODES128); put("Cipher.AES SupportedPaddings", BLOCK_PADS); put("Cipher.AES SupportedKeyFormats", "RAW"); put("Cipher.AESWrap", "com.sun.crypto.provider.AESWrapCipher"); put("Cipher.AESWrap SupportedModes", "ECB"); put("Cipher.AESWrap SupportedPaddings", "NOPADDING"); put("Cipher.AESWrap SupportedKeyFormats", "RAW"); put("Cipher.ARCFOUR", "com.sun.crypto.provider.ARCFOURCipher"); put("Alg.Alias.Cipher.RC4", "ARCFOUR"); put("Cipher.ARCFOUR SupportedModes", "ECB"); put("Cipher.ARCFOUR SupportedPaddings", "NOPADDING"); put("Cipher.ARCFOUR SupportedKeyFormats", "RAW"); /* * Key(pair) Generator engines */ put("KeyGenerator.AES", "com.sun.crypto.provider.AESKeyGenerator"); put("Alg.Alias.KeyGenerator.Rijndael", "AES"); put("KeyGenerator.ARCFOUR", "com.sun.crypto.provider.KeyGeneratorCore$" + "ARCFOURKeyGenerator"); put("Alg.Alias.KeyGenerator.RC4", "ARCFOUR"); put("KeyGenerator.HmacMD5", "com.sun.crypto.provider.HmacMD5KeyGenerator"); put("KeyGenerator.HmacSHA256", "com.sun.crypto.provider.KeyGeneratorCore$HmacSHA256KG"); put("KeyPairGenerator.DiffieHellman", "com.sun.crypto.provider.DHKeyPairGenerator"); put("Alg.Alias.KeyPairGenerator.DH", "DiffieHellman"); put("Alg.Alias.KeyPairGenerator.OID."+OID_PKCS3, "DiffieHellman"); put("Alg.Alias.KeyPairGenerator."+OID_PKCS3, "DiffieHellman"); /* * Algorithm parameter generation engines */ put("AlgorithmParameterGenerator.DiffieHellman", "com.sun.crypto.provider.DHParameterGenerator"); put("Alg.Alias.AlgorithmParameterGenerator.DH", "DiffieHellman"); put("Alg.Alias.AlgorithmParameterGenerator.OID."+OID_PKCS3, "DiffieHellman"); put("Alg.Alias.AlgorithmParameterGenerator."+OID_PKCS3, "DiffieHellman"); /* * Key Agreement engines */ put("KeyAgreement.DiffieHellman", "com.sun.crypto.provider.DHKeyAgreement"); put("Alg.Alias.KeyAgreement.DH", "DiffieHellman"); put("Alg.Alias.KeyAgreement.OID."+OID_PKCS3, "DiffieHellman"); put("Alg.Alias.KeyAgreement."+OID_PKCS3, "DiffieHellman"); put("KeyAgreement.DiffieHellman SupportedKeyClasses", "javax.crypto.interfaces.DHPublicKey" + "|javax.crypto.interfaces.DHPrivateKey"); /* * Algorithm Parameter engines */ put("AlgorithmParameters.DiffieHellman", "com.sun.crypto.provider.DHParameters"); put("Alg.Alias.AlgorithmParameters.DH", "DiffieHellman"); put("Alg.Alias.AlgorithmParameters.OID."+OID_PKCS3, "DiffieHellman"); put("Alg.Alias.AlgorithmParameters."+OID_PKCS3, "DiffieHellman"); put("AlgorithmParameters.PBEWithMD5AndDES", "com.sun.crypto.provider.PBEParameters"); put("Alg.Alias.AlgorithmParameters.OID."+OID_PKCS5_MD5_DES, "PBEWithMD5AndDES"); put("Alg.Alias.AlgorithmParameters."+OID_PKCS5_MD5_DES, "PBEWithMD5AndDES"); put("AlgorithmParameters.OAEP", "com.sun.crypto.provider.OAEPParameters"); /* * Key factories */ put("KeyFactory.DiffieHellman", "com.sun.crypto.provider.DHKeyFactory"); put("Alg.Alias.KeyFactory.DH", "DiffieHellman"); put("Alg.Alias.KeyFactory.OID."+OID_PKCS3, "DiffieHellman"); put("Alg.Alias.KeyFactory."+OID_PKCS3, "DiffieHellman"); /* * Secret-key factories */ put("SecretKeyFactory.PBEWithMD5AndDES", "com.sun.crypto.provider.PBEKeyFactory$PBEWithMD5AndDES" ); put("Alg.Alias.SecretKeyFactory.OID."+OID_PKCS5_MD5_DES, "PBEWithMD5AndDES"); put("Alg.Alias.SecretKeyFactory."+OID_PKCS5_MD5_DES, "PBEWithMD5AndDES"); /* * MAC */ put("Mac.HmacMD5", "com.sun.crypto.provider.HmacMD5"); put("Mac.HmacSHA256", "com.sun.crypto.provider.HmacCore$HmacSHA256"); put("Mac.HmacMD5 SupportedKeyFormats", "RAW"); put("Mac.HmacSHA256 SupportedKeyFormats", "RAW"); /* * KeyStore */ put("KeyStore.JCEKS", "com.sun.crypto.provider.JceKeyStore"); return null; } }); } }
次に示すのは、インストールされているプロバイダのデフォルトのリストを示す java.security
ファイルの一部です。これは、すべての JRE インストールで表示されます。ファイルにはその他のエントリも含まれていますが、簡潔にするために、ここでは一部のみを示します。完全なファイルは次の場所にあります。
<java-home>/lib/security/java.security [Solaris] <java-home>\lib\security\java.security [Win32]
ここで、<java-home> は JRE がインストールされているディレクトリを指します。
このファイルにプロバイダに関する情報を追加する例については、ステップ 5 を参照してください。
# # 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: 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.pkcs11.SunPKCS11 \ ${java.home}/lib/security/sunpkcs11-solaris.cfg security.provider.2=sun.security.provider.Sun security.provider.3=sun.security.rsa.SunRsaSign security.provider.4=com.sun.net.ssl.internal.ssl.Provider security.provider.5=com.sun.crypto.provider.SunJCE security.provider.6=sun.security.jgss.SunProvider security.provider.7=com.sun.security.sasl.Provider security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI security.provider.9=sun.security.smartcardio.SunPCSC # Rest of file deleted