Java Security API は,Java における暗号認証機能を実現する API であり,Sun Microsytems (Oracle に吸収合併) から仕様が公開され,Java におけるデファクトスタンダードとなっている. この API は,基本となる API の枠組を抽象クラスとして与えるもので,具体的な暗号認証アルゴリズムに対応した実装はソフトウェアベンダが任意に組み込むことができる (Providerクラスとして組み込む).Sun Microsystens の提供する JDK/JRE にもデフォルトの実装として,ハッシュ関数やディジタル署名などの暗号認証機能が組み込まれている.
java.security パッケージの構成を以下に示す.
ここでは,一連の暗号認証機能(鍵生成,ハッシュ関数,ディジタル署名,暗号化・復号,鍵交換)の機能に関するクラスとその使い方を示し,Java Security API の概要を解説する.
KeyPairGeneratorクラスは,公開鍵暗号方式における公開鍵と秘密鍵の鍵ペアの生成を行うクラスである.
鍵ペアの生成方法には,アルゴリズム独立型の方法とアルゴリズム特定型の方法の2つがある.この2つの唯一の相違点は,オブジェクトの初期化にある.
public static KeyPairGenerator getInstance(String algorithm) public static KeyPairGenerator getInstance(String algorithm, String provider)
これにより,KeyPairGeneratorクラスのインスタンスが生成される.
public void initialize(int strength, SecureRandom random)このアルゴリズム独立型 initializeメソッドを呼び出すときは,他のパラメータは指定しないため,その他のパラメータ値はすべてデフォルトの標準値が用いられる.
public void initialize(DSAParams params, SecureRandom random)
public KeyPair generateKeyPair()generateKeyPairを呼び出すたびに,異なる鍵のペアが作られる.
public PrivateKey getPrivate() public PublicKey getPublic()PublicKey および PrivateKey は,メソッドを持たないインタフェースであり,型の安全性および型の識別に使われている. また,PublicKey および PrivateKey は,Keyインタフェースを継承している. Key インタフェースは,すべての鍵に関するトップレベルのインタフェースであり,すべての鍵オブジェクトが共有する機能を定義している.
public String getAlgorithm()
public byte[] getEncoded()
public String getFormat()
上記の KeyPairGeneratorオブジェクトを用いた鍵ペア生成のコーディング例を示す. ここでは,DSAアルゴリズム用の 1024ビット長の鍵ペア(秘密鍵と公開鍵)を作成する. DSAアルゴリズムのパラメータはデフォルト値を使う.
// KeyPairGeneratorオブジェクトの生成 KeyPairGenerator kpGen = KeyPairGenerator.getInstance("DSA"); // KeyPairGeneratorオブジェクトの初期化 (seedは乱数種) kpGen.initialize(1024, new Securerandom(seed)); // 鍵ペアの生成 KeyPair pair = kpGen.generateKeyPair();
MessageDigestクラスは,SHA-1 や MD5 のようなメッセージダイジェストを生成する機能を提供するクラスである.任意長の入力(バイト列)を受け取り,ダイジェストまたはハッシュと呼ばれる固定長の出力を生成する.
メッセージダイジェストの生成は次の手順で行う.
public static MessageDigest getInstance(String algorithm) public static MessageDigest getInstance(String algorithm, String provider)
public void update(byte input) public void update(byte[] input) public void update(byte[] input, int offset, int len)
public byte[] digest() public byte[] digest(byte[] input)
上記の MessageDigestオブジェクトを用いたコーディング例を示す. ここでは,SHA-1 アルゴリズムを用いて2つのバイト配列 data1,data2 のダイジェストをバイト配列 hash として求める.
// MessageDigestオブジェクトの生成 MessageDigest sha = MessageDigest.getInstance("SHA-1"); // メッセージの設定 sha.update(data1); sha.update(data2); // ダイジェストの取得 byte hash[] = sha.digest();
Signatureクラスは,DSA や RSA などアルゴリズムを用いたディジタル署名機能を提供するクラスである.署名アルゴリズムは任意サイズの入力と秘密鍵を受け取り,署名と呼ばれる比較的短いバイト文字列を生成する.
Signatureオブジェクトを使って,データに署名を付けたり,署名が関連データの実際の署名かどうかを検証することができる.
public static Signature getInstance(String algorithm)
public final void initSign(PrivateKey privateKey)privatekey は,署名生成者の秘密鍵である. initSignメソッドにより Signatureオブジェクトの状態は SIGN になる. 同様に,検証を行なう場合は次のメソッドにより署名生成者の公開鍵 publickey を使って初期化する.
public final void initVerify(PublicKey publicKey)initVerifyメソッドにより Signatureオブジェクトの状態は VERIFY になる.
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メソッドを呼び出す.
public final byte[] sign()このメソッドは,署名をバイト配列に入れて返す. signメソッドを呼び出すと,Signatureオブジェクトは,initSignを呼び出して最初に署名用に初期化されたときの状態にリセットされる.つまり,オブジェクトをリセットするので,必要であれば update と sign を呼び出して,同じ署名者の別の署名を生成できる. あるいは異なる署名者の署名を生成するために異なる秘密鍵を指定して initSignを呼び出したり,署名を検証するために Signature オブジェクトを初期化する目的で initVerifyを呼び出したりできる.
public final void update(byte b) public final void update(byte[] data) public final void update(byte[] data, int off, int len)このあとで,次のverifyメソッドを呼び出して署名を検証する.
public final boolean verify(byte[] encodedSignature)verifyメソッドは,署名がupdateメソッドで設定されたデータの署名かどうかを示すboolean値を返す.
上記の Signatureオブジェクトを用いた署名生成・検証のコーディング例を示す. ここでは,署名・検証用の鍵ペア(秘密鍵と公開鍵)を pair とし,対象データのbyte配列は data としてこれらは別途与えられているものとする.また,署名アルゴリズムとして RSA暗号を用いるものとする.
// 署名の生成 Signature sigObj = Signature.getInstance("RSA"); // 秘密鍵でSignatureオブジェクトを署名用に初期化 PrivateKey priKey = pair.getPrivate(); sigObj.initSign(priKey); // 署名対象データ(data)の設定と署名生成 sigObj.update(data); byte[] sig = sigObj.sign(); // 署名の検証 // 公開鍵で署名オブジェクトを検証用に初期化 PublicKey pubkey = pair.getPublic(); sigObj.initVerify(pubKey); // 検証対象データ(data)の設定と署名検証 sigObj.update(data); boolean result = sigObj.verify(sig); // 検証結果の表示 System.out.println("Signature verification: " + result);
データの暗号化・復号機能は,Cipherクラスにより行う.Cipherクラスは,任意サイズの入力と鍵を受け取り,暗号化/復号データのバイト文字列を生成する.
public static Cipher.getInstance(String transformation) public static Cipher.getInstance(String transformation, String provider)transformationは,以下の形式の文字列である.
algorithm/mode/padding algorithmここで,algorithm は"DES"のような暗号アルゴリズムを示し,mode は"ECB"や"CBC"のような動作モードであり,padding はパディングモードを示し,"NoPadding"や"PKCS5Padding"である. なお,mode および padding は共通鍵暗号の場合のみ意味を持つ.
public void init(int opmode, Key key)ここで,opmode は暗号化の場合 Cipher.ENCRYPT_MODE,復号の場合 Cipher.DECRYPT_MODEである. key は,暗号化/復号に使用する鍵である. 暗号化/復号のいずれの場合も,使用する暗号アルゴリズムに応じた動作モード等のオプションを指定することができる.これは,使用する暗号アルゴリズムに応じたAllgorithmParameterSpecを指定することにより行う. Cipherオブジェクトに対して以下のメソッドを呼び出して設定する.
public void init(int opmode, Key key, AlgorithmParameterSpec params)
public byte[] update(byte[] in, int inOff, int inLen) public void update(byte[] in, int inOff, int inLen, byte[] out, int outOff)暗号化/復号するデータがすべて Cipherオブジェクトに入るまで,update メソッド を呼び出す. 最終的な暗号化/復号データを得るには,doFinalメソッドを呼び出す.
public byte[] doFinal() public byte[] doFinal(byte[] input) public byte[] doFinal(byte[] input, int inputOff, int inputLen)このメソッドは,暗号化/復号データをバイト配列に入れて返す.Updateメソッドを使用せず,doFinalメソッドを呼び出し一回の処理で暗号化/復号することもできる.
鍵配送(鍵交換)は,2つのエンティティ間で同一の鍵(共通鍵暗号用の鍵)を保有するための手順である.鍵配送(鍵交換)は,KeyAgreeementクラスにより行う.
public static KeyAgreement.getInstance(String algorithm) public static KeyAgreement.getInstance(String algorithm, String provider)
init(Key pubKey, AlgrithmParameterSpec spec, SecureRandom random)次に,doPahseメソッドを実行する.
doPhase(Key key, boolean phase)このとき,doPhase の戻り値として配送用の鍵が取得できる.これをB側に送信する. 配送側では, key は null,phase は false を指定する.
generateSecret()
init(Key priKey, AlgrithmParameterSpec spec, SecureRandom random)次に,doPahseメソッドを実行する.
doPhase(Key key, boolean phase)受信側では, key は配送側より受け取った鍵,phase は true を指定する.
generateSecret()上記の処理により,A,B の双方で generateSecret() により同一の鍵が得られる.