レシピ
プラットフォーム:Windows XP / Vista
使用言語:Visual Basic 2005,.NET Framework 2.0以上

 異なるPC間でのファイルのやり取りはネットワーク経由が当たり前になってきました。メール添付やFTPやサイトからのダウンロードと方法はいくつかあります。ただ誰でも数度は経験しているように,添付やダウンロードではファイルが破損しているといったことがあります。オリジナルと入手したファイルが同一であるかどうかの確認にはMD5ハッシュ値での比較という方法がポピュラーです。今回はMD5ハッシュ算出プログラムを作成します。

Visual Basic 2005でやってみよう

 これまで本連載では,スクリプト言語でサンプルを組み上げてきました。しかし,たまには目先を変えてみようということで,今回はVisual Basic 2005を使います。HTAなどで無理矢理インタフェースを作ることと比べれば,さすがはRAD。インタフェースに制約が少ないというのは楽チンです。特にエンタープライズな機能などは使用していないので,無償版であるVisual Basic 2005 Express Editionをマイクロソフトのサイトからダウンロードしてお試しください。

 なお,今回は.NET Framework 2.0の機能を使用します。.NET Framework 2.0以上がインストールされていることを確認してください。ダウンロードが必要な場合はマイクロソフトのサイト から無償でダウンロードできます(上記のVisual Basic 2005がインストールしてあれば大丈夫です)。

 コードは単純で短いものですから,VBの使用経験がない人,経験の浅い人でも簡単に作れます。

MD5ハッシュとは?

 今回は,MD5ハッシュ値算出プログラムを作ります。MD5はファイル/文字列の暗号化手法(ハッシュといいます)の一種です。GPLやフリーソフトのダウンロード・ページにいくと,ときどき「MD5 0248ecb07f3f…」のような表記を見かけますね。

図1●MD5表記があるサイトの例。MySQLのダウンロード・ページ
図1●MD5表記があるサイトの例。MySQLのダウンロード・ページ
[画像のクリックで拡大表示]

 これはオリジナル・ファイルをMD5暗号化した値の表記で,ダウンロードしたものをMD5暗号化してオリジナルのMD5値と比較すると,正しくダウンロードができたかを確認することができるというひとつの指標になります。

 通信エラーでのファイル破損の確認のほか,データ改ざんが行われていないかといったチェックにも使えます。一般的なMD5暗号化はファイルの中身を暗号化しますので,タイムスタンプやファイル名,ファイルサイズが同一でも,ファイルの中身が1バイトでも変化していれば異なる結果になります。

 通信エラーやこちら側のハードディスクの不調などいろんな要因でファイルは壊れます。メール添付されたドキュメントが壊れていて開けないといったことも,添付で送付することが多くなってくると目につくようになります。実際にはMD5はオリジナルとコピーが同一のものであるかの比較ができるだけで,通信エラーそのものを回避する手段とはなりえませんが,保険みたいなもので精神的安心感にはつながるかもしれません。

 MD5は暗号化に使用される手法の一つで次のような特徴を持っています。

・不可逆暗号化である
・結果は固定長である
・RFCに定義され標準化している

 不可逆というのは,ある文字列から暗号を生成することはできるが,その暗号から原文に戻すことはできないという意味です。復号できる暗号は可逆暗号といいます。MD5は不可逆で,暗号化した結果から原文は取り出せません。

 結果が固定長という特徴もファイルの比較に便利なポイントです。NULL文字を暗号化しても,数百Mバイトのファイルを暗号化しても常に暗号化結果は固定長です。結果は一般的な表記方法(後述)で32桁の半角英数です。ファイル確認のために数百Mバイトだと2000桁…のような結果になると少なくても目視レベルではありませんね。常に32桁であるというところがファイル比較方法として考えたときに,極めて現実的なアドバンテージになっています。

 MD5はRFCで規定されているので国際規格です。ファイル比較の方法としてはスタンダードだといえます。

コーディングしてみよう

 Visual StudioないしVisual Basicを起動してください。Visual BasicのWindowsアプリケーションで新しいプロジェクトを作成します。プロジェクト名は「CHK_MD5」としておきます。

図2●Visual Basicで新規プロジェクトを作成します
図2●Visual Basicで新規プロジェクトを作成します
[画像のクリックで拡大表示]

 フォームのデザインはテキストボックスが4個とボタンが二つです。テキストボックスは上からTextBox1,TextBox2,TextBox3,TextBox4です。TextBox2とTextBox4はマルチラインになっていますが,フォームとテキストボックスの幅を調整して,32桁が表示できればシングルラインでかまいません。ボタンは上からButton1,Button2です。

図3●フォームのデザイン
図3●フォームのデザイン

 上半分はテキストボックスに入力された文字を直接MD5暗号化するサンプルです。下半分はテキストボックスに入力されたファイルをMD5暗号化します。

 ではコードをご覧ください(リスト1)。

Public Class Form1
Dim md5 As New System.Security.Cryptography.MD5CryptoServiceProvider
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        ・
        ・
        ・
リスト1●MD5暗号化するサンプルのコード

動作の確認

 一番上のテキストボックスに適当な文字を打ち込んで,「MD5算出」ボタンを押すと,入力されたテキストをMD5化した結果がTextBox2に出ます。全く文字を入力しないままボタンを押しても結果がでることも確認しておいてください。入力した文字の長さに関係なく,常にMD5値は32文字で固定長です。

図4●入力された文字列のMD5暗号化結果
図4●入力された文字列のMD5暗号化結果

 なおマイクロソフトのサイトでMD5についての説明を探すと,サンプル・コード内でコメントアウトしてある

 MD5_STR &= BytData.ToString & " "

 という記述方法が紹介されています。MD5は元々16ブロックの数値に分けて暗号化結果を格納しています。マイクロソフト方式は,16ブロックをそのまま表示し,ブロックごとの区切りがわかりやすいようにスペースで区切っているわけです。

図5●マイクロソフト提供サンプル型の表示
図5●マイクロソフト提供サンプル型の表示

 一般的に利用されているMD5表記は,図4のように16ブロックそれぞれを16進数化して,スペースなどの区切りをつけない形です。今後MD5を触る際に,マイクロソフト提供のサンプルを見て動作結果に違和感を感じたら,この話を思い出していただければと思います。

 続いて下半分です。テキストボックスにファイルのフルパス名(C:\foo\test.txtなど)を入力して「MD5算出」ボタンを押します。

図6●ファイルのMD5化
図6●ファイルのMD5化

 ファイルのMD5化は,該当ファイルを開いてバイナリ形式でファイル内容を読み込み,バイナリからMD5暗号化結果を出します。バイナリ扱いなのでtest.jpgやtest.exeのような非テキスト・ファイルからもMD5算出できます。

 ファイル名が空欄だったときと,指定されたファイルが存在しなかったときの簡単なエラートラップは仕込んでおきました。

 もし機能拡張するならば,例えばフォームにファイルをドロップするとMD5算出してくれるといった機能があると便利かもしれません。

使い方のアイデア

 ベーシックな使い方としては,ファイルのダウンロード・ページなどにMD5の値を出して,ダウンロードした人に比較してもらうというのが一般的ですね。オンライン・ソフトの配布などにも利用できます。

 そのほか,すでに一部のソフトは実装していますが,自分自身のMD5値を記録しておいて,ソフトの起動時に自身のMD5を算出してオリジナルと比較し,自分自身が壊れていないかの確認をするといった使い方もあります。この場合,ソースの中に直接MD5を書いておくことはできません。

 どういうことかといいますと,自分のMD5を調べてそれをコードに埋め込むと,埋め込んだ時点でソースが変化するのでMD5値が変わってしまい,また調べてソースを書き換えると,またMD5が…の繰り返しになってしまうからです。

 こうした用途では完成したexeファイルのMD5を算出して,外部の設定ファイルなどにMD5値を書いておき,ファイルI/Oで読み込んで比較するという処理にする必要があります。

 MD5算出ソフトはオンライン・ソフトとしてそこそこの数が世に出ています。いろんなソフトを見て,機能拡張してみるのも楽しいかもしれません。