JDK Security API は Java プログラミング言語のコア API で、
java.security
パッケージ (およびそのサブパッケージ) に組み込まれています。この API は、開発者が低レベルと高レベルの両方のセキュリティ機能をプログラムに組み込めるように設計されています。JDK 1.1 で JDK Security が初めてリリースされた際、「Java 暗号化アーキテクチャ」(JCA) が導入されました。JCA とは、Java プラットフォームに暗号機能を開発し、これにアクセスするためのフレームワークのことです。JDK 1.1 では、JCA にデジタル署名とメッセージダイジェストの API が含められました。
JDK 1.2 では、このドキュメントで説明するように、Java 暗号化アーキテクチャが著しく拡張されています。また、JDK 1.2 では、X.509 v3 証明書をサポートする証明書管理インフラストラクチャがアップグレードされ、柔軟性と拡張性があり、適合性が高く細かいアクセス制御が可能な新しい Java セキュリティアーキテクチャが導入されています。
Java 暗号化アーキテクチャは、暗号に関連した JDK 1.2 Security API の一部、およびこのドキュメントに記載の規則および仕様セットを含む、多重かつ互いに操作可能な暗号の実装を可能にする「プロバイダ」アーキテクチャを含みます。
Java 暗号化拡張機能 (JCE) は、JCA API を拡張して暗号化、鍵交換、およびメッセージ認証コード (MAC) 用の API を組み込んだものです。JCE と JDK の暗号化機能により、完全なプラットフォーム独立型の暗号化 API が提供されます。JCE は JDK の拡張機能として別にリリースされており、米国の輸出規制条例に従っています。
このドキュメントには、Java Development Kit (JDK) 1.2 に同梱の Java 暗号化アーキテクチャ API およびそのデフォルトのプロバイダについて、レベルの高い説明と仕様が記載されています。JCE API に関するドキュメントは、JCE のリリース時に別途提供されます。JDK Security API の Java セキュリティアーキテクチャの情報については、「Java セキュリティアーキテクチャ (JDK 1.2)」を参照してください。
注: この仕様の最新バージョンは、弊社の公開 Web サイト http://java.sun.com/products/jdk/1.2/docs/guide/security/CryptoSpec.html にあります。
Java 暗号化アーキテクチャ (JCA) は、以下の方針に基づいて設計されました。
- 実装のリファレンス独立性と相互操作性
- アルゴリズムの独立性と拡張性
実装の独立性とアルゴリズムの独立性は相補関係にあります。つまりこの 2 つの目的は、デジタル署名やメッセージダイジェストなどの暗号化「概念」について、API ユーザが実装やこれらの概念を実装するアルゴリズムを意識しないで使えるようにすることです。完全なアルゴリズムの独立性が不可能なときは、JCA は標準化された、アルゴリズム依存の API を開発者に提供します。実装の独立性が望ましくないときには、JCA は開発者が必要とする特定の実装を示します。
アルゴリズムの独立性は、暗号化「エンジン」(サービス) の型を定義し、これらの暗号化エンジンの機能を提供するクラスを定義することにより実現しています。これらのクラスは「エンジンクラス」と呼ばれ、MessageDigest クラスおよび KeyFactory クラスがこれに含まれます。
実装の独立性は、「プロバイダ」ベースのアーキテクチャを使って実現されます。暗号化サービスプロバイダ (略して「プロバイダ」) とは、デジタル署名アルゴリズム、メッセージダイジェスト、および鍵の変換サービスなどの 1 つ以上の暗号化を実行するパッケージやパッケージセットを意味します。プログラムは単に、特定のサービス (たとえば DSA 署名アルゴリズム) を実行する特定型のオブジェクト (たとえば Signature オブジェクト) を要求するだけで、インストールされているプロバイダの 1 つから実装を獲得できます。必要に応じて、プログラムは特定プロバイダから実装を要求することもできます。たとえば、より高速で安全性の高いバージョンが利用できるときは、プロバイダをアプリケーションに対して透過的に更新することができます。
実装の相互操作性とは、様々な実装が互いに機能でき、互いの鍵を使ったり、互いの署名を検証できることを意味します。つまり、1 つのプロバイダが生成した同じアルゴリズムや鍵を別のプロバイダが使ったり、あるプロバイダが生成した署名を別のプロバイダが検証するということです。
アルゴリズムの拡張性とは、サポートされるエンジンクラスの 1 つに当てはまる新規アルゴリズムを容易に追加できることを意味します。
暗号化サービスプロバイダ
Java 暗号化アーキテクチャに、「暗号化サービスプロバイダ」(略して「プロバイダ」) の概念が導入されました。これは、JDK Security API の暗号化に関するサブセットの具体的な実装を提供するパッケージ (またはパッケージセット) です。
JDK 1.1 では、プロバイダには、1 つ以上のデジタル署名アルゴリズム、メッセージダイジェストアルゴリズム、および鍵生成アルゴリズムの実装などを含めることができました。JDK 1.2 では、鍵ファクトリ、キーストアの作成および管理、アルゴリズムパラメータの管理、アルゴリズムパラメータの生成、および証明書ファクトリの 5 種類のサービスが追加されています。また、JDK 1.2 では、プロバイダが乱数の生成 (RNG) アルゴリズムを提供できます。これまで、JDK では、特定のアルゴリズムはハードコードされており、RNG もプロバイダベースではありませんでした。
すでに説明したように、プログラムは単に、特定サービス (たとえば DSA 署名アルゴリズム) 用の特定型のオブジェクト (たとえば Signature オブジェクト) を要求するだけで、インストールされているプロバイダの 1 つから実装を獲得できます。あるいは、特定プロバイダを要求することもできます (各プロバイダは、それぞれの参照名を持つ)。
Java Runtime Environment の Sun バージョンには、SUN という名前のデフォルトのプロバイダが標準で搭載されています。ほかの Java Runtime Environment には、SUN プロバイダが含まれない場合があります。SUN プロバイダパッケージには、以下のものが含まれています。
- NIST FIPS 186 に記述されたデジタル署名アルゴリズム (DSA) の実装
- MD5 (RFC 1321) および SHA-1 (NIST FIPS 180-1) メッセージダイジェストアルゴリズムの実装
- DSA アルゴリズムに適した公開鍵および非公開鍵のペアの生成に必要な DSA 鍵のペアのジェネレータ
- DSA アルゴリズムパラメータジェネレータ
- DSA アルゴリズムパラメータマネージャ
- (不透明な) DSA 非公開鍵および公開鍵オブジェクトとそれらの背後の鍵データとの双方向変換を可能にする DSA 「鍵ファクトリ」
- IEEE P1363 標準 (Appendix G.7) の推奨に準拠した専用の "SHA1PRNG" 擬似乱数生成アルゴリズムの実装
- X.509 証明書の取り消しリスト (CRL) のための「証明書ファクトリ」
- JKS という独自のキーストア型のためのキーストアの実装
JDK では 1 つ以上のプロバイダパッケージがインストールされます。新規プロバイダは静的または動的に追加できます (Provider クラスと Security クラスを参照)。Java 暗号化アーキテクチャには、インストールされているプロバイダおよびそれらがサポートするサービスについて、ユーザが問い合わせることができる API セットがあります。
クライアントは異なるプロバイダを用いて実行環境を構成し、各プロバイダの「優先順位」を指定できます。優先順位とは、特定プロバイダの指定がない場合に、要求されたサービスに関して検索されるプロバイダの順位です。
鍵管理
鍵および証明書のリポジトリの管理には、「キーストア」と呼ばれるデータベースを使うことができます。
キーストアは、証明書または署名の目的でキーストアが必要なアプリケーションで利用できます。
アプリケーションは、キーストアクラスの実装によってキーストアにアクセスできます。キーストアクラスの実装は、
java.security
パッケージ内にあります。デフォルトのキーストアの実装は、米国 Sun Microsystems, Inc によって提供されます。ここでは、JKS という専用のキーストア型 (形式) を利用してキーストアをファイルとして実装してあります。アプリケーションでは、
KeyStore
クラスで提供される getInstance ファクトリメソッドを使って、異なるプロバイダから提供される数種類のキーストア実装から選択できます。詳細は、「鍵管理」の項を参照してください。
この項では、API に導入された重要概念について説明します。
エンジンクラスとアルゴリズム
「エンジンクラス」は、具体的な実装のない抽象的な方法で暗号化サービスを定義します。
暗号化サービスは、常に特定のアルゴリズムまたは型に関連付けられています。このサービスによって、暗号化の操作 (デジタル署名またはメッセージダイジェスト用など) の提供、暗号化の操作に必要な暗号化データ (鍵またはパラメータ) の生成や提供、あるいは暗号化の操作で使う暗号化鍵を安全にカプセル化するデータオブジェクト (キーストアまたは証明書) の生成が行われます。たとえば、Signature クラスおよび KeyFactory クラスは、エンジンクラスです。Signature クラスは、デジタル署名アルゴリズムの機能へのアクセスを提供します。DSA KeyFactory は、(コード化形式または透明な仕様から) DSA 非公開鍵または公開鍵を、それぞれ DSA Signature オブジェクトの
initSign
またはinitVerify
メソッドから利用可能な形式で提供します。Java 暗号化アーキテクチャには、エンジンクラスなどの、暗号化に関連する JDK 1.2 Security パッケージが含まれています。API のユーザは、エンジンクラスを要求および利用して対応する処理を実行します。JDK 1.2 では、次のエンジンクラスが定義されています。
- MessageDigest - 指定データのメッセージダイジェスト (ハッシュ) の計算に使います。
- Signature - デジタル署名の署名および検証に使います。
- KeyPairGenerator - 指定のアルゴリズムに適合した、公開鍵、非公開鍵ペアの生成に使います。
- KeyFactory - Key 型の不透明な暗号化鍵を「鍵仕様」(背後キーデータの透明な表現) に変換したり、その逆の変換を行うために使います。
- CertificateFactory - 公開鍵の証明書および証明書の取り消しリスト (CRL) の作成に使います。
- KeyStore - 「キーストア」の作成および管理に使います。キーストアは、鍵のデータベースです。キーストア内の非公開鍵には、鍵に関連付けられた証明連鎖があります。証明連鎖は、対応する公開鍵を認証します。また、キーストアには、信頼できるエンティティからの証明書も格納されています。
- AlgorithmParameters - パラメータの符号化および復号化など、特定のアルゴリズムのパラメータの管理に使います。
- AlgorithmParameterGenerator - 特定のアルゴリズムに適したパラメータセットの生成に使います。
- SecureRandom - 乱数または擬似乱数の生成に使います。
「ジェネレータ (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 暗号化サービスプロバイダが提供します。プロバイダとは、1 つまたは複数の暗号化サービスの実装を提供する基本パッケージです。たとえば、SUN という Java Development Kit のデフォルトのプロバイダは、DSN 署名アルゴリズム、MD5 と SHA-1 メッセージダイジェストアルゴリズム、DSA 鍵のペアの生成アルゴリズム、および SHA1PRNG 擬似乱数生成アルゴリズムを提供します。また、このプロバイダは、DSA 非公開鍵および公開鍵の鍵ファクトリ、X.509 証明書および CRL 用の証明書ファクトリ、DSA パラメータの実装 (生成を含む)、および JKS という専用のキーストア型の実装も提供します。
その他のプロバイダは、上記のサービスまたはその他のサービス (RSA ベースの署名アルゴリズムや MD2 メッセージダイジェストアルゴリズムなど) について、独自の実装を定義できます。
実装のインスタンスを獲得するためのファクトリメソッド
API の各エンジンクラスについては、エンジンクラス特有の「ファクトリメソッド」を呼び出すことによって特定の実装が要求され、インスタンスが生成されます。ファクトリメソッドは、クラスのインスタンスを返す static メソッドです。
たとえば、該当の Signature オブジェクト獲得機構は次のとおりです。ユーザは Signature クラスの
getInstance
メソッドを呼び出して、オブジェクトを要求します。署名アルゴリズム名 (SHA1withDSA など) を指定し、オプションで必要な実装を持つプロバイダ名も指定します。getInstance
メソッドが、指定のアルゴリズムおよびプロバイダのパラメータを満たす実装を検索します。プロバイダの指定がない場合、getInstance
は優先順位に従って登録プロバイダを検索し、指定のアルゴリズムを満たす実装を見つけ出します。プロバイダの登録の詳細は、Provider クラス を参照してください。
この項では、Java 暗号化アーキテクチャで提供するコアクラスとインタフェースについて説明します。
- Provider クラスと Security クラス
- MessageDigest エンジンクラス、 Signature エンジンクラス、 KeyPairGenerator エンジンクラス、 KeyFactory エンジンクラス、 AlgorithmParameters エンジンクラス、 AlgorithmParameterGenerator エンジンクラス、 CertificateFactory エンジンクラス、 KeyStore エンジンクラス、および SecureRandom エンジンクラス
- Key インタフェースおよびクラス
- 「アルゴリズムパラメータの仕様のインタフェースおよびクラス」および「鍵仕様のインタフェースおよびクラス」
この項では、各クラスおよびインタフェースのメインメソッドの署名を示します。該当する例の項には、クラス (MessageDigest、Signature、KeyPairGenerator、SecureRandom、KeyFactory、および鍵仕様クラス) の使用例があります。 セキュリティ API パッケージの完全なリファレンスドキュメントを以下に示します。
「暗号化サービスプロバイダ」 (短縮して「プロバイダ」) とは、JDK Security API の暗号化に関するサブセットの具体的な実装を提供するパッケージまたはパッケージセットです。Provider クラスは、このようなパッケージやパッケージセットへのインタフェースです。プロバイダ名、バージョン番号、その他の情報にアクセスするためのメソッドを備えています。
実際に暗号化サービスの実装を提供するには、エンティティ (たとえば開発グループ) は実装コードを作成し、Provider クラスのサブクラスを生成します。サブクラスのコンストラクタは、プロバイダが実装したサービスを検索するために JDK Security API に必要な各種プロパティの値を設定します。つまり、サービスを実装するクラス名を指定します。
プロバイダパッケージが実装できるサービスには、さまざまな種類があります。「エンジンクラスとアルゴリズム」を参照してください。
実装が違うと、特徴も違ってくる場合があります。ソフトウェアベースのものもあれば、ハードウェアベースのものもあります。プラットフォーム独立のものもあれば、プラットフォーム固有のものもあります。また、レビューや評価用に使えるプロバイダコードもあれば、使えないものもあります。
Java 暗号化アーキテクチャ (JCA) では、エンドユーザと開発者の双方が独自のニーズを決定できます。この項では、エンドユーザのための暗号実装のインストール方法とニーズへの合わせ方、および開発者のための必要な実装の要求方法を説明します。
注: プロバイダの実装の詳細は、「Java 暗号化アーキテクチャ用プロバイダの実装方法」を参照してください。
プロバイダ実装の要求および獲得方法
この API の各エンジンクラスについては、特定の実装が要求され、そのエンジンクラスのgetInstance
メソッドを呼び出してインスタンスが生成されます。このときに、希望するアルゴリズムの名前と、実装したいプロバイダの名前 (オプション) を指定します。プロバイダを指定しない場合、
getInstance
は、名前付きアルゴリズムに関連付けられ、要求された暗号化サービスの実装の登録プロバイダを検索します。どの Java Virtual Machine (JVM) でも、プロバイダは指定の「優先順位」でインストールされます。これは特定のプロバイダが要求されないときのプロバイダの検索順序です。たとえば、JVM にプロバイダが 2 つインストールされているとします。1 つは PROVIDER_1 であり、もう 1 つは PROVIDER_2 です。さらに、次のことを想定します。
- PROVIDER_1 は SHA1withDSA、SHA、MD5、DES、DES3 を実装
- PROVIDER_2 は SHA1withDSA、MD5withRSA、MD2withRSA、MD2、MD5、RC4、RC5、DES、RSA を実装
PROVIDER_1 の優先順位が 1 (最高の優先順位) で、PROVIDER_2 の優先順位が 2 の場合、以下の動作が行われます。
- MD5 実装を検索するとする。どちらのプロバイダもこの実装を供給する。PROVIDER_1 が最高の優先順位を持ち最初に検索されるので、PROVIDER_1 実装が返される
- MD5withRSA 署名アルゴリズムを検索する場合、まず最初に PROVIDER_1 が検索される。実装が見つからないので次に PROVIDER_2 が検索される。実装が見つかるので、このプロバイダが返される
- SHA1withRSA 署名アルゴリズムを検索する場合を想定する。これを実装するプロバイダはインストールされていないので、
NoSuchAlgorithmException
が発行されるプロバイダ引数を持つ
getInstance
メソッドは、必要なアルゴリズムを提供するプロバイダを指定したい開発者のためのものです。たとえば、連邦証明書を受け取ったプロバイダ実装を連邦局が使いたいとします。PROVIDER_1 の SHA1withDSA 実装はこの証明書を受け取っていないのに対し、PROVIDER_2 の DSA 実装がこれを受け取っていると仮定します。連邦プログラムは以下の呼び出しを実行します。PROVIDER_2 が認証された実装を持つため、これを指定します。
Signature dsa = Signature.getInstance("SHA1withDSA", "PROVIDER_2");この場合、「PROVIDER_2」がインストールされていないと、インストールされている別のプロバイダが要求アルゴリズムを実装している場合であっても、
NoSuchProviderException
が発行されます。プログラムは、(Security クラスの
getProviders
メソッドを使って) インストールされているプロバイダの一覧を獲得し、一覧から選択することもできます。プロバイダのインストール
プロバイダのインストールは 2 つの部分に分かれます。つまり、プロバイダパッケージクラスのインストールとプロバイダの構成です。
プロバイダクラスのインストール
プロバイダクラスのインストールには、次の 2 つの方法があります。
- クラスが格納されている zip または JAR ファイルを、CLASSPATH の任意の場所に置く
- プロバイダ JAR ファイルを、「インストールされた」または「バンドルされた」拡張機能として指定する。拡張機能の配置方法の詳細については、「拡張機能の配置」を参照
プロバイダの構成
次の手順では、認可プロバイダのリストにこのプロバイダを追加します。この処理は、JDK の
lib/security
ディレクトリにあるjava.security
ファイルを編集して静的に行います。つまり、JDK がjdk1.2
というディレクトリにインストールされている場合は、ファイルはjdk1.2/lib/security/java.security
です。java.security
に設定できるプロパティ型の 1 つは、以下の形式を取ります。security.provider.n=masterClassNameこれはプロバイダを宣言し、その優先順位 n を指定します。優先順位とは、特定プロバイダの指定がないときに、要求アルゴリズムについてプロバイダを検索する順序です。順位は 1 から始まり、1 が最優先で次に 2、3 ...と続きます。
masterClassName には、プロバイダの「マスター」クラスを指定する必要があります。プロバイダのドキュメントでそのマスタークラスを指定します。このクラスは、常に Provider クラスのサブクラスです。サブクラスコンストラクタは、プロバイダが実装したアルゴリズムやその他の機能を検索するために Java 暗号化 API に必要な各種プロパティの値を設定します。
マスタークラスが
COM.acme.provider.Acme
で、優先順位が第 3 位のプロバイダとしてAcme
を構成したいとします。このためには、次の行をjava.security
ファイルに追加します。security.provider.3=COM.acme.provider.Acmeプロバイダは、動的に登録することもできます。このためには、Security
クラスのaddProvider
またはinsertProviderAt
のどちらかのメソッドを呼び出します。この登録は恒久的ではなく、「信頼できる」プログラムでしか実行できません。Security クラスを参照してください。Provider クラスのメソッド
各 Provide クラスインタフェースは、名前 (現時点では大文字小文字を区別する)、バージョン番号、およびプロバイダとそのサービスの文字列記述を持ちます。以下のメソッドを呼び出して、これらの情報について Provider のインスタンスを照会できます。
public String getName() public double getVersion() public String getInfo()
Security クラスは、インストールされているプロバイダおよびセキュリティに関するプロパティを管理します。このクラスに含まれるのは、インスタンスが生成されない static メソッドだけです。
注: プロバイダの追加または削除、および Security プロパティの設定用メソッドは、信頼できるプログラムによってしか実行できません。現時点での「信頼できるプログラム」は、以下のどれかです
あるコードが、実行しようとしているアクション (プロバイダの追加など) を行うことができるような、信頼できるコードであると判断するには、そのアクションを行う権限がそのアプレットに与えられている必要があります。
- セキュリティマネージャの下で動作していないローカルアプリケーション
- 指定されたメソッドを実行する権限のあるアプレットまたはアプリケーション (以下を参照)
たとえば、デフォルトのポリシーの実装では、JDK インストールのポリシー構成ファイルには、指定されたコードソースのコードにより許可された権限 (システムリソースへのアクセスの種類) が指定されています。詳細は、以降の説明および「デフォルトの Policy の実装とポリシーファイルの構文」と「Java セキュリティアーキテクチャ (JDK 1.2)」を参照してください。
実行されているコードは、常に特定の「コードソース」のコードであるとみなされます。コードソースには、そのアプレットの元の場所 (URL) だけでなく、コードの署名に使われた非公開鍵に対応する公開鍵への参照も含まれています。コードソース内の公開鍵は、ユーザのキーストアの別名 (記号名) で参照します。
ポリシー構成ファイル内では、コードソースは、コードベース (URL)、および (signedBy で始まる) 別名の 2 つのコンポーネントで表現されます。別名は、コードの署名の検証に使う必要のある公開鍵を含んだキーストアのエントリを識別します。
このようなファイル内の各「許可」文は、指定されたコードソースにアクセス権のセットを与え、許可された処理を指定します。
ポリシー構成ファイルの内容の例を次に示します。
grant signedBy "sysadmin", codeBase "file:/home/sysadmin/" { permission java.security.SecurityPermission "Security.insertProvider.*"; permission java.security.SecurityPermission "Security.removeProvider.*"; permission java.security.SecurityPermission "Security.setProperty.*"; };これは、ローカルファイルシステム上の /home/sysadmin/ ディレクトリ内の署名された JAR ファイルからロードされたコードだけが、Security クラスのメソッドを呼び出して、プロバイダの追加または削除、あるいは Security プロパティの設定ができることを示します。JAR ファイルの署名は、ユーザのキーストア内の別名 sysadmin で参照する公開鍵を使って検証できます。コードソースとコンポーネントのどちらか (または両方) がない場合もあります。
codeBase
がない場合の例は、次のとおりです。grant signedBy "sysadmin" { permission java.security.SecurityPermission "Security.insertProvider.*"; permission java.security.SecurityPermission "Security.removeProvider.*"; };このポリシーが施行された場合、sysadmin によって署名された JAR ファイルのコードによるプロバイダの追加または削除が可能になります。JAR ファイルの場所は関係ありません。署名者がない場合の例は、次のとおりです。
grant codeBase "file:/home/sysadmin/" { permission java.security.SecurityPermission "Security.insertProvider.*"; permission java.security.SecurityPermission "Security.removeProvider.*"; };この場合は、ローカルファイルシステム上の /home/sysadmin/ ディレクトリの下にある任意のコードによるプロバイダの追加または削除が可能になります。コードが署名されている必要はありません。codeBase と signedBy のどちらも含まれていない場合の例は、次のとおりです。
grant { permission java.security.SecurityPermission "Security.insertProvider.*"; permission java.security.SecurityPermission "Security.removeProvider.*"; };この場合は、コードソースのコンポーネントが両方とも含まれていないので、任意のコードによるプロバイダの追加または削除が可能になります。コードの場所、コードが署名されているか、あるいはだれが署名したかは関係ありません。プロバイダの管理
セキュリティクラスを使って、インストールされているプロバイダを照会するだけでなく、実行時に新規のプロバイダをインストールすることもできます。
プロバイダの照会
public Provider[] getProviders()このメソッドは、インストールされているすべてのプロバイダを含む配列 (つまり、各パッケージプロバイダの Provider サブクラス) を返します。配列内のプロバイダの順序は、優先順位に従います。
public Provider getProvider(String providerName)このメソッドは、
providerName
という名前のプロバイダを返します。このプロバイダが見つからないとnull
を返します。プロバイダの追加
public static int addProvider(Provider provider) {このメソッドは、インストールされたプロバイダ一覧の末尾にプロバイダを追加します。プロバイダが追加された優先順位を返すか、すでにインストールされているためにプロバイダが追加されなかった場合は -1 を返します。
public int insertProviderAt(Provider provider, int position)このメソッドは、指定位置に新規のプロバイダを追加します。位置とは、特定プロバイダの指定がない場合に、要求アルゴリズムに対してプロバイダが検索される優先順位です。位置は 1 から始まり、1 が最優先で次に 2、3 ...と続きます。あるプロバイダが要求された場所にインストールされた場合は、それまでその場所にあったプロバイダ、および
position
よりあとの位置のすべてのプロバイダの順位は、1 つあとになり、インストールされたプロバイダ一覧の最後尾に向かって 1 つ移動します。プロバイダが要求位置に必ず追加されるとは限らないことに注意してください。たとえば、プロバイダを追加できても、一番最後の位置だけに限られる場合もあります。このような場合は、
position
引数は無視されます。また、すでにインストール済みのプロバイダは追加できません。このメソッドは、プロバイダが追加された実際の位置を返します。すでにインストールされているためプロバイダが追加されなかった場合は、-1 を返します。
注: プロバイダの優先順位を変更する場合は、まず目的のプロバイダを削除してから、希望する優先順位の位置に挿入し直す必要があります。
プロバイダの削除
public void removeProvider(String name)このメソッドは、指定した名前のプロバイダを削除します。プロバイダがインストールされていない場合は、何もせず復帰します。指定されたプロバイダが削除されると、そのプロバイダよりもあとの位置にあるすべてのプロバイダの位置が 1 つ前になり、インストールされたプロバイダ一覧の先頭に向かって 1 つ移動します。
セキュリティのプロパティ
Security クラスは、システムに関するセキュリティのプロパティリストを保持します。これらのプロパティは、以下のメソッドを使って、信頼できるプログラムからアクセスして設定できます。
public static String getProperty(String key) public static void setProperty(String key, String datum)
MessageDigest クラスはエンジンクラスで、安全な暗号化メッセージダイジェスト (SHA-1 や MD5 など) の機能を提供するように設計されています。安全な暗号化メッセージダイジェストは、任意サイズの入力 (バイト配列) を取り、固定サイズ出力を生成します。これを「ダイジェスト」または「ハッシュ」と言います。ダイジェストのプロパティは次のとおりです。
- 計算によって、同じ値にハッシュされた 2 つのメッセージを検索できない
- ダイジェストの生成に使った入力情報を明らかにしない
メッセージダイジェストを使い、一意で、信頼できるデータ識別子を生成します。データ識別子をデータの「デジタル指紋」と呼ぶこともあります。
MessageDigest オブジェクトの生成
ダイジェスト計算では、まず最初にメッセージダイジェストのインスタンスを生成します。どのエンジンクラスの場合も同様に、MessageDigest クラスの static ファクトリメソッド
getInstance
を呼び出して、特定型のメッセージダイジェストアルゴリズムの MessageDigest オブジェクトを獲得します。
public static MessageDigest getInstance(String algorithm)注: アルゴリズム名は、大文字と小文字が区別されません。たとえば、次の呼び出しはすべて等価とみなされます。
MessageDigest.getInstance("SHA") MessageDigest.getInstance("sha") MessageDigest.getInstance("sHa")呼び出し側は、オプションでプロバイダ名を指定できます。こうすると、要求するアルゴリズムの実装を確実に指定プロバイダから取得できます。
public static MessageDigest getInstance(String algorithm, String provider)
getInstance
を呼び出すと、初期化されたメッセージダイジェストオブジェクトが返ります。従って、このあとで初期化を行う必要はありません。メッセージダイジェストオブジェクトのアップデート
データのダイジェストを計算するための次の手順は、初期化したメッセージダイジェストオブジェクトにデータを入れることです。次の
update
メソッドのどれか 1 つを 1 回または複数回呼び出して実行します。
public void update(byte input) public void update(byte[] input) public void update(byte[] input, int offset, int len)ダイジェストの計算
update
メソッドを呼び出してデータを入れたあとで、次のdigest
メソッドのうちのどれか 1 つを使ってダイジェストを計算します。
public byte[] digest() public byte[] digest(byte[] input) public int digest(byte[] buf, int offset, int len)最初の 2 つのメソッドは、計算されたダイジェストを返します。最後のメソッドは、与えられたバッファ buf 内の offset 以降の計算されたダイジェストを格納します。len は、ダイジェストに割り当てられた buf 内のバイト数です。このメソッドは、実際に buf 内に格納されたバイト数を返します。
入力バイトの配列を引数にとる
digest
メソッドの呼び出しは、以下の呼び出しと等価です。public void update(byte[] input)入力を指定し、そのあとに引数を持たないdigest
メソッドの呼び出しが続きます。詳細は例の項を参照してください。
Signature クラスはエンジンクラスで、DSA や MD5 を使う RSA などの暗号化デジタル署名機能を提供するように設計されています。安全な暗号化署名アルゴリズムは、任意サイズの入力と非公開鍵を取り、「署名」と呼ばれる比較的短い (固定サイズの場合もよくある) バイト文字列を生成します。このプロパティは次のとおりです。
- 署名の生成に使う非公開鍵に対応する公開鍵が与えられる。これは入力の認証性および整合性を検証できる
- 署名および公開鍵は、非公開鍵に関する情報を明らかにはしない
Signature オブジェクトを使って、データに署名を付けることができます。また、指定の署名が、関連データの実際の認証署名かどうかを検証することもできます。データの署名および検証の例は、例の項を参照してください。
Signature オブジェクトの状態
Signature オブジェクトはモデルオブジェクトです。つまり、Signature オブジェクトは、常に指定の状態にあり、この状態で 1 つの型のオペレーションだけを実行できます。状態は、個々のクラス (たとえば Signature など) で定義した final (ファイナル) 整数の定数で表されます。Signature オブジェクトに可能な状態は、次の 3 つです。
Signature オブジェクトが初めて生成されるときは、UNINITIALIZED の状態です。Signature クラスは、状態を
- UNINITIALIZED
- SIGN
- VERIFY
SIGN
に変更するinitSign
と、状態をVERIFY
に変更するinitVerify
の 2 つの初期化メソッドを定義します。Signature オブジェクトの生成
署名を付けたり、検証したりするには、最初に Signature のインスタンスを生成します。どのエンジンクラスの場合も同様に、Signature クラスのgetInstance
static (スタティック) ファクトリメソッドを呼び出して、特定型の署名アルゴリズムの Signature オブジェクトを獲得します。public static Signature getInstance(String algorithm)注: アルゴリズム名の大文字と小文字は区別されません。
呼び出し側は、オプションでプロバイダ名を指定できます。こうすると、要求するアルゴリズムの実装を確実に指定プロバイダから取得できます。
public static Signature getInstance(String algorithm, String provider)Signature オブジェクトの初期化
Signature オブジェクトを使うには、最初に必ずこれを初期化します。初期化メソッドは、オブジェクトを最初に署名用に使うか検証用に使うかに応じて異なります。
署名で使う場合、オブジェクトは最初に、署名を生成するエンティティの非公開鍵を使って初期化する必要があります。この初期化は、以下のメソッドを呼び出して実行します。
public final void initSign(PrivateKey privateKey)このメソッドでは、Signature オブジェクトは SIGN 状態になります。Signature オブジェクトを検証で使う場合は、まず最初に、署名を検証するエンティティの公開鍵を使って初期化する必要があります。この初期化は、以下のメソッドを呼び出して実行します。
public final void initVerify(PublicKey publicKey)このメソッドでは、Signature オブジェクトは VERIFY 状態になります。
署名
Signature オブジェクトを署名用に初期化した場合 (このオブジェクトが SIGN 状態の場合)、署名を付けるデータをオブジェクトに入れることができます。これは、以下の
update
メソッドのどれか 1 つを 1 回または複数回呼び出して実行します。
public final void update(byte b) public final void update(byte[] data) public final void update(byte[] data, int off, int len)署名を付けるデータがすべて Signature オブジェクトに入るまで、
update
メソッドを呼び出します。署名を生成するには、
sign
メソッドの 1 つを呼び出すだけです。
public final byte[] sign() public final int sign(byte[] outbuf, int offset, int len)最初のメソッドは、署名の結果をバイト配列で返します。2 番目のメソッドは、指定されたバッファ outbuf 内の offset 以降に署名の結果を格納します。len は、署名に割り当てられた outbuf 内のバイト数です。このメソッドは、実際に格納されたバイト数を返します。
署名は、2 つの整数
r
およびs
の、標準 ASN.1 シーケンスとしてコード化されます。Java 暗号化アーキテクチャでの ASN.1 コード化の使用方法については、付録 B を参照してください。
sign
メソッドを呼び出すと、signature (署名) オブジェクトは、initSign
を呼び出して最初に署名用に初期化されたときの状態にリセットされます。つまり、オブジェクトをリセットするので、必要であればupdate
とsign
を呼び出して、同じ非公開鍵を使って別の署名を生成できます。あるいは異なる非公開鍵を指定し、
initSign
への新規呼び出しを作成したり、(署名を検証するために Signature オブジェクトを初期化する目的で)initVerify
への新規呼び出しを作成できます。検証
Signature オブジェクトを検証用に初期化した場合 (VERIFY 状態にある場合) は、指定の署名が、それに関連したデータの実際の認証署名であるかどうかを検証できます。この処理を開始するには、検証データ (署名自体ではない) をオブジェクトに入れます。これは、以下の
update
メソッドのどれか 1 つを 1 回または複数回呼び出して実行します。public final void update(byte b) public final void update(byte[] data) public final void update(byte[] data, int off, int len)すべてのデータが Signature オブジェクトに入るまで、
update
メソッドを呼び出します。このあとで、
verify
メソッドを呼び出して署名を検証できます。
public final boolean verify(byte[] encodedSignature)引数は、2 つの整数
r
およびs
の標準 ASN.1 シーケンスとしてコード化した署名を含むバイト配列である必要があります。これは頻繁に使用する標準コード化です。sign
メソッドが生成するものと同じです。
verify
メソッドは、コード化した署名がupdate
メソッドに入れたデータの認証署名かどうかを示すboolean
を返します。
verify
メソッドを呼び出すと、signature (署名) オブジェクトは、initVerify
を呼び出して最初に検証用に初期化されたときの状態にリセットされます。つまり、オブジェクトをリセットするので、initVerify
への呼び出しで指定した公開鍵を持つ識別の別の署名を検証できます。あるいは異なる非公開鍵を指定し、(異なるエンティティの署名を検証するために Signature オブジェクトを初期化する目的で)
initVerify
への新規呼び出しを作成したり、(署名を生成するために Signature オブジェクトを初期化する目的で)initSign
への新規呼び出しを作成できます。
アルゴリズムパラメータの仕様のインタフェースおよびクラス
アルゴリズムパラメータの仕様は、アルゴリズムとともに使われるパラメータのセットの透明な表現です。
パラメータのセットの「透明な」表現とは、対応する仕様クラスに定義された get メソッドの 1 つを使って、セットの各パラメータの値に個々にアクセスできるということです。たとえば、DSAParameterSpec は、
getP
、getQ
、およびgetG
メソッドを定義して、それぞれ p、q、および g にアクセスします。これと対照的なのが、AlgorithmParameters クラスによって提供される場合のような「不透明な」表現です。この場合は、パラメータフィールドに直接アクセスすることはできません。パラメータセットに関連付けられたアルゴリズム名の取得 (
getAlgorithm
による)、およびそのパラメータセット用のある種の符号化の取得 (getEncoded
による) しかできません。以下は、
java.security.spec
パッケージに含まれるアルゴリズムパラメータ仕様のインタフェースおよびクラスの説明です。AlgorithmParameterSpec インタフェース
AlgorithmParameterSpec は、暗号化パラメータの透明な仕様へのインタフェースです。このインタフェースには、メソッドまたは定数が含まれていません。このインタフェースの唯一の目的は、すべてのパラメータの仕様をグループ化すること (およびそれらのパラメータに安全な型を提供すること) です。すべてのパラメータの仕様で、このインタフェースを実装する必要があります。
DSAParameterSpec クラス
AlgorithmParameterSpec インタフェースを実装するこのクラスは、DSA アルゴリズムで使われるパラメータのセットを指定します。次のメソッドがあります。public BigInteger getP() public BigInteger getQ() public BigInteger getG()これらのメソッドは、DSA アルゴリズムのパラメータ (プライムのp
、サブプライムのq
、およびベースのg
) を返します。AlgorithmParameters クラス
AlgorithmParameters クラスは、暗号化パラメータの不透明な表現を提供するエンジンクラスです。「不透明な」表現では、パラメータフィールドに直接アクセスすることはできません。パラメータセットに関連付けられたアルゴリズム名の取得、およびそのパラメータセット用のある種の符号化の取得しかできません。これと対照的なのが、パラメータの「透明な」表現です。この場合、対応する仕様クラスで定義された get メソッドの 1 つを使って、各値に個々にアクセスできます。AlgorithmParameters に
getParameterSpec
メソッドを呼び出して、AlgorithmParameters オブジェクトを透明な仕様に変換できます (以下を参照)。AlgorithmParameters オブジェクトの作成
ほかのエンジンクラスと同様に、特定の型のアルゴリズムに対する AlgorithmParameters オブジェクトを取得するには、AlgorithmParameters クラスの
getInstance
static ファクトリメソッドを呼び出します。
public static AlgorithmParameters getInstance(String algorithm)注: アルゴリズム名の大文字と小文字は区別されません。
呼び出し側は、オプションでプロバイダ名を指定できます。これにより、要求されたアルゴリズムパラメータの実装を指定したプロバイダから確実に取得できます。
public static AlgorithmParameters getInstance(String algorithm, String provider)AlgorithmParameters オブジェクトの初期化
AlgorithmParameters オブジェクトのインスタンスが生成されたら、適切なパラメータの仕様またはパラメータの符号化を使って、
init
への呼び出しによる初期化を行う必要があります。public void init(AlgorithmParameterSpec paramSpec) public void init(byte[] params) public void init(byte[] params, String format)上のparams
は、符号化されたパラメータを含む配列で、format
は、復号化形式の名前です。params
引数を指定し、format
引数を指定しないinit
メソッドでは、パラメータのプライマリ復号化形式が使われます。パラメータの ASN.1 仕様が存在する場合は、プライマリ復号化形式は、ASN.1 です。注: AlgorithmParameters オブジェクトは、1 度だけ初期化できます。再利用はできません。
符号化されたパラメータの取得
AlgorithmParameters オブジェクトで表現されるパラメータのバイト符号化は、
getEncoded
への呼び出しによって取得できます。public byte[] getEncoded()これにより、パラメータがプライマリ符号化形式で返されます。この種のパラメータの ASN.1 仕様が存在する場合は、プライマリ復号化形式は、ASN.1 です。
特定の形式でパラメータが返されるようにするには、次のように記述します。
public byte[] getEncoded(String format)format
が null の場合は、ほかのgetEncoded
メソッドと同様に、プライマリ復号化形式が使われます。注: SUN プロバイダによって提供されるデフォルトの AlgorithmParameters の実装では、
format
引数は、現在のところ無視されます。AlgorithmParameters オブジェクトから透明な仕様への変換
アルゴリズムパラメータの透明なパラメータの仕様は、
getParameterSpec
への呼び出しにより、AlgorithmParameters オブジェクトから取得できます。public AlgorithmParameterSpec getParameterSpec(Class paramSpec)paramSpec
は、パラメータが返されるべき仕様クラスを識別します。たとえば、パラメータが、(java.security.spec
パッケージ内の)DSAParameterSpec
クラスのインスタンス内に返されることを示すのは、DSAParameterSpec.class
です。AlgorithmParameterGenerator クラス
AlgorithmParameterGenerator クラスは、特定のアルゴリズム (AlgorithmParameterGenerator のインスタンスの作成時に指定されるアルゴリズム) に適したパラメータのセットの生成に使用されるエンジンクラスです。AlgorithmParameterGenerator オブジェクトの作成
ほかのエンジンクラスと同様に、特定の型のアルゴリズム用の AlgorithmParameterGenerator オブジェクトを取得するには、AlgorithmParameterGenerator クラスの
getInstance
static ファクトリメソッドを呼び出します。
public static AlgorithmParameterGenerator getInstance( String algorithm)注: アルゴリズム名の大文字と小文字は区別されません。
呼び出し側は、オプションでプロバイダ名を指定できます。これにより、アルゴリズムパラメータジェネレータの実装を指定したプロバイダから確実に取得できます。
public static AlgorithmParameterGenerator getInstance( String algorithm, String provider)AlgorithmParameterGenerator オブジェクトの初期化
AlgorithmParameterGenerator オブジェクトは、アルゴリズム独立型、またはアルゴリズム特定型の 2 種類の方法で初期化できます。
アルゴリズム独立型の方法では、すべてのパラメータジェネレータが「サイズ」および乱数の発生源という概念を共有するという特性を利用します。サイズの単位は、すべてアルゴリズムパラメータで普遍的に共通していますが、その解釈はアルゴリズムにより異なります。たとえば、DSA アルゴリズムのパラメータの場合、「サイズ」はプライム係数のビット数のサイズに一致します。特定のアルゴリズムのサイズについては、付録 B「アルゴリズム」を参照してください。この方法を使うと、アルゴリズム特定型のパラメータの生成値が (ある場合は)、デフォルト基準値になります。普遍的に共有されるこれら 2 つの引数の型をとる
init
メソッドがあります。public void init(int size, SecureRandom random);また、size
引数だけをとるinit
メソッドもあります。このメソッドでは、システムが提供する乱数の発生源が使われます。public void init(int size)もう 1 つの方法では、パラメータジェネレータオブジェクトの初期化にアルゴリズム特定型のセマンティクスを使います。アルゴリズム特定型のセマンティクスは、AlgorithmParameterSpec オブジェクト内に提供されるアルゴリズム特定型のパラメータ生成値のセットによって表されます。
public void init(AlgorithmParameterSpec genParamSpec, SecureRandom random) public void init(AlgorithmParameterSpec genParamSpec)たとえば、Diffie-Hellman システムパラメータを生成するには、通常、パラメータ生成値は、プライム係数およびランダム指数のサイズで構成されます。どちらのサイズもビット数で指定します。Diffie-Hellman アルゴリズムは、JCE 1.2 の一部として提供されます。アルゴリズムパラメータの生成
AlgorithmParameterGenerator オブジェクトを作成および初期化したら、generateParameters
メソッドを使ってアルゴリズムパラメータを生成できます。public AlgorithmParameters generateParameters()
Key インタフェースは、すべての不透明な鍵に関するトップレベルのインタフェースです。すべての不透明な鍵オブジェクトが共有する機能を定義します。
「不透明な」鍵の表現では、鍵を構成する鍵データに直接アクセスできません。「不透明」であるために、鍵へのアクセスが、Key インタフェースによって定義される
getAlgorithm
、getFormat
、およびgetEncoded
の 3 つのメソッドだけに制限されます。これと対照的なのが「透明な」表現で、この場合は、対応する仕様クラス内に定義された get メソッドの 1 つを使って、各鍵データの値に個々にアクセスできます。不透明な鍵はすべて、次の 3 つの特性を持ちます。
鍵は一般的に、鍵ジェネレータ、証明書、鍵仕様 (KeyFactory を使用) または鍵管理で使う「キーストア」データベースにアクセスする KeyStore の実装から獲得します。
- アルゴリズム
鍵に対するの鍵のアルゴリズムである。通常、鍵のアルゴリズムは、暗号化または非対称オペレーションアルゴリズム (DSA や RSA など) で、これらのアルゴリズムや関連アルゴリズム (RSA を使う MD5、RSA を使う SHA-1 など) と連携して機能する。鍵のアルゴリズム名は、以下のメソッドを使って獲得する
public String getAlgorithm()
- コード化形式
これは鍵の外部コード化形式で、鍵を別の組織に転送する際に、鍵の標準表示が Java Virtual Machine の外部で必要なときに使う。鍵は標準形式 (X.509 や PKCS#8 など) に従ってコード化され、以下のメソッドを使って返される
public byte[] getEncoded()
- フォーマット
これはコード化した鍵のフォーマット名である。以下のメソッドから返される
public String getFormat()
KeyFactory を使って、アルゴリズム依存型の方法で符号化された鍵を解析することが可能です。
また、CertificateFactory を使って、認証を解析することも可能です。
PublicKey および PrivateKey インタフェース
PublicKey および PrivateKey インタフェースはどちらも Key インタフェースを継承しますが、これらはメソッドを使わないインタフェースで、型の安全性および型の識別に使用します。
鍵仕様は、鍵を構成する鍵データの透明な表現です。鍵がハードウェアデバイス上に格納されている場合は、その鍵仕様には、デバイス上の鍵の識別を助ける情報が含まれていることがあります。 鍵の「透明な」表現とは、対応する仕様クラスで定義された get メソッドの 1 つを使って、各鍵データに個々にアクセスできるということです。たとえば、DSAPrivateKeySpec は、
getX
、getP
、getQ
、およびgetG
メソッドを定義し、非公開鍵x
および鍵の計算に使う DSA アルゴリズムのパラメータ (プライムのp
、サブプライムのq
およびベースのg
) にアクセスします。これと対照的なのが、Key インタフェースによって定義されるような、「不透明な」表現です。「不透明な」鍵の表現では、鍵要素フィールドに直接アクセスできません。「不透明な」ため、鍵へのアクセスが、Key インタフェースによって定義される
getAlgorithm
、getFormat
、およびgetEncoded
の 3 つのメソッドだけに制限されます。鍵は、アルゴリズム特定型か、またはアルゴリズム独立型の符号化形式 (ASN.1 など) の方法で指定できます。たとえば、DSA 非公開鍵は、非公開鍵のコンポーネント
x
、p
、q
、およびg
によって指定するか (DSAPrivateKeySpec を参照)、または、非公開鍵の DER 符号化を使って指定することが可能です (PKCS8EncodedKeySpec を参照)。鍵仕様のインタフェースおよびクラスは、
java.security.spec
パッケージ内に含まれています。これらについては、以下で説明します。KeySpec インタフェース
このインタフェースには、メソッドまたは定数が含まれていません。このインタフェースの唯一の目的は、すべての鍵仕様をグループ化すること (およびそれらのグループに安全な型を提供すること) です。すべての鍵仕様で、このインタフェースを実装する必要があります。
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 クラスを継承) は、PKCS#1 標準で定義されているように、中国剰余定理 (CRT) 情報の値を使って、RSA 非公開鍵を指定します。このクラスには、スーパークラスの RSAPrivateKeySpec から継承したメソッドのほかに、次のメソッドがあります。public BigInteger getPublicExponent() public BigInteger getPrimeP() public BigInteger getPrimeQ() public BigInteger getPrimeExponentP() public BigInteger getPrimeExponentQ() public BigInteger getCrtCoefficient()これらのメソッドは、公開指数e
および CRT 情報の整数を返します。CRT 情報の整数は、係数n
の素因数p
、n
の素因数q
、指数d mod (p-1)
、指数d mod (q-1)
、および中国剰余定理の係数(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();具体的な実装 PKCS8EncodedKeySpec および X509EncodedKeySpec については、以下を参照してください。
PKCS8EncodedKeySpec クラス
このクラスは、EncodedKeySpec のサブクラスで、PKCS #8 標準で指定された形式に従って、非公開鍵の DER 符号化を表現します。このクラスの
getEncoded
メソッドは、PKCS #8 標準に従って符号化された鍵のバイトを返します。このクラスのgetFormat
メソッドは、文字列 PKCS#8 を返します。X509EncodedKeySpec クラス
このクラスは、EncodedKeySpec のサブクラスで、X.509 標準で指定された形式に従って、公開鍵または非公開鍵の DER 符号化を表現します。このクラスの
getEncoded
メソッドは、X.509 標準に従って符号化された鍵のバイトを返します。このクラスのgetFormat
メソッドは、文字列 X.509 を返します。
KeyFactory クラスは、不透明な暗号化鍵 (Key 型) と、鍵仕様 (背後の鍵データの透明な表現) 間の変換を提供する目的で設計されたエンジンクラスです。鍵ファクトリは、双方向性があります。つまり、これによって、与えられた鍵仕様 (鍵のデータ) から不透明な鍵オブジェクトを構築することも、鍵オブジェクトの背後の鍵データを適切な形式で取得することもできます。
同一の鍵に対して、複数の互換性のある鍵仕様が存在することがあります。たとえば、DSA 公開鍵は、コンポーネント
y
、p
、q
、およびg
によって指定することも (DSAPublicKeySpec を参照)、X.509 標準に従って DER 符号化を使って指定することも (X509EncodedKeySpec を参照) できます。鍵ファクトリは、互換性のある鍵仕様間の変換に使用できます。互換性のある鍵仕様間の翻訳では、鍵の構文解析が行われます。たとえば、X509EncodedKeySpec を DSAPublicKeySpec に翻訳する場合は、基本的に符号化された鍵をコンポーネント単位で解釈処理します。例については、「鍵仕様および KeyFactory を使った署名の生成と検証」の最後を参照してください。
KeyFactory オブジェクトの作成
ほかのエンジンクラスと同様に、特定の型の鍵アルゴリズム用の KeyFactory オブジェクトを取得するには、KeyFactory クラスの
getInstance
static ファクトリメソッドを呼び出します。
public static KeyFactory getInstance(String algorithm)注: アルゴリズム名は、大文字と小文字が区別されません。
呼び出し側は、オプションでプロバイダ名を指定できます。こうすると、要求された鍵ファクトリの実装を指定プロバイダから確実に取得できます。
public static KeyFactory getInstance(String algorithm, String provider)鍵仕様と Key オブジェクト間の変換
公開鍵用の鍵仕様がある場合は、
generatePublic
メソッドを使って、その仕様から不透明な PublicKey オブジェクトを取得できます。public PublicKey generatePublic(KeySpec keySpec)同様に、非公開鍵用の鍵仕様がある場合は、
generatePrivate
メソッドを使って、その仕様から不透明な PrivateKey オブジェクトを取得できます。public PrivateKey generatePrivate(KeySpec keySpec)Key オブジェクトと鍵仕様間の変換
Key オブジェクトがある場合は、
getKeySpec
メソッドの呼び出しによって、対応する鍵仕様を取得できます。public KeySpec getKeySpec(Key key, Class keySpec)keySpec
は、鍵のデータが返されるべき仕様クラスを識別します。たとえば、DSAPublicKeySpec.class
は、鍵のデータがDSAPublicKeySpec
クラスのインスタンスに返されるべきであることを指示します。詳細は、例を参照してください。
CertificateFactory クラスは、証明書ファクトリの機能を定義するエンジンクラスです。証明書ファクトリは、証明書および証明書の取り消しリスト (CRL) オブジェクトをその符号化から生成するために使用されます。X.509 の証明書ファクトリは、
java.security.cert.X509Certificate
のインスタンスである証明書、およびjava.security.cert.X509CRL
のインスタンスである CRL を返します。CertificateFactory オブジェクトの作成
ほかのエンジンクラスと同様に、特定の証明書または CRL の型に対して CertificateFactory オブジェクトを取得するには、CertificateFactory クラスの
getInstance
static ファクトリメソッドを呼び出します。
public static CertificateFactory getInstance(String type)注: 型名の大文字と小文字は区別されません。
呼び出し側は、オプションでプロバイダ名を指定できます。こうすると、要求された証明書ファクトリの実装を指定プロバイダから確実に取得できます。
public static CertificateFactory getInstance(String type, String provider)証明書オブジェクトの生成
証明書オブジェクトを生成し、入力ストリームから読み込まれたデータを使って初期化するには、generateCertificate
メソッドを使います。public final Certificate generateCertificate(InputStream inStream)特定の入力ストリームから読み込まれた証明書のコレクションビュー (空の可能性もある) を返すには、generateCertificates
メソッドを使います。public final Collection generateCertificates(InputStream inStream)CRL オブジェクトの生成
(CRL) 証明書の取り消しリストオブジェクトを生成し、入力ストリームから読み込まれたデータを使って初期化するには、generateCRL
メソッドを使います。public final CRL generateCRL(InputStream inStream)特定の入力ストリームから読み込まれた CRL のコレクションビュー (空の可能性もある) を返すには、generateCRLs
メソッドを使います。public final Collection generateCRLs(InputStream inStream)
KeyPair クラスは鍵のペア (公開鍵と非公開鍵) の簡単なホルダーで、2 つの public メソッドがあります。1 つは非公開鍵を返し、もう 1 つは公開鍵を返します。
public PrivateKey getPrivate() public PublicKey getPublic()
KeyPairGenerator クラスはエンジンクラスで、public および非公開鍵のペアの生成に使います。
鍵のペアの生成方法には、アルゴリズム独立型とアルゴリズム特定型の 2 つがあります。この 2 つの唯一の相違点は、オブジェクトの初期化にあります。以下のメソッドの呼び出し例は、例の項を参照してください。
KeyPairGenerator の生成
すべての鍵のペアは、まず最初に KeyPairGenerator を使って生成します。これは、KeyPairGenerator の以下のファクトリメソッドのどれか 1 つを使って実行します。
public static KeyPairGenerator getInstance(String algorithm) public static KeyPairGenerator getInstance(String algorithm, String provider)注: アルゴリズム名の大文字と小文字は区別されません。
KeyPairGenerator の初期化
特定のアルゴリズム用の鍵のペアのジェネレータは、そのアルゴリズムで使うことができる公開鍵または非公開鍵を作成します。また、アルゴリズム特定型のパラメータを生成された各鍵に関連付けます。まず、鍵のペアを初期化してからでなければ、鍵のペアは鍵を生成できません。ほとんどの場合、アルゴリズム独立型の初期化で十分です。ただし、アルゴリズム特定型の初期化を利用する必要のある場合もあります。
アルゴリズム独立型の初期化
すべての鍵ジェネレータは、キーサイズおよび乱数の発生源の概念を共有します。キーサイズは、アルゴリズムごとに解釈が異なります。たとえば、DSA アルゴリズムの場合、キーサイズは係数の長さと一致します。特定のアルゴリズムのキーサイズについては、「付録 B: アルゴリズム」を参照してください。
一般的に共有されるこの 2 つの型の引数を取る
initialize
メソッドがあります。public void initialize(int keysize, SecureRandom random)また、keysize
引数だけを取るinitialize
メソッドもあります。このメソッドでは、システムが提供する乱数の発生源が使われます。public void initialize(int keysize)上のアルゴリズム独立型
initialize
メソッドを呼び出すときは、その他のパラメータは指定しないため、各鍵に関連付けられるアルゴリズム特定型のパラメータがある場合は、そのパラメータの処理は、プロバイダによって異なります。アルゴリズムが DSA アルゴリズムで、係数のサイズ (キーサイズ) が 512、768、または 1024 の場合は、SUN プロバイダは
p
、q
、およびg
パラメータ用に事前に計算した値を使います。係数のサイズが上記の値の 1 つでない場合は、SUN プロバイダは、新しいパラメータのセットを作成します。これらの 3 つの係数サイズ以外の、事前に計算されたパラメータセットを持つプロバイダが存在する可能性もあります。また、事前に計算されたパラメータがなく、常に新しいパラメータセットを作成するプロバイダが存在する可能性もあります。アルゴリズム特定型の初期化
アルゴリズム特定型パラメータのセットがすでに存在する状況では (いわゆる DSA の「コミュニティパラメータ」)、AlgorithmParameterSpec 引数を取る
initialize
メソッドが 2 つあります。このうちの一方は、SecureRandom 引数も取りますが、他方では、乱数の発生源はシステムによって提供されます。public void initialize(AlgorithmParameterSpec params, SecureRandom random) public void initialize(AlgorithmParameterSpec params)詳細は例の項を参照してください。
鍵のペアの生成
鍵のペアの生成は、初期化 (およびアルゴリズム) に関係なく、常に同じです。必ず KeyPairGenerator から以下のメソッドを呼び出します。
public KeyPair generateKeyPair()generateKeyPair を呼び出すたびに、異なる鍵のペアが作られます。
「キーストア」と呼ばれるデータベースは、鍵および証明書のリポジトリを管理するために使用できます。「証明書」は、あるエンティティからのデジタルに署名された文で、別のあるエンティティの公開鍵に特定の値が含まれていることを示します。キーストアの実装
キーストアクラスは、キーストア内の情報へのアクセスおよび情報の変更を行うための、明確に定義されたインタフェースを提供します。複数の具体的な実装が存在しつつ、各実装が特定のタイプのキーストアに対応することも可能です。現在、キーストアを利用するコマンド行ツールには、keytool と jarsigner の 2 つがあります。また、GUI ベースの policytool というツールもあります。さまざまなソースのコードに対して (システムリソースへの) アクセス権を指定するポリシーファイルを処理する場合、このツールはデフォルトポリシーの実装によっても使われます。キーストアは、広範に利用できるので、JDK のユーザは、キーストアを使ったほかのセキュリティアプリケーションを記述することもできます。
米国 Sun Microsystems, Inc によって提供される組込み型のデフォルト実装があります。この実装により、JKS という専用のキーストアのタイプ (形式) を利用して、ファイルとしてキーストアが実装されます。この実装では、各非公開鍵が個々のパスワードによって保護され、キーストア全体の整合性もパスワード (別のパスワードの可能性もある) によって保護されています。
キーストアの実装は、プロバイダベースです。
KeyStore
が提供するアプリケーションインタフェースは、Service Provider Interface (SPI) に置き換えて実装されます。つまり、対応する抽象KeystoreSpi
クラスがjava.security
パッケージ内にも存在し、そのクラスによって「プロバイダ」が実装しなければならない Service Provider Interface が定義されます。「プロバイダ」とは、JDK Security API によってアクセス可能なサービスのサブセットの具体的な実装を提供するパッケージまたはパッケージのセットのことです。このため、キーストアの実装を提供するには、「Java 暗号化アーキテクチャ用プロバイダの実装方法」に記述されているように、クライアントは「プロバイダ」を実装し、さらに KeystoreSpi サブクラスの実装を提供する必要があります。アプリケーションは、
KeyStore
クラスで提供される getInstance ファクトリメソッドを使って、異なるプロバイダから複数のタイプのキーストア実装を選択できます。キーストアのタイプは、キーストア情報の格納方法とデータ形式、およびキーストア内の非公開鍵とキーストア自体の整合性との保護に使われるアルゴリズムを定義します。異なるタイプのキーストアの実装間では、互換性がありません。キーストアのデフォルトタイプは、SUN プロバイダによって提供されるキーストア実装専用の jks です。このタイプは、セキュリティプロパティファイルの次の行で指定されます。
keystore.type=jksツールおよびほかのアプリケーションでデフォルト以外のキーストア実装を利用するには、この行を変更して別のタイプのキーストアを指定します。また、作成するツールおよびアプリケーションのユーザにキーストアのタイプを指定させて、その値をキーストアの
getInstance
メソッドに渡すという方法もあります。最初の方法の例を次に示します。pkcs12 というタイプのキーストア実装を提供するプロバイダパッケージがある場合は、この行を次のように変更します。
keystore.type=pkcs12注: キーストアの種類の指定では、大文字と小文字が区別されません。たとえば、JKS も jks と同じであるとみなされます。キーストアクラス
キーストアクラスは、キーストア内の情報へのアクセスおよび情報の変更を行うための明確に定義されたインタフェースを提供するエンジンクラスです。このクラスは、メモリ内の鍵および証明書のコレクションを表現するもので、2 種類のエントリを管理します。
- 鍵エントリ
このタイプのキーストアエントリには、非常に重要な暗号化鍵の情報が保持されます。情報は、保護された形式で格納され、権限のないアクセスを防ぎます。
通常、この種類のエントリで格納される鍵は非公開鍵で、対応する公開鍵を証明書する証明連鎖が伴います。
非公開鍵および証明連鎖は、デジタル署名を使った自己認証用に特定のエンティティが使用します。たとえば、ソフトウェア配布団体は、リリースまたはライセンスするソフトウェアの一部として JAR ファイルにデジタル署名を付けます。
- 信頼できる証明書エントリ
この種類のエントリには、別の組織に属する単一の公開鍵が含まれ、「信頼できる証明書」と呼ばれます。これは、キーストアの所有者が、証明書内の公開鍵が実際に証明書の「被認証者」(所有者) によって識別されたアイデンティティに属することを信頼するためです。
この種類のエントリは、ほかの組織の認証に使うことができます。
キーストア内の各エントリは、「別名」文字列によって識別されます。非公開鍵とそれに関連付けられた証明連鎖の場合は、これらの文字列は、エンティティ自体が認証するというように、方法別に区別されます。たとえば、エンティティが異なる証明書発行局を使ったり、異なる公開鍵アルゴリズムを使ったりして、エンティティ自体を認証することも可能です。
キーストアが持続性があるかどうか、および持続性がある場合に使われる機構は、ここでは指定されません。これにより、重要な (秘密または非公開) 鍵を保護するためのさまざまな技術を使うことができます。スマートカードまたはその他の統合暗号化エンジン (SafeKeyper) を使うことも 1 つの方法です。また、ファイルなどのより単純な機構をさまざまな形式で使うこともできます。
主要なキーストアメソッドを以下で説明します。
キーストアオブジェクトの作成
ほかのエンジンクラスと同様に、キーストアオブジェクトを取得するには、キーストアクラスの
getInstance
static ファクトリメソッドを呼び出します。
public static KeyStore getInstance(String type)呼び出し側は、オプションでプロバイダ名を指定できます。こうすると、要求する型の実装を指定プロバイダから確実に取得できます。
public static KeyStore getInstance(String type, String provider)特定キーストアのメモリへのロード
キーストアオブジェクトを使う前に、load
メソッドによってメモリ内に実際のキーストアデータをロードする必要があります。public final void load(InputStream stream, String password)オプションのパスワードを使って、キーストアデータの整合性をチェックします。パスワードが提供されない場合は、整合性のチェックは行われません。空のキーストアを作成するには、
InputStream
引数としてnull
をload
メソッドに渡します。キーストアの別名一覧の取得
キーストアエントリには、すべて一意の「別名」(aliases) からアクセスします。
aliases
メソッドは、キーストア内の別名の列挙を返します。public final Enumeration aliases()キーストアエントリの種類の決定
「キーストアクラス」で説明したように、キーストアのエントリには、2 種類あります。次のメソッドは、与えられた別名によって指定されたエントリが、それぞれ鍵または証明書か、信頼できる証明書エントリであることを決定します。
public final boolean isKeyEntry(String alias) public final boolean isCertificateEntry(String alias)キーストアエントリの追加、設定、および削除
setCertificateEntry
メソッドは、証明書を指定された別名に割り当てます。public final void setCertificateEntry(String alias, Certificate cert)alias
が存在しない場合は、その別名のついた信頼できる証明書のエントリが作成されます。alias
が存在し、信頼できる証明書のエントリが識別された場合は、それに関連付けられた証明書がcert
によって置き換えられます。
setKeyEntry
メソッドは、alias
がまだ存在しない場合に、鍵のエントリの追加または設定を行ないます。public final void setKeyEntry(String alias, Key key, String password, Certificate[] chain) public final void setKeyEntry(String alias, byte[] key, Certificate[] chain)バイト配列としてkey
を取るメソッドでは、この引数は、保護された形式の鍵のバイトです。たとえば、SUN プロバイダによって提供されるキーストアの実装では、key
バイト配列は、PKCS#8 標準の定義に従ってEncryptedPrivateKeyInfo
として符号化された、保護された非公開鍵を格納します。もう一方のメソッドのpassword
は、鍵の保護に使うパスワードです。
deleteEntry
メソッドは、エントリを削除します。public final void deleteEntry(String alias)キーストアからの情報の取得
getKey
メソッドは、与えられた別名に関連付けられた鍵を返します。鍵は、与えられたパスワードを使って復元されます。public final Key getKey(String alias, String password)次のメソッドは、与えられた別名に関連付けられた証明書、または証明連鎖をそれぞれ返します。public final Certificate getCertificate(String alias) public final Certificate[] getCertificateChain(String alias)次の文を使って、与えられた証明書と一致した最初のエントリの名前 (別名) を決定できます。public final String getCertificateAlias(Certificate cert)キーストアの保存
メモリ内のキーストアを、store
メソッドを使って保存できます。public final void store(OutputStream stream, String password)パスワードは、キーストアデータの統合チェックサムの計算に使われます。統合チェックサムは、キーストアデータのあとに追加されます。
SecureRandom クラスは、乱数ジェネレータの機能を提供するエンジンクラスです。
SecureRandom オブジェクトの作成
ほかのエンジンクラスと同様に、SecureRandom オブジェクトを取得するには、SecureRandom クラスのgetInstance
static ファクトリメソッドを呼び出します。
public static SecureRandom getInstance(String algorithm)呼び出し側は、オプションでプロバイダ名を指定できます。こうすると、要求する乱数生成 (RNG) アルゴリズムの実装を指定プロバイダから確実に取得できます。
public static final SecureRandom getInstance(String algorithm, String provider)SecureRandom オブジェクトのシードまたは再シード
呼び出し側が、
setSeed
メソッドの 1 つへの呼び出しで、getInstance
メソッドへの呼び出しに従う場合以外は、SecureRandom の実装は、ジェネレータの内部状態自体を完全にランダム化しようとします。synchronized public void setSeed(byte[] seed) public void setSeed(long seed)SecureRandom オブジェクトに一度シードが入れられると、これはオリジナルのシードと同じようにランダムにビットを生成します。SecureRandom オブジェクトは、
setSeed
メソッドの 1 つを使って常に再シードされる可能性があります。与えられたシードは、既存のシードと置き換わるのではなく、既存のシードに追加されます。これにより、呼び出しを繰り返しても、ランダム性が減少しないことが保証されます。SecureRandom オブジェクトの使い方
ランダムバイトを得るには、呼び出し側は単純に任意の長さの配列を渡します。すると、この配列にランダムバイトが入ります。
synchronized public void nextBytes(byte[] bytes)シードバイトの生成
ほかの乱数ジェネレータにシードを入れる場合など、必要な場合は、generateSeed
メソッドを呼び出して、与えられた数のシードバイトを生成できます。public byte[] generateSeed(int numBytes)
MessageDigest オブジェクトの計算
まず最初に、以下の例のようにして MessageDigest を生成します。
MessageDigest sha = MessageDigest.getInstance("SHA");この呼び出しは、正しく初期化されたメッセージダイジェストオブジェクトを変数
sha
に代入します。この実装は、National Institute for Standards and Technology の (NIST) FIPS 180-1 ドキュメントの定義に従って、ソースハッシュアルゴリズム (SHA) を実装します。付録 A を参照してください。次に、3 つのバイト配列
i1
、i2
およびi3
があるとします。計算するメッセージダイジェストを持つ合計入力は、この 3 つの配列から形成されます。このダイジェスト (または「ハッシュ」) は、以下の呼び出しを使って計算できます。sha.update(i1); sha.update(i2); sha.update(i3); byte[] hash = sha.digest();以下の一連の呼び出しを使っても同じです。
sha.update(i1); sha.update(i2); byte[] hash = sha.digest(i3);メッセージダイジェストが計算されると、メッセージダイジェストオブジェクトは自動的にリセットされ、新しいデータをレビューしてそのダイジェストを計算できる状態になります。以前の状態 (たとえば
update
呼び出しで入れたデータ) はすべて失われます。ハッシュ実装によっては、複製 (コピー) を介して中間ハッシュをサポートするものもあります。以下について、別々のハッシュを計算すると仮定します。
i1
i1 and i2
i1, i2, and i3
次のように処理します。
/* 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();これは、SHA 実装が複製 (コピー) 可能な場合にだけ機能します。メッセージダイジェストの実装の中には、複製 (コピー) 可能なものもあれば、不可能なものもあります。複製 (コピー) が可能かどうかを判断するには、次のように MessageDigest オブジェクトを複製し、発生する可能性のある例外をキャッチします。
try { // try and clone it /* compute the hash for i1 */ sha.update(i1); byte[] i1Hash = sha.clone().digest(); . . . byte[] i123hash = sha.digest(); } catch (CloneNotSupportedException cnse) { // do something else, such as the code shown below }メッセージダイジェストが複製 (コピー) 不可能な場合は、別の多少複雑な方法を使います。つまり、複数のダイジェストを生成して中間ダイジェストを計算します。この場合、計算する中間ダイジェストの数をあらかじめ知っておく必要があります。
MessageDigest i1 = MessageDigest.getMessageDigest("SHA"); MessageDigest i12 = MessageDigest.getMessageDigest("SHA"); MessageDigest i123 = MessageDigest.getMessageDigest("SHA"); byte[] i1Hash = i1.digest(i1); i12.update(i1); byte[] i12Hash = i12.digest(i2); i123.update(i1); i123.update(i2); byte[] i123Hash = i123.digest(i3);鍵のペアの生成
この例では、「DSA」 (デジタル署名アルゴリズム) という名前のアルゴリズムについて、「公開 - 非公開」の鍵のペアを生成します。
userSeed
というユーザ作成のシードを使って、1024 ビット係数の鍵を生成します。ここでは、アルゴリズム実装を提供するプロバイダは考慮しません。KeyPairGenerator の生成
最初の手順は、DSA アルゴリズムの鍵を生成するための鍵のペアジェネレータオブジェクトの獲得です。
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA");KeyPairGenerator の初期化
次の手順は、鍵のペアジェネレータの初期化です。たいていの場合、アルゴリズム独立型の初期化で十分ですが、アルゴリズム特定型の初期化を使う必要がある場合もあります。アルゴリズム独立型の初期化
すべての鍵ジェネレータは、キーサイズおよび乱数の発生源の概念を共有します。KeyPairGenerator クラスの
initialize
メソッドには、2 つの型の引数があります。つまり鍵を生成するには、1024 のキーサイズとuserSeed
値を使ってシードした新規の SecureRandom オブジェクトを指定し、以下のコードを使うことができます。SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN"); random.setSeed(userSeed); keyGen.initialize(1024, random);上のアルゴリズム独立型
initialize
メソッドを呼び出すときは、その他のパラメータは指定しないため、各鍵に関連付けられるアルゴリズム特定型のパラメータがある場合は、パラメータをどうするかは、プロバイダによって異なります。プロバイダは、事前に計算されたパラメータ値を使うことも、新しい値を生成することもできます。アルゴリズム特定型の初期化
アルゴリズム特定型パラメータのセットがすでに存在する状況では (いわゆる DSA の「コミュニティパラメータ」)、AlgorithmParameterSpec 引数を取る
initialize
メソッドが 2 つあります。鍵のペアのジェネレータが DSA アルゴリズムのジェネレータで、DSA 特定パラメータのセットp
、q
、およびg
があり、これを使って鍵のペアを生成したいとします。次のコードを実行して鍵のペアのジェネレータを初期化できます。DSAParameterSpec は AlgorithmParameterSpec です。DSAParameterSpec dsaSpec = new DSAParameterSpec(p, q, g); SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN"); random.setSeed(userSeed); keyGen.initialize(dsaSpec, random);注: 名前が p のパラメータは、長さが係数の長さ (サイズ) のプライム数です。従って、係数の長さを指定するために他のメソッドを呼び出す必要はありません。鍵のペアの生成
最終手順は、鍵のペアの生成です。使用した初期化の型 (アルゴリズム独立型またはアルゴリズム特定型) に関係なく、同じコードを使って鍵のペアを生成します。KeyPair pair = keyGen.generateKeyPair();
生成された鍵を使った署名の生成および検証
次の署名の生成および検証の例では、上の鍵のペアの例で生成された鍵のペアを利用しています。
署名の生成
まず最初に署名オブジェクトを生成します。
Signature dsa = Signature.getInstance("SHA1withDSA");鍵のペアの例で生成した鍵のペアを使い、非公開鍵を指定してオブジェクトを初期化します。このあとで
data
というバイト配列に署名を付けます。
/* Initializing the object with a private key */ PrivateKey priv = pair.getPrivate(); dsa.initSign(priv); /* Update and sign the data */ dsa.update(data); byte[] sig = dsa.sign();
署名の検証
署名の検証は簡単です。ここでも、鍵のペアの例で生成した鍵のペアを使います。
/* Initializing the object with the public key */ PublicKey pub = pair.getPublic(); dsa.initVerify(pub); /* Update and verify the data */ dsa.update(data); boolean verifies = dsa.verify(sig); System.out.println("signature verifies: " + verifies);鍵仕様および KeyFactory を使った署名の生成と検証
上の鍵のペアの例のような公開鍵と非公開鍵のペアを使うよりも、単に DSA 非公開鍵のコンポーネントx
(非公開鍵)、p
(プライム)、q
(サブプライム)、およびg
(ベース) を使いたいとします。さらに、非公開鍵を使って
someData
というバイト配列内のあるデータにデジタル署名を付けたいとします。次の手順を実行します。この手順は、鍵仕様の作成、および鍵ファクトリを使って鍵仕様から PrivateKey を取得する方法も示しています。initSign
には PrivateKey が必要です。DSAPrivateKeySpec dsaPrivKeySpec = new DSAPrivateKeySpec(x, p, q, g); KeyFactory keyFactory = KeyFactory.getInstance("DSA"); PrivateKey privKey = keyFactory.generatePrivate(dsaPrivKeySpec); Signature sig = Signature.getInstance("SHA1withDSA"); sig.initSign(privKey); sig.update(someData); byte[] signature = sig.sign();Alice が署名したデータを使いたいとします。彼女がそのデータを使うため、および署名を検証するためには、彼女に次の 3 つのものを送る必要があります。
- データ
- 署名
- データの署名に使った非公開鍵に対応する公開鍵
someData
バイトをあるファイルに格納し、signature
バイトを別のファイルに格納し、両方を Alice に送ることができます。公開鍵に関しては、上の署名の例のように、データの署名に使った DSA 非公開鍵に対応する DSA 公開鍵のコンポーネントを持っていると想定します。この場合は、コンポーネントから DSAPublicKeySpec を作成できます。
DSAPublicKeySpec dsaPubKeySpec = new DSAPublicKeySpec(y, p, q, g);ただし、鍵バイトをファイルに記述できるように、鍵バイトを抽出する必要があります。このためには、まず、上の例ですでに作成した DSA 鍵ファクトリのgeneratePublic
メソッドを呼び出します。PublicKey pubKey = keyFactory.generatePublic(dsaPubKeySpec);次に、以下のコードを使って符号化された鍵バイトを抽出します。byte[] encKey = pubKey.getEncoded();この時点でバイトをファイルに保存し、データおよび署名を保存したファイルと一緒に Alice に送ることができます。ここで、Alice がこれらのファイルを受け取り、データファイルのデータバイトを
data
というバイト配列に、署名ファイルの署名バイトをsignature
というバイト配列に、公開鍵ファイルの符号化された公開鍵バイトをencodedPubKey
というバイト配列にコピーしたとします。Alice は、次のコードを実行して署名を検証できます。このコードは、符号化された状態から DSA 公開鍵のインスタンスを生成するために、鍵ファクトリを使う方法も示しています。
initVerify
には PublicKey が必要です。X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encodedPubKey); KeyFactory keyFactory = KeyFactory.getInstance("DSA"); PublicKey pubKey = keyFactory.generatePublic(pubKeySpec); Signature sig = Signature.getInstance("SHA1withDSA"); sig.initVerify(pubKey); sig.update(data); sig.verify(signature);注: 上のコードでは、initVerify
が PublicKey を必要とするため、Alice は符号化された鍵ビットから PublicKey を生成する必要がありました。PublicKey を得たら、KeyFactorygetKeySpec
メソッドを使って、PublicKey を DSAPublicKeySpec に変換して、必要な場合にコンポーネントにアクセスすることが可能です。DSAPublicKeySpec dsaPubKeySpec = (DSAPublicKeySpec)keyFactory.getKeySpec(pubKey, DSAPublicKeySpec.class)これで Alice は、コンポーネントy
、p
、q
、およびg
に、DSAPublicKeySpec の対応する get メソッド (getY
、getP
、getQ
、およびgetG
) を使ってアクセスできます。Base64−符号化された証明書の読み取り
次の例は、Base64−符号化された証明書を読み取ります。認証の開始は、次のコードで指定されます。
-----BEGIN CERTIFICATE-----終了は次のコードで指定されます。-----END CERTIFICATE-----FileInputStream
(mark
およびreset
をサポートしない) をByteArrayInputStream
(mark
およびreset
をサポートする) に変換し、generateCertificate
への各呼び出しに証明書が 1 つだけ使われて、入力ストリームの読み取られた位置がファイル内の次の証明書に配置されるようにします。
FileInputStream fis = new FileInputStream(filename); DataInputStream dis = new DataInputStream(fis); CertificateFactory cf = CertificateFactory.getInstance("X.509"); byte[] bytes = new byte[dis.available()]; dis.readFully(bytes); ByteArrayInputStream bais = new ByteArrayInputStream(bytes); while (bais.available() > 0) { Certificate cert = cf.generateCertificate(bais); System.out.println(cert.toString()); }認証応答の解析
次の例は、ファイル内に保存された PKCS#7 形式の認証応答を解析し、そこから証明書をすべて抽出します。
FileInputStream fis = new FileInputStream(filename); CertificateFactory cf = CertificateFactory.getInstance("X.509"); Collection c = cf.generateCertificates(fis); Iterator i = c.iterator(); while (i.hasNext()) { Certificate cert = (Certificate)i.next(); System.out.println(cert); }
「JDK Security API」は、様々なアルゴリズム、証明書、およびキーストアのタイプの標準名を必要とし、これらを使用します。ここに記載の仕様は、標準名として以下の名前を確立するものです。
注: 暗号化および協定済みの鍵のアルゴリズムの標準名の対応一覧は、Java 暗号化拡張 (JCE 1.2) の『API 仕様 & リファレンス』ガイドの付録 A に記載されています。このリリースの詳細については、http://java.sun.com/products/jdk/1.2/jce/index.html を参照してください。
アルゴリズムの仕様については、付録 B を参照してください。
メッセージダイジェストアルゴリズム
この項のアルゴリズム名は、
MessageDigest
のインスタンスの生成時に指定できます。SHA: セキュアハッシュ標準 NIST FIPS 180-1 で定義されいるセキュアハッシュアルゴリズム
MD2: RFC 1319 で定義されている MD2 メッセージダイジェストアルゴリズム
MD5: RFC 1321 で定義されている MD5 メッセージダイジェストアルゴリズム
鍵およびパラメータのアルゴリズム
この項のアルゴリズム名は、
KeyPairGenerator
、KeyFactory
、AlgorithmParameterGenerator
、およびAlgorithmParameters
のインスタンスの生成時に指定できます。RSA: PKCS#1 で定義されている RSA 暗号化アルゴリズム
DSA: FIPS PUB 186 で定義されているデジタル署名アルゴリズム
デジタル署名アルゴリズム
この項のアルゴリズム名は、
Signature
のインスタンスの生成時に指定できます。SHA1withDSA: FIPS PUB 186 に定義されている SHA-1 を使った DSA 署名アルゴリズム。SHA-1 ダイジェストアルゴリズムおよび DSA を使って DSA デジタル署名を作成および検証します。
MD2withRSA: PKCS#1 に定義されている RSA 暗号を使った MD2 署名アルゴリズム。MD2 ダイジェストアルゴリズムおよび RSA を使って RSA デジタル署名を作成および検証します。
MD5withRSA: PKCS#1 に定義されている RSA 暗号を使った MD5 署名アルゴリズム。MD5 ダイジェストアルゴリズムおよび RSA を使って RSA デジタル署名を作成および検証します。
SHA1withRSA: OSI Interoperability Workshop に定義されている SHA-1 および RSA 暗号化アルゴリズムを使った署名アルゴリズム。PKCS #1 で説明されているパディング変換を使います。
乱数生成 (RNG) アルゴリズム
この項のアルゴリズム名は、
SecureRandom
のインスタンスの生成時に指定できます。SHA1PRNG: SUN プロバイダが提供する擬似乱数生成 (PRNG) アルゴリズム。この実装は、IEEE P1363 標準の付録 G.7「Expansion of source bits」に準拠し、PRNG の基盤として SHA1 を使います。各操作につき値が 1 増加する 64 ビットカウンタを使って鎖状につながった真にランダムなシード値から、SHA1 ハッシュを計算します。160 ビットの SHA1 出力のうち、64 ビットだけが使用されます。
証明書のタイプ
この項のアルゴリズム名は、
CertificateFactory
のインスタンスの生成時に指定できます。X.509: X.509 に定義されている証明書のタイプ
キーストアのタイプ
この項のアルゴリズム名は、
KeyStore
のインスタンスの生成時に指定できます。JKS: SUN プロバイダが提供するキーストア実装の名前
PKCS12: PKCS#12 に定義されている、個人のアイデンティティ情報のための転送構文
この付録では、付録 A で定義したいくつかのアルゴリズムに関する詳細を示します。一覧されているアルゴリズムの実装を与えるプロバイダは、この付録の仕様に従うことが必要です。このドキュメントの最新バージョンは、公開 Web サイト http://java.sun.com/products/jdk/1.2/docs/guide/security/index.html から入手できます。
ここに記載のない新しいアルゴリズムを追加するには、まず最初にプロバイダパッケージの供給先に問い合わせて、該当アルゴリズムが追加済みでないかどうかを確認します。すでに追加されている場合は、可能であれば開示されている定義を使います。まだ追加されていない場合は、アルゴリズムの仕様を添えて、この付録 B に記載のテンプレートに類似した使用可能なテンプレートを作成します。
仕様テンプレート
以下のアルゴリズム仕様には、次のフィールドが含まれます。名前:
アルゴリズムの認識名。これは、既存のアルゴリズムオブジェクト名を判別するために、(アルゴリズムの要求時に)
getInstance
メソッドに渡される名前で、getAlgorithm
メソッドによって返されます。この 2 つのメソッドは、関連エンジンクラス、Signature、MessageDigest、KeyPairGenerator、および AlgorithmParameterGenerator 内にあります。型:
アルゴリズムの型、Signature、MessageDigest、KeyPairGenerator、または ParameterGenerator を示します。
説明:
アルゴリズムに関する一般的なメモ。このアルゴリズムが実装する標準、適用される特許件などを含みます。
KeyPair アルゴリズム (オプション指定):
このアルゴリズムの KeyPair アルゴリズムを示します。
キーサイズ (オプション指定):
鍵のアルゴリズムまたは鍵生成アルゴリズムの場合は、正しいキーサイズを示します。
サイズ (オプション指定):
アルゴリズムパラメータ生成アルゴリズムの場合は、アルゴリズムパラメータ生成の正しいサイズを示します。パラメータのデフォルト値 (オプション指定):
鍵生成アルゴリズムの場合は、デフォルトのパラメータ値を示します。
Signature フォーマット (オプション指定):
Signature アルゴリズムの場合は、署名のフォーマットを示します。つまり、検証メソッドの入力と署名メソッドの出力です。
アルゴリズムの仕様
SHA-1 メッセージダイジェストアルゴリズム
名前: SHA
型: MessageDigest
説明: NIST の FIPS 180-1 で定義したメッセージダイジェストアルゴリズム。このアルゴリズムの出力は 160 ビットのダイジェストです。
MD2 メッセージダイジェストアルゴリズム
名前: MD2
型: MessageDigest
説明: RFC 1319 で定義したメッセージダイジェストアルゴリズム。このアルゴリズムの出力は 128 ビット (16 バイト) のダイジェストです。
MD5 メッセージダイジェストアルゴリズム
名前: MD5
型: MessageDigest
説明: RFC 1321 で定義したメッセージダイジェストアルゴリズム。このアルゴリズムの出力は 128 ビット (16 バイト) のダイジェストです。
デジタル署名アルゴリズム
名前: SHA1withDSA
型: Signature
説明: このアルゴリズムは、NIST FIPS 186 に記述の署名アルゴリズムです。DSA は SHA-1 メッセージダイジェストアルトリズムを使います。
KeyPair アルゴリズム: DSA
署名フォーマット: 2 つの INTEGER 値の ASN.1 シーケンス
r
およびs
(この順序): SEQUENCE ::= { r INTEGER, s INTEGER }RSA ベースの署名アルゴリズム、MD2、MD5 または SHA-1 を使用します。
名前: MD2withRSA、MD5withRSA、および SHA1withRSA
型: Signature
説明: それぞれに MD2、MD5、および SHA1 メッセージアルゴリズムを RSA 暗号化とともに使う署名アルゴリズムです。
KeyPair アルゴリズム: RSA
署名フォーマット: RSA Laboratory の公開鍵暗号化標準ノート #1 で定義の DER コード化 PKCS#1 ブロック。暗号化データは署名付きデータのダイジェストです。
DSA KeyPair 生成アルゴリズム
名前: DSA
型: KeyPairGenerator
説明: このアルゴリズムは、DSA 対応 NIST FIPS 186 に記載の鍵のペア生成アルゴリズムです。
キーサイズ: 係数
p
の長さ (ビット単位)。512 から 1024 の範囲で、64 の倍数でなければなりません。デフォルトのキーサイズは、1024 です。パラメータのデフォルト値: 以下のデフォルトのパラメータ値は、512、768、および 1024 ビットのキーサイズ用に使います。
512 ビットの鍵パラメータ
SEED = b869c82b 35d70e1b 1ff91b28 e37a62ec dc34409b counter = 123 p = fca682ce 8e12caba 26efccf7 110e526d b078b05e decbcd1e b4a208f3 ae1617ae 01f35b91 a47e6df6 3413c5e1 2ed0899b cd132acd 50d99151 bdc43ee7 37592e17 q = 962eddcc 369cba8e bb260ee6 b6a126d9 346e38c5 g = 678471b2 7a9cf44e e91a49c5 147db1a9 aaf244f0 5a434d64 86931d2d 14271b9e 35030b71 fd73da17 9069b32e 2935630e 1c206235 4d0da20a 6c416e50 be794ca4768 ビットの鍵パラメータ
SEED = 77d0f8c4 dad15eb8 c4f2f8d6 726cefd9 6d5bb399 counter = 263 p = e9e64259 9d355f37 c97ffd35 67120b8e 25c9cd43 e927b3a9 670fbec5 d8901419 22d2c3b3 ad248009 3799869d 1e846aab 49fab0ad 26d2ce6a 22219d47 0bce7d77 7d4a21fb e9c270b5 7f607002 f3cef839 3694cf45 ee3688c1 1a8c56ab 127a3daf q = 9cdbd84c 9f1ac2f3 8d0f80f4 2ab952e7 338bf511 g = 30470ad5 a005fb14 ce2d9dcd 87e38bc7 d1b1c5fa cbaecbe9 5f190aa7 a31d23c4 dbbcbe06 17454440 1a5b2c02 0965d8c2 bd2171d3 66844577 1f74ba08 4d2029d8 3c1c1585 47f3a9f1 a2715be2 3d51ae4d 3e5a1f6a 7064f316 933a346d 3f5292521024 ビットの鍵パラメータ
SEED = 8d515589 4229d5e6 89ee01e6 018a237e 2cae64cd counter = 92 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 fecf492aRSA KeyPair 生成アルゴリズム
名前: RSA
型: KeyPairGenerator
説明: このアルゴリズムは、PKCS#1 に記載の鍵のペア生成アルゴリズムです。
強度: 512 以上で 8 の倍数の任意の整数
DSA パラメータ生成アルゴリズム
名前: DSA
型: ParameterGenerator
説明: このアルゴリズムは、NIST FIPS 186 for DSA に記載のパラメータ生成アルゴリズムです。
サイズ: 係数
p
の長さ (ビット単位)。512 から 1024 の範囲で、64 の倍数でなければなりません。デフォルトのサイズは、1024 です。
Copyright © 1996-98 Sun Microsystems, Inc. All Rights Reserved. コメントの送付先: java-security@java.sun.com このアドレスで購読を申し込むことはできません。 |
Java ソフトウェア |