Javaセキュリティの概要

Javaセキュリティには、API、ツール、およびよく使用されるセキュリティ・アルゴリズム、メカニズムおよびプロトコルの実装が大規模なセットとして含まれています。JavaセキュリティAPIは、暗号化、公開キーインフラストラクチャ、安全な通信、認証、アクセス制御など、広範な領域に及んでいます。Javaセキュリティ・テクノロジでは、開発者に、アプリケーションを記述するための包括的なセキュリティ・フレームワークが提供され、ユーザーまたは管理者に、アプリケーションを安全に管理するための一連のツールが提供されます。

Javaセキュリティの紹介

JDKは、セキュリティを重視して設計されました。その中核では、Java言語自体が型保証されており、自動ガベージ・コレクションを提供してアプリケーション・コードの堅牢性を強化しています。安全なクラス・ロードおよび検証メカニズムによって、正当なJavaコードのみが実行されます。Javaセキュリティ・アーキテクチャには、アプリケーション・プログラミング・インタフェース(API)、ツール、および一般的に使用されるセキュリティ・アルゴリズム、メカニズムおよびプロトコルの実装の、大規模なセットが含まれています。

JavaセキュリティAPIは、広範な領域に及びます。暗号化および公開キーインフラストラクチャ(PKI)インタフェースは、安全なアプリケーションを開発するための基盤となります。認証およびアクセス制御を実行するためのインタフェースにより、アプリケーションは、保護されたリソースへの承認されていないアクセスから保護できます。

APIでは、アルゴリズムおよびその他のセキュリティ・サービスについて、複数の相互運用可能な実装が可能です。サービスはプロバイダに実装され、プロバイダは、アプリケーションがセキュリティ・サービスの実装を意識せずに簡単に取得できるようにする標準インタフェースによって、JDKにプラグインされます。これにより、開発者は、複雑なセキュリティ・メカニズムを実際に実装する方法ではなく、セキュリティをアプリケーションに統合する方法に重点を置くことができます。

JDKには、基本的なセキュリティ・サービスを実装する多数のプロバイダが含まれています。追加のカスタム・プロバイダをインストールすることも可能です。これにより、開発者は新しいセキュリティ・メカニズムでプラットフォームを拡張できます。

JDKは、複数のモジュールに分けられています。セキュリティAPIを含むモジュールには、次のものがあります。

表1-1 セキュリティAPIを含むモジュール

モジュール 説明
java.base Java SEの基本APIを定義します。含まれるパッケージには、java.securityjavax.cryptojavax.net.sslおよびjavax.security.authがあります
java.security.jgss IETF Generic Security Services API (GSS-API)のJavaバインディングを定義します。このモジュールには、Kerberos v5やSPNEGOなどのGSS-APIメカニズムも含まれています
java.security.sasl IETF Simple Authentication and Security Layer (SASL)のJavaサポートを定義します。このモジュールには、DIGEST-MD5、CRAM-MD5およびNTLMなどのSASLメカニズムも含まれています
java.smartcardio Javaスマートカード入出力APIを定義します
java.xml.crypto XML暗号化のAPIを定義します
jdk.jartool jarファイルの署名用のAPIを定義します
jdk.security.auth javax.security.auth.*インタフェースおよび様々な認証モジュールの実装を提供します
jdk.security.jgss GSS-APIのJava拡張、およびSASL GSS-APIメカニズムの実装を定義します

Java言語セキュリティおよびバイト・コード検証

Java言語は、型保証されるように設計されており、簡単に使用できます。自動メモリー管理、ガベージ・コレクション、および配列の範囲チェックを備えています。これにより、開発者の全体的なプログラミングの負荷を軽減し、見つかりにくいプログラミング・エラーの減少および安全で堅牢なコードを実現します。

コンパイラは、Javaプログラムをマシンに依存しないバイト・コード表現に変換します。正当なバイト・コードのみがJava Runtimeで実行されるように、バイトコード・ベリファイアが呼び出されます。これは、バイト・コードがJava言語仕様に準拠しており、Javaの言語規則または名前空間制限に違反していないことをチェックします。ベリファイアは、メモリー管理違反、スタック・アンダーフローまたはオーバーフロー、および不正な型キャストもチェックします。バイト・コードが検証されると、Java Runtimeはそれらの実行を準備します。

また、Java言語は、異なるアクセス修飾子を定義してJavaクラス、メソッド、およびフィールドに割り当てることができるため、開発者はクラス実装へのアクセスを必要に応じて制限できます。この言語は、4つの異なるアクセス・レベルを定義します。
  • private: 最も制限された修飾子。アクセスは、privateメンバー(メソッドなど)が定義された特定のクラス以外では許可されません。

  • protected: 任意のサブクラス、または同じパッケージ内の他のクラスへのアクセスを許可します。

  • Package-private: 指定されない場合、これがデフォルトのアクセス・レベルとなります。同じパッケージ内のクラスへのアクセスを許可します。

  • public: 要素にどこからでもアクセスできることは保証されなくなります。アクセス可能性は、その要素を含むパッケージがその定義モジュールによってエクスポートされるかどうか、およびそのモジュールをそれにアクセスしようとしているコードを含むモジュールで読み取れるかどうかによって異なります。

基本的なセキュリティ・アーキテクチャ

JDKでは、暗号化、公開キーインフラストラクチャ、認証、安全な通信、アクセス制御など、主要なセキュリティ分野に渡る一連のAPIが定義されています。これらのAPIによって、開発者はアプリケーション・コードにセキュリティを簡単に統合できます。

これらのAPIは、次の方針に基づいて設計されました。

実装の独立性
アプリケーションでセキュリティを実装する必要はありません。JDKからセキュリティ・サービスを要求できます。セキュリティ・サービスはプロバイダに実装されています(セキュリティ・プロバイダの項を参照)。プロバイダは、標準インタフェースによってJDKにプラグインされます。アプリケーションは、複数の独立したプロバイダにセキュリティ機能を依存する場合があります。
実装の相互運用性

プロバイダは、アプリケーション間で相互運用できます。具体的に述べると、アプリケーションは、プロバイダからのデフォルト値に依存しない場合は、特定のプロバイダにバインドされません。

アルゴリズムの拡張性
JDKには、現在広く使用されている、一連の基本的なセキュリティ・サービスを実装する、多数の組込みプロバイダが含まれています。ただし、一部のアプリケーションは、まだ実装されていない普及しつつある規格や独自のサービスに依存している場合があります。JDKでは、そのようなサービスを実装するカスタム・プロバイダのインストールがサポートされています。

セキュリティ・プロバイダ

java.security.Providerクラスは、セキュリティ・プロバイダの概念をJavaプラットフォームでカプセル化します。プロバイダの名前を指定し、実装するセキュリティ・サービスを一覧します。複数のプロバイダが同時に構成される場合があり、それらは優先順にリストされます。セキュリティ・サービスが要求されると、そのサービスを実装する、優先順位がいちばん高いプロバイダが選択されます。

アプリケーションは、関連するgetInstanceメソッドによって、基盤となるプロバイダからセキュリティ・サービスを要求します。

たとえば、メッセージ・ダイジェストの作成は、プロバイダから利用可能なサービスの1つのタイプを表します。特定のメッセージ・ダイジェスト・アルゴリズムの実装を要求するには、メソッドjava.security.MessageDigest.getInstanceを呼び出します。次の文は、プロバイダ名を指定せずにSHA-256メッセージ・ダイジェスト実装を要求します。

    MessageDigest md = MessageDigest.getInstance("SHA-256");

次の図では、この文でSHA-256メッセージ・ダイジェスト実装がどのように取得されるかを示します。プロバイダが優先順位に従って検索され、その特定のアルゴリズムを提供する最初のプロバイダであるProviderBからの実装が返されます。

図1-1 プロバイダ指定なしでのSHA-256メッセージ・ダイジェスト実装の要求


図1-1の説明が続きます
「図1-1 プロバイダ指定なしでのSHA-256メッセージ・ダイジェスト実装の要求」の説明

オプションで、プロバイダ名を指定することで特定のプロバイダからの実装を要求できます。次の文は、特定のプロバイダProviderCからのSHA-256メッセージ・ダイジェスト実装を要求します。

    MessageDigest md = MessageDigest.getInstance("SHA-256", "ProviderC");

次の図では、この文で特定のプロバイダProviderCからのSHA-256メッセージ・ダイジェスト実装がどのように要求されるかを示します。この場合は、優先順位の高いプロバイダであるProviderBもSHA-256実装を提供していても、指定されたプロバイダからの実装が返されます。

図1-2 特定のプロバイダからのSHA-256メッセージ・ダイジェスト実装の要求


図1-2の説明が続きます。
「図1-2 特定のプロバイダからのSHA-256メッセージ・ダイジェスト実装の要求」の説明

メッセージ・ダイジェスト・アルゴリズムなどの暗号化サービスの詳細は、Javaの暗号化の項を参照してください。

OracleのJavaプラットフォーム実装には、アプリケーションによって使用できる一連の基本的なセキュリティ・サービスを実装する、組込みの多数のデフォルト・プロバイダが含まれています。Javaプラットフォームのほかのベンダーの実装には、ベンダー固有のセキュリティ・サービスのセットをカプセル化した、異なるプロバイダのセットが含まれている場合があります。組込みのデフォルト・プロバイダという用語は、Oracleの実装で利用可能なプロバイダのことを指しています。

Javaの暗号化

Java暗号化アーキテクチャは、Javaプラットフォームの暗号化機能へのアクセスおよび開発のためのフレームワークです。

これには、各種暗号化サービスのためのAPIが含まれています。それらを次に示します。

  • メッセージ・ダイジェスト・アルゴリズム
  • デジタル署名アルゴリズム
  • 対称バルクおよびストリーム暗号化
  • 非対称暗号化
  • パスワードベース暗号化(PBE)
  • 楕円曲線暗号(ECC)
  • キー協定アルゴリズム
  • キー・ジェネレータ
  • メッセージ認証コード(MAC)
  • 安全な乱数ジェネレータ
歴史的な理由(輸出規制)により、暗号化APIは2つの別個のパッケージに編成されています。
  • java.securityおよびjava.security.*パッケージには、輸出規制の対象ではないクラス(SignatureMessageDigestなど)が含まれています。

  • javax.cryptoパッケージには、輸出規制の対象のクラス(CipherKeyAgreementなど)が含まれています。

暗号化インタフェースはプロバイダ・ベースであり、複数の相互運用性のある暗号化実装が可能です。ソフトウェアで暗号化操作を行うプロバイダもあれば、スマートカード・デバイスやハードウェア暗号化アクセラレータなどのハードウェア・トークン上で暗号化操作を行うプロバイダもあります。輸出規制の対象のサービスを実装するプロバイダには、Oracle JCE証明書発行局によって発行された証明書でデジタル署名を行う必要があります。

Javaプラットフォームには、最も一般的に使用される暗号化アルゴリズムの多くのための組込みプロバイダが含まれています。それらは、RSA、DSAおよびECDSA署名アルゴリズム、AES暗号化アルゴリズム、SHA-2メッセージ・ダイジェスト・アルゴリズム、Diffie-Hellman (DH)およびElliptic Curve Diffie-Hellman (ECDH)キー協定アルゴリズムなどです。組込みプロバイダの大部分は、Javaコードで暗号化アルゴリズムを実装しています。

Javaプラットフォームには、ネイティブPKCS#11 (v2.x)トークンへのブリッジとして機能する組込みプロバイダも含まれています。このプロバイダはSunPKCS11という名前であり、JavaアプリケーションはPKCS#11に準拠するトークンに存在する暗号化サービスにシームレスにアクセスできます。

Windowsでは、JavaプラットフォームにネイティブMicrosoft CryptoAPIへのブリッジとして機能する組込みプロバイダが含まれています。このプロバイダはSunMSCAPIという名前であり、JavaアプリケーションはCryptoAPIを介してWindows上の暗号化サービスにシームレスにアクセスできます。

公開キーインフラストラクチャ

公開キー・インフラストラクチャ(PKI)は、公開キー暗号方式に基づいて情報のセキュアな交換を可能にするフレームワークに対して使用される用語です。(人や組織などの)識別情報のデジタル証明書へのバインドを可能にし、証明書の信頼性を検証する手段を提供します。PKIには、キー、証明書、公開キー暗号化および信頼できる証明書発行局(CA)が含まれます。CAは、証明書を生成してデジタル署名を行います。

Javaプラットフォームには、X.509デジタル証明書と証明書失効リスト(CRL)のAPIおよびプロバイダ・サポート、PKIXに準拠した証明書パスの構築および検証が含まれています。PKIに関係するクラスは、java.securityおよびjava.security.certパッケージ内にあります。

キーおよび証明書ストレージ

Javaプラットフォームは、キーストアおよび証明書ストアを使用して、暗号化キーおよび証明書の長期にわたる永続的なストレージを提供します。具体的には、java.security.KeyStoreクラスがキーストアを表し、java.security.cert.CertStoreクラスが証明書ストアを表します。キーストアは、(たとえば、証明書パス検証中に使用される)暗号化キーまたは信頼できる証明書、あるいはその両方のセキュアなリポジトリです。証明書ストアは、関連がなく通常は信頼されない証明書が含まれるため非常に大きくなる可能性がある公開リポジトリです。CertStoreはCRLを格納する場合もあります。

KeyStoreCertStoreの実装は、タイプによって区別されます。Javaプラットフォームには、標準のPKCS11とPKCS12キーストア・タイプ(その実装は、RSA Securityの対応するPKCS仕様に準拠する)が含まれています。さらに、JKS (Java Key Storeを表す)と呼ばれる独自のファイルベースのキーストア・タイプと、DKS (Domain Key Store)と呼ばれるタイプも含まれます。DKSは単一の論理キーストアとして存在するキーストアのコレクションです。

Javaプラットフォームには、特別な組込みキーストアcacertsが含まれています。このキーストアには、既知の信頼できるCAの多数の証明書が含まれています。keytoolユーティリティでは、cacertsに含まれている証明書をリストできます。Java Development Kitツール仕様keytoolに関する項を参照してください。

Javaの暗号化の項で説明されているSunPKCS11プロバイダには、PKCS11 KeyStore実装が含まれています。つまり、安全なハードウェア(スマートカードなど)に存在するキーや証明書は、KeyStore APIによってJavaアプリケーションからアクセスおよび使用できます。スマートカードのキーがデバイスを離れることは許可されない場合があります。このような場合、KeyStore APIから返されるjava.security.Keyオブジェクトは、単純にキーの参照になる(つまり、実際のキー・データは含まれない)ことがあります。このようなKeyオブジェクトは、実際のキーが存在するデバイスでの暗号化操作の実行にのみ使用できます。

Javaプラットフォームには、LDAP証明書ストア・タイプ(LDAPディレクトリに格納されている証明書へのアクセス用)、およびメモリー内のCollection証明書ストア・タイプ(java.util.Collectionオブジェクトで管理されている証明書へのアクセス用)も含まれています。

公開キーインフラストラクチャのツール

キー、証明書、およびキー・ストアを操作するための2つの組込みツールがあります。

  • keytoolでは、キーストアを作成および管理します。これは、次のタスクを実行するために使用します。

    • 公開キーと秘密キーのペアを作成する
    • ファイルとして格納されたX.509 v1、v2、およびv3証明書を表示、インポート、エクスポートする
    • X.509証明書の作成
    • CAに送信される証明書(PKCS#10)要求を発行する
    • 証明書要求に基づいて証明書を作成する
    • 証明書応答をインポートする(証明書要求の送信先のCAから取得する)
    • 公開キー証明書を信頼できるものとして指定する
    • パスワードを受け付け、それを秘密キーとしてセキュアに保存する
  • jarsignerは、JARファイルに署名し、署名付きJARファイルの署名を検証します。Java ARchive (JAR)ファイル形式を使用すると、複数のファイルを1つのファイルに統合できます。JARファイルには、主にアプレットおよびアプリケーションに関連したクラス・ファイルおよび補助リソースが含まれています。

コードにデジタル署名を行うには、次のことを実行します。
  1. keytoolを使用して、適切なキーおよび証明書を生成するかキー・ストアにインポートします(それらがまだキーストアにない場合)。

  2. jarツールを使用して、コードをJARファイルにパッケージ化します。

  3. jarsignerツール(またはjdk.security.jarsigner API)を使用して、JARファイルに署名します。jarsignerツールは、キー・ストアにアクセスし、JARファイルへの署名、または署名付きJARファイルの署名の検証に必要なキーおよび証明書を見つけます。

    ノート:

    jarsignerは、オプションで、タイムスタンプを含む署名を生成できます。JARファイルの署名を検証するシステムは、タイムスタンプをチェックして、証明書が最新であることを要求するかわりに、証明書が有効な間に署名されたJARファイルを受け入れることができます。証明書は、通常1年で期限切れになります。配備されたJARファイルにJARファイルの作成者が毎年再署名すると考えるのは妥当ではありません。

Java Development Kitツール仕様keytoolおよびjarsignerに関する項を参照してください。

認証

認証とは、ユーザーのアイデンティティを判別するプロセスのことです。Java Runtime Environmentのコンテキストでは、実行中のJavaプログラムのユーザーを識別するプロセスのことです。このプロセスは、Javaの暗号化の項で説明したサービスに依存する場合があります。

Javaプラットフォームは、アプリケーションがプラガブルなログイン・モジュールによってユーザー認証を実行できるようにするAPIを提供します。アプリケーションはLoginContextクラス(javax.security.auth.loginパッケージ内)を呼び出し、このクラスは構成を参照します。構成は、実際の認証を実行するために使用するログイン・モジュール(javax.security.auth.spi.LoginModuleインタフェースの実装)を指定します。

アプリケーションは、標準のLoginContext APIと通信するだけなので、基盤となるプラグイン・モジュールから独立したままの状態を維持できます。アプリケーションでは、新規または更新されたモジュールをプラグインとして使用でき、アプリケーションを変更する必要はありません。次の図では、アプリケーションと基盤となるログイン・モジュールとの間の独立性を示します。

図1-3 認証フレームワークにプラグインする認証ログイン・モジュール

図1-3の説明が続きます
「図1-3 認証フレームワークにプラグインする認証ログイン・モジュール」の説明

ログイン・モジュールはJavaプラットフォームで構成できるプラガブルなコンポーネントですが、セキュリティ・プロバイダを介してプラグインされません。したがって、セキュリティ・プロバイダの項で説明されているプロバイダ検索モデルには従いません。かわりに、図1-3で示したように、ログイン・モジュールは固有の構成によって管理されます。

Javaプラットフォームは、次の組込みログイン・モジュールを提供します。これらはすべて、com.sun.security.auth.moduleパッケージ内にあります。

  • Krb5LoginModule (Kerberosプロトコルを使用した認証用)
  • JndiLoginModule (LDAPまたはNISデータベースを使用したユーザー名/パスワード認証用)
  • KeyStoreLoginModule (PKCS#11トークン・キーストアなど、任意のタイプのキーストアへのログイン用)

認証は、2つのピア間のセキュアな通信チャネルの確立プロセス中に実現することもできます。Javaプラットフォームは、多数の標準通信プロトコルの実装を提供します。これについては、セキュアな通信の項で説明します。

セキュアな通信

ネットワークを通じてやり取りされるデータには、意図された受信者以外の人もアクセスできます。データにパスワードやクレジット・カード番号などの個人情報が含まれる場合、権限のない者がデータを理解できないよう、手段を講じる必要があります。また、適切な相手にデータを送信し、意図的であるかどうかにかかわらず、通信中にデータが変更されないようにすることも重要です。

暗号化はセキュアな通信に必要な基盤を形成します。Javaの暗号化の項を参照してください。Javaプラットフォームは、多くの標準のセキュアな通信プロトコルにAPIのサポートとプロバイダ実装も提供します。

TLSおよびDTLSプロトコル

Transport Layer Security (TLS)とその前身であるSecure Sockets Layer (SSL)は、2つの通信ピア間のセキュアなチャネルを実現する暗号プロトコルです。TLSでは、信頼されないまたは潜在的に攻撃的なネットワーク経由の通信に対して、認証、機密性および整合性のプロパティを提供することで、複数の暗号化プロセスを組み合せて使用します。TLSは、信頼できるストリーム指向のトランスポート・チャネル(通常はTransport Control Protocol (TCP))を介して実行されます。TLSはアプリケーション・プロトコルに依存しません。Hypertext Transfer Protocol (HTTP)などの高レベル・プロトコルは、TLS上に透過的にレイヤー化できます。

Datagram Transport Layer Security (DTLS)プロトコルは、ストリーム指向のTLSプロトコルを基盤とし、信頼できる順次のデータ配信を提供しないデータグラム・トランスポート(User Datagram Protocol (UDP)など)に対して同様のセキュリティ・プロパティを提供することを目的としています。

JDKは、SSL、TLSおよびDTLSプロトコルのAPIおよび実装を提供しています。これには、データの暗号化、メッセージの整合性、およびサーバーとクライアントの認証の機能が含まれています。アプリケーションは、(D)TLSを使用して、TCP/IP上のHTTPなど、任意のアプリケーション・プロトコル上の2つのピア間でセキュアなデータのやり取りを実現できます。

javax.net.ssl.SSLSocketクラスは、通常のストリーム・ソケット(java.net.Socket)上でTLSサポートをカプセル化するネットワーク・ソケットを表します。一部のアプリケーションは、別のデータ・トランスポート抽象化(New-I/Oなど)を使用する場合があります。javax.net.ssl.SSLEngineクラスを使用して、TLS/DTLSパケットを生成および消費できます。

JDKには、プラガブルな(プロバイダ・ベースの)キー・マネージャおよびトラスト・マネージャの概念をサポートするAPIも含まれています。キー・マネージャjavax.net.ssl.KeyManagerクラスによってカプセル化され、認証の実行に使用されるキーを管理します。トラスト・マネージャTrustManagerクラス(同じパッケージ内)によってカプセル化され、管理するキーストア内の証明書に基づいて信頼できる人を決定します。

JDKには、次のSSL/TLS/DTLSプロトコルを実装する組込みプロバイダが含まれています。

Simple Authentication and Security Layer(SASL)

Simple Authentication and Security Layer (SASL)は、認証およびオプションでクライアント・アプリケーションとサーバー・アプリケーション間のセキュリティ層の確立を行うプロトコルを指定するインターネット標準です。SASLは、認証データの交換方法を定義しますが、そのデータの内容は指定しません。認証データの内容およびセマンティックスを指定する特定の認証メカニズムが適合できるフレームワークです。さまざまなセキュリティ・レベルおよび配備シナリオ用にインターネット・コミュニティによって定義された、多数の標準SASLメカニズムがあります。

Java SASL APIは、java.security.saslモジュール内にあり、SASLメカニズムを使用するアプリケーション用のクラスおよびインタフェースを定義します。これは、メカニズムに依存しないように定義されています。APIを使用するアプリケーションを、特定のSASLメカニズムの使用に固定する必要はありません。アプリケーションは、必要なセキュリティ機能に基づいて、使用するメカニズムを選択できます。このAPIは、クライアントとサーバーの両方のアプリケーションをサポートしています。javax.security.sasl.Saslクラスを使用して、SaslClientおよびSaslServerオブジェクトを作成します。

SASLメカニズムの実装は、プロバイダ・パッケージで提供されます。各プロバイダは、1つ以上のSASLメカニズムをサポートする場合があり、標準プロバイダ・アーキテクチャによって登録されて呼び出されます。

Javaプラットフォームには、次のSASLメカニズムを実装する組込みプロバイダが含まれています。

  • CRAM-MD5、DIGEST-MD5、EXTERNAL、GSSAPI、NTLM、およびPLAINクライアント・メカニズム
  • CRAM-MD5、DIGEST-MD5、GSSAPI、およびNTLMサーバー・メカニズム

Generic Security Service APIとKerberos

Javaプラットフォームには、Generic Security Service Application Programming Interface (GSS-API)用のJava言語バインディングを持つAPIが含まれています。これは、java.security.jgssモジュール内にあります。GSS-APIにより、アプリケーション・プログラマは、様々な基盤となるセキュリティ・メカニズム上のセキュリティ・サービスに統一されたアクセスができます。Java GSS-APIでは現在Kerberos v5メカニズムを使用する必要があり、Javaプラットフォームにはこのメカニズムの組込み実装が含まれています。現時点では、追加のメカニズムをプラグインすることはできません。

ノート:

認証の項で説明されているKrb5LoginModuleを、GSS Kerberosメカニズムとともに使用できます。

Javaプラットフォームには、Simple and Protected GSS-API Negotiation Mechanism (SPNEGO) GSS-APIメカニズムの組込み実装も含まれています。

2つのアプリケーションがGSS-APIを利用して安全にメッセージを交換するには、事前にジョイント・セキュリティ・コンテキストを確立しておく必要があります。コンテキストは、共有状態の情報(暗号化キーなどを含む)をカプセル化します。両方のアプリケーションが、org.ietf.jgss.GSSContextオブジェクトを作成および使用して、セキュリティ・コンテキストを構成する共有情報の確立および保守を行います。セキュリティ・コンテキストが確立されると、安全なメッセージ交換を準備するために使用できます。

Java GSS APIはorg.ietf.jgssパッケージ内にあります。Javaプラットフォームは、KerberosPrincipalKerberosTicketKerberosKeyKeyTabなど、基本的なKerberosクラスも定義します。これらはjavax.security.auth.kerberosパッケージ内にあります。

アクセス制御

Javaプラットフォームのアクセス制御アーキテクチャは、機密リソース(ローカル・ファイルなど)または機密アプリケーション・コード(クラス内のメソッドなど)へのアクセスを保護します。すべてのアクセス制御の決定は、java.lang.SecurityManagerクラスによって表されるセキュリティ・マネージャが仲介します。アクセス制御チェックを有効にするには、SecurityManagerをJava Runtimeにインストールする必要があります。

警告:

セキュリティ・マネージャおよびそれに関連するAPIは非推奨であり、今後のリリースでは削除されます。セキュリティ・マネージャの代わりとなるものはありません。詳細および代替手段については、JEP 411を参照してください。

javaコマンドによって実行されるローカル・アプリケーションは、SecurityManagerがインストールされていてもデフォルトでは実行されません。ローカル・アプリケーションをSecurityManagerで実行するには、アプリケーション自体がsetSecurityManagerメソッド(java.lang.Systemクラス内)によってプログラムでそれを設定するか、またはコマンド行で-Djava.security.manager引数を使用してjavaを呼び出す必要があります。

アクセス権

アクセス権は、システム・リソースへのアクセスを表します。アプレット(またはセキュリティ・マネージャとともに実行するアプリケーション)が、リソースへのアクセスを許可されるためには、アクセスを試みるコードに対し、該当するアクセス権を明示的に与える必要があります。

Javaコードがクラス・ローダーによってJava Runtimeにロードされると、クラス・ローダーは次の情報をそのコードに自動的に関連付けます。

  • コードのロード元の場所
  • コードに署名した人(存在する場合)
  • コードに付与されたデフォルトのアクセス権

この情報は、コードが信頼されないネットワークからダウンロードされたか(アプレットなど)、ファイル・システムからロードされたか(ローカル・アプリケーションなど)に関係なく、コードに関連付けられます。コードのロード元の場所はURLで表され、コード署名者は署名者の証明書チェーンによって表され、デフォルトのアクセス権はjava.security.Permissionオブジェクトによって表されます。

ダウンロードされたコードに自動的に付与されるデフォルトのアクセス権には、コードの出所であるホストへのネットワーク接続を行う機能が含まれています。ローカル・ファイル・システムからロードされたコードに自動的に付与されるデフォルトのアクセス権には、コードの出所であるディレクトリおよびそのディレクトリのサブディレクトリからファイルを読み取る機能が含まれています。

コードを実行しているユーザーのアイデンティティは、クラス・ローディング時に利用できません。アプリケーション・コードで、必要に応じてエンド・ユーザーを認証する必要があります(認証の項を参照)。ユーザーが認証されると、javax.security.auth.SubjectクラスのdoAsメソッドを呼び出すことによって、アプリケーションはそのユーザーを実行コードに動的に関連付けることができます。

セキュリティ・ポリシー

クラスローダによって、限られた一連のデフォルト・アクセス権がコードに付与されます。管理者は、セキュリティ・ポリシーによって、追加のコード・アクセス権を柔軟に管理できます。

Java SEは、セキュリティ・ポリシーの概念をjava.security.Policyクラスにカプセル化します。Java RuntimeにインストールされるPolicyオブジェクトはいつでも1つのみです。Policyオブジェクトの基本的な役割は、保護されたリソースへのアクセスがコード(ロード元の場所、署名者、および実行者によって特徴付けられる)に許可されるかどうかを決定することです。Policyオブジェクトがこの決定を行う方法は、実装によって異なります。たとえば、承認データを含むデータベースに問い合わせたり、別のサービスに問い合わせたりする場合があります。

Java SEには、セキュリティ・プロパティ・ファイル内に構成された1つ以上のASCII (UTF-8)ファイルから承認データを読み込む、デフォルトのPolicy実装が含まれています。これらのポリシー・ファイルには、コードに付与されるアクセス権の厳密なセットが含まれています。具体的には、特定の場所からロードされ、特定のエンティティによって署名され、特定のユーザーとして実行されるコードに付与されるアクセス権の厳密なセットです。各ファイル内のポリシー・エントリは、ドキュメント化された独自の構文に準拠する必要があり、単純なテキスト・エディタを使用して作成できます。

アクセス制御の実施

Java Runtimeは、プログラムの実行時に行われた一連のJava呼出しを追跡します。保護されたリソースへのアクセスが要求された場合、デフォルトでは、要求されたアクセスを許可するかどうかを決定するために呼出しスタック全体が評価されます。

前述したように、リソースはSecurityManagerによって保護されます。JDK内およびアプリケーション内の、セキュリティの影響を受けるコードは、次のようなコードでリソースへのアクセスを保護します。

SecurityManager sm = System.getSecurityManager();
if (sm != null) {
   sm.checkPermission(perm);
}

Permissionオブジェクトpermは、要求されたアクセスに対応します。たとえば、ファイル/tmp/abcを読み取ろうとすると、アクセス権は次のように構成される場合があります。

Permission perm = new java.io.FilePermission("/tmp/abc", "read");

SecurityManagerのデフォルトの実装は、その決定をjava.security.AccessController実装に委譲します。AccessControllerは、呼出しスタックをトラバースして、スタック内の各コード要素を、要求されたアクセス権(たとえば、前述の例ではFilePermission)とともに、インストールされているセキュリティPolicyに渡します。Policyは、管理者によって構成されたアクセス権に基づいて、要求されたアクセスを付与するかどうかを決定します。アクセスが付与されない場合、AccessControllerjava.lang.SecurityException.をスローします。

図1-4は、アクセス制御の適用を示しています。この特定の例では、最初に2つの要素ClassAおよびClassBが呼出しスタックにあります。ClassAは、ClassB内のメソッドを呼び出します。これは次に、java.io.FileInputStreamのインスタンスを作成することで、ファイル/tmp/abcへのアクセスを試みます。FileInputStreamコンストラクタは、FilePermissionpermを作成してから、前述のように、permSecurityManagerクラスのcheckPermissionメソッドに渡します。この特定の例では、ClassAおよびClassBのアクセス権のみをチェックする必要があります。これは、FileInputStreamSecurityManagerおよびAccessControllerなど、java.baseモジュール内のすべてのクラスは、すべてのアクセス権を自動的に受け取るためです。

この例では、ClassAClassBには異なるコード特性があります(出所および署名者が異なります)。それぞれに異なるアクセス権が付与されている場合があります。要求されたFilePermissionが両方のクラスに付与されていることをPolicyが示した場合にのみ、AccessControllerは要求されたファイルへのアクセスを付与します。

図1-4 リソースへのアクセスの制御


図1-4の説明が続きます
「図1-4 リソースへのアクセスの制御」の説明

XML署名

Java XMLデジタル署名APIは、XML署名を生成および検証するための標準のJava APIです。

XML署名は、どのタイプ(XMLまたはバイナリ)のデータにも適用できます(XML署名の構文と処理を参照)。結果の署名は、XMLで表されます。XML署名は、データを保護するために使用でき、データの整合性、メッセージ認証、および署名者認証を提供します。

APIは、「XML-Signature Syntax and Processing」でのW3C勧告の必須機能または推奨機能をすべてサポートするように設計されています。APIは拡張可能およびプラガブルであり、Java暗号化サービス・プロバイダ・アーキテクチャに基づいてます。

Java XMLデジタル署名APIは、java.xml.cryptoモジュール内にあり、次の6つのパッケージで構成されます。

  • javax.xml.crypto
  • javax.xml.crypto.dsig
  • javax.xml.crypto.dsig.keyinfo
  • javax.xml.crypto.dsig.spec
  • javax.xml.crypto.dom
  • javax.xml.crypto.dsig.dom

Java API for XML Processing(JAXP)

Java API for XML Processing (JAXP)は、Javaアプリケーションを使用してXMLデータを処理するためのものです。これには、Simple API for XML (SAX)、Document Object Model (DOM)、Streaming API for XML (StAX)の各パーサー、XMLスキーマ検証、およびExtensible Stylesheet Language Transformations (XSLT)のサポートが含まれています。また、JAXPは、XML関連の攻撃からアプリケーションおよびシステムを保護するための安全な処理機能も備えています。『Java API for XML Processing (JAXP)セキュリティ・ガイド』を参照してください。

ノート:

Java SEのセキュア・コーディング・ガイドラインには、XML関連の攻撃を防御できる追加の推奨事項が含まれています。

セキュリティ・ツールのサマリー

次の表では、JavaセキュリティおよびKerberos関連のツールを示します。

表1-2 Javaセキュリティのツール

ツール 使用方法
jar Java Archive (JAR)ファイルを作成します
jarsigner JARファイルの署名および署名の検証を行います
keytool キーストアを作成および管理します

Windows用のJDKに同梱される3つのKerberos関連ツールもあります。同等の機能が、自動的にLinuxおよびmacOSの一部になる同じ名前のツールで提供されています。

表1-3 Kerberos関連のツール

ツール 使用方法
kinit Kerberosチケット認可チケットを取得およびキャッシュします
klist ローカルのKerberos資格キャッシュおよびキー表のエントリを一覧します
ktab ローカルのKerberosキー表に格納された名前およびサービス・キーを管理します

組込みのプロバイダ

OracleのJava SE実装には、多数の組込みプロバイダ・パッケージが含まれています。JDKプロバイダ・ドキュメントを参照してください。