JavaTM 暗号化アーキテクチャ用プロバイダの実装方法


最終更新日: 1998 年 9 月 21 日


はじめに
このドキュメントの対象者
関連ドキュメント


エンジンクラスと対応する SPI クラス


プロバイダの実装と統合の手順
手順 1: サービスの実装コードを記述する
手順 2: プロバイダの名前を指定する
手順 3: プロバイダのサブクラスである「マスタークラス」を記述する
手順 4: コードをコンパイルする
手順 5: テストの準備としてプロバイダをインストールする
手順 6: テストプログラムを作成してコンパイルする
手順 7: テストプログラムを実行する
手順 8: プロバイダとサポートされているサービスをドキュメント化する
手順 9: クラスファイルとドキュメントをクライアントが利用できるようにする


実装の詳細と要件
別名
サービスの相互依存性
デフォルトの初期化
鍵ペアジェネレータのデフォルトパラメータの要件
署名の形式
DSA インタフェースと必要な実装
RSA インタフェースと必要な実装
ほかのアルゴリズムタイプのためのインタフェース
アルゴリズムパラメータ仕様のインタフェースとクラス
鍵ファクトリで必要な鍵仕様のインタフェースとクラス
新しいオブジェクト識別子の追加


付録 A: SUN プロバイダのマスタークラス

付録 B: java.security プロパティファイル

はじめに

JDK 1.1 では、「暗号化サービスプロバイダ」 (略してプロバイダ) の概念が導入されました。これは、JDK Security API の暗号化に関するサブセットの具体的な実装を提供するパッケージ (またはパッケージセット) です。

たとえば、JDK 1.1 では、プロバイダに、デジタル署名アルゴリズム、メッセージダイジェストアルゴリズム、および鍵生成アルゴリズムを 1 つ以上含めることができました。JDK 1.2 では、鍵ファクトリ、キーストアの作成と管理、アルゴリズムパラメータ管理、アルゴリズムパラメータ生成、および証明書ファクトリという 5 種類のサービスが追加されています。また、プロバイダで乱数生成 (RNG) アルゴリズムも提供できるようになっています。これまで、RNG はプロバイダで提供されるものではなく、専用のアルゴリズムが JDK の中にハードコードされていました。

暗号化機能を使う必要のあるプログラムは、単に、特定のサービス (DSA 署名アルゴリズムなど) を実行する特定の型のオブジェクト (たとえば Signature オブジェクト) の実装を要求するだけで、インストールされているプロバイダの 1 つから実装を獲得できます。特定のプロバイダからの実装が必要な場合は、プログラムから、目的のサービスとともに、名前でプロバイダを要求できます。

JDK の各インストール環境には、1 つ以上のプロバイダパッケージがインストールされています。クライアントは、別のプロバイダを用いて実行環境を構成し、それぞれに「優先順位」を指定できます。優先順位とは、特定のプロバイダが指定されていない場合に、要求されているアルゴリズムに対してプロバイダを検索するときの順序です。

Java Runtime Environment の Sun バージョンには、SUN という名前のデフォルトのプロバイダが標準で搭載されています。ほかの Java Runtime Environment には、SUN プロバイダが含まれない場合があります。SUN プロバイダのパッケージには、次のものが含まれています。

新しいプロバイダは、静的または動的に追加できます。また、クライアントは、どのプロバイダが現在インストールされているかを問い合わせることができます。

実装が違うと、その特性も異なります。ソフトウェアベースのものもあれば、ハードウェアベースのものもあります。プラットフォームに依存しないものもあれば、プラットフォーム固有のものもあります。また、ソースコードを入手して調査および分析できるプロバイダもあれば、できないプロバイダもあります。

このドキュメントの対象者

このドキュメントは、暗号化サービスの実装を提供する独自のプロバイダパッケージを作成しようとする、熟練したプログラマのためのものです。ここでの説明に従って環境を構成すれば、作成したプロバイダを JDK Security に統合し、JDK Security API のクライアントからの要求に対して、アルゴリズムとサービスを見つけることができるようになります。

既存の暗号化アルゴリズムとサービスにアクセスするためだけに JDK Security API を使う場合は、このドキュメントを読む必要はありません。

関連ドキュメント

このドキュメントを読む前に、「Java 暗号化アーキテクチャ API 仕様 & リファレンス」を読む必要があります。

このドキュメントでは、JDK Security API のさまざまなクラスとインタフェースについても触れています。関連する Security API パッケージの詳細な説明については、次のドキュメントを参照してください。

エンジンクラスと対応する Service Provider Interface (SPI) クラス

「エンジンクラス」は、暗号化サービスを (具体的な実装ではなく) 抽象的な形式で定義しています。

暗号化サービスは、必ず特定のアルゴリズムまたはタイプと関連付けられていて、暗号化の操作 (デジタル署名やメッセージダイジェストなど) を提供したり、暗号化操作に必要な暗号化の構成要素 (鍵やパラメータ) を生成および提供したり、暗号化操作で使える暗号化の鍵を機密保護された形式でカプセル化するデータオブジェクト (キーストアまたは証明書) を生成したりします。たとえば、Signature クラスと KeyFactory クラスはエンジンクラスです。Signature クラスを使うと、デジタル署名アルゴリズムの機能にアクセスできます。DSA の KeyFactory クラスは、符号化形式または透過形式から生成した DSA の非公開鍵または公開鍵を、DSA の Signature オブジェクトの initSign メソッドまたは initVerify メソッドで使用できる形式で提供します。

Java 暗号化アーキテクチャは、暗号化に関連する JDK 1.2 Security パッケージのクラスを、エンジンクラスも含めて、包含しています。API のユーザは、エンジンクラスのインスタンスを要求して利用し、対応する操作を実行します。JDK 1.2 では、次のエンジンクラスが定義されています。

注: 「ジェネレータ(generator)」は最新の内容でオブジェクトを作成しますが、「ファクトリ(factory)」は既存の構成要素 (符号化法など) からオブジェクトを作成します。

エンジンクラスは、特定の種類の暗号化サービス (特定の暗号化アルゴリズムから独立) の機能へのインタフェースを提供します。エンジンクラスではアプリケーションプログラミングインタフェース (API) メソッドが定義されており、アプリケーションはそのメソッドを使って、エンジンクラスが提供する特定の種類の暗号化サービスにアクセスできます。プロバイダから取得する実際の実装は、特定のアルゴリズムのためのものです。たとえば Signature エンジンクラスは、デジタル署名アルゴリズムという機能へのアクセスを提供します。SignatureSpi サブクラス (次の段落を参照) で実際に提供される実装は、DSA を使う SHA-1、RSA を使う SHA-1、または RSA を使う MD5 など、特定の種類の署名アルゴリズムに対するものです。

エンジンクラスによって提供されるアプリケーションインタフェースは、「Service Provider Interface (SPI)」として実装されます。つまり、各エンジンクラスについて、対応する抽象的な SPI クラスがあり、暗号化サービスプロバイダが実装する必要のある Service Provider Interface メソッドが定義されています。

エンジンクラスのインスタンスである「API オブジェクト」は、対応する SPI クラスのインスタンスである「SPI オブジェクト」を、private フィールドとしてカプセル化しています。API オブジェクトのすべての API メソッドは final と宣言されて、その実装は、カプセル化されている SPI オブジェクトの対応する SPI メソッドを呼び出しています。エンジンクラスおよびそれに対応する SPI クラスのインスタンスは、エンジンクラスの getInstance ファクトリメソッドを呼び出して作成します。

各 SPI クラスの名前は、対応するエンジンクラスの名前のあとに「Spi」が付加されたものです。たとえば、Signature エンジンクラスに対応する SPI クラスは、SignatureSpi クラスです。

SPI クラスはどれも抽象的です。特定のアルゴリズムについて、特定種類のサービスの実装を提供するには、プロバイダは、対応する SPI クラスをサブクラス化し、すべての抽象メソッドに実装を提供する必要があります。

エンジンクラスのもう 1 つの例は MessageDigest クラスで、このクラスはメッセージダイジェストアルゴリズムへのアクセスを提供します。MessageDigestSpi サブクラスでのその実装は、SHA-1、MD5、MD2 などさまざまなメッセージダイジェストアルゴリズムの実装になります。

最後の例として、KeyFactory エンジンクラスは、隠された鍵仕様から透過的な鍵仕様への変換およびその逆の変換をサポートします (「鍵ファクトリで必要な鍵仕様のインタフェースとクラス」を参照)。KeyFactorySpi サブクラスで提供される実際の実装は、DSA の公開鍵や非公開鍵などのように、特定の種類の鍵に対する実装になります。

プロバイダの実装と統合の手順

プロバイダを実装し、JDK Security に統合するために必要な手順を次に示します。

手順 1: サービスの実装コードを記述する

まず、サポートする予定の暗号化サービスについて、アルゴリズム固有の実装を提供するコードを記述します。

JDK 1.2 では、署名、メッセージダイジェスト、鍵ペアの生成、(疑似) 乱数生成アルゴリズム、および鍵と証明書のファクトリとキーストアの作成と管理、アルゴリズムパラメータ管理、アルゴリズムパラメータ生成などのサービスを提供できます。

それぞれに暗号化サービスについて、SignatureSpi、MessageDigestSpi、KeyPairGeneratorSpi、SecureRandomSpi、AlgorithmParameterGeneratorSpi、AlgorithmParametersSpi、KeyFactorySpi、CertificateFactorySpi、および KeyStoreSpi の中から該当する SPI クラスのサブクラスを作成する必要があります (「エンジンクラスと対応する SPI クラス」を参照)。

サブクラスでは、次のことが必要です。

  1. 抽象メソッドの実装を提供します。抽象メソッドの名前は、通常、「engine」で始めます。詳細については、「実装の詳細と要件」を参照してください。

  2. 引数のない public コンストラクタを用意します。どれかのサービスが要求されたとき、JDK Security は、「マスタークラス」(「手順 3」参照) のプロパティでの指定に従って、そのサービスを実装しているサブクラスを検索します。次に、JDK Security はサブクラスに関連した Class オブジェクトを作成し、その Class オブジェクトの newInstance メソッドを呼び出して、サブクラスのインスタンスを作成します。newInstance メソッドでは、パラメータのない public コンストラクタを持つサブクラスが必要です。

    サブクラスにコンストラクタがない場合、引数のないデフォルトのコンストラクタが自動的に生成されます。ただし、サブクラスでコンストラクタを定義する場合は、引数を持たない public コンストラクタを明示的に定義する必要があります。

手順 2: プロバイダの名前を指定する

プロバイダの名前を決めます。クライアントアプリケーションは、この名前を使ってプロバイダを参照します。

手順 3: プロバイダのサブクラスである「マスタークラス」を記述する

3 番目の作業は、Provider クラスのサブクラスの作成です。

サブクラスは final クラスとし、コンストラクタでは次のことが必要です。

マスタークラスのプロパティのさらに詳細な設定例については、「付録 A」にある現在の JDK 1.2 Sun.java のソースファイルを参照してください。この例を見ると、Sun クラスのコンストラクタで SUN プロバイダに対するすべてのプロパティがどのように設定されているかがわかります。

注: Provider サブクラスは、必要な情報をどこからでも取得できます。したがって、情報は、ハードウェアに組み込むことも、ファイルなどから実行時に取得することもできます。

手順 4: コードをコンパイルする

実装のコードを作成し (手順 1)、プロバイダの名前を指定して (手順 2)、マスタークラスを作成した (手順 3) あと、コンパイラを使ってファイルをコンパイルします。

手順 5: テストの準備としてプロバイダをインストールする

プロバイダをテストするための準備として、プロバイダを使うクライアントと同じ方法で、プロバイダをインストールする必要があります。インストールすることで、クライアントからの要求に対して、JDK Security はアルゴリズムの実装を検索できます。

プロバイダのインストールは、プロバイダパッケージクラスのインストールとプロバイダの構成という 2 つの手順で行います。

プロバイダクラスのインストール

まず、要求されたときに探し出せるよう、クラスを利用可能な状態にする必要があります。プロバイダクラスは、JAR (Java ARchive) ファイルまたは ZIP ファイルとして提供します。

プロバイダクラスをインストールするには 2 つの方法があります。

プロバイダの構成

次に、認可プロバイダのリストにこのプロバイダを追加します。これは、JDK の lib/security ディレクトリ (Windows の場合は lib¥security) にある java.security ファイルを編集して静的に行います。したがって、JDK が jdk1.2 というディレクトリにインストールされている場合、ファイルは次のようになります。

  • jdk1.2/lib/security/java.security (Solaris)

  • jdk1.2¥lib¥security¥java.security (Windows)

各プロバイダについて、このファイルで次の形式の文を指定する必要があります。

    security.provider.n=masterClassName

この文では、プロバイダを宣言し、その優先順位 n を指定しています。優先順位とは、特定のプロバイダが要求されていないときに、要求されているアルゴリズムのプロバイダを検索する順序です。順位は 1 から始まり、1 が最優先で次に 2、3 と続きます。

masterClassName には、プロバイダの「マスタークラス」の完全な名前を指定する必要があります。マスタークラスは、「手順 3」で実装したものです。このクラスは、常に Provider クラスのサブクラスです。

JDK をインストールすると、必ず、SUN という名前の組み込み (デフォルト) プロバイダがインストールされます。java.security ファイルには、次のプロバイダ指定だけが含まれています。

    security.provider.1=sun.security.provider.Sun
SUN プロバイダのマスタークラスが、sun.security.provider パッケージの Sun クラスであったことを思い出してください。

マスタークラスが COM.acme.provider パッケージの Acme クラスで、プロバイダの優先順位を 2 番目にする場合を考えます。そのためには、java.security ファイルの SUN プロバイダに対する行の下に、次の文を追加します。

    security.provider.2=COM.acme.provider.Acme
注: 動的にプロバイダを登録することもできます。そのためには、プログラム (「手順 7」で作成するテストプログラムなど) で、Security クラスの addProvider メソッドまたは insertProviderAt メソッドを呼び出します。この登録は恒久的ではなく、「信頼できる」プログラムでしか実行できません。「Java 暗号化アーキテクチャ API 仕様 & リファレンス」の「Security クラス」を参照してください。

手順 6: テストプログラムを作成してコンパイルする

Security API へのプロバイダの統合およびアルゴリズムの正しさを検査するテストプログラムを作成し、コンパイルします。ハッシュや署名の対象となるテストデータなど、必要なサポートファイルも作成します。

最初に行うテストは、プロバイダが見つかり、名前、バージョン番号、および付加情報が意図したとおりのものかどうかの確認です。そのためには、次のようなコードを作成します。ただし、"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());

次に、サービスが見つかることを確認します。たとえば、メッセージダイジェストアルゴリズムの SHA-1 を実装した場合は次のコードを使って要求し、このアルゴリズムが見つかることを確認します。この場合も、"MyPro" は実際のプロバイダ名に置き換えます。

    MessageDigest sha = MessageDigest.getInstance("SHA", "MyPro");

    System.out.println("My MessageDigest algorithm name is " + 
        sha.getAlgorithm());

getInstance メソッドの呼び出しでプロバイダ名を指定しない場合は、そのアルゴリズムを実装しているプロバイダが見つかるまで、登録されているすべてのプロバイダが優先順位 (「プロバイダの構成」を参照) の順序で検索されます。

手順 7: テストプログラムを実行する

テストプログラムを実行します。必要があればコードをデバッグし、テストを続けます。JDK Security API で検索できないアルゴリズムがある場合は、ここまでの手順を調べて、すべて完了していることを確認します。

手順 8: プロバイダとサポートされているサービスをドキュメント化する

テストが済んだら、クライアント向けのドキュメントを作成します。少なくとも、次の記述が必要です。 さらに、ドキュメントでは、デフォルトのアルゴリズムパラメータなど、クライアントが必要とする情報を記述する必要があります。

メッセージダイジェスト

各メッセージダイジェストアルゴリズムについて、実装が複製 (コピー) 可能かどうかを記述する必要があります。これは、技術的に必要なものではなく、複製 (コピー) を介した中間ハッシュが可能かどうかを示すことで、クライアントの時間とコーディングを節約できるためです。メッセージダイジェストの実装が複製 (コピー) 可能かどうかわからないクライアントは、次の例に示す方法で MessageDigest オブジェクトを複製し、発生する可能性のある例外がキャッチされるかどうかで、実装の状態を確認できます。

try {
   // try and clone it
    /* compute the hash for i1 */
    sha.update(i1); 
    byte[] i1Hash = sha.clone().digest();

    /* compute the hash for i1 and i2 */
    sha.update(i2); 
    byte[] i12Hash = sha.clone().digest(); 

    /* compute the hash for i1, i2 and i3 */
    sha.update(i3); 
    byte[] i123Hash = sha.digest();
} catch (CloneNotSupportedException cnse) {
  // have to use an approach not involving cloning
}

署名アルゴリズム

署名アルゴリズムを実装する場合は、sign 系メソッドのいずれかで生成される署名が符号化される形式を、ドキュメント化する必要があります。たとえば、SUN プロバイダで提供される SHA1withDSA 署名アルゴリズムは、2 つの整数値 rs の標準の ASN.1 シーケンスとして、署名を符号化します。

乱数生成 (SecureRandom) アルゴリズム

乱数生成アルゴリズムについては、生成される数値がどの程度「不規則」か、また乱数ジェネレータが自己シーディングの場合はシードの品質に関して、情報を提供する必要があります。また、SecureRandom オブジェクトおよびカプセル化されている SecureRandomSpi 実装オブジェクトが直列化復元される場合にはどのように処理されるかを、記述する必要があります。復元されたオブジェクトで次に nextBytes メソッドを呼び出すと (カプセル化されている SecureRandomSpi オブジェクトの engineNextBytes メソッドが呼び出される)、元のオブジェクトで呼び出した場合とまったく同じ (乱数) バイトが生成される場合に、このような動作が好ましくないときには setSeed メソッドを呼び出して、復元された乱数オブジェクトにシードを設定する必要があることを、ユーザに伝える必要があります。

鍵ペアジェネレータ

鍵ペアジェネレータアルゴリズムでは、クライアントが initialize メソッドを呼び出して鍵ペアジェネレータを明示的に初期化しないときのために、各プロバイダでデフォルトの初期化処理を提供し、それについてドキュメントに記述する必要があります。たとえば、SUN プロバイダでは、デフォルトの係数サイズ (強度) として 1024 ビットが使われています。

鍵ファクトリ

プロバイダの鍵ファクトリでサポートされているすべての鍵仕様をドキュメント化する必要があります。

証明書ファクトリ

ファクトリで作成できる証明書の種類 (関係がある場合はバージョン番号も) をドキュメント化する必要があります。

キーストア

基になっているデータ形式など、キーストアの実装に関する関連情報をドキュメント化する必要があります。

アルゴリズムパラメータジェネレータ

クライアントが AlgorithmParameterGenerator エンジンクラスの init メソッドを呼び出してアルゴリズムパラメータジェネレータを明示的に初期化しないときのために、各プロバイダでデフォルトの初期化処理を提供し、それについてドキュメント化する必要があります。たとえば、SUN プロバイダは、デフォルトの係数プライムサイズである 1024 ビットを使って、DSA パラメータを生成します。

手順 9: クラスファイルとドキュメントをクライアントが利用できるようにする

最後の手順では、適当と考えられるどのような形式 (.class ファイル、zip ファイル、JAR ファイルなど) と方法 (Web からのダウンロード、フロッピーディスク、メールなど) でも、クライアントがクラスファイルとドキュメントを利用できるように設定します。

実装の詳細と要件

別名

暗号化のアルゴリズムとタイプの多くには、「Java 暗号化アーキテクチャ API 仕様 & リファレンス」の「付録 A」で定義されている単一の公式な「標準名」があります。

たとえば、RFC 1321 の RSA DSI で定義されている RSA-MD5 メッセージダイジェストアルゴリズムの標準名は、「MD5」です。

JDK 1.2 には、クライアントでアルゴリズムやタイプを参照するときに標準名ではなく別名を使えるようにする、別名化方式があります。たとえば、SUN プロバイダのマスタークラス (Sun.java) では、標準名が SHA1withDSA のアルゴリズムに対し、SHA1/DSA という別名が定義されています。したがって、次の 2 つの文は等しくなります。

    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");

現在、SUN プロバイダで定義されている別名は、どのプロバイダをクライアントが要求するかにかかわらず、すべてのクライアントから利用できます。たとえば、SHA1withDSA アルゴリズムを実装する「MyPro」という名前のプロバイダを作成した場合、そのプロバイダでは別名を定義していない場合でも、次のように、SUN で定義されている別名「SHA1/DSA」を使って、MyPro プロバイダで実装している SHA1withDSA を参照できます。

    Signature sig = Signature.getInstance("SHA1/DSA", "MyPro");

警告: 別名機能は、将来のリリースで変更または削除される場合があります。

サービスの相互依存性

一部のアルゴリズムでは、ほかのタイプのアルゴリズムを使う必要があります。たとえば、署名アルゴリズムでは、通常、データの署名と検証のために、メッセージダイジェストアルゴリズムを使う必要があります。

別のアルゴリズムを必要とするタイプのアルゴリズムを実装する場合は、次のどれかが可能です。

  1. どれも独自の実装を提供します。

  2. 独自に実装するアルゴリズムから、すべての JDK インストール環境に含まれるデフォルトの SUN プロバイダで定義されている、ほかのタイプのアルゴリズムのインスタンスを利用します。たとえば、メッセージダイジェストアルゴリズムを必要とする署名アルゴリズムを実装する場合、次のメソッドを呼び出すことで、MD5 メッセージダイジェストアルゴリズムを実装するクラスのインスタンスを取得できます。
        MessageDigest.getInstance("MD5", "SUN")
    

  3. 独自に実装するアルゴリズムから、別の特定のプロバイダで提供されているほかのタイプのアルゴリズムのインスタンスを利用します。この方法を使用できるのは、独自のプロバイダを使うすべてのクライアントに、ほかのクライアントもインストールされていることが確実な場合に限られます。

  4. 独自に実装するアルゴリズムから、別の (不特定の) プロバイダで提供されているほかのタイプのアルゴリズムのインスタンスを利用します。つまり、次のように、名前でアルゴリズムを要求しますが、特定のプロバイダは指定しません。
        MessageDigest.getInstance("MD5")
    
    この方法が使用できるのは、独自のプロバイダを使うすべての Java プラットフォームに、要求するアルゴリズム (上の例では MD5) の実装が少なくとも 1 つはインストールされていることが確実な場合に限られます。

次に、アルゴリズムの相互依存の一般的なタイプをいくつか示します。

署名アルゴリズムとメッセージダイジェストアルゴリズム

署名アルゴリズムでは、しばしば、メッセージダイジェストアルゴリズムの使用が必要になります。たとえば、SHA1withDSA 署名アルゴリズムでは、SHA-1 メッセージダイジェストアルゴリズムが必要です。

署名アルゴリズムと (疑似) 乱数生成アルゴリズム

署名アルゴリズムでは、(疑似) 乱数生成アルゴリズムの使用が必要になることがあります。たとえば、DSA の署名を生成するには、(疑似) 乱数生成アルゴリズムが必要です。

鍵ペア生成アルゴリズムとメッセージダイジェストアルゴリズム

鍵ペア生成アルゴリズムでは、メッセージダイジェストアルゴリズムの使用が必要になることがあります。たとえば、DSA の鍵は SHA-1 メッセージダイジェストアルゴリズムを使って生成されます。

アルゴリズムパラメータ生成アルゴリズムとメッセージダイジェストアルゴリズム

アルゴリズムパラメータジェネレータでは、メッセージダイジェストアルゴリズムの使用が必要になることがあります。たとえば、DSA パラメータは SHA-1 メッセージダイジェストアルゴリズムを使って生成されます。

キーストアアルゴリズムとメッセージダイジェストアルゴリズム

キーストアの実装では、しばしば、メッセージダイジェストアルゴリズムを利用してキーハッシュ (キーはユーザが指定したパスワード) を計算し、キーストアの完全性を検査して、キーストアが改変されていないことを確認します。

鍵ペア生成アルゴリズムとアルゴリズムパラメータジェネレータ

鍵ペア生成アルゴリズムでは、新しいアルゴリズムパラメータ群の生成が必要になる場合があります。パラメータを直接生成することも、アルゴリズムパラメータジェネレータを使って生成することもできます。

鍵ペア生成アルゴリズム、アルゴリズムパラメータ生成アルゴリズム、および (疑似) 乱数生成アルゴリズム

鍵ペア生成アルゴリズムでは、新しい鍵ペアと、場合によってはその鍵に関連する新しいパラメータ群を生成するために、乱数の発生源が必要になる場合があります。乱数の発生源は、SecureRandom オブジェクトで表されます。鍵ペア生成アルゴリズムの実装では、それ自体で鍵のパラメータを生成する場合と、アルゴリズムパラメータジェネレータを使って鍵のパラメータを生成する場合があります。どちらの場合も、乱数の発生源でアルゴリズムパラメータジェネレータを初期化する場合としない場合があります。

アルゴリズムパラメータジェネレータとアルゴリズムパラメータ

アルゴリズムパラメータジェネレータの engineGenerateParameters メソッドは、AlgorithmParameters のインスタンスを返す必要があります。

署名アルゴリズムと鍵ペア生成アルゴリズムまたは鍵ファクトリ

署名アルゴリズムを実装する場合、実装の engineInitSign メソッドと engineInitVerify メソッドは、基になっているアルゴリズムで有効な鍵 (DSS アルゴリズムに対する DSA 鍵など) を受け取る必要があります。次のどちらかの方法で行うことができます。

  1. 適切なインタフェースを実装するクラス (パッケージ java.security.interfaces から DSAPrivateKey インタフェースと DSAPublicKey インタフェースを実装するクラスなど) も独自に作成し、目的の種類の鍵を返す鍵ペアジェネレータまたは鍵ファクトリのどちらか一方または両方を独自に作成します。engineInitSign メソッドと engineInitVerify メソッドに渡される鍵の種類には、実装した鍵、つまり独自の鍵ペアジェネレータまたは鍵ファクトリで生成される鍵の種類と同じものを要求します。

  2. ほかの鍵ペアジェネレータまたは鍵ファクトリから鍵を受け取ります。ただし、その鍵ペアジェネレータまたは鍵ファクトリは、独自の署名の実装で必要な情報 (非公開鍵と公開鍵と鍵パラメータなど) を獲得できるようにする適切なインタフェースのインスタンスである場合に限ります。たとえば、DSS Signature クラスに対する engineInitSign メソッドは、java.security.interfaces.DSAPrivateKey のインスタンスである任意の非公開鍵を受け付けます。

キーストアと鍵ファクトリおよび証明書ファクトリ

キーストアの実装は、しばしば、鍵ファクトリを利用してキーストアに格納されている鍵を解析し、証明書ファクトリを利用してキーストアに格納されている証明書を解析します。

デフォルトの初期化

鍵ペアジェネレータまたはアルゴリズムパラメータジェネレータをクライアントが明示的に初期化しない場合は、そのサービスの各プロバイダがデフォルトの初期化を提供し、その内容をドキュメントに記述する必要があります。たとえば、SUN プロバイダでは、DSA パラメータの生成に、デフォルトの係数サイズ (強度) として 1024 が使われています。

鍵ペアジェネレータのデフォルトパラメータの要件

鍵ペアジェネレータを実装する場合は、クライアントがパラメータを指定しないときに使われるデフォルトのパラメータを提供する必要があります。提供するドキュメント (「手順 8」) では、デフォルトパラメータの内容を記述する必要があります。

たとえば、SUN プロバイダの DSA 鍵ペアジェネレータでは、512、768、および 1024 ビットの鍵ペアを生成するために、あらかじめ計算されている pq、および g の組がデフォルト値として提供されています。次の pq、および 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

ここで与えられている pq の値は、160 ビットを使う素数生成標準で生成されています。

SEED:  8d515589 4229d5e6 89ee01e6 018a237e 2cae64cd
このシードを使う場合、アルゴリズムはカウンタが 92 のときに pq を発見しました。

署名の形式

署名アルゴリズムを実装する場合は、sign メソッドのどれかで生成される署名が符号化される形式を、提供するドキュメント (「手順 8」) に明記する必要があります。

たとえば、SUN プロバイダが提供する SHA1withDSA 署名アルゴリズムは、2 つの ASN.1 INTEGER 値の標準 ASN.1 シーケンスとして署名を符号化します。

	SEQUENCE ::= {
		r INTEGER,
		s INTEGER }

DSA インタフェースと必要な実装

DSA サービスを実装するプログラマのため、JDK Security API では、java.security.interfaces パッケージに次のインタフェースが含まれています。 次に、これらのインタフェースを実装するための要件を説明します。

DSAKeyPairGenerator の実装

このインタフェースは、これからは使用されなくなります。このインタフェースは、実装が提供するデフォルトのパラメータではなく、DSA 固有のパラメータをクライアントが提供できるようにするために必要でした。しかし、JDK 1.2 ではこれを使う必要はなく、AlgorithmParameterSpec パラメータを受け取る KeyPairGenerator の新しい initialize メソッドを使うと、クライアントはアルゴリズム固有のパラメータを指定できます。

DSAParams の実装

DSA の鍵ペアジェネレータを実装する場合は、pqg の各パラメータを保持して返すために、DSAParams を実装するクラスが必要です。

DSAPrivateKey インタフェースと DSAPublicKey インタフェースを実装する場合も、DSAParams の実装が必要。DSAPublicKey と DSAPrivateKey はどちらも DSAKey インタフェースを継承しており、DSAKey インタフェースには、DSAParams オブジェクトを返す必要のある getParams メソッドが含まれている。詳細については、「DSAPrivateKey と DSAPublicKey の実装」を参照

注: JDK に組み込まれている DSAParams の実装として、java.security.spec.DSAParameterSpec クラスがあります。

DSAPrivateKeyDSAPublicKey の実装

DSA の鍵ペアジェネレータまたは鍵ファクトリを実装する場合は、DSAPrivateKey インタフェースと DSAPublicKey インタフェースを実装するクラスを作る必要があります。

DSA の鍵ペアジェネレータを実装する場合、KeyPairGeneratorSpi サブクラスの generateKeyPair メソッドは、これらのインタフェースの実装のインスタンスを返します。

DSA の鍵ファクトリを実装する場合、KeyFactorySpi サブクラスの engineGeneratePrivate メソッドは DSAPrivateKey の実装のインスタンスを返し、engineGeneratePublic メソッドは DSAPublicKey の実装のインスタンスを返します。

また、engineGetKeySpec メソッドと engineTranslateKey メソッドは、受け取る鍵として、DSAPrivateKey または DSAPublicKey の実装のインスタンスを想定しています。インタフェースの実装で提供される getParams メソッドは、鍵からパラメータを取得して抽出し、そのパラメータを使う場合に便利です。たとえば、DSA の KeyPairGenerator オブジェクトの初期化に使われるパラメータ値からパラメータ仕様を作成するために呼び出される、DSAParameterSpec コンストラクタに対するパラメータの場合などです。

DSA の署名アルゴリズムを実装する場合、SignatureSpi サブクラスの engineInitSign メソッドは DSAPrivateKey を渡されることを想定し、engineInitVerify メソッドは DSAPublicKey を渡されることを想定しています。

注: DSAPublicKey インタフェースと DSAPrivateKey インタフェースは、それぞれ、DSA の公開鍵と非公開鍵に対する、非常に一般的でプロバイダに依存しないインタフェースを定義しています。KeyFactorySpi サブクラスの engineGetKeySpec メソッドと engineTranslateKey メソッドを使うと、渡された鍵が実際に DSAPrivateKey または DSAPublicKey のプロバイダ独自の実装のインスタンスかどうかを、さらに検査できます。たとえば、プロバイダ固有の実装の詳細を利用する場合などです。DSA 署名アルゴリズムの SignatureSpi サブクラスの 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 インタフェースからの getAlgorithmgetEncoded、および getFormat の各メソッド (DSAPrivateKey は java.security.PrivateKey を継承し、PrivateKey は Key を継承するため) 同様に、DSA の公開鍵についても次のメソッドを実装するクラスを提供する必要があります。
    • DSAPublicKey インタフェースからの getY メソッド

    • java.security.interfaces.DSAKey インタフェースからの getParams メソッド (DSAPublicKey は DSAKey を継承するため)。getParams メソッドは DSAParams オブジェクトを返すので、DSAParams の実装も必要

    • java.security.Key インタフェースからの getAlgorithmgetEncoded、および getFormat の各メソッド (DSAPublicKey は java.security.PublicKey を継承し、PublicKey は Key を継承するため)

RSA インタフェースと必要な実装

RSA サービスを実装するプログラマのため、JDK Security API では、java.security.interfaces パッケージに次のインタフェースが含まれています。 次に、これらのインタフェースを実装するための要件を説明します。

RSAPrivateKey RSAPrivateCrtKey、および RSAPublicKey の実装

RSA の鍵ペアジェネレータまたは鍵ファクトリを実装する場合は、RSAPrivateKey インタフェース (および RSAPrivateCrtKey インタフェースのどちらか一方または両方) と RSAPublicKey インタフェースを実装するクラスを作る必要があります。RSAPrivateCrtKey は、RSA の非公開鍵に対するインタフェースで、中国剰余定理 (CRT) の表現を使います。

RSA の鍵ペアジェネレータを実装する場合、KeyPairGeneratorSpi サブクラスの generateKeyPair メソッドは、これらのインタフェースの実装のインスタンスを返します。

RSA の鍵ファクトリを実装する場合、KeyFactorySpi サブクラスの engineGeneratePrivate メソッドは RSAPrivateKey (または RSAPrivateCrtKey) の実装のインスタンスを返し、engineGeneratePublic メソッドは RSAPublicKey の実装のインスタンスを返します。

また、engineGetKeySpec メソッドと engineTranslateKey メソッドは、受け取る鍵として、RSAPrivateKey、RSAPrivateCrtKey、または RSAPublicKey の実装のインスタンスを想定しています。

RSA の署名アルゴリズムを実装する場合、SignatureSpi サブクラスの engineInitSign メソッドは RSAPrivateKey または RSAPrivateCrtKey を渡されることを想定し、engineInitVerify メソッドは RSAPublicKey を渡されることを想定します。

注: RSAPublicKey、RSAPrivateCrtKey、および RSAPrivateKey の各インタフェースは、RSA の公開鍵と非公開鍵に対する、非常に一般的でプロバイダに依存しないインタフェースを定義しています。KeyFactorySpi サブクラスの engineGetKeySpec メソッドと engineTranslateKey メソッドを使うと、渡された鍵が実際に RSAPrivateKey、RSAPrivateCrtKey、または RSAPublicKey のプロバイダ独自の実装のインスタンスかどうかを、さらに検査できます。たとえば、プロバイダ固有の実装の詳細を利用する場合などです。RSA 署名アルゴリズムの SignatureSpi サブクラスの engineInitSign メソッドと engineInitVerify メソッドについても同様です。

RSAPublicKey、RSAPrivateCrtKey、および RSAPrivateKey の各インタフェースを実装するクラスで実装する必要のあるメソッドを調べるには、まず、次のインタフェースのシグニチャーに注目します。

  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 メソッド
  • java.security.Key インタフェースからの getAlgorithmgetEncoded、および getFormat の各メソッド (RSAPrivateKey は java.security.PrivateKey を継承し、PrivateKey は Key を継承するため)

    同様に、中国剰余定理 (CRT) 表現を使う RSA の非公開鍵では、次のメソッドを実装するクラスを提供する必要があります。

    • RSAPrivateCrtKey は java.security.interfaces.RSAPrivateKey を継承するので、上記の RSA 非公開鍵で指定されているすべてのメソッド

    • RSAPrivateCrtKey インタフェースからの、getPublicExponentgetPrimePgetPrimeQgetPrimeExponentPgetPrimeExponentQ、および getCrtCoefficient の各メソッド

      RSA の公開鍵については、次のメソッドを実装するクラスを提供する必要があります。

      • RSAPublicKey インタフェースからの getModulus メソッドと getPublicExponent メソッド

      • java.security.Key インタフェースからの getAlgorithmgetEncoded、および getFormat の各メソッド (RSAPublicKey は java.security.PublicKey を継承し、PublicKey は Key を継承するため)

ほかのアルゴリズムタイプのためのインタフェース

前述のように、JDK Security API には、DSA サービスと RSA サービスを実装するプログラマのためのインタフェースが含まれています。現時点では、ほかのタイプのアルゴリズムに対する同様のインタフェースは API に含まれていません。したがって、独自に定義する必要があります。

ほかのアルゴリズムの鍵ペアジェネレータを実装する場合は、1 つ以上の initialize メソッドを含むインタフェースを作る必要があります。このメソッドは、実装が提供するデフォルトのパラメータではなく、アルゴリズム固有のパラメータを提供する場合に、クライアントが呼び出すことのできるものです。KeyPairGeneratorSpi のサブクラスは、このインタフェースを実装する必要があります。

DSA でも RSA でもないアルゴリズムに対する非公開鍵と公開鍵については、現時点では、DSA の DSAPrivateKey インタフェースと DSAPublicKey インタフェース、および RSA の RSAPrivateKey、 RSAPrivateCrtKey、および RSAPublicKey の各インタフェースに対応する java.security.interfaces インタフェースはありません。同様のインタフェースを作成し、実装クラスを提供することが推奨されます。公開鍵のインタフェースは、PublicKey インタフェースを継承する必要があります。同様に、非公開鍵のインタフェースは、PrivateKey インタフェースを継承する必要があります。

アルゴリズムパラメータ仕様のインタフェースとクラス

アルゴリズムパラメータ仕様は、アルゴリズムで使われるパラメータ群の透過的な表現です。

パラメータの「透過的な」表現とは、対応する仕様クラスで定義されている get メソッドのどれかを使って、各パラメータの値に個別にアクセスできることを意味しています。たとえば、DSAParameterSpec で定義されている getPgetQ、および getG の各メソッドを使うと、p、q、および g の各パラメータにアクセスできます。

これは、AlgorithmParameters エンジンクラスで提供される「隠された」表現とは対照的なものです。隠された表現の場合は、鍵データの値に直接アクセスすることはできません。getAlgorithm を使ってパラメータ群に関連するアルゴリズムの名前を取得することと、getEncoded を使ってパラメータ群のある種の符号化を取得することだけが可能です。

AlgorithmParametersSpi、AlgorithmParameterGeneratorSpi、または KeyPairGeneratorSpi のどれかの実装を提供する場合、これらのクラスはどれも AlgorithmParameterSpec パラメータを受け取るメソッドを含んでいるので、AlgorithmParameterSpec インタフェースを利用する必要があります。このようなメソッドは、そのインタフェースの実際の実装の中のどれが渡されたのかを判断し、それに応じて動作する必要があります。

JDK 1.2 には、AlgorithmParameterSpec の実装として、DSAParameterSpec クラスが 1 つだけ含まれています。DSA アルゴリズムのパラメータを扱う場合は、このクラスを利用できます。別の種類のアルゴリズムに対するアルゴリズムパラメータを操作する場合は、アルゴリズムの種類に適した AlgorithmParameterSpec の実装を独自に提供する必要があります。

JDK 1.2 では、java.security.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 クラスのインスタンスを返します。

鍵ファクトリで必要な鍵仕様のインタフェースとクラス

鍵ファクトリは、隠された鍵 (Key 型) と鍵仕様の間の双方向の変換を提供します。したがって、鍵ファクトリを実装する場合は、鍵仕様を理解して利用する必要があります。場合によっては、独自の鍵仕様を実装する必要もあります。 次に、鍵仕様、JDK 1.2 で提供されるインタフェースとクラス、および仕様に関する鍵ファクトリの要件について、さらに詳しく説明します。

鍵仕様は、鍵を構成する要素の透過的な表現です。鍵がハードウェア装置に格納される場合、その仕様には装置上で鍵を識別する際の、補助になる情報が含まれる場合があります。

鍵の「透過的な」表現とは、対応する仕様クラスで定義されている「get」メソッドのどれかを使って、鍵データの値に個別にアクセスできることを意味しています。たとえば、java.security.spec.DSAPrivateKeySpec クラスで定義されている getXgetPgetQ、および getG の各メソッドを使うと、非公開鍵 x および鍵の計算に使われている DSA アルゴリズムパラメータのプライム p、サブプライム q、ベース g に、アクセスできます。

これに対し、Key インタフェースで定義されているような鍵の「隠された」表現の場合は、パラメータフィールドに直接アクセスすることはできません。つまり、「隠された」表現では、鍵に対しては、Key インタフェースで定義されている 3 つのメソッド getAlgorithmgetFormat、および getEncoded だけによる限られたアクセスしか認められていません。

鍵は、アルゴリズム固有の方法で指定される場合と、アルゴリズムとは独立した符号化形式 (ASN.1 など) で指定される場合があります。たとえば、DSA の非公開鍵は、構成要素の xpq、および g (「DSAPrivateKeySpec」参照) で指定される場合と、DER 符号化 (「PKCS8EncodedKeySpec」参照) を使って指定される場合があります。

JDK 1.2 では、java.security.spec パッケージの中で、次の鍵仕様のインタフェースとクラスが定義されています。

KeySpec インタフェース

このインタフェースにはメソッドまたは定数はありません。このクラスの目的は、すべての鍵仕様をグループ化し、型の安全性を提供することです。すべての鍵仕様はこのインタフェースを実装する必要があります。

JDK 1.2 では、KeySpec インタフェースを実装するクラスとして、DSAPrivateKeySpecDSAPublicKeySpecRSAPrivateKeySpecRSAPublicKeySpecEncodedKeySpecPKCS8EncodedKeySpec、および X509EncodedKeySpec が提供されています。

独自のプロバイダで使う鍵のタイプ (Your_PublicKey_type や Your_PrivateKey_type など) に対し、対応する KeySpec クラスが JDK で提供されていない場合は、2 種類のシナリオが考えられます。そのうちの 1 つでは独自の鍵仕様の実装が必要になります。

  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 のインスタンス) を返します。

  2. 独自に定義する鍵のタイプで、鍵の特定の構成要素の値にユーザがアクセスする必要があると考えられる場合、または、符号化から (上の場合のように) ではなく、鍵データおよび関連するパラメータ値から独自のタイプの鍵を生成する必要があると考えられる場合は、新しい KeySpec クラス (KeySpec インタフェースを実装するクラス) を指定し、適切なコンストラクタメソッドと、独自の鍵のタイプに対する鍵要素フィールドおよび関連するパラメータ値を返す get メソッドを提供する必要があります。これらのクラスは、JDK で提供されている DSAPrivateKeySpec クラスと DSAPublicKeySpec クラスで行われているのと同じ方法で指定します。これらのクラスは、たとえばプロバイダの JAR ファイルの一部として、プロバイダクラスとともに提供する必要があります。

DSAPrivateKeySpec クラス

KeySpec インタフェースを実装するこのクラスは、関連するパラメータとともに、DSA の非公開鍵を規定しています。このクラスには、次のメソッドがあります。
    public BigInteger getX()

    public BigInteger getP()

    public BigInteger getQ()

    public BigInteger getG()
これらのメソッドからは、非公開鍵 x と、鍵の計算に使われる DSA アルゴリズムのパラメータであるプライム p、サブプライム q、およびベース g が返されます。

DSAPublicKeySpec クラス

KeySpec インタフェースを実装するこのクラスは、関連するパラメータとともに DSA の公開鍵を規定しています。このクラスには、次のメソッドがあります。
    public BigInteger getY()

    public BigInteger getP()

    public BigInteger getQ()

    public BigInteger getG()
これらのメソッドからは、公開鍵 y と、鍵の計算に使われる DSA アルゴリズムのパラメータであるプライム p、サブプライム q、およびベース g が返されます。

RSAPrivateKeySpec クラス

KeySpec インタフェースを実装するこのクラスは、RSA の非公開鍵を規定しています。このクラスには次のメソッドがあります。
    public BigInteger getModulus()

    public BigInteger getPrivateExponent()
これらのメソッドからは、RSA の非公開鍵を生成するための RSA 係数値 n と非公開の指数値 d が返されます。

RSAPrivateCrtKeySpec クラス

RSAPrivateKeySpec クラスを継承するこのクラスは、中国剰余定理 (CRT) 情報の値を使って、PKCS#1 標準で定義されている RSA 非公開鍵を規定しています。このクラスには、スーパークラス RSAPrivateKeySpec から継承するメソッドのほかに、次のメソッドがあります。
    public BigInteger getPublicExponent()

    public BigInteger getPrimeP()

    public BigInteger getPrimeQ()

    public BigInteger getPrimeExponentP()

    public BigInteger getPrimeExponentQ()

    public BigInteger getCrtCoefficient()
これらのメソッドからは、公開指数 e と、CRT 情報の整数値として、係数 n の素因数 pn の素因数 q、指数 d mod (p-1)、CRT 係数 (q の送数) mod p が返されます。

RSA の非公開鍵は、理論的には係数と非公開の指数だけで構成されます。CRT 値があるのは効率のためです。

RSAPublicKeySpec クラス

KeySpec インタフェースを実装するこのクラスは、RSA の公開鍵を規定しています。このクラスには次のメソッドがあります。
    public BigInteger getModulus()

    public BigInteger getPublicExponent()
これらのメソッドからは、RSA の公開鍵を構成する RSA 係数 n と公開指数 e が返されます。

EncodedKeySpec クラス

KeySpec インタフェースを実装するこの抽象クラスは、符号化形式の公開鍵と非公開鍵を表しています。このクラスの getEncoded メソッドからは、符号化された鍵が返されます。
    public abstract byte[] getEncoded();
また、getFormat メソッドからは、符号化形式の名前が返されます。
    public abstract String getFormat();

JDK 1.2 では、EncodedKeySpec インタフェースを実装するクラスとして、PKCS8EncodedKeySpecX509EncodedKeySpec の 2 つが提供されています。必要に応じて、これらのタイプまたはほかのタイプの鍵符号化に対する独自の EncodedKeySpec の実装を提供できます。

PKCS8EncodedKeySpec クラス

このクラスは EncodedKeySpec のサブクラスで、PKCS #8 標準で指定されている形式に従って非公開鍵の DER 符号化を表します。

このクラスの getEncoded メソッドからは、PKCS #8 標準に従って符号化された鍵のバイトが返されます。また、getFormat メソッドからは文字列「PKCS#8」が返されます。

X509EncodedKeySpec クラス

このクラスは EncodedKeySpec のサブクラスで、X.509 標準で指定されている形式に従って公開鍵または非公開鍵の DER 符号化を表します。

このクラスの getEncoded メソッドからは、X.509 標準に従って符号化された鍵のバイトが返されます。また、getFormat メソッドからは、文字列「X.509」が返されます。

新しいオブジェクト識別子の追加

以下の情報は、「JavaTM 暗号化アーキテクチャ API 仕様 & リファレンス」の「付録 A」の一覧に、標準アルゴリズムとして記載されていないアルゴリズムを提供するプロバイダに適用されます。

OID から名前へのマッピング

JCA で、証明書にエンコードされているアルゴリズム識別子など、定義によりアルゴリズムのオブジェクト識別子 (OID) を含んでいるアルゴリズム識別子から、暗号化アルゴリズムの実装のインスタンスを生成する必要があることがあります。たとえば、X.509 証明書上のシグニチャーを検証するために、JCA は、証明書にエンコードされているシグニチャーアルゴリズム識別子からシグニチャーアルゴリズムを特定し、そのアルゴリズム用の Signature オブジェクトのインスタンスを生成し、それを検証のために初期化します。

このためには、JCA がアルゴリズムを見つけられるように、プロバイダのマスタファイルに、そのアルゴリズム用のオブジェクト識別子を別名のエントリとして提供する必要があります。

たとえば、プロバイダの実装が com.xyz パッケージ内にあり、アルゴリズムのタイプが 、名前が MyAlg で、オブジェクト識別子が (文字列で) 「1.2.3.4.5.6.7.8」の場合、プロバイダのマスタファイルには、次のエントリが必要です。

    put(".MyAlg", "com.xyz.MyAlg");
    put("Alg.Alias..1.2.3.4.5.6.7.8", "MyAlg");
アルゴリズムが複数のオブジェクト識別子で認識される場合は、それらの各オブジェクト識別子について、別名のエントリを作成する必要があります。

JCA がこの種のマッピングを実行する例として、アルゴリズムが署名アルゴリズムで、ユーザが keytool -genkey コマンドを実行し、-sigalg オプションを使ってその (シグニチャー) アルゴリズムを指定する場合があります。この場合、プロバイダのマスタファイルには、次のエントリが含まれている必要があります。

    put("Signature.MyAlg", "com.xyz.MyAlg");
    put("Alg.Alias.Signature.1.2.3.4.5.6.7.8", "MyAlg");
このマッピングが実行されるその他の例には、(1) アルゴリズムがキータイプアルゴリズムで、Signature オブジェクトを初期化して検証するために、プログラムが SUN プロバイダの X.509 実装を使って証明書を解析し、証明書から公開鍵を抽出する場合、および (2) keytool のユーザが、デジタル署名を実行するなどのために、対応するキーペアの生成後にキータイプの非公開鍵にアクセスしようとする場合があります。これらの場合には、プロバイダのマスタファイルには、次のエントリが含まれている必要があります。
    put("KeyFactory.MyAlg", "com.xyz.MyAlg");
    put("Alg.Alias.KeyFactory.1.2.3.4.5.6.7.8", "MyAlg");

名前から OID へのマッピング

JCA がアルゴリズム名から関連付けられた OID への逆マッピングを実行する必要がある場合は、アルゴリズムを認識する OID の 1 つに対して次の形式で別名のエントリを提供する必要があります。
    put("Alg.Alias.Signature.OID.1.2.3.4.5.6.7.8", "MySigAlg");
アルゴリズムが複数のオブジェクト識別子で認識される場合は、優先するものに対して接頭辞「OID.」を付けます。

JCA がこの種のマッピングを実行する例として、-sigalg オプションをとるモードで、ユーザが keytool を実行する場合があります。たとえば、-genkey および -certreq コマンドが呼び出されたときに、ユーザは -sigalg オプションを使って (シグニチャー) アルゴリズムを指定できます。




付録 A: SUN プロバイダのマスタークラス

次に示すのは、Sun.java ファイルのコピーで、Sun という名前のクラスが含まれています。これは、「SUN」という名前のプロバイダのマスタークラスです。このプロバイダは、すべての JDK インストール環境で提供されています。

すべてのマスタークラスがそうであるように、このクラスは Provider のサブクラスです。このクラスは、SUN プロバイダで提供されているすべての暗号化サービスの実装に対して、クラスの名前とパッケージの場所を指定しています。JDK Security は、サービスが要求されると、この情報を使ってさまざまなアルゴリズムとほかのサービスを検索します。

次のコードは、マスタークラスの例です。

/*
* Copyright 1996-1998 by Sun Microsystems, Inc.,
* 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
* All rights reserved.
*
* This software is the confidential and proprietary information
* of Sun Microsystems, Inc. ("Confidential Information").  You
* shall not disclose such Confidential Information and shall use
* it only in accordance with the terms of the license agreement
* you entered into with Sun.
*/

package sun.security.provider;

import java.io.*;
import java.util.*;
import java.security.*;

/**
* The SUN Security Provider.
*/

/**
* 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");
		
		return null;
	    }
	});
    }
}



付録 B: java.security プロパティファイル

次に示すのは、すべての JDK インストール環境に作成される java.security ファイルのコピーです。このファイルは、JDK の lib/security (Windows では lib¥security) ディレクトリにあります。したがって、JDK が jdk1.2 というディレクトリにインストールされている場合、ファイルのパスは次のようになります。 独自のプロバイダについての情報をこのファイルに追加する例については、「手順 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 
# Cryptographic Service 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

#
# 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=


Copyright © 1996-98 Sun Microsystems, Inc. All Rights Reserved.

コメントの送付先: java-security@java.sun.com これは購読リストではありません。
Sun
Java ソフトウェア