argius note

プログラミング関連

MessageDigest

メッセージダイジェストについて、初歩的なことですがおさらいしてみました。
メッセージダイジェストはハッシュ関数と呼ばれることの方が多いかもしれませんが、あるデータから一意のハッシュ値を算出するものです。大きなデータをダウンロードしたときに、そのファイルが壊れていないかを簡易的にチェックするチェックサムとして使われたり、一方向関数の性質から暗号処理の一部で使われたりします。詳細については、用語辞典などを参照してください。


良く使われるアルゴリズムに、MD5とSHAがあります。それぞれ派生したアルゴリズムがあります。MD5は最近では脆弱性が指摘されていて、一般にはSHAのビット長が大きいものが使われるようになってきているようです。ここでは、GNUのコマンドとJava6を使用して、実際にメッセージダイジェストを扱ってみます。

GNUコマンド

GNUのコマンドでは、"sha1sum"のような「アルゴリズム+sum」コマンド(coreutilsに含まれています)があります。また、OpenSSLというツールでメッセージダイジェスト機能が利用できます。ここでは前者を使用します。また、コマンドの環境はCygwinとFedoraCore6です。例はCygwinですが、FedoraCoreでも確認しています。

# Cygwinのバージョンチェック Cygwinだけ
$ cygcheck -c cygwin bash coreutils
Cygwin Package Information
Package              Version        Status
bash                 3.2.25-17      OK
coreutils            6.7-2          OK
cygwin               1.5.24-2       OK
$ echo $SHELL
/bin/bash
$ for a in md5 sha1 sha224 sha256 sha384 sha512
> do
> echo $a=`echo -n 123 | ${a}sum -t`
> done
md5=202cb962ac59075b964b07152d234b70 -
sha1=40bd001563085fc35165329ea1ff5c5ecbdbbeef -
sha224=78d8045d684abd2eece923758f3cd781489df3a48e1278982466017f -
sha256=a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3 -
sha384=9a0a82f0c0cf31470d7affede3406cc9aa8410671520b727044eda15b4c25532a9b5cd8aaf9cec4919d76255b6bfb00f -
sha512=3c9909afec25354d551dae21590bb26e38d53f2173b8d3dc3eee4c047e7ab1c1eb8b85103e3be7ba613b31bb5c9c36214dc9f14a42fd7a2fdb84856bca5c44c2 -
$

"-t"オプションは標準入力からデータを取得します。"123"のハッシュ値をそれぞれのアルゴリズムで出力しています。(echoは-nオプションを付けないと改行が含まれてしまいます。)

Java6

Javaでは、java.security.MessageDigestクラスを使います。GNUのコマンドのようなプログラムをJavaで実装してみます。以下のmainメソッドを"jmd"というコマンドで実行できるようにします。

public static void main(String[] args) {
    if (args.length < 2) {
        System.err.println("USAGE : jmd algorithm input");
        System.exit(0);
    }
    try {
        String algorithm = args[0];
        byte[] bytes = args[1].getBytes();
        byte[] digest = MessageDigest.getInstance(algorithm).digest(bytes);
        StringBuilder buffer = new StringBuilder();
        for (byte b : digest) {
            buffer.append(0 <= b && b < 16 ? "0" : "");
            buffer.append(Integer.toHexString(b & 0xFF));
        }
        System.out.println(buffer);
        System.exit(0);
    } catch (NoSuchAlgorithmException ex) {
        System.err.println("jmd : " + ex.getMessage());
        System.exit(1);
    }
}

Java6で実装されているMessageDigestアルゴリズムは、Java PKCS#11 リファレンスガイド 付録 A:Sun PKCS#11 プロバイダでサポートされるアルゴリズムに記載されています。
では、実行してみます。

$ java -version
java version "1.6.0_05-ea"
Java(TM) SE Runtime Environment (build 1.6.0_05-ea-b05)
Java HotSpot(TM) Client VM (build 1.6.0_05-ea-b05, mixed mode, sharing)
$ jmd
USAGE : jmd algorithm input
$ for a in md2 md4 md5 sha-0 sha-1 sha-224 sha-256 sha-384 sha-512
> do
> echo $a=`jmd $a 123`
> done
md2=ef1fedf5d32ead6b7aaf687de4ed1b71
md5=202cb962ac59075b964b07152d234b70
sha-1=40bd001563085fc35165329ea1ff5c5ecbdbbeef
sha-256=a665a45920422f9d417e4867efdc4fb8a04a1f3fff1fa07e998e86f7f7a27ae3
sha-384=9a0a82f0c0cf31470d7affede3406cc9aa8410671520b727044eda15b4c25532a9b5cd8aaf9cec4919d76255b6bfb00f
sha-512=3c9909afec25354d551dae21590bb26e38d53f2173b8d3dc3eee4c047e7ab1c1eb8b85103e3be7ba613b31bb5c9c36214dc9f14a42fd7a2fdb84856bca5c44c2
$