Since: Jun./06th/2004
メッセージダイジェストが得られれば、手元のメッセージが改竄されていないことが保証されます。更に、メッセージダイジェストを暗号化することで、 当該のダイジェストが認証されたユーザから送信されたことを検証できます。メッセージダイジェストを暗号化したものは、電子署名と呼ばれ、メッセージごと に異なる拇印(フィンガープリント)として機能します。
この仕組みは、公開鍵暗号方式 (Public Key Cryptography) で提供されます。公開鍵暗号方式では、データの暗号化と復号化を、公開鍵 (public key) と秘密鍵 (private key) と呼ばれる鍵のペアで実装します。
送信者は、ダイジェストを自分だけが知っている秘密鍵で暗号化した署名をコードに埋め込みます。受信者は、誰でも知ることができる公開鍵を使って署名を復号化します。得られたダイジェストを、受信したメッセージと比較することで、次のことをチェックできます:
利用可能なアルゴリズムには、RSA Security Inc. による RSA (Rivest, Shamir, Adleman)、NIST による DSA (Digest Signature Algorithm) などが使えますが、ここでは Sun のセキュリティプロバイダが標準で提供している DSA を利用することにします。
送信側は、次の操作が必要です。
KeyPairGeneratorのインスタンスをgetInstance()で取得して、generateKeyPair()で生成し、Signature型オブジェクトのインスタンスをgetInstance()で取得して、KeyPair型オブジェクトのgetPrivate()で取得した秘密鍵によって、Signature型オブジェクトをinitSign()で初期化した後、updete()でデータを渡し、sign()で暗号化された署名を取得します。受信側は、次の操作が必要です。
SignatureのインスタンスをgetInstance()で取得して、initVerify()で公開鍵を指定して初期化して、update()で署名を渡し、verify()で検証します。リスト1は、DSA 鍵ペアを生成してメッセージを暗号化した署名を作成し、同様に検証するコードです。
ここでは、単純にメッセージを与えましたが、通常はダイジェストを暗号化して署名を作成します。KeyPairGeneratorの初期化で渡している数値は、DSA のキーサイズ (モジュラスサイズ) と呼ばれる鍵の強度を決定するもので、512から1024の間の64の倍数を指定します。
リスト1. 電子署名の実装例 (DegitalSignDemo.java)
import java.security.*;
class SignImpl {
// 署名の生成
byte[] getSign(String message, String alg, PrivateKey key) {
try {
// Signatureの初期化
Signature signAlg = Signature.getInstance(alg);
signAlg.initSign(key);
signAlg.update(message.getBytes());
// 署名の生成
byte[] sign = signAlg.sign();
return sign;
} catch (Exception ex) {
ex.printStackTrace();
}
byte[] bytes = null;
return bytes;
}
// メッセージと署名の検証
void verifySign(String message, String alg, byte[] sign, PublicKey key) {
try {
// Signatureの初期化
Signature signAlg = Signature.getInstance(alg);
signAlg.initVerify(key);
signAlg.update(message.getBytes());
// メッセージの検証
if (signAlg.verify(sign)) {
System.out.println("Sign is verified.");
} else {
System.out.println("Sign is not verified.");
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
class DegitalSignDemo {
public static void main(String[] args) {
String message = "This is Signature Demo.",
alg = "DSA";
SignImpl signImpl = new SignImpl();
try {
// KeyPairGeneratorの初期化
KeyPairGenerator keygen = KeyPairGenerator.getInstance(alg);
SecureRandom random = new SecureRandom();
keygen.initialize(768, random);
// 鍵の生成
KeyPair keys = keygen.generateKeyPair();
PublicKey pubkey = keys.getPublic();
PrivateKey privkey = keys.getPrivate();
// 署名の生成
byte[] sign = signImpl.getSign(message, alg, privkey);
// メッセージと署名の検証
signImpl.verifySign(message, alg, sign, pubkey);
// 別の鍵の生成
KeyPair keys2 = keygen.generateKeyPair();
PublicKey pubkey2 = keys2.getPublic();
PrivateKey privkey2 = keys2.getPrivate();
// 別の鍵によるメッセージと署名の検証
signImpl.verifySign(message, alg, sign, pubkey2);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
リスト2. リスト1 の実行結果
>java DegitalSignDemo Sign is verified. Sign is not verified.