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.security、javax.crypto、javax.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はそれらの実行を準備します。
-
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
からの実装が返されます。
オプションで、プロバイダ名を指定することで特定のプロバイダからの実装を要求できます。次の文は、特定のプロバイダProviderC
からのSHA-256メッセージ・ダイジェスト実装を要求します。
MessageDigest md = MessageDigest.getInstance("SHA-256", "ProviderC");
次の図では、この文で特定のプロバイダProviderC
からのSHA-256メッセージ・ダイジェスト実装がどのように要求されるかを示します。この場合は、優先順位の高いプロバイダであるProviderB
もSHA-256実装を提供していても、指定されたプロバイダからの実装が返されます。
メッセージ・ダイジェスト・アルゴリズムなどの暗号化サービスの詳細は、Javaの暗号化の項を参照してください。
OracleのJavaプラットフォーム実装には、アプリケーションによって使用できる一連の基本的なセキュリティ・サービスを実装する、組込みの多数のデフォルト・プロバイダが含まれています。Javaプラットフォームのほかのベンダーの実装には、ベンダー固有のセキュリティ・サービスのセットをカプセル化した、異なるプロバイダのセットが含まれている場合があります。組込みのデフォルト・プロバイダという用語は、Oracleの実装で利用可能なプロバイダのことを指しています。
Javaの暗号化
Java暗号化アーキテクチャは、Javaプラットフォームの暗号化機能へのアクセスおよび開発のためのフレームワークです。
これには、各種暗号化サービスのためのAPIが含まれています。それらを次に示します。
- メッセージ・ダイジェスト・アルゴリズム
- デジタル署名アルゴリズム
- 対称バルクおよびストリーム暗号化
- 非対称暗号化
- パスワードベース暗号化(PBE)
- 楕円曲線暗号(ECC)
- キー協定アルゴリズム
- キー・ジェネレータ
- メッセージ認証コード(MAC)
- 安全な乱数ジェネレータ
-
java.security
およびjava.security.*
パッケージには、輸出規制の対象ではないクラス(Signature
やMessageDigest
など)が含まれています。 -
javax.crypto
パッケージには、輸出規制の対象のクラス(Cipher
やKeyAgreement
など)が含まれています。
暗号化インタフェースはプロバイダ・ベースであり、複数の相互運用性のある暗号化実装が可能です。ソフトウェアで暗号化操作を行うプロバイダもあれば、スマートカード・デバイスやハードウェア暗号化アクセラレータなどのハードウェア・トークン上で暗号化操作を行うプロバイダもあります。輸出規制の対象のサービスを実装するプロバイダには、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を格納する場合もあります。
KeyStore
とCertStore
の実装は、タイプによって区別されます。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ファイルには、主にアプレットおよびアプリケーションに関連したクラス・ファイルおよび補助リソースが含まれています。
-
keytool
を使用して、適切なキーおよび証明書を生成するかキー・ストアにインポートします(それらがまだキーストアにない場合)。 -
jar
ツールを使用して、コードをJARファイルにパッケージ化します。 -
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と通信するだけなので、基盤となるプラグイン・モジュールから独立したままの状態を維持できます。アプリケーションでは、新規または更新されたモジュールをプラグインとして使用でき、アプリケーションを変更する必要はありません。次の図では、アプリケーションと基盤となるログイン・モジュールとの間の独立性を示します。
ログイン・モジュールは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プラットフォームにはこのメカニズムの組込み実装が含まれています。現時点では、追加のメカニズムをプラグインすることはできません。
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プラットフォームは、KerberosPrincipal
、KerberosTicket
、KerberosKey
、KeyTab
など、基本的な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
は、管理者によって構成されたアクセス権に基づいて、要求されたアクセスを付与するかどうかを決定します。アクセスが付与されない場合、AccessController
はjava.lang.SecurityException.
をスローします。
図1-4は、アクセス制御の適用を示しています。この特定の例では、最初に2つの要素ClassA
およびClassB
が呼出しスタックにあります。ClassA
は、ClassB
内のメソッドを呼び出します。これは次に、java.io.FileInputStream
のインスタンスを作成することで、ファイル/tmp/abc
へのアクセスを試みます。FileInputStream
コンストラクタは、FilePermission
、perm
を作成してから、前述のように、perm
をSecurityManager
クラスのcheckPermission
メソッドに渡します。この特定の例では、ClassA
およびClassB
のアクセス権のみをチェックする必要があります。これは、FileInputStream
、SecurityManager
およびAccessController
など、java.base
モジュール内のすべてのクラスは、すべてのアクセス権を自動的に受け取るためです。
この例では、ClassA
とClassB
には異なるコード特性があります(出所および署名者が異なります)。それぞれに異なるアクセス権が付与されている場合があります。要求されたFilePermission
が両方のクラスに付与されていることをPolicy
が示した場合にのみ、AccessController
は要求されたファイルへのアクセスを付与します。
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関連の攻撃を防御できる追加の推奨事項が含まれています。