|
2002/12/13 日記: ファイルのMD5値を求めるサンプル[いがぴょんの日記v2,diary,igapyon] Javaで入力ファイルのMD5値を求めるサンプルを作成してみました。 |
| 広告:
BlancoEclipseDistribution 最新安定版 (3.5.0-20090708) リリース
07/16 最新版の Eclipse である Eclipse Classic (SDK) 3.5.0 一式 (日本語化済み) が Windowsインストーラを用いてインストールできます。 BlancoEclipseDistribution は Eclipseディストリビューションのひとつに該当します。 |
| MD5取得サンプル |
ファイルのMD5値を求めるサンプルプログラム
| MyDigest.java |
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MyDigest {
private static final String FILENAME = "aaa.txt";
public static void main(String[] args) {
try {
DigestInputStream inStream =
new DigestInputStream(
new BufferedInputStream(
new FileInputStream(FILENAME)),
MessageDigest.getInstance("MD5"));
byte[] buf = new byte[1024];
for (;;) {
if (inStream.read(buf) <= 0)
break;
}
inStream.close();
MessageDigest md5 = inStream.getMessageDigest();
byte[] digest = md5.digest();
System.out.print("[" + FILENAME + "] のMD5は [");
for (int loop = 0;loop < digest.length;loop++) {
System.out.print(
Integer.toHexString(0xff&(char)digest[loop]));
}
System.out.println("] です。");
} catch (IOException ex) {
ex.printStackTrace();
} catch (NoSuchAlgorithmException ex) {
ex.printStackTrace();
}
}
}
|
なんのことはないコーディングなのですが、いざサンプルを探そうとしたらちょっと手こずりました。
結城浩さんのツッコミ
Subject: [igapyon:01082] MD5 サンプル
結城です。細かい突っ込みです。
いがぴょんさんのMD5を求めるサンプルで、
16進表示を行う以下の部分には小さなバグがあります。
System.out.print(
Integer.toHexString(0xff&(char)digest[loop]));
|
このままですと、16未満の数が一桁になってしまいます。
たとえば、
| 012 |
という3バイトからなるファイルの正しいMD5値は、
| D2490F048DC3B77A457E3E450AB4EB38 |
なのですが、これが、
| d249f48dc3b77a457e3e45ab4eb38 |
のように短くなってしまいます。
一バイトごとに空白をあけてみると、原因がわかります。
| d2 49 f 4 8d c3 b7 7a 45 7e 3e 45 a b4 eb 38 |
修正としてはたとえば、
int n = digest[loop] & 0xFF;
if (n <= 0xF) {
System.out.print("0");
}
System.out.print(Integer.toHexString(n));
|
のようにします。もっとうまい方法があるかも…。
MD5を求めるプログラムの本質的なところではありませんけれど、
ちょっと気になったのでご報告します。
あ、それから、
| 0xff&(char)digest[loop] |
でcharにキャストしているのはなぜでしょう。
もしもunsignedのこころでしたら、0xffでマスクをしているので、intの符号ビットは落ちているのですから、キャストは不要ではないかと思います。
サンプル
| Sample.java |
class Sample {
public static void main(String[] args) {
byte a = 1;
byte b = -1;
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("a & 0xFF = " + (a & 0xFF));
System.out.println("b & 0xFF = " + (b & 0xFF));
}
}
|
実行結果
| a = 1 b = -1 a & 0xFF = 1 b & 0xFF = 255 |
現在、結城は暗号本を書いているので、
似たようなコードを書いております。参考まで。
私のはDigestInputStreamも使わず、バッファリングもせず、1バイトずつupdateしていますが(^_^;
| Digest.java |
import java.security.*;
import java.io.*;
public class Digest {
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.out.println("Usage: java Digest inputfilename");
System.exit(0);
}
String filename = args[0];
System.out.println("filename = " + filename);
MessageDigest sha = MessageDigest.getInstance("SHA");
MessageDigest md5 = MessageDigest.getInstance("MD5");
DataInputStream in = new DataInputStream(new FileInputStream(filename));
try {
while (true) {
byte b = in.readByte();
sha.update(b);
md5.update(b);
}
} catch (EOFException ignore) {
}
in.close();
System.out.println("SHA =" + toHexString(sha.digest()));
System.out.println("MD5 =" + toHexString(md5.digest()));
}
private static String toHexString(byte[] buf) {
String s = "";
for (int i = 0; i < buf.length; i++) {
int n = buf[i] & 0xff;
if (n < 16) {
s += " 0";
} else {
s += " ";
}
s += Integer.toHexString(n).toUpperCase();
}
return s;
}
}
|
◆実行結果
> type input.txt 012 > java Digest input.txt filename = input.txt SHA = C4 A2 D9 9B C2 8D 23 60 98 A0 95 27 7B 7E B0 71 8D 6B E0 68 MD5 = D2 49 0F 04 8D C3 B7 7A 45 7E 3E 45 0A B4 EB 38 |
ここからいがぴょん
…MLから未転載… もといMLに返信する前に 出張に旅立ちました (苦笑)
| Eclipse.orgに接続できない件 |
昨日 Eclipse.orgへの接続が怪しかったですが、これは eclipse.orgのDNSが異常だったのが原因だったとのことです。(と www.eclipse.orgに書いてありました)
| 世間のニュースから (RSS) 2002 |