このドキュメントは、「JavaTM 暗号化アーキテクチャ (JCA) 仕様およびリファレンス」とともに使用してください。このドキュメントに存在しない章への言及がなされている 場合、「JCA 仕様」の章を参照してください。
JavaTM 暗号化拡張機能 (JCE) は、暗号化、鍵生成と鍵協定、およびメッセージ認証コード (MAC) アルゴリズム用のフレームワークおよび実装を提供します。暗号化サポートには、対称、非対称、ブロック、およびストリーム暗号が含まれます。このソフト ウェアは、セキュリティ保護されたストリームおよびシールされたオブジェクトもサポートします。
JavaTM 2 SDK, Standard Edition (Java 2 SDK) バージョン 1.2.x および 1.3.x では、JCE はオプションパッケージ (拡張機能) でした。Java 2 SDK 1.4 リリース以降では JCE が統合されています。
JCE は、実装非依存および可能な場合にはアルゴリズム非依存など、JCA の他の場所と同じ設計方針に基づいています。使用する「プロバイダ」アーキテクチャは、同一です。信頼できるエン ティティにより署名されたプロバイダは、JCE フレームワークへのプラグインが可能です。また、新規アルゴリズムをシームレスに追加できます。
JCE API には、以下が含まれます。
- 対称バルク暗号化 (DES、RC2、および IDEA など)
- 対称ストリーム暗号化 (RC4 など)
- 非対称暗号化 (RSA など)
- パスワードベース暗号化 (PBE)
- 鍵協定
- メッセージ認証コード (MAC)
JDK 5.0 リリースでは、「
SunJCE
」という名前の標準 JCE プロバイダがあらかじめインストールおよび登録されています。SunJCE は、次の暗号化サービスを提供します。
- Electronic Code Book (ECB)、Cipher Block Chaining (CBC)、Cipher Feedback (CFB)、Output Feedback (OFB)、および Propagating Cipher Block Chaining (PCBC) モードの DES (FIPS PUB 46-1)、トリプル DES、および Blowfish 暗号化アルゴリズムの実装 (なお、このドキュメントでは、「トリプル DES」と「DES-EDE」を同じものとする)
- DES、トリプル DES、Blowfish、HMAC-MD5、および HMAC-SHA1 アルゴリズムに適した鍵を生成する鍵ジェネレータ
- PKCS #5 で定義された DES-CBC パスワードベース暗号化 (PBE) アルゴリズムを使用する MD5 の実装
- 不透明な DES、トリプル DES、PBE 鍵オブジェクトと、背後の鍵データの透明な表現との双方向変換を提供する「秘密鍵ファクトリ」
- 複数のパーティ間での Diffie-Hellman 鍵協定アルゴリズムの実装
- Diffie-Hellman アルゴリズムに適した公開値および非公開値のペアの生成に必要な Diffie-Hellman 鍵ペアジェネレータ
- Diffie-Hellman アルゴリズムのパラメータジェネレータ
- 不透明な Diffie-Hellman 鍵オブジェクトと背後の鍵データの透明な表現との間の双方向変換を提供する Diffie-Hellman「鍵ファクトリ」
- Diffie-Hellman、DES、トリプル DES、Blowfish、および PBE パラメータ用のアルゴリズムパラメータマネージャ
- RFC 2104 に定義されている、HMAC-MD5 および HMAC-SHA1 キーハッシュアルゴリズムの実装
- PKCS #5 に記載されているパディング方式の実装
- JCEKS という独自のキーストア型のためのキーストアの実装
用語に関する注記
JDK 5.0 の JCE には、2 つのソフトウェアコンポーネントがあります。
このドキュメントでは、「JCE」という語は JDK 5.0 の JCE フレームワークを指して使われています。JDK 5.0 とともに提供される JCE プロバイダに言及する場合、これは常に「SunJCE」プロバイダのことを明示的に指しています。
- プロバイダが実装を提供可能な暗号化サービスを定義および提供するフレームワーク。このフレームワークには、
javax.crypto
パッケージ内のすべてが含まれる- 「SunJCE」という名前のプロバイダ
JCE v1.4 と 5.0 の相違点を次に示します。
- PKCS #11 の追加機能のサポート
- Solaris 暗号化フレームワークの統合
- ECC アルゴリズムのサポート
- JCA/JCE への
ByteBuffer
API サポートの追加RC2ParameterSpec
のサポート- XML 暗号化 RSA-OAEP アルゴリズムの完全サポート
javax.crypto.EncryptedPrivateKeyInfo
からのPKCS8EncodedKeySpec
の取得の簡略化- 「PBEWithSHA1AndDESede」と 「PBEWithSHA1AndRC2_40」暗号のサポート
- JCE Block Encryption 暗号での XML Encryption Padding アルゴリズムのサポート
- 鍵の最大許容長の動的判定
- SunJCE プロバイダへの RSA 暗号のサポート
- SunJCE プロバイダへの RC2 および ARCFOUR 暗号のサポート
- HmacSHA256、HmacSHA384、および HmacSHA512 のサポート
PKCS #11 ベースの暗号プロバイダのサポート
JDK 5.0 では、ネイティブの PKCS#11 API に対する汎用ゲートウェイとして動作する JCA/JCE プロバイダ、SunPKCS11
が実装されました。PKCS #11 は暗号アクセラレータのデファクトスタンダードで、暗号化スマートカードへのアクセスに広く使用されています。管理者およびユーザは、このプロバイダを設 定して、任意の PKCS#1 v2.x 互換トークンと通信できます。設定ファイル形式の例を示します。
Solaris 暗号化フレームワークの統合
デフォルトの Java セキュリティプロバイダ設定が JDK 5.0 で変更され、Solaris 10 では Solaris 暗号化フレームワークを使用する
SunPKCS11
プロバイダのインスタンスが含まれるようになりました。これは最高の優先度をもつプロバイダで、既存のアプリケーションすべてが Solaris 10 でパフォーマンス向上のメリットを享受できます。Solaris 8 および Solaris 9 での動作に変更はありません。この変更のため、すべての Solaris 10 システムでは、多くの暗号化演算が以前の何倍もの速度で実行されるようになります。暗号によるハードウェア高速化を搭載したシステムでは、100 倍のパフォーマンス向上を見込めます。
ECC アルゴリズムのサポート
JDK 5.0 より前では、JCA/JCE フレームワークでは、ECC 関連の暗号化アルゴリズムのクラスはサポートされていませんでした。ECC を利用するユーザは、ECC を実装したサードパーティのライブラリに頼らなければなりませんでした。しかし、このようなライブラリは既存の JCA/JCE フレームワークとはうまく統合されませんでした。JDK 5.0 以降は、ECC をサポートするプロバイダ用の ECC クラスが完全にサポートされるようになりました。
次のインタフェースが追加されました。
- java.security.spec.ECField
- java.security.interfaces.ECKey
- java.security.interfaces.ECPublicKey
- java.security.interfaces.ECPrivateKey
次のクラスが追加されました。
ByteBuffer API サポートの追加
ByteBuffer 引数をとるメソッドが、バルクデータの処理に使用する JCE API および SPI クラスに追加されました。ByteBuffer を byte[] より効率的に処理できる場合、プロバイダは engine* メソッドをオーバーライドできます。次の JCE メソッドが ByteBuffer のサポートのために追加されました。
javax.crypto.Mac.update(ByteBuffer input)次の JCA メソッドが ByteBuffer のサポートのために追加されました。
javax.crypto.MacSpi.engineUpdate(ByteBuffer input)
javax.crypto.Cipher.update(ByteBuffer input, ByteBuffer output)
javax.crypto.Cipher.doFinal(ByteBuffer input, ByteBuffer output)
javax.crypto.CipherSpi.engineUpdate(ByteBuffer input, ByteBuffer output)
javax.crypto.CipherSpi.engineDoFinal(ByteBuffer input, ByteBuffer output)java.security.MessageDigest.update(ByteBuffer input)
java.security.Signature.update(ByteBuffer data)
java.security.SignatureSpi.engineUpdate(ByteBuffer data)
java.security.MessageDigestSpi.engineUpdate(ByteBuffer input)RC2ParameterSpec のサポート
JDK 5.0 では RC2 アルゴリズム実装が拡張され、入力された鍵の長さとは異なる有効な鍵サイズをサポートします。XML 暗号化 RSA-OAEP アルゴリズムの完全サポート
JDK 5.0 より前の JCE では、PKCS#1 v2.1 および W3C Recommendation for XML Encryption の RSA-OAEP 鍵転送アルゴリズムに定義されているように、OAEP および PSS パディングで使用されるデフォルト以外の値を指定するパラメータクラスが定義されていませんでした。したがって、OAEP および PSS パディングに使用されたデフォルト以外の値をアプリケーションで指定する一般的な方法はありませんでした。
JDK 5.0 では、新しいパラメータクラスが追加され、OAEP パディングが完全にサポートされます。また、PSS パラメータクラスが拡張されて、API が RSA PSS シグニチャー実装を完全にサポートします。さらに、SunJCE プロバイダが拡張され、OAEPPadding が使用された場合に、
OAEPParameterSpec
を受け入れるようになりました。次のクラスが追加されました。
次のメソッドおよびフィールドが、
java.security.spec.PSSParameterSpec
に追加されました。public static final PSSParameterSpec DEFAULT
public PSSParameterSpec(String mdName, String mgfName,
AlgorithmParameterSpec mgfSpec,
int saltLen, int trailerField)
public String getDigestAlgorithm()
public String getMGFAlgorithm()
public AlgorithmParameterSpec getMGFParameters()
public int getTrailerField()
javax.crypto.EncryptedPrivateKeyInfo
からの PKCS8EncodedKeySpec
の取得の簡略化JDK 5.0 では、javax.crypto.EncryptedPrivateKeyInfo
はただ 1 つのメソッドgetKeySpec(Cipher)
を持ち、暗号化されたデータからPKCS8EncodedKeySpec
を取得します。この制限のため、ユーザは暗号解読鍵およびパラメータで初期化される暗号を指定する必要があります。ユーザが暗号解読鍵のみを持つ場合、ま ずパラメータをこのEncryptedPrivateKeyInfo
オブジェクトから取得し、適合するCipher
実装を確保し、初期化し、そしてgetKeySpec(Cipher)
メソッドを呼び出さなければなりません。
EncyptedPrivateKeyInfo
の使用をより簡単にし、API にjavax.crypto.SealedObject
と一貫性を持たせるため、次のメソッドが javax.crypto.EncryptedPrivateKeyInfo に追加されました。getKeySpec(Key decryptKey)
getKeySpec(Key decryptKey, String provider)
1.4.2 では、J2SE にバンドルされた暗号化管轄ポリシーファイルによって、暗号/暗号解読に使用する鍵の最大長が制限されます。また、ある種の暗号アルゴリズムのパラメータ 値も制限されます。制限のない暗号化管轄ファイルを使用したいユーザは、ファイルを個別にダウンロードする必要があります。また、Cipher インスタンスが、暗号化管轄ファイルで許容された最大値を超える鍵 (またはある種の暗号アルゴリズムのパラメータ) で初期化されると、例外がスローされます。
JDK 5.0 では、
Cipher
クラスが更新され、管轄ポリシーファイルで設定された鍵の最大長およびパラメータを定義するようになったため、デフォルトの (強度の制限された) 管轄ポリシーファイルがインストールされている場合、アプリケーションはより短かい鍵を使用できます。次のメソッドが javax.crypto.Cipher に追加されました。
public static final int getMaxAllowedKeyLength(String transformation)
throws NoSuchAlgorithmException
public static final AlgorithmParameterSpec
getMaxAllowedParameterSpec(String transformation)
throws NoSuchAlgorithmException;
HmacSHA-256、HmacSHA-384、および HmacSHA-512 アルゴリズムのサポートが JDK 5.0 で追加されました。
パブリックにアクセスできる RSA 暗号化実装が、SunJCE プロバイダに追加されました。
SunJCE プロバイダに、RC2 (RFC 2268) および ARCFOUR (RC4TM 互換アルゴリズム) 暗号が実装されました。
SunJCE プロバイダに、PBEWithSHA1AndDESede と PBEWithSHA1AndRC2_40 暗号のサポートが追加されました。
W3C XML 暗号で、新しいパディングアルゴリズム、ブロック暗号に対する「ISO10126Padding」が定義されます。詳細については、「5.2 Block Encryption Algorithms」を参照してください。Sun のプロバイダを XML 暗号実装よび JSR 106 プロバイダで使用できるようにするため、JDK 5.0 ではこのパディングに対するサポートが追加されました。
このセクションでは、API により実装される概念、および API 仕様で使用される技術用語の正確な意味に関する高度な説明を提供します。
暗号化および暗号解読
暗号化とは、データ (「クリアテキスト」と呼ばれる) および短い文字列 (「キー」) を受け取って、鍵を知らないサードパーティにとって無意味なデータ (「暗号テキスト」) を生成する処理です。暗号解読とはその逆で、暗号テキストおよび短い鍵文字列を受け取り、クリアテキストを生成する処理です。
パスワードベース暗号化
パスワードベース暗号化 (PBE) では、パスワードから暗号化鍵を導き出します。パスワードから暗号化鍵を取得しようとする攻撃者のタスクを非常に時間のかかるものにするため、大半の PBE 実装では、キーの作成時に乱数への混入 (salt と呼ばれる) が行われます。
暗号
暗号化および暗号解読は、暗号を使って行われます。暗号とは、暗号化方式に従って暗号化および暗号解読を実行可能なオブジェクトのことです。
鍵協定
鍵協定とは、複数のパーティが秘密情報を交換しなくても同じ暗号化鍵を確立可能なプロトコルを指します。
メッセージ認証コード
メッセージ認証コード (MAC) は、信頼できない媒体に送信または格納された情報の完全性を、秘密鍵に基づいてチェックする方法を提供します。一般に、メッセージ認証コードは、秘密鍵を 共有する 2 つのパーティ間で送信される情報の有効性を検証する場合に使用されます。
暗号化ハッシュ機能に基づくMAC 機構は、HMAC と呼ばれます。HMAC は、秘密共有鍵と組み合わせて、MD5 や SHA-1 などの任意の暗号化ハッシュ機能で使用できます。HMAC については、RFC 2104 で規定されています。
Cipher クラス
Cipher
クラスは、暗号化および暗号解読で使用される暗号機能を提供します。これは、JCE フレームワークのコア部分を構成します。Cipher オブジェクトの作成
API 内の他のエンジンクラスと同様、
Cipher
オブジェクトはCipher
クラスのgetInstance
ファクトリメソッドを使って作成されます。ファクトリメソッドは、クラスのインスタンスを返す static メソッドです。この場合は、要求された transformation を実装するCipher
のインスタンスです。
Cipher
オブジェクトを作成するには、変換名を指定する必要があります。要求された変換の実装を提供するプロバイダを指定することもできます。
public static Cipher getInstance(String transformation);
public static Cipher getInstance(String transformation,
String provider);変換名だけを指定すると、要求された変換の実装がその環境で使用可能かどうか、また複数の実装が存在する場合には優先度の高い 実装が存在するかどうかをシステムが判別します。
変換名とパッケージプロバイダの両方を指定すると、システムは要求されたパッケージ内に要求された変換の実装が存在するかどう かを確認し、存在しない場合には例外をスローします。
"DES/CBC/PKCS5Padding"
"DES"Cipher c1 = Cipher.getInstance("DES/ECB/PKCS5Padding");Cipher c1 = Cipher.getInstance("DES");このドキュメントの「付録 A」には、変換のアルゴリズム名、モード、およびパディ ング方式コンポーネントの指定に使用可能な標準名のリストが掲載されています。
ファクトリメソッドにより返されるオブジェクトは初期化されていないため、使用する前に初期化する必要があります。
Cipher オブジェクトの初期化
getInstance
を介して取得された Cipher オブジェクトは、次の 4 つのモードのいずれかで初期化する必要があります。これらのモードは、Cipher
クラスの final (ファイナル) 整数の定数として定義されます。モードは、シンボル名で参照できます。以下に、各モードのシンボル名および目的を示します。
- ENCRYPT_MODE
データの暗号化- DECRYPT_MODE
データの暗号解読- WRAP_MODE
安全に転送するために鍵をラッピングする- UNWRAP_MODE
ラッピングされた鍵をjava.security.Key
オブジェクトにアンラッピングするCipher 初期化メソッドは、それぞれモードパラメータ (
opmode
) をとり、そのモード用の Cipher オブジェクトを初期化します。他のパラメータには、鍵 (key
) または鍵を含む証明書 (certificate
)、アルゴリズムパラメータ (params
)、 および乱数の発生源 (random
) が含まれます。Cipher オブジェクトを初期化する場合、次のいずれかの
init
メソッドを呼び出します。public void init(int opmode, Key key);
public void init(int opmode, Certificate certificate)
public void init(int opmode, Key key,
SecureRandom random);
public void init(int opmode, Certificate certificate,
SecureRandom random)
public void init(int opmode, Key key,
AlgorithmParameterSpec params);
public void init(int opmode, Key key,
AlgorithmParameterSpec params,
SecureRandom random);
public void init(int opmode, Key key,
AlgorithmParameters params)
public void init(int opmode, Key key,
AlgorithmParameters params,
SecureRandom random)初期化ベクトルなどのパラメータを必要とする Cipher オブジェクトを暗号化用に初期化する場合、
init
メソッドにパラメータを何も指定しないと、ランダムパラメータを生成するか、プロバイダ固有のパラメータセット (デフォルト) を使用することにより、基盤となる暗号実装が必須パラメータを提供すると見なされます。ただし、パラメータを必要とする Cipher オブジェクトを暗号解読用に初期化する場合、
init
メソッドにパラメータを何も指定しないと、使用したinit
メソッドに応じてInvalidKeyException
またはInvalidAlgorithmParameterException
例外が発生します。詳細は、「アルゴリズムパラメータの管理」に関するセ クションを参照してください。
暗号解読には、暗号化に使用したのと同じパラメータを使用する必要があります。
Cipher オブジェクトを初期化すると、それまでに獲得した状態がすべて失われることに留意してください。つまり、Cipher を初期化することは、その Cipher の新規インスタンスを作成して初期化することと等価です。たとえば、指定された鍵で暗号解読を行うために Cipher を初期化してから、暗号化を行うために初期化すると、暗号解読モードで獲得した状態はすべて失われます。
データの暗号化および暗号解読
データの暗号化または暗号解読は、1 つのステップで実行 (「単一部分操作」) することも 、複数のステップで実行 (「複数部分操作」) することもできます。データの長さが不明な場合、またはデータが長すぎて一度にメモリに格納できない場合に、複数部分操作は有用です。
単独のステップでデータの暗号化または暗号解読を行う場合、次のいずれかの
doFinal
メソッドを呼び出します。public byte[] doFinal(byte[] input);
public byte[] doFinal(byte[] input, int inputOffset,
int inputLen);
public int doFinal(byte[] input, int inputOffset,
int inputLen, byte[] output);
public int doFinal(byte[] input, int inputOffset,
int inputLen, byte[] output, int outputOffset)複数のステップでデータの暗号化または暗号解読を行うには、次のいずれかの
update
メソッドを呼び出します。public byte[] update(byte[] input);
public byte[] update(byte[] input, int inputOffset, int inputLen);
public int update(byte[] input, int inputOffset, int inputLen,
byte[] output);
public int update(byte[] input, int inputOffset, int inputLen,
byte[] output, int outputOffset)複数部分操作は、上記の
doFinal
メソッドのいずれか (最後のステップで入力データが残される場合)、または次のdoFinal
メソッドのいずれか (最後のステップで入力データが残らない場合) を使って終了させます。public byte[] doFinal();
public int doFinal(byte[] output, int outputOffset);指定された変換の一部としてパディング (またはアンパディング) が要求された場合、すべての
doFinal
メソッドで、必要なパディング (またはアンパディング) 操作がすべて処理されます。
doFinal
を呼び出すと、Cipher オブジェクトはinit
を呼び出して初期化した時の状態にリセットされます。つまり、Cipher はリセットされて、データをさらに暗号化または暗号解読 (init
の呼び出しで指定された操作モードに基づく) できるようになります。鍵のラッピングとアンラッピング
鍵をラッピングすると、ある場所から別の場所へ安全に転送できます。
wrap/unwrap
API は鍵オブジェクトに対して直接機能するため、この API を使用するとコードの記述が容易になります。次のメソッドを使用すると、ハードウェアベースの鍵の安全な転送も可能になります。Key を wrap する場合、まず WRAP_MODE の Cipher オブジェクトを初期化し、次のメソッドを呼び出します。
public final byte[] wrap(Key key);ラップされた鍵のバイト (
wrap
を呼び出した結果) を、そのラップを解除する他のユーザに提供する場合、受信者がunwrap
を実行するのに必要な、次の追加情報も送信する必要があります。
- 鍵アルゴリズムの名前
- ラップされた鍵の型 (
Cipher.SECRET_KEY
、Cipher.PRIVATE_KEY
、 またはCipher.PUBLIC_KEY
のいずれか)鍵アルゴリズム名は、次に示すように Key インタフェースから
getAlgorithm
メソッドを呼び出すことにより確認できます。public String getAlgorithm();
wrap
への呼び出しにより返されたバイトのラップを解除するには、 UNWRAP_MODE の Cipher オブジェクトを初期化してから、以下を呼び出します。public final Key unwrap(byte[] wrappedKey,
String wrappedKeyAlgorithm,
int wrappedKeyType));ここで、
wrappedKey
はラップへの呼び出しにより返されたバイトを、wrappedKeyAlgorithm
はラップされた鍵に関連付けられたアルゴリズムを、wrappedKeyType
はラップされた鍵の型をそれぞれ指します。これは、Cipher.SECRET_KEY
、Cipher.PRIVATE_KEY
、 またはCipher.PUBLIC_KEY
のいずれかでなければなりません。アルゴリズムパラメータの管理
基盤となる Cipher 実装により使用されるパラメータ (アプリケーションにより
init
メソッドに明示的に渡されたか、基盤となる実装自体により生成された) は、getParameters
メソッドを呼び出すことにより Cipher オブジェクトから取得できます。このメソッドは、パラメータをjava.security.AlgorithmParameters
オブジェクト (パラメータが使用されない場合はnull
) として返します。パラメータが初期化ベクトル (IV) の場合、getIV
メソッドを呼び出すことによりパラメータを取得できます。次の例では、パスワードベース暗号化を実装する Cipher オブジェクトを、パラメータを使用せずに鍵のみを使用して初期化します。ただし、選択されたパスワードベース暗号化用に選択されたアルゴリズムは、salt および iteration count という 2 つのパラメータを必要とします。これらは、基盤となるアルゴリズム実装自体により生成されます。アプリケーションは、生成されたパラメータを以下の方法で Cipher オブジェクトから取得できます。
import javax.crypto.*;
import java.security.AlgorithmParameters;
// get cipher object for password-based encryption
Cipher c = Cipher.getInstance("PBEWithMD5AndDES");
// initialize cipher for encryption, without supplying
// any parameters.Here, "myKey" is assumed to refer
// to an already-generated key.
c.init(Cipher.ENCRYPT_MODE, myKey);
// encrypt some data and store away ciphertext
// for later decryption
byte[] cipherText = c.doFinal("This is just an example".getBytes());
// retrieve parameters generated by underlying cipher
// implementation
AlgorithmParameters algParams = c.getParameters();
// get parameter encoding and store it away
byte[] encodedAlgParams = algParams.getEncoded();暗号解読には、暗号化に使用したのと同じパラメータを使用する必要があります。これらは、エンコーディングからインスタンス化 することが可能であり、次に示すように、対応する Cipher オブジェクトを暗号解読用に初期化する際に使用できます。
import javax.crypto.*;
import java.security.AlgorithmParameters;
// get parameter object for password-based encryption
AlgorithmParameters algParams;
algParams =
AlgorithmParameters.getInstance("PBEWithMD5AndDES");
// initialize with parameter encoding from above
algParams.init(encodedAlgParams);
// get cipher object for password-based encryption
Cipher c = Cipher.getInstance("PBEWithMD5AndDES");
// initialize cipher for decryption, using one of the
// init() methods that takes an AlgorithmParameters
// object, and pass it the algParams object from above
c.init(Cipher.DECRYPT_MODE, myKey, algParams);Cipher オブジェクトの初期化時にパラメータを一切指定せず、基盤となる実装がいずれかのパラメータを使用するかどうか不明な場合、Cipher オブジェクトの
getParameters
メソッドを呼び出して、返される値をチェックするだけで確認できます。返される値がnull
の場合、パラメータが使用されなかったことを示します。SunJCE プロバイダにより実装される次の暗号アルゴリズムは、パラメータを使用します。
- DES、DES-EDE、および Blowfish は、フィードバック (つまり CBC、CFB、OFB、または PCBC) モードでの使用時に、初期化ベクトル (IV) を使用する。
javax.crypto.spec.IvParameterSpec
クラスは、指定された IV での Cipher オブジェクトの初期化に使用できる- PBEWithMD5AndDES は、salt および iteration count で構成されるパラメータセットを使用する。
javax.crypto.spec.PBEParameterSpec
クラスは、指定された salt および iteration count を使って PBEWithMD5AndDES を実装する Cipher オブジェクトを初期化する場合に使用できる
SealedObject
クラスを使用する場合、暗号解読操作に使用するアルゴリズムパラメータの格納または転送について心配する必要はありません。このクラスは、シール (暗号化) に使用されるパラメータを暗号化されたオブジェクトコンテンツに添付します。また、アンシール (暗号解読) でも同じパラメータを使用します。暗号出力時の考慮事項
Cipher の
update
およびdoFinal
の中には、呼び出し側による出力バッファの指定が可能なものがあります。暗号化または暗号解読されたデータは、このバッファ内に出力されます。この場合、 暗号化または暗号解読操作の結果を保持できるだけの大きさのバッファを渡すことは重要です。Cipher 内の次のメソッドを使用して、設定すべき出力バッファのサイズを確認できます。
public int getOutputSize(int inputLen)Cipher Stream クラス
JCE に、セキュリティ保護されたストリームという概念が導入されました。これは、InputStream または OutputStream を Cipher オブジェクトと結び付けることにより実現されています。セキュリティ保護されたストリームは、
CipherInputStream
およびCipherOutputStream
クラスにより提供されます。
CipherInputStream クラス
このクラスは、通過するデータの暗号化または暗号解読を行う
FilterInputStream
です。これは、InputStream
またはそのサブクラスのいずれか、およびCipher
で構成されます。CipherInputStream は、Cipher オブジェクトの挿入先の、セキュリティ保護された入力ストリームを表します。CipherInputStream のread
メソッドは、基盤となる InputStream から読み取られ、埋め込まれた Cipher オブジェクトによりさらに処理されたデータを返します。Cipher オブジェクトは、CipherInputStream で使用する前に完全に初期化する必要があります。たとえば、埋め込まれた Cipher が暗号解読用に初期化されている場合、CipherInputStream は基盤となる InputStream から読み込んだデータの暗号解読を試みてから、データをアプリケーションに返します。
このクラスは、上位クラス
java.io.FilterInputStream
およびjava.io.InputStream
のセマンティクス (特にエラーに関するセマンティクス) に厳密に準拠します。このクラスは、上位クラスで指定されたメソッドを正確に保持し、それらすべてをオーバーライドします。このため、埋め込まれた暗号に よるデータの追加処理が可能になります。さらに、このクラスは、上位クラスがスローしない例外をすべてキャッチします。特に、skip(long)
メソッドは、Cipher により処理されたデータだけを無視します。このクラスを使用するプログラマにとって、このクラスが定義またはオーバーライドされていないメソッド (上位クラスのいずれかにあとで追加された新規メソッドまたはコンストラクタ) を使用しないようにすることは重要です。これらのメソッド実装は、CipherInputStream へのセキュリティ面の影響を考慮に入れていないためです。
使用方法の一例として、
cipher1
が暗号化用に初期化されている場合を考えてみましょう。以下のコードは、暗号および FileInputStream を含む CipherInputStream を使用して、入力ストリームデータを暗号化する方法を示します。FileInputStream fis;
FileOutputStream fos;
CipherInputStream cis;
fis = new FileInputStream("/tmp/a.txt");
cis = new CipherInputStream(fis, cipher1);
fos = new FileOutputStream("/tmp/b.txt");
byte[] b = new byte[8];
int i = cis.read(b);
while (i != -1) {
fos.write(b, 0, i);
i = cis.read(b);
}上記のプログラムは、ファイル
/tmp/a.txt
からコンテンツを読み取って暗号化し、結果 (暗号化されたバイト) を/tmp/b.txt
に格納します。次の例は、CipherInputStream および FileInputStream の複数インスタンスを簡単に接続する方法を示します。この例では、
cipher1
およびcipher2
が、それぞれ暗号化および暗号解読用に (対応する鍵を使用して) 初期化されているものとします。FileInputStream fis;
FileOutputStream fos;
CipherInputStream cis1, cis2;
fis = new FileInputStream("/tmp/a.txt");
cis1 = new CipherInputStream(fis, cipher1);
cis2 = new CipherInputStream(cis1, cipher2);
fos = new FileOutputStream("/tmp/b.txt");
byte[] b = new byte[8];
int i = cis2.read(b);
while (i != -1) {
fos.write(b, 0, i);
i = cis2.read(b);
}上記のプログラムは、ファイル
/tmp/a.txt
の内容を/tmp/b.txt
にコピーします。ただし、/tmp/a.txt
からの読み取り時に、最初に内容の暗号化、次に暗号解読が行われます。実際のところ、このプログラムはテキストを暗号化したあと、すぐに暗号解読を行うた め、CipherInputStreams のチェーンをわかりやすく示す以外は特に有用なものではありません。CipherOutputStream クラス
このクラスは、通過するデータの暗号化または暗号解読を行う
FilterOutputStream
です。これは、OutputStream
またはそのサブクラスのいずれか、およびCipher
で構成されます。CipherOutputStream は、Cipher オブジェクトの挿入先の、セキュリティ保護された出力ストリームを表します。CipherOutputStream のwrite
メソッドは、埋め込まれた Cipher オブジェクトを使ってデータを処理してから、基盤となる OutputStream にデータを書き出します。Cipher オブジェクトは、CipherOutputStream で使用する前に完全に初期化する必要があります。たとえば、埋め込まれた Cipher が暗号化用に初期化されている場合、CipherOutputStream はデータを暗号化してから、基盤となる出力ストリームに書き出します。
このクラスは、上位クラス
java.io.OutputStream
およびjava.io.FilterOutputStream
のセマンティクス (特にエラーに関するセマンティクス) に厳密に準拠します。このクラスは、上位クラスで指定されたメソッドを正確に保持し、それらすべてをオーバーライドします。このため、埋め込まれた暗号に よるすべてのデータの追加処理が可能になります。さらに、このクラスは、上位クラスがスローしない例外をすべてキャッチします。このクラスを使用するプログラマにとって、このクラスが定義またはオーバーライドされていないメソッド (上位クラスのいずれかにあとで追加された新規メソッドまたはコンストラクタ) を使用しないようにすることは重要です。これらのメソッド実装は、CipherOutputStream へのセキュリティ面の影響を考慮に入れていないためです。
使用方法の一例として、
cipher1
が暗号化用に初期化されている場合を考えてみましょう。以下のコードは、暗号および FileOutputStream を含む CipherOutputStream を使用して、暗号化されたデータを出力ストリームに書き出す方法を示します。FileInputStream fis;
FileOutputStream fos;
CipherOutputStream cos;
fis = new FileInputStream("/tmp/a.txt");
fos = new FileOutputStream("/tmp/b.txt");
cos = new CipherOutputStream(fos, cipher1);
byte[] b = new byte[8];
int i = fis.read(b);
while (i != -1) {
cos.write(b, 0, i);
i = fis.read(b);
}
cos.flush();上記のプログラムは、ファイル
/tmp/a.txt
からコンテンツを読み取って暗号化し、結果 (暗号化されたバイト) を/tmp/b.txt
に格納します。次の例は、CipherOutputStream および FileOutputStream の複数インスタンスを簡単に接続する方法を示します。この例では、
cipher1
およびcipher2
が、それぞれ暗号解読および暗号化用に (対応する鍵を使用して) 初期化されているものとします。FileInputStream fis;
FileOutputStream fos;
CipherOutputStream cos1, cos2;
fis = new FileInputStream("/tmp/a.txt");
fos = new FileOutputStream("/tmp/b.txt");
cos1 = new CipherOutputStream(fos, cipher1);
cos2 = new CipherOutputStream(cos1, cipher2);
byte[] b = new byte[8];
int i = fis.read(b);
while (i != -1) {
cos2.write(b, 0, i);
i = fis.read(b);
}
cos2.flush();上記のプログラムは、ファイル
/tmp/a.txt
の内容を/tmp/b.txt
にコピーします。ただし、/tmp/b.txt
に書き込む前に、内容の暗号化および暗号解読が行われます。このクラスの
flush
とclose
メソッドには 1 つの重要な相違点があります。カプセル化された Cipher オブジェクトが、パディングを有効にしてブロック暗号アルゴリズムを実装する場合、この相違点に特に留意する必要があります。
flush
は、カプセル化された Cipher オブジェクトにより処理済みのバッファリングされた出力バイトをすべて強制的に書き出すことにより、基盤となる OutputStream をフラッシュします。カプセル化された Cipher オブジェクトによりバッファリングされ、処理待ち状態にあるバイトは、書き出されません。
close
は、基盤となる OutputStream を閉じて、関連付けられたすべてのシステムリソースを解放します。カプセル化された Cipher オブジェクトのdoFinal
メソッドを呼び出して、このオブジェクトによりバッファリングされたすべてのバイトを処理します。さらにflush
メソッドを呼び出して、処理したバイトを基盤となるストリームに書き出します。KeyGenerator クラス
鍵ジェネレータは、対称アルゴリズム用の秘密鍵を生成します。
鍵ジェネレータの作成
API 内の他のエンジンクラスと同様、KeyGenerator オブジェクトは KeyGenerator クラスの
getInstance
ファクトリメソッドを使って作成されます。ファクトリメソッドは、クラスのインスタンスを返す static メソッドです。この場合は、要求された鍵ジェネレータの実装を提供するKeyGenerator
のインスタンスです。
getInstance
は、秘密鍵を生成する対称アルゴリズムの名前を引数としてとります。オプションで、パッケージプロバイダ名を指定することもできます。public static KeyGenerator getInstance(String algorithm);
public static KeyGenerator getInstance(String algorithm,
String provider);アルゴリズム名だけを指定すると、要求された鍵ジェネレータの実装がその環境で使用可能かどうか、また複数の実装が存在する場 合には優先度の高い実装が存在するかどうかをシステムが判別します。
アルゴリズム名とパッケージプロバイダの両方を指定すると、システムは要求されたパッケージ内に要求された鍵ジェネレータの実 装が存在するかどうかを確認し、存在しない場合には例外をスローします。
KeyGenerator オブジェクトの初期化
特定の対称鍵アルゴリズムの鍵ジェレネータは、そのアルゴリズムで使用可能な対称鍵を作成します。また、生成された鍵に、アル ゴリズムに特定のパラメータ (存在する場合) を関連付けます。
鍵の生成方法には、アルゴリズム独立型とアルゴリズム特定型の 2 つがあります。この 2 つの唯一の相違点は、オブジェクトの初期化にあります。
- アルゴリズム独立型の初期化
すべての鍵ジェネレータは、「キーサイズ」および「乱数の発生源」の概念を共有します。普遍的に共有されるこれら 2 つの引数の型をとる
init
メソッドが存在します。また、keysize
引数のみをとり、システムにより提供される乱数の発生源を使用するinit
メソッドや、乱数の発生源だけをとるinit
メソッドも存在します。public void init(SecureRandom random);
public void init(int keysize);
public void init(int keysize, SecureRandom random);上のアルゴリズムに依存しない
init
メソッドを呼び出すときは、その他のパラメータは指定しないため、生成された鍵に関連付けられるアルゴリズムに特定のパラメータが存在する場合、そのパラ メータの処理は、プロバイダによって異なります。- アルゴリズム特定型の初期化
アルゴリズムに特定のパラメータのセットがすでに存在する状況では、
AlgorithmParameterSpec
引数をとるinit
メソッドが 2 つあります。このうちの一方はSecureRandom
引数もとりますが、他方では、乱数の発生源はシステムによって提供されます。public void init(AlgorithmParameterSpec params);
public void init(AlgorithmParameterSpec params,
SecureRandom random);クライアントが (
init
メソッドの呼び出しを介して) KeyGenerator を明示的に初期化しない場合、各プロバイダはデフォルトの初期化を提供およびドキュメント化する必要があります。鍵の作成
次のメソッドにより、秘密鍵が生成されます。public SecretKey generateKey();SecretKeyFactory クラス
このクラスは、秘密鍵のファクトリを表します。
鍵ファクトリは、「鍵」(
java.security.Key
型の不透明な暗号化鍵) を「鍵仕様」(背後の鍵データの適切な形式の透明表現) に変換したり、その逆の変換を行うために使用します。
javax.crypto.SecretKeyFactory
オブジェクトは、秘密 (対称) 鍵のみを処理するのに対し、java.security.KeyFactory
オブジェクトは鍵ペアの公開鍵および非公開鍵コンポーネントを処理します。
java.security.Key
型のオブジェクト (java.security.PublicKey
、java.security.PrivateKey
、 およびjavax.crypto.SecretKey
はそのサブクラス) は、その実装方法が不明であるため、不透明な鍵オブジェクトになります。基盤となる実装はプロバイダ依存であるため、ソフトウェアベースにもハードウェア ベースにもできます。鍵ファクトリを使用すると、プロバイダは独自の暗号化鍵実装を提供できるようになります。たとえば、公開値
y
、プライム係数p
、ベースg
で構成される Diffie Hellman 公開鍵の鍵仕様を保持しており、同じ仕様を別のプロバイダの Diffie-Hellman 鍵ファクトリに送る場合、生成されるPublicKey
オブジェクトはたいてい、異なる基盤実装を保持するようになります。プロバイダは、秘密鍵ファクトリがサポートする鍵仕様をドキュメント化する必要があります。たとえば、「SunJCE」プロバイダ により提供される DES 鍵の
SecretKeyFactory
は、DESKeySpec
を DES 鍵の透明表現としてサポートします。また、DES-EDE 鍵のSecretKeyFactory
はDESedeKeySpec
を DES-EDE 鍵の透明表現として、PBE のSecretKeyFactory
はPBEKeySpec
を基盤となるパスワードの透明表現として、それぞれサポートします。次の例は、
SecretKeyFactory
を使用して秘密鍵データをSecretKey
オブジェクトに変換する方法を示します。これは、以降のCipher
操作で使用できます。// Note the following bytes are not realistic secret key data
// bytes but are simply supplied as an illustration of using data
// bytes (key material) you already have to build a DESKeySpec.
byte[] desKeyData = { (byte)0x01, (byte)0x02, (byte)0x03,
(byte)0x04, (byte)0x05, (byte)0x06, (byte)0x07, (byte)0x08 };
DESKeySpec desKeySpec = new DESKeySpec(desKeyData);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = keyFactory.generateSecret(desKeySpec);この場合、
secretKey
の基盤実装は、keyFactory
のプロバイダに基づきます。別の方法として、プロバイダに依存せずに、同じ鍵データから等価な機能を持つ
SecretKey
オブジェクトを作成することも可能です。その場合、javax.crypto.SecretKey
インタフェースを実装するjavax.crypto.spec.SecretKeySpec
クラスを使用します。byte[] desKeyData = { (byte)0x01, (byte)0x02, ...};
SecretKeySpec secretKey = new SecretKeySpec(desKeyData, "DES");SealedObject クラス
プログラマは、このクラスを使用してオブジェクトを作成し、暗号化アルゴリズムを利用してその機密性を保護することができます。
java.io.Serializable
インタフェースを実装するオブジェクトが指定された場合、元のオブジェクトを直列化形式 (「ディープコピー」) でカプセル化するSealedObject
を作成し、DES などの暗号化アルゴリズムを使用して直列化された内容をシール (暗号化) することにより、機密性を保護できます。その後、暗号化された内容の暗号解読 (適正な暗号解読鍵を使用)、および直列化解除を行うことにより、元のオブジェクトを復元できます。一般的な使用法を、次のコード例に示します。オブジェクトをシールする場合、シール対象のオブジェクトから
SealedObject
を作成し、直列化されたオブジェクト内容を暗号化する、完全に初期化されたCipher
オブジェクトを作成します。この例では、文字列「This is a secret」が DES アルゴリズムを使用してシールされます。シール操作に使用されるすべてのアルゴリズムパラメータは、SealedObject
の内部に格納されることに留意してください。// create Cipher object
// Note:sKey is assumed to refer to an already-generated
// secret DES key.
Cipher c = Cipher.getInstance("DES");
c.init(Cipher.ENCRYPT_MODE, sKey);
// do the sealing
SealedObject so = new SealedObject("This is a secret", c);シールされた元のオブジェクトは、次の異なる 2 つの方法で復元可能です。
- 厳密に同一のアルゴリズム、鍵、パディング方式などで初期化され、オブジェクトのシールに使用された
Cipher
オブジェクトを使用する方法c.init(Cipher.DECRYPT_MODE, sKey);
try {
String s = (String)so.getObject(c);
} catch (Exception e) {
// do something
};この方法には、暗号解読鍵に関する知識がなくても、シールされたオブジェクトのアンシールを実行できるという利点がありま す。たとえば、あるパーティが暗号オブジェクトを必須の暗号解読鍵を使って初期化したあとで、別のパーティに渡すと、そのパーティはシールされたオブジェ クトをアンシールできます。
- 適切な暗号解読鍵を使用する方法 (DES は対称暗号化アルゴリズムであるため、シールとアンシールに同じ鍵を使用できる)
try {
String s = (String)so.getObject(sKey);
} catch (Exception e) {
// do something
};この方法では、
getObject
メソッドは、適切な暗号解読アルゴリズム用の暗号オブジェクトを作成し、シール済みのオブジェクトに格納された暗号解読鍵およびアルゴリズムパラメータ (存在する場合) を使用して初期化を行います。この方法の利点は、オブジェクトをアンシールするパーティが、オブジェクトのシールに使用したパラメータ (例: IV) を追跡する必要がないことです。KeyAgreement クラス
KeyAgreement クラスは、鍵協定プロトコルの機能を提供します。共有の秘密作成に関係する鍵は、
KeyPairGenerator
またはKeyGenerator
のいずれかの鍵ジェネレータか、KeyFactory
により、または鍵協定プロトコルの中間フェーズの結果として作成されます。KeyAgreement オブジェクトの作成
鍵協定に関係する各パーティは、KeyAgreement オブジェクトを作成する必要があります。API 内の他のエンジンクラスと同様、KeyAgreement オブジェクトは KeyAgreement クラスの
getInstance
ファクトリメソッドを使って作成されます。ファクトリメソッドは、クラスのインスタンスを返す static メソッドです。この場合は、要求された鍵協定アルゴリズムを提供するKeyAgreement
のインスタンスです。
getInstance
は、引数として鍵協定アルゴリズムの名前をとります。オプションで、パッケージプロバイダ名を指定することもできます。public static KeyAgreement getInstance(String algorithm);
public static KeyAgreement getInstance(String algorithm,
String provider);アルゴリズム名だけを指定すると、要求された鍵協定の実装がその環境で使用可能かどうか、また複数の実装が存在する場合には優 先度の高い実装が存在するかどうかをシステムが判別します。
アルゴリズム名とパッケージプロバイダの両方を指定すると、システムは要求されたパッケージ内に要求された鍵協定の実装が存在 するかどうかを確認し、存在しない場合には例外をスローします。
KeyAgreement オブジェクトの初期化
非公開情報を使用して KeyAgreement オブジェクトを初期化できます。Diffie-Hellman の場合、Diffie-Hellman 非公開鍵を使用して初期化します。補足的な初期化情報には、乱数の発生源、アルゴリズムパラメータのセットが含まれます。要求された鍵協定アルゴリズム で、アルゴリズムパラメータを指定する必要があり、また KeyAgreement オブジェクトの初期化にパラメータではなく鍵だけが提供される場合、必須のアルゴリズムパラメータを鍵に含める必要があります。たとえば、Diffie- Hellman アルゴリズムは、プライム係数
p
およびベースジェネレータg
をパラメータとして使用します。KeyAgreement オブジェクトを初期化する場合、次のいずれかの
init
メソッドを呼び出します。public void init(Key key);
public void init(Key key, SecureRandom random);
public void init(Key key, AlgorithmParameterSpec params);
public void init(Key key, AlgorithmParameterSpec params,
SecureRandom random);KeyAgreement フェーズの実行
各協定プロトコルは、鍵協定に関係する各パーティが実行する必要のある多数のフェーズで構成されます。
鍵協定の次のフェーズを実行するには、
doPhase
メソッドを呼び出します。public Key doPhase(Key key, boolean lastPhase);
key
パラメータには、そのフェーズで処理する鍵が含まれます。たいていの場合、これは、鍵協定に関係する他のパーティのいずれかの公開鍵、または前のフェーズ で生成された中間鍵です。doPhase
は、この鍵協定の他のパーティに送信する必要のある中間鍵を返すため、続くフェーズでその鍵を処理できます。
lastPhase
パラメータには、実行するフェーズが鍵協定の最後のフェーズかどうかを指定します。値FALSE
は、これが鍵協定の最後のフェーズではない (このあとにフェーズが続く) ことを示します。値TRUE
は、これが鍵協定の最後のフェーズであり、鍵協定が完了する (次にgenerateSecret
が呼び出される) ことを示します。Diffie-Hellman で 2 つのパーティが存在する場合 (「付録 F」を 参照)、
lastPhase
をTRUE
に設定してdoPhase
を呼び出します。Diffie-Hellman で 3 つのパーティが存在する場合、doPhase
を 2 度呼び出します。最初はlastPhase
をFALSE
に設定し、2 度目にはlastPhase
をTRUE
に設定します。共有される秘密の生成
各パーティがすべての必須鍵協定フェーズを実行したあとで、
generateSecret
メソッドのいずれかを呼び出して共有される秘密を計算できます。public byte[] generateSecret();
public int generateSecret(byte[] sharedSecret, int offset);
public SecretKey generateSecret(String algorithm);Mac クラス
Mac クラスは、メッセージ認証コード (MAC) の機能を提供します。「付録 F」の「コー ド例」を参照してください。
Mac オブジェクトの作成
API 内の他のエンジンクラスと同様、Mac オブジェクトは Mac クラスの
getInstance
ファクトリメソッドを使って作成されます。ファクトリメソッドは、クラスのインスタンスを返す static メソッドです。この場合は、要求された MAC アルゴリズムを提供するMac
のインスタンスです。
getInstance
は、引数として Mac アルゴリズムの名前をとります。オプションで、パッケージプロバイダ名を指定することもできます。public static Mac getInstance(String algorithm);
public static Mac getInstance(String algorithm,
String provider);アルゴリズム名だけを指定すると、要求された MAC アルゴリズムの実装がその環境で使用可能かどうか、また複数の実装が存在する場合には優先度の高い実装が存在するかどうかをシステムが判別します。
アルゴリズム名とパッケージプロバイダの両方を指定すると、システムは要求されたパッケージ内に要求された MAC アルゴリズムの実装が存在するかどうかを確認し、存在しない場合には例外をスローします。
Mac オブジェクトの初期化
Mac オブジェクトは、常に (秘密) 鍵を使って初期化されます。また、基盤となる MAC アルゴリズムによっては、パラメータセットを使って初期化することもできます。
Mac オブジェクトを初期化する場合、次のいずれかの
init
メソッドを呼び出します。public void init(Key key);
public void init(Key key, AlgorithmParameterSpec params);
javax.crypto.SecretKey
インタフェースを実装する任意の (秘密) 鍵オブジェクトを使って、Mac オブジェクトを初期化できます。これは、javax.crypto.KeyGenerator.generateKey()
が返すオブジェクト、javax.crypto.KeyAgreement.generateSecret()
などが返す鍵協定プロトコルの結果生成されるオブジェクト、またはjavax.crypto.spec.SecretKeySpec
のインスタンスです。MAC アルゴリズムの中には、Mac オブジェクトの初期化に使用される (秘密) 鍵オブジェクトに関連付けられた (秘密) 鍵アルゴリズムが重要ではないものがあります (SunJCE プロバイダの HMAC-MD5 および HMAC-SHA1 実装の場合)。ただし、それ以外の場合、(秘密) 鍵アルゴリズムは重要であり、(秘密) 鍵オブジェクトが不適切な (秘密) 鍵アルゴリズムで使用されると、
InvalidKeyException
がスローされます。MAC の計算
MAC は、1 つのステップで計算 (「単一部分操作」) することも 、複数のステップで計算 (「複数部分操作」) することもできます。データの長さが不明な場合、またはデータが長すぎて一度にメモリに格納できない場合に、複数部分操作は有用です。
あるデータの MAC を 1 回のステップで計算するには、次の
doFinal
メソッドを呼び出します。public byte[] doFinal(byte[] input);複数のステップでデータの MAC を計算するには、次のいずれかの
update
メソッドを呼び出します。public void update(byte input);
public void update(byte[] input);
public void update(byte[] input, int inputOffset, int inputLen);複数部分操作は、上記の
doFinal
メソッド (最後のステップで入力データが残される場合)、または次のdoFinal
メソッドのいずれか (最後のステップで入力データが残らない場合) を使って終了させます。public byte[] doFinal();
public void doFinal(byte[] output, int outOffset);
注 1: 大半のアプリケーション開発者には、このセクションで説明する内容は関係ありません。関係があるのは、作成するアプリケーションが、政府により暗号化制限 の課された国に輸出される可能性があり、アプリケーションをその制限に適合させる必要がある場合だけです。このセクションをスキップして、「JDK 5.0 での JCE プロバイダのインストール」に進むこともできます。注 2: このセクション全体で、「アプリケーション」という語は、アプリケーションとアプレットの両方を指します。JDK 5.0 の JCE フレームワークには、異なる管轄コンテキスト (位置) のアプレット/アプリケーションから利用可能な暗号化アルゴリズムおよび最大暗号化強度に関する制限を施行する機能が含まれます。これらの制限はすべて、 「管轄ポリシーファイル」に指定されます。
輸入制御の制限された国が存在するため、Sun Microsystems の JDK 5.0 に同梱される管轄ポリシーファイルでは、「強力」ではあっても制限付きの暗号化が使用可能になっています。適格国 (大半の国が該当) の在住者は、暗号化機能に制限のない「強度無制限」のバージョンを利用できます。ただし、政府が制限を課しているこれらの国が輸入できるのは「強力な」 バージョンだけです。JCE フレームワークでは、インストール済みの管轄ポリシーファイルで指定された制限が施行されます。
これらの国の一部またはすべてで、特定のアプリケーションに対し、暗号化制限の一部またはすべての免責が許可されています。たとえば、特定の種 類のアプリケーションは「特別」と見なされ、免責されます。また、鍵復元などの「免責機構」を利用するアプリケーションは、免責可能です。この種の国で は、免責されたと見なされるアプリケーションは、免責されていないアプリケーションに許可されるよりも強力な暗号化にアクセスできます。
実行時にアプリケーションが「免責されている」と認識されるようにするには、次の条件を満たす必要があります。
- JAR ファイル内にアクセス権ポリシーファイルを保持する必要がある。アクセス権ポリシーファイルには、アプリケーションが保持する暗号化関連のアクセス権、お よびそれを保持する条件 (存在する場合) を指定する
- アプリケーションおよびアクセス権ポリシーファイルを含む JAR ファイルには、アプリケーションが免責を受け取ったあとで発行されたコード署名証明書を使用して署名する必要がある
以下に、暗号化制限の一部またはすべての免責をアプリケーションに設定するために必要な手順のサンプルを示します。これは、免責されたものとし てアプリケーションを認識および処理するため、JCE により要求される情報を含む、基本情報です。実際には、アプリケーションを実行可能にする (政府が暗号化制限を課している) 特定の国の免責要件を知る必要があります。また、免責されたアプリケーションの処理プロセスを保持する JCE フレームワークベンダーの要件も理解しておく必要があります。詳細は、ベンダーにお尋ねください。なお、SunJCE プロバイダは、ExemptionMechanismSpi クラスの実装を提供しません。
- ステップ 1: アプリケーションコードの記述およびコンパイル
- ステップ 2: 適切な暗号化アクセス権を付与するアクセス権ポリシーファイルの作成
- ステップ 3: テストの準備
- ステップ 3a: 政府の課す制限に関する政府承認の申請
- ステップ 3b: コード署名証明書の取得
- ステップ 3c: アプリケーションおよびアクセス権ポリシーファイルの JAR ファイルへのバンドル
- ステップ 3d: JAR ファイルへの署名
- ステップ 3e: 制限国のユーザと同じ環境の設定
- ステップ 3f: アクセス権ポリシーファイルで指定された免責機構を実装するプロバイダのインストール (免責機構を使用するアプリケーションのみ)
- ステップ 4: アプリケーションのテスト
- ステップ 5: 米国政府による輸出承認の申請 (必要な場合)
- ステップ 6: アプリケーションの配備
免責機構を使用するアプリケーションに対する特殊コード要件
アプリケーションが関連付けられたアクセス権ポリシーファイルを (同じ JAR ファイル内に) 保持し、アクセス権ポリシーファイルで免責機構が指定されている場合、Cipher
getInstance
メソッドが呼び出されて Cipher がインスタンス化されると、JCE コードはインストール済みのプロバイダ内で指定された免責機構を実装するものを検索します。目的のプロバイダが見つかると、JCE は、プロバイダの実装に関連付けられた ExemptionMechanism API オブジェクトをインスタンス化してから、ExemptionMechanism オブジェクトをgetInstance
が返す Cipher と関連付けます。Cipher をインスタンス化したあと、かつ初期化する前に (Cipher
init
メソッドを呼び出して)、コードから次の Cipher メソッドを呼び出す必要があります。public ExemptionMechanism getExemptionMechanism()この呼び出しにより、Cipher に関連付けられた ExemptionMechanism オブジェクトが返されます。次に、返された ExemptionMechanism に対して次のメソッドを実行して、免責機構の実装を初期化する必要があります。
public final void init(Key key)ここで指定する引数の型は、このあとで Cipher
init
メソッドに指定する引数の型と同じにする必要があります。ExemptionMechanism の初期化が完了したら、通常と同じ方法で Cipher を初期化して使用できます。
アクセス権ポリシーファイル
実行時にアプリケーションが暗号化制限の一部またはすべてを「免責」されていると認識されるには、JAR ファイル内にアクセス権ポリシーファイルをバンドルする必要があります。アクセス権ポリシーファイルには、アプリケーションが保持する暗号化関連のアクセ ス権、およびそれを保持する条件 (存在する場合) を指定します。
注: アプリケーションにバンドルするアクセス権ポリシーファイルの名前は、
cryptoPerms
にする必要があります。免責されるアプリケーションにバンドルされるアクセス権ポリシーファイル内のアクセス権エントリの書式は、JDK 5.0 とともにダウンロードされる管轄ポリシーファイルの書式と同じです。以下にその書式を示します。
permission <crypto permission class name>[ <alg_name>
[[, <exemption mechanism name>][, <maxKeySize>
[, <AlgorithmParameterSpec class name>,
<parameters for constructing an AlgorithmParameterSpec object>]]]];管轄ポリシーファイルの書式の詳細は、「付録 D」を参照してください。
免責されるアプリケーションのアクセス権ポリシーファイル
アプリケーションの中には、制限を完全に解除可能なものもあります。通常、その種のアプリケーションにバンドルするアクセス権ポリシー ファイルには、以下を含めるだけで十分です。
grant {
// There are no restrictions to any algorithms.
permission javax.crypto.CryptoAllPermission;
};アプリケーションが 1 つ (またはいくつかの特定の) アルゴリズムだけを使用する場合、アクセス権ポリシーファイルには、CryptoAllPermission を付与するのではなく、そのアルゴリズムを明示的に記述します。たとえば、アプリケーションが Blowfish アルゴリズムだけを使用する場合、アクセス権ポリシーファイルですべてのアルゴリズムに CryptoAllPermission を付与する必要はありません。Blowfish アルゴリズムが使用される場合、暗号化制限が存在しないことを指定するだけで十分です。この場合、アクセス権ポリシーファイルは、次のようになります。
grant {
permission javax.crypto.CryptoPermission "Blowfish";
};免責機構により免責されるアプリケーションのアクセス権ポリシーファイル
免責機構が導入されるためにアプリケーションが「免責される」と見なされる場合、アプリケーションにバンドルされるアクセス権ポリシー ファイルに 1 つ以上の免責機構を指定する必要があります。実行時に、これらの免責機構のいずれかが機能していると、アプリケーションは免責されたものと見なされます。 次のようなアクセス権エントリ内に、各免責機構を指定する必要があります。
// No algorithm restrictions if specified
// exemption mechanism is enforced.
permission javax.crypto.CryptoPermission *,
"<ExemptionMechanismName>";ここで、
<ExemptionMechanismName>
には免責機構の名前を指定します。指定可能な免責機構の名前には、以下が含まれます。例として、鍵復元または鍵エスクローのいずれかが機能すると、アプリケーションが免責される場合を考えましょう。その場合、アクセス権ポリシーファイルに は、以下が含まれます。
- KeyRecovery
- KeyEscrow
- KeyWeakening
grant {
// No algorithm restrictions if KeyRecovery is enforced.
permission javax.crypto.CryptoPermission *,
"KeyRecovery";
// No algorithm restrictions if KeyEscrow is enforced.
permission javax.crypto.CryptoPermission *,
"KeyEscrow";
};注: 免責機構を指定するアクセス権エントリには、最大キーサイズを指定してはなりません。許可される鍵のサイズは、実際にはインストールされた免責管轄ポリ シーファイルにより決定されます。詳細は、次のセクションを参照してください。
バンドルされたアクセス権ポリシーファイルによる暗号化アクセス権への影響
実行時にアプリケーションが Cipher をインスタンス化し (
getInstance
メソッドを呼び出して)、かつそのアプリケーションが関連するアクセス権ポリシーファイルを保持する場合、JCE はアクセス権ポリシーファイルにgetInstance
の呼び出しで指定されたアルゴリズムに適用されるエントリが含まれるかどうかをチェックします。該当するエントリが含まれ、エントリが CryptoAllPermission を付与するか免責機構の実施を指定しない場合、このアルゴリズムには暗号化制限が存在しないことを意味します。アクセス権ポリシーファイルに
getInstance
の呼び出しで指定されたアルゴリズムに適用されるエントリが含まれ、かつエントリで免責機構の実施が指定されている場合、免責管轄ポリシーファイルが チェックされます。免責されるアクセス権が関連するアルゴリズムおよび免責機構のエントリを含み、そのエントリがアプリケーションに添付のアクセス権ポリ シーファイル内のアクセス権により暗黙的に設定されている場合、および指定された免責機構の実装がいずれかの登録済みプロバイダから利用可能な場合、 Cipher の最大キーサイズおよびアルゴリズムパラメータ値は、免責アクセス権エントリにより決定されます。アプリケーションにバンドルされるアクセス権ポリシーファイル内の関連するエントリに、暗黙的に設定された免責アクセス権が存在しない 場合、またはいずれかの登録済みプロバイダから利用可能な、指定された免責機構の実装が存在しない場合、デフォルトの標準暗号化アクセス権のみがアプリ ケーションに付与されます。
暗号化プロバイダを使用するには、静的または動的にインストールおよび登録する必要があります。JDK 5.0 の JCE 用暗号化プロバイダのインストールおよび構成方法は、JavaTM 2 プラットフォームの他のプロバイダと同様です。プロバイダのインストールおよび構成方法の詳細は、「JavaTM 暗号化アーキテクチャ API の仕様およびリファレンス」の「プロバイダのインストール」を参照してくださ い。
「SunJCE」はあらかじめインストールされているため、インストールする必要はありません。他のプロバイダを使用する場合は、後述のセク ションでプロバイダの登録方法を確認してください。
プロバイダのインストールには、プロバイダパッケージクラスのインストール、およびプロバイダの構成という 2 つのステップが含まれます。状況によっては、使用する前に、プロバイダのアクセス権の設定が必 要な場合があります。
プロバイダクラスのインストール
最初に行う事柄は、プロバイダクラスを利用可能にして、要求時に検出できるようにすることです。プロバイダクラスは、署名付 き JAR (Java ARchive) ファイル形式で提供されます。プロバイダクラスのインストールには、次の 2 つの方法があります。
- プロバイダクラスを含む JAR ファイルを、「インストール型」または「バンドル型」の拡張機能としてインストールする方法
- プロバイダクラスを含む JAR ファイルをクラスパスに含める方法
プロバイダ JAR ファイルは、以下に示すインストール型拡張機能 JAR ファイルの標準位置に配置された場合、「インストール型」拡張機能と見なされます。
<java-home>/lib/ext [Solaris]
<java-home>\lib\ext [Windows]
ここで、<java-home> は、ランタイムソフトウェアのインストール先ディレクトリ (JavaTM 2 Runtime Environment (JRE) のトップレベルディレクトリまたは JavaTM 2 SDK (Java 2 SDK) ソフトウェアの jre ディレクトリ) を指します。たとえば、JDK 5.0 を
/home/user1/JDK1.5.0
ディレクトリ (Solaris)、またはC:\Java DK1.5.0
ディレクトリ (Microsoft Windows) にインストールした場合、JAR ファイルを次のディレクトリにインストールする必要があります。/home/user1/JDK1.5.0/jre/lib/ext [Solaris]
C:\JDK1.5.0\jre\lib\ext [Windows]同様に、JRE 5.0 を
/home/user1/jre1.5.0
ディレクトリ (Solaris)、またはC:\jre1.5.0
ディレクトリ (Microsoft Windows) にインストールした場合、JAR ファイルを次のディレクトリにインストールする必要があります。/home/user1/jre1.5.0/lib/ext [Solaris]
C:\jre1.5.0\lib\ext [Windows]詳細については、「拡張機構アーキテクチャ」仕様の「インストール型拡張機能」と「バ ンドル型拡張機能」のセクションを参照してください。
プロバイダの構成
次の手順では、認可プロバイダのリストにこのプロバイダを追加します。これは、セキュリティプロパティファイルを編集することにより、静的 に行われます。
<java-home>/lib/security/java.security [Solaris]
<java-home>\lib\security\java.security [Windows]ここで、<java-home> は JRE がインストールされているディレクトリを指します。たとえば、JDK 5.0 を
/home/user1/JDK1.5.0
ディレクトリ (Solaris)、またはC:\JDK1.5.0
ディレクトリ (Microsoft Windows) にインストールした場合、次のファイルを編集する必要があります。/home/user1/JDK1.5.0/jre/lib/security/java.security [Solaris]
C:\JDK1.5.0\jre\lib\security\java.security [Windows]同様に、Java 2 Runtime Environment v 1.4 を
/home/user1/jre1.5.0
ディレクトリ (Solaris) またはC:\jre1.5.0
ディレクトリ (Microsoft Windows ) にインストールしている場合は、次のファイルを編集する必要があります。/home/user1/jre1.5.0/lib/security/java.security [Solaris]
C:\jre1.5.0\lib\security\java.security [Windows]プロバイダごとに、このファイルは次の形式の文を保持します。
security.provider.n=masterClassName
これはプロバイダを宣言し、その優先順位 n を指定します。優先順位とは、特定プロバイダの指定がないときに、要求されたアルゴリズムについてプロバイダを検索する順序です。順位は 1 から始まり、1 が最優先で次に 2、3 ... と続きます。
masterClassName には、プロバイダの「マスタークラス」を完全修飾名で指定します。この名前は、プロバイダベンダーから入手する必要があります。
JDK 5.0 には、「SUN」という名前のプロバイダが標準で搭載されています。このプロバイダは、次に示すように、静的プロバイダとして
java.security
プロパティファイル内で自動的に構成されます。security.provider.1=sun.security.provider.Sun「SUN」プロバイダのマスタークラスは、
sun.security.provider
パッケージ内のSun
クラスです。JCE プロバイダ「SunJCE」および Java 2 プラットフォームに含まれる他のセキュリティ関連プロバイダは、静的プロバイダとして自動的に構成されます。
別の JCE プロバイダを利用する場合、代替プロバイダを登録する行を追加し、優先順位を適切に設定します (必要に応じて他のプロバイダの順序も調整)。
登録するプロバイダのマスタークラスが
com.cryptox.provider
パッケージのCryptoX
クラスで、このプロバイダを優先順位の第 2 位にする場合を考えましょう。その場合、java.security
ファイルにある「SUN」プロバイダの行の下に次の行を追加して、さらに他のプロバイダの優先順位を 2 より大きくします。security.provider.2=com.cryptox.provider.CryptoX注: プロバイダは、動的に登録することもできます。このためには、Security
クラスのaddProvider
またはinsertProviderAt
のどちらかのメソッドを呼び出します。こうした登録は持続的なものではありません。また、実行できるのは次の権限を付与されたコードだけです。ここで、java.security.SecurityPermission "insertProvider.{name}"{name}
には実際のプロバイダ名を指定します。たとえば、プロバイダ名が「MyJCE」であり、このプロバイダを動的に登録するコードが/localWork
ディレクトリのMyApp.jar
ファイル内に存在する場合、アクセス権を付与するサンプルポリシーファイルのgrant
文は次のようになります。grant codeBase "file:/localWork/MyApp.jar" {
permission java.security.SecurityPermission
"insertProvider.MyJCE";
};プロバイダアクセス権の設定
JCE プロバイダがインストール型拡張機能ではない場合、セキュリティマネージャがインストール済みの状態で、JCE を使用するアプレットまたはアプリケーションを実行する際、常に JCE プロバイダにアクセス権を付与する必要があります。通常、アプレットの実 行時にはセキュリティマネージャが常にインストールされます。アプリケーションの場合でも、アプリケーション自体のコード内またはコマンド行引数で指定す ることにより、セキュリティマネージャをインストールできます。デフォルトシステムのポリシー構成ファイルは、インストール型拡張機能にすべての アクセス権を付与するため、インストール型拡張機能にアクセス権を設定する必要はありません。
ベンダーの提供する各プロバイダ用ドキュメントには、必須のアクセス権やそれを付与する方法が記載されています。たとえば、拡張機能がイン ストール型ではなく、セキュリティマネージャがインストールされている場合、プロバイダに次のアクセス権を付与する必要があります。
java.lang.RuntimePermission
(クラス保護ドメインを取得するため)。プロバイダは、自己完全性チェックの実行過程で、独自の保護ドメインの取得が必要になる場合があるjava.security.SecurityPermission "putProviderProperty.{name}"
(プロバイダプロパティを設定するため、{name}
には実際のプロバイダ名を指定)たとえば、名前が「MyJCE」で、コードが
myjce_provider.jar
内に存在するプロバイダにアクセス権を付与するサンプルコードを次に示します。この種の文は、ポリシーファイルに記述されます。この例では、myjce_provider.jar
ファイルは/localWork
ディレクトリに格納されるものとします。grant codeBase "file:/localWork/myjce_provider.jar" {
permission java.lang.RuntimePermission "getProtectionDomain";
permission java.security.SecurityPermission
"putProviderProperty.MyJCE";
};
「SunJCE」プロバイダは、JDK 5.0 の
java.security.KeyStore
クラスの実装を独自に提供します。この実装は、(トリプル DES に対しパスワードベース暗号化を使用して) JDK 5.0 の「SUN」プロバイダが提供するキーストア実装よりも強力に非公開鍵を保護します。JDK 5.0 の配布は、世界規模でバイナリおよびソース形式で行われるため、これより強力な暗号化機構は使用できません。「SunJCE」プロバイダのキーストア実装のメリットを享受するには、キーストア型に「JCEKS」を指定します。
「JKS」型 (Java 2 SDK の「SUN」プロバイダにより実装されたキーストア型の名前) のキーストアを、JCE キーストア型「JCEKS」にアップグレードできます。これは、キーストア内の非公開鍵エントリのパスワードを変更することにより実行します。
「SunJCE」の提供する (より) 強力な暗号化による鍵保護を、デフォルトキーストア内の「signkey」という名前の非公開鍵に適用する場合は、次のコマンドを入力します。このコマン ドにより、旧パスワードおよび新規パスワードの指定が求められます。
keytool -keypasswd -alias signkey -storetype jceks同じコマンドを使用して、パスワードを以前の値に戻すこともできます。
keytool
とキーストア、およびその管理方法の詳細は、「セキュリティツール」を参照してください。
このセクションでは、JDK 5.0 の JCE API の主な機能の使用方法について説明します。この API を実行する完全なサンプルプログラムは、このドキュメントの「付録 F」に掲載されています。
暗号化の使用
このセクションでは、鍵の生成、Cipher オブジェクトの作成と初期化、およびファイルの暗号化と暗号解読という一連の処理について説明します。この例全体で、データ暗号化規格 (DES) を使用します。
鍵の生成
DES を作成するには、DES 用の KeyGenerator をインスタンス化する必要があります。特定の DES 鍵生成実装について考慮する必要はないため、プロバイダは指定しません。KeyGenerator を初期化しないため、DES 鍵の作成にはシステム提供の乱数発生源が使用されます。
KeyGenerator keygen = KeyGenerator.getInstance("DES");
SecretKey desKey = keygen.generateKey();鍵を生成したあと、同じ KeyGenerator を使用して他の鍵を再度作成できます。
Cipher の作成
次のステップは、Cipher インスタンスの作成です。これには、Cipher クラスのいずれかの
getInstance
ファクトリメソッドを使用します。次のコンポーネントを含む必須の変換名を、スラッシュ (/) で区切って指定する必要があります。
- アルゴリズム名
- モード (オプション)
- パディング方式 (オプション)
この例では、Electronic Codebook モードおよび PKCS #5 パディング方式で DES (データ暗号化規格) 暗号を作成します。特定の必須変換の実装について考慮する必要はないため、プロバイダは指定しません。
DES の標準アルゴリズム名は「DES」、Electronic Codebook モードの標準名は「ECB」、PKCS #5 パディング方式の標準名は「PKCS5Padding」です。
Cipher desCipher;
// Create the cipher
desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");上で生成された
desKey
を使用して、Cipher オブジェクトを暗号化用に初期化します。// Initialize the cipher for encryption
desCipher.init(Cipher.ENCRYPT_MODE, desKey);
// Our cleartext
byte[] cleartext = "This is just an example".getBytes();
// Encrypt the cleartext
byte[] ciphertext = desCipher.doFinal(cleartext);
// Initialize the same cipher for decryption
desCipher.init(Cipher.DECRYPT_MODE, desKey);
// Decrypt the ciphertext
byte[] cleartext1 = desCipher.doFinal(ciphertext);
cleartext
とcleartext1
は、同一です。パスワードベース暗号化の使用
この例では、ユーザにパスワードを要求し、暗号化鍵をそのパスワードから導き出します。
java.lang.String
型のオブジェクトにパスワードを収集および格納するのは、適切と考えられます。ただし、注意すべき点があります。それは、String
型のオブジェクトは不変であるということです。このため、使用後にString
の内容を変更 (上書き) またはゼロにするようなメソッドは存在しません。この機能のために、String
オブジェクトは、ユーザパスワードなどセキュリティ上重要な情報の格納には適しません。セキュリティ関連の情報は、常に char 型の配列に収集および格納するようにしてください。この理由で、
javax.crypto.spec.PBEKeySpec
クラスは、パスワードを char 型の配列として受け取り、返します。次のメソッド例に、ユーザパスワードを char 型の配列として収集する方法を示します。
/**
* Reads user password from given input stream.
*/
public char[] readPasswd(InputStream in) throws IOException {
char[] lineBuffer;
char[] buf;
int i;
buf = lineBuffer = new char[128];
int room = buf.length;
int offset = 0;
int c;
loop:while (true) {
switch (c = in.read()) {
case -1:
case '\n':
break loop;
case '\r':
int c2 = in.read();
if ((c2 != '\n') && (c2 != -1)) {
if (!(in instanceof PushbackInputStream)) {
in = new PushbackInputStream(in);
}
((PushbackInputStream)in).unread(c2);
} else
break loop;
default:
if (--room < 0) {
buf = new char[offset + 128];
room = buf.length - offset - 1;
System.arraycopy(lineBuffer, 0, buf, 0, offset);
Arrays.fill(lineBuffer, ' ');
lineBuffer = buf;
}
buf[offset++] = (char) c;
break;
}
}
if (offset == 0) {
return null;
}
char[] ret = new char[offset];
System.arraycopy(buf, 0, ret, 0, offset);
Arrays.fill(buf, ' ');
return ret;
}PKCS #5 で定義された パスワードベースの暗号化 (PBE) を使用するには、salt と繰り返し処理の回数を指定する必要があります。暗号解読時にも、暗号化時と同じ salt および繰り返し処理の回数を使用する必要があります。
PBEKeySpec pbeKeySpec;
PBEParameterSpec pbeParamSpec;
SecretKeyFactory keyFac;
// Salt
byte[] salt = {
(byte)0xc7, (byte)0x73, (byte)0x21, (byte)0x8c,
(byte)0x7e, (byte)0xc8, (byte)0xee, (byte)0x99
};
// Iteration count
int count = 20;
// Create PBE parameter set
pbeParamSpec = new PBEParameterSpec(salt, count);
// Prompt user for encryption password.
// Collect user password as char array (using the
// "readPasswd" method from above), and convert
// it into a SecretKey object, using a PBE key
// factory.
System.out.print("Enter encryption password:");
System.out.flush();
pbeKeySpec = new PBEKeySpec(readPasswd(System.in));
keyFac = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
SecretKey pbeKey = keyFac.generateSecret(pbeKeySpec);
// Create PBE Cipher
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
// Initialize PBE Cipher with key and parameters
pbeCipher.init(Cipher.ENCRYPT_MODE, pbeKey, pbeParamSpec);
// Our cleartext
byte[] cleartext = "This is another example".getBytes();
// Encrypt the cleartext
byte[] ciphertext = pbeCipher.doFinal(cleartext);鍵協定の使用
2 つおよび 3 つのパーティ間で Diffie-Hellman 鍵交換を実行するサンプルプログラムに関しては、「付録 F」を参照してください。
JCE API では、アルゴリズム、アルゴリズムモード、およびパディング方式の標準名のセットが必要とされ、使用されます。ここに記載の仕様は、標準名として以下の名 前を確立するものです。また、「JavaTM 暗号化アーキテクチャ API の仕様およびリファレンス」の「付録 A」で定義された標準名のリストを 補足する内容となっています。アルゴリズム名の大文字と小文字が区別されることに留意してください。
場合によっては、複数のプロバイダの実装にわたって名前の一貫性を維持できるように、明示的に記載されていない名前の命名規約が提案されること があります。それらの提案では、特定のメッセージダイジェスト、暗号化アルゴリズム、その他の名前で置き換えるためのプレースホルダとして、山括弧で囲ま れた項目 (<digest>、<encryption> など) が使用されます。
暗号
アルゴリズム
Cipher
のインスタンスを要求する場合、次の名前を変換内の algorithm コンポーネントとして指定できます。
- AES: Advanced Encryption Standard として、NIST によって FIPS ドラフトに指定された。Joan Daemen、Vincent Rijmen 両氏による Rijndael アルゴリズムに基づいた 128 ビットのブロック暗号であり、128 ビット、192 ビット、256 ビットの鍵をサポートする
- ARCFOUR/RC4: Ron Rivest が開発したストリーム暗号。詳細については、K. Kaukonen、R. Thayer 著「A Stream Cipher Encryption Algorithm 'Arcfour'」、Internet Draft (expired)、draft-kaukonen-cipher-arcfour-03.txt を参照
- Blowfish: Bruce Schneier 氏の設計によるブロック暗号
- DES: データ暗号化規格 (FIPS PUB 46-2 で定義)
- DESede: トリプル DES 暗号化 (DES-EDE)
- ECIES (Elliptic Curve Integrated Encryption Scheme)
- PBEWith<digest>And<encryption> または PBEWith<prf>And<encryption>: パスワードベースの暗号アルゴリズム (PKCS #5) で、指定されたメッセージダイジェスト (<digest>) または擬似暗号関数 (<prf>)、暗号アルゴリズム (<encryption>) を使用する。以下に例を示す
- PBEWithMD5AndDES: 1993 年 11 月、RSA Laboratories の「PKCS #5: Password-Based Encryption Standard」バージョン 1.5 に定義されたパスワードベースの暗号化アルゴリズム。このアルゴリズムでは、CBC は暗号モード、PKCS5Padding はパディング方式とされている。他の暗号モードやパディング方式で使用することはできない
- PBEWithHmacSHA1AndDESede: 1999 年 3 月、RSA Laboratories の「PKCS #5: Password-Based Cryptography Standard」バージョン 2.0 に定義されたパスワードベースの暗号化アルゴリズム
- RC2、RC4、および RC5: RSA Data Security, Inc の Ron Rivest により開発された可変キーサイズ暗号化アルゴリズム
- RSA: PKCS #1 で定義されている RSA 暗号化アルゴリズム
モード
Cipher
のインスタンスを要求する場合、次の名前を変換内の mode コンポーネントとして指定できます。
- NONE: モードなし
- CBC: FIPS PUB 81 で定義された Cipher Block Chaining Mode
- CFB: FIPS PUB 81 で定義された Cipher Feedback Mode
- ECB: 米国商務省 National Institute of Standards and Technology (NIST) の Federal Information Processing Standard (FIPS) PUB 81「DES Modes of Operation」で定義された Electronic Codebook Mode (1980 年 12 月)
- OFB: FIPS PUB 81 で定義された Output Feedback Mode
- PCBC: Kerberos バージョン 4 で定義された Propagating Cipher Block Chaining
パディング
Cipher
のインスタンスを要求する場合、次の名前を変換内の padding コンポーネントとして指定できます。
- ISO10126Padding: このブロック暗号用パディングは、W3C の「XML Encryption Syntax and Processing」ドキュメントの 5.2 Block Encryption Algorithms に記載されている
- NoPadding: パディングなし
- OAEPWith<digest>And<mgf>Padding: PKCS #1 に定義されている Optimal Asymmetric Encryption Padding スキーマ。<digest> はメッセージダイジェスト、<mgf> はマスク生成関数で置き換える(例: OAEPWithMD5AndMGF1Padding)
- PKCS5Padding: 「PKCS #5: Password-Based Encryption Standard」バージョン 1.5 (RSA Laboratories、1993 年 11 月) で規定されたパディング方式
- SSL3Padding: SSL Protocol バージョン 3.0 のセクション 5.2.3.2 (CBC ブロック暗号) で規定されたパディング方式
block-ciphered struct {
opaque content[SSLCompressed.length];
opaque MAC[CipherSpec.hash_size];
uint8 padding[GenericBlockCipher.padding_length];
uint8 padding_length;
} GenericBlockCipher;GenericBlockCipher のインスタンスのサイズは、ブロック暗号のブロック長の倍数でなければなりません。
パディングは、パディング長 (常に存在) に影響を受けます。次の式が当てはまる場合を考えましょう。
sizeof(content) + sizeof(MAC) % block_length = 0,この場合、padding_length
が存在するため、パディング長を (block_length - 1) バイトにする必要があります。このため、パディング方式は PKCS5Padding に類似した (まったく同一ではない) ものになります。パディング長は、パディング内で符号化され、1 〜 block_length の範囲の値になります。SSL スキーマでは、パディングのサイズは、常に存在する
padding_length
内で符号化されるため、0 〜 block_length-1 の範囲の値になります。「SunJCE」プロバイダは、このパディング機構をサポートしない点に留意してください。
KeyAgreement
KeyAgreement
のインスタンスを要求する際、次のアルゴリズム名を指定できます。
- DiffieHellman: 「PKCS #3: Diffie-Hellman Key-Agreement Standard」バージョン 1.4 (RSA Laboratories、1993 年 11 月) で定義された Diffie-Hellman 鍵協定
- ECDH (Elliptic Curve Diffie-Hellman): RFC 3278、「Use of Elliptic Curve Cryptography (ECC) Algorithms in Cryptographic Message Syntax (CMS)」に記載
- ECMQV (Elliptic Curve Menezes-Qu-Vanstone): ECC Cipher Suites for TLS (2004 年 1 月 ドラフト) に記載
KeyGenerator
KeyGenerator
のインスタンスを要求する際、次のアルゴリズム名を指定できます。
- AES
- ARCFOUR/RC4
- Blowfish
- DES
- DESede
- HmacMD5
- HmacSHA1
- HmacSHA256
- HmacSHA384
- HmacSHA512
- RC2
KeyPairGenerator
KeyPairGenerator
のインスタンスを要求する際、次のアルゴリズム名を指定できます。
- DiffieHellman
SecretKeyFactory
SecretKeyFactory
のインスタンスを要求する際、次のアルゴリズム名を指定できます。
- DES
- DESede
- PBEWith<digest>And<encryption> または PBEWith<prf>And<encryption>: パスワードベースの暗号化 PKCS #5 で使用される秘密鍵ファクトリ。<digest> はメッセージダイジェスト、<prf> は擬似ランダム関数、<encryption> は暗号化アルゴリズム。たとえば、PBEWithMD5AndDES (PKCS #5, v 1.5)、PBEWithHmacSHA1AndDESede (PKCS #5, v 2.0) などがある。注: これらは各パスワード文字の下位 8 ビットのみを使用
KeyFactory
KeyFactory
のインスタンスを要求する際、次のアルゴリズム名を指定できます。
- DiffieHellman
AlgorithmParameterGenerator
AlgorithmParameterGenerator
のインスタンスを要求する際、次のアルゴリズム名を指定できます。
- DiffieHellman
AlgorithmParameters
AlgorithmParameters
のインスタンスを要求する際、次のアルゴリズム名を指定できます。
- AES
- Blowfish
- DES
- DESede
- DiffieHellman
- OAEP
- PBE
- PBEWith<digest>And<encryption>
- RC2
MAC
Mac
のインスタンスを要求する際、次のアルゴリズム名を指定できます。
- HmacMD5: RFC 2104「HMAC: Keyed-Hashing for Message Authentication」 (1997 年 2 月) で定義された HMAC-MD5 キーハッシュアルゴリズム
- HmacSHA1: RFC 2104「HMAC: Keyed-Hashing for Message Authentication」 (1997 年 2 月) で定義された HMAC-SHA1 キーハッシュアルゴリズム
- HmacSHA256: RFC 2104「HMAC: Keyed-Hashing for Message Authentication」 (1997 年 2 月) で定義された、
SHA-256
をメッセージダイジェストアルゴリズムとする HmacSHA256 アルゴリズム- HmacSHA384: RFC 2104「HMAC: Keyed-Hashing for Message Authentication」 (1997 年 2 月) で定義された、
SHA-384
をメッセージダイジェストアルゴリズムとする HmacSHA384 アルゴリズム- HmacSHA512: RFC 2104「HMAC: Keyed-Hashing for Message Authentication」 (1997 年 2 月) で定義された、
SHA-512
をメッセージダイジェストアルゴリズムとする HmacSHA512 アルゴリズム- PBEWith<mac>: パスワードベースのメッセージ認証規格、PKCS #5 バージョン 2.0 で使用される MAC。<mac> はメッセージ認証コードのアルゴリズム名。例: PBEWithHmacSHA1
キーストアのタイプ
KeyStore
のインスタンスを要求する際、次の型を指定できます。
- JCEKS: 「SunJCE」により実装された独自のキーストア型
免責機構
暗号化制限を「免責された」と見なされるアプリケーションに付属するアクセス権ポリシーファイル内で、次の免責機構名を指定できます。
- KeyEscrow: バックアップ暗号解読機能付き暗号化システム。このシステムを利用すると、特定条件下で、承認された人物 (ユーザ、組織役員、政府職員) が、特別なデータ復元鍵を保持する信頼できる 1 つ以上のパーティの提供する情報を利用して、暗号解読を実行できる
- KeyRecovery: 暗号化データのロックに使用する秘密鍵を取得するメソッド。これは、災害発生時に、企業独自の暗号化情報への復旧アクセスを実行する手段として使用できる
- KeyWeakening: 鍵の一部をエスクローまたは復元可能なメソッド
SunJCE プロバイダは、次のデフォルトキーサイズを使用します。
- KeyGenerator
- DES: 56 ビット
- トリプル DES: 112 ビット
- Blowfish: 56 ビット
- HmacMD5: 64 バイト
- HmacSHA1: 64 バイト
- KeyPairGenerator
- Diffie-Hellman: 1024 ビット
- AlgorithmParameterGenerator
- Diffie-Hellman: 1024 ビット
SunJCE プロバイダでは、次のクラスの初期化メソッドに渡すキーサイズに制限が課されます。
- KeyGenerator
制限 (アルゴリズム別):
- DES: キーサイズを
56
にする必要がある- トリプル DES: キーサイズを
112
または168
にする必要がある注: キーサイズが
112
の場合には 2 つの中間鍵を保持するトリプル DES 鍵が、168
の場合には 3 つの中間鍵を保持するトリプル DES 鍵が、それぞれ生成される- Blowfish: キーサイズを、
8
の倍数 (32
以上448
以下) にする必要がある- KeyPairGenerator
制限 (アルゴリズム別):
- Diffie-Hellman: キーサイズを、
64
の倍数 (512
以上1024
以下) にする必要がある- AlgorithmParameterGenerator
制限 (アルゴリズム別):
- Diffie-Hellman: キーサイズを、
64
の倍数 (512
以上1024
以下) にする必要がある
JCE の管轄ポリシーファイルは、J2SE 形式のポリシーファイル (対応するアクセス権を指定する文を含む) で表されます。「デフォルトの Policy の実装とポリシーファイルの構文」に説明されているよ うに、J2SE ポリシーファイルでは、指定されたコードソースのコードに付与するアクセス権を指定します。アクセス権は、システムリソースへのアクセスを表します。 JCE の場合、「リソース」は暗号化アルゴリズムです。また、暗号化制限はすべてのコードに適用されるため、コードソースを指定する必要はありません。
管轄ポリシーファイルは、1 つ以上の「アクセス権エントリ」を含む、非常に基本的な「付与エントリ」で構成されます。
grant {
<permission entries>;
};以下に、管轄ポリシーファイルのアクセス権エントリの書式を示します。
permission <crypto permission class name>[ <alg_name>
[[, <exemption mechanism name>][, <maxKeySize>
[, <AlgorithmParameterSpec class name>,
<parameters for constructing an
AlgorithmParameterSpec object>]]]];以下に、「Blowfish」アルゴリズムを 64 ビットの最大キーサイズに制限する、管轄ポリシーファイルのサンプルを示します。
grant {
permission javax.crypto.CryptoPermission "Blowfish", 64;
. . .;
};アクセス権エントリは、
permission
で始まります。上記のテンプレート内の<crypto permission class name>
には、javax.crypto.CryptoPermission
などの具体的なアクセス権クラス名を指定します。暗号化アクセス権クラスは、特定の環境下で特定のキーサイズを使用するアプリケーション/アプレットの機 能に対応します。暗号化アクセス権クラスには、CryptoPermission
およびCryptoAllPermission
の 2 つが存在します。特別なCryptoAllPermission
クラスは、暗号化関連のアクセス権すべてを表します。つまり、暗号化関連の制限はないことを示します。<alg_name> を指定する場合、"DES" や "RSA" など暗号化アルゴリズムの標準名を表す文字列 (「付録 A」を参照) を引用符で囲んで指定します。
<免責機構名> を指定する場合、免責機構を指す文字列を引用符で囲んで指定します。免責機構を実施すると、暗号化制限が緩和されます。使用可能な免責機構名には、 「KeyRecovery」、「KeyEscrow」、および「KeyWeakening」が含まれます。
<maxKeySize> には、指定したアルゴリズムに許可する最大鍵サイズ (ビット) を示す整数値を指定します。
アルゴリズムによっては、キーサイズでアルゴリズムの強度を指定するだけでは不十分な場合があります。たとえば、"RC5" アルゴリズムの場合には、ラウンド数も考慮する必要があります。アルゴリズムの強度をキーサイズだけで表現するのでは不十分な場合、アクセス権エントリで AlgorithmParameterSpec クラス名 (
javax.crypto.spec.RC5ParameterSpec
など)、および指定された AlgorithmParameterSpec オブジェクトの構築用パラメータリストも指定する必要があります。アクセス権エントリの各項目は、指定された順序で記述する必要があります。各エントリはセミコロンで終わります。
識別子 (
grant
、permission
) では大文字と小文字は区別されませんが、<crypto permission class name>
、および 値として引き渡される文字列では大文字と小文字が区別されます。注: 「*」は、すべてのアクセス権エントリオプションでワイルドカードとして使用できます。たとえば、<alg_name> に「*」を指定すると、「すべてのアルゴリズム」という意味になります。
輸入制御上の制限のために、JDK 5.0 に同梱される管轄ポリシーファイルでは、「強力」ではあっても制限付きの暗号化の使用が許可されます。以下に、この「強力な」バージョンの管轄ポリシー ファイルで許可される最大キーサイズを示します。
アルゴリズム
最大キーサイズ
DES
64
DESede
*
RC2
128
RC4
128
RC5
128
RSA
2048
* (その他すべて)
128