=========================================
The Shadow Penguin Documents. No. 16
- MD5(Message Digest 5) -
Written by Hariru Feb. 6, 1999
=========================================
1.MD5とは
MD5(Message Digest 5)は、公開鍵の暗号化方式であるRSA(Rivest,Shamir,Adleman)を考案した
3人の中の一人であるR.L.Rivest博士らによって考案された、実装が簡単なメッセージ暗号化
アルゴリズムです。
このアルゴリズムは、任意の長さのメッセージを128ビットのメッセージダイジェストに
圧縮変換するもので、POP3をはじめとして、IPの認証、PC UNIXのフリーソフトであるFreeBSDや、
ITU-T勧告のX.500で利用されています。このアルゴリズムの以前のものとしてMD2やMD4があり、
Rivest博士本人の言によれば、現在MD6も進行中です。
2.MD5の処理手順
実際の処理は、次のような5つの処理手順で行います。なお、入力メッセージの文字列はビット列
として取り扱われます。
(1)手順1
ビット列と化した入力メッセージのビット数が、512で割ったときのあまりが448に
なるように、入力メッセージの後ろに当て物ビット(Padding Bits)を追加します。
この追加するPadは"100・・・"と続くもので、仮に入力メッセージが
440ビット長だとすると、8ビットのPad="10000000"が追加されることになります。
次の手順2とともに図に示しますので、参照してください。
(2)手順2
もとの入力メッセージの文字列の長さを64ビットで表して、手順1で得られたビット列に
追加します。そのとき追加する64ビットは、下位32ビット、上位32ビットの順で
追加します。
これによって新しいメッセージのビット数が、512の倍数になるわけです。図を参照。
ちなみに、このビット列は手順4で示す、ブロック[k]を意味します。また、64ビットで
入力メッセージの長さを表すため、264ビット
(≒2.30×1018文字)以上の入力メッセージでは
動作を保証していません。ちょっと現実的な文字数ではありませんけどね。
(3)手順3
アルゴリズム演算に使用する4つのワードを、次の値によって初期化します。
ワード A=0x67452301
ワード B=0xefcdab89
ワード C=0x98badcfe
ワード D=0x10325476
ちなみに"0x"とは16進数という意味で、1ワードは32ビット長です。
(4)手順4
ここでは、とある計算を行います。とその前に、その際利用する4つの論理関数を示して
おきます。
関数F(X,Y,Z) = (X AND Y) OR (NOT(X) AND Z)
関数G(X,Y,Z) = (X AND Z) OR (Y AND NOT(Z))
関数H(X,Y,Z) = X XOR Y XOR Z
関数I(X,Y,Z) = Y XOR (X OR NOT(Z))
AND,OR,XOR,NOTはそれぞれ、論理積,論理和,排他的論理和,否定です。これらがわからないと
いう方は、文章の最後に説明してありますのでそちらを参照してください。
さて、前述したある計算というのは次の通りです。
a = b + (( a + 関数f(b,c,d) + ブロック[k] + T[i] ) <<< s )
a,b,c,d :ワードA,B,C,Dの組み合わせのいずれか
関数f :関数F,G,H,Iのいずれか
ブロック[k]:手順2の結果を16ワード(512ビット)ずつに区切ったk番目のブロック
T[i] :sin(i=1〜64ラジアン)の絶対値に"0x10000000"をかけた整数部のテーブル
<<< :循環左シフト
s :ビットシフト数
ワード A,B,C,Dの組み合わせとは4通りあり、[ABCD],[DABC],[CDAB],[BCDA]順の並びで
扱うことになります。また、一つの関数、一つのワードで演算を4回します。そのため、4(4通りの
ワード)×4(演算4回)×4(4つの関数)=64回の演算を行うことになります。
とまあ書きましたが、文章じゃわかりにくいのでプログラム的な説明を。
/* 16ワード(512ビット)ごとに処理を行います */
For i = 0 to N/16-1 do
/* 16ワード(512ビット)のメッセージMを、Xに入れる */
For j = 0 to 15 do
Set X[j] to M[i*16+j].
end /* jループの終わり */
/* AをAAに記憶, BをBBに記憶, CをCCに記憶, DをDDに記憶 */
AA = A
BB = B
CC = C
DD = D
/* ラウンド1 */
/* [abcd k s i]と示した場合、次のような形で処理をします
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s) */
/* 次の16個の処理を行います */
[ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA 3 22 4]
[ABCD 4 7 5] [DABC 5 12 6] [CDAB 6 17 7] [BCDA 7 22 8]
[ABCD 8 7 9] [DABC 9 12 10] [CDAB 10 17 11] [BCDA 11 22 12]
[ABCD 12 7 13] [DABC 13 12 14] [CDAB 14 17 15] [BCDA 15 22 16]
/* ラウンド2 */
/* [abcd k s i]と示した場合、次のような形で処理をします
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s) */
/* 次の16個の処理を行います */
[ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA 0 20 20]
[ABCD 5 5 21] [DABC 10 9 22] [CDAB 15 14 23] [BCDA 4 20 24]
[ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA 8 20 28]
[ABCD 13 5 29] [DABC 2 9 30] [CDAB 7 14 31] [BCDA 12 20 32]
/* ラウンド3 */
/* [abcd k s i]と示した場合、次のような形で処理をします
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s) */
/* 次の16個の処理を行います */
[ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35] [BCDA 14 23 36]
[ABCD 1 4 37] [DABC 4 11 38] [CDAB 7 16 39] [BCDA 10 23 40]
[ABCD 13 4 41] [DABC 0 11 42] [CDAB 3 16 43] [BCDA 6 23 44]
[ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA 2 23 48]
/* ラウンド4 */
/* [abcd k s i]と示した場合、次のような形で処理をします
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s) */
/* 次の16個の処理を行います */
[ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51] [BCDA 5 21 52]
[ABCD 12 6 53] [DABC 3 10 54] [CDAB 10 15 55] [BCDA 1 21 56]
[ABCD 8 6 57] [DABC 15 10 58] [CDAB 6 15 59] [BCDA 13 21 60]
[ABCD 4 6 61] [DABC 11 10 62] [CDAB 2 15 63] [BCDA 9 21 64]
/* その後、次の足し算を実行してください。(それはこのブロックが
始められる前に、持っていた値によって4つの各々のレジストリを
増加させます) */
A = A + AA
B = B + BB
C = C + CC
D = D + DD
end /* iループの終わり */
(5)手順5
生成されたA,B,C,Dから得られるビット列が、メッセージダイジェスト(MD)です。
その順列はAの下位8ビットから始めて、Dの上位8ビットで終わる順列になります。
例で示すなら、次の通りです。
A = A1, A2, A3, A4
B = B1, B2, B3, B4
C = C1, C2, C3, C4
D = D1, D2, D3, D4
↓
MD = A4, A3, A2, A1, B4, B3, ・・・ , D2, D1
このように128ビットのビット列が、最終的なメッセージダイジェスト(MD)の出力です。
これでMD5アルゴリズムは、完了となります。
3.プログラム(RFC1321)
ここで紹介するプログラムは、RFC1321の付録A(APPENDIX A)にある、C言語によるMD5
メッセージダイジェストアルゴリズム処理の参考実装(Reference Implementation)からの
切り抜きです。簡単な訳と説明をつけましたが、詳しく知りたい方は本文の方を参照した方が
確実です。
RFC 1321 ・・・ 付録A - 参照実装より
この付録は、RSAREFから得られたプライバシー強化メイルのための暗号のツールキット
(Cryptographic Toolkit)のファイルを含んでいます。
global.h --- グローバルヘッダーファイル
md5.h --- MD5のためのヘッダーファイル
md5c.c --- MD5のためのソースコード
RSAREFについて、より詳細なことを知りたい方は、rsaref@rsa.comに電子メールを送って
ください。
付録はさらに、次のファイルを含んでいます。
mddriver.c --- MD2、MD4およびMD5のためのテストドライバー
このドライバーをデフォルトでコンパイルすると、MD5アルゴリズムを行います。
しかし、シンボルMDがCコンパイラのコマンドライン上で2または4として定義される場合、
MD2またはMD4のアルゴリズムとしてコンパイルすることができます。
これは携帯型であり、様々な種類のプラットフォームに使われるべきです。
しかしながら、それぞれの特別のプラットフォーム上へ実装して最適化することは、
これを読んだ人に残された課題になります。
実際のプログラムは長くなりますので、まとめてこちらに。
ただし、本文の"mddriver.c"をコンパイルしても動かなかったので、
"mddriver.c"のインクルードの辺りを多少変更させてもらいました。
また実行テストの仕方ですが、それぞれのプログラムを同じディレクトリ上に作って
"mddriver.c"をコンパイル、実行してください。
実行の際つけるオプションは、次の通りです。
引数はいくつか連結することもできます
-sstring - stringをダイジェストする
-t - タイムトライアルを行う
-x - テストスクリプトを行う
filename - 指定したファイルをダイジェストする
(none) - 標準入力をダイジェストする
オプション"-s"を付けて、その後スペースなどせずにそのまま文字列を打ち込んで
実行すると、その文字列のメッセージダイジェストが表示されます。オプション"-t"は
入力メッセージ1000文字とし、MD5を1000回行ってその実行時間を表示するのですが、高速なため
なのかうまく表示されないみたいです。オプション"-x"を付けると、正しく機能して
いるのかテストスクリプトを行います。そのとき得られる結果は、以下の通りになるはずです。
MD5 test suite:
MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = d174ab9
8d277d9f5a5611c2c9f419d9f
MD5 ("12345678901234567890123456789012345678901234567890123456789012345678901234
567890") = 57edf4a22be3c955ac49da2e2107b67a
オプションなしでファイル名を入力して実行すると、そのファイルの内容をメッセージ
ダイジェストをして表示します。オプションなしの実行はキーボードからの標準入力ですが、
うまく終了しないみたいなので使わない方がよいでしょう。
〜〜 お わ り 〜〜
論理演算(AND,OR,NOT,XOR) 論理演算にはAND,OR,NOT,XORがあり、ビット単位でそれぞれ次のような演算を行います。 AND OR a b | (a AND b) a b | (a OR b) ---------+----------- ---------+---------- 0 0 | 0 0 0 | 0 0 1 | 0 0 1 | 1 1 0 | 0 1 0 | 1 1 1 | 1 1 1 | 1 NOT XOR a | NOT(a) a b | (a XOR b) ---------+---------- ---------+----------- 0 | 1 0 0 | 0 1 | 0 0 1 | 1 1 0 | 1 1 1 | 0 参考文献 [1]Ronald L.Rivest:RFC 1321 (The MD5 Message-Digest Algorithm),1992 [2]笠野 英松:通信プロトコル事典,アスキー出版局,1996 [3]金子 俊夫:OPENDESIGN No.14,CQ出版社,1996