=readme charset shift-jis LastModified : 2005-08/18 /_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ RFC 1321 The MD5 Message-Digest Algorithm ftp://ftp.isi.edu/in-notes/rfc1321.txt Written by kerry http://202.248.69.143/~goma/ /_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ 当ライブラリはモジュールが使えない環境用に書かれたコードです。 * Usage; 文字列の MD5 を得る $strMD5 = digest'md5( $str ); ファイルの MD5 を得る $fileMD5 = digest'md5f( $file ); ------------------------------------------------------------------------- * 返り値 # 通常は以下( 16進数に整形されたハッシュ値が返ってくる) $hexHash = digest'md5( $str ); # 整形前の値が欲しい時は配列で受け取れる @decHashz = digest'md5( $str ); # e.g. $md5bin = pack("N4", @decHashz); ファイルを開けなかった場合は "error" という文字列が返る /_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ =cut package digest; sub md5 { &md5init; mdFinal( mdStr( shift) ) } sub md5f { &md5init; mdFinal( mdFile(shift) ) } sub md5r { &md5init; mdFinal( mdStrr(shift) ) } sub mdFinal { if ($_[0] eq "error") { return wantarray ? @_ : shift; } for (0..$#state) { $state[$_] = ($state[$_] & 0x000000ff) << 24 | ($state[$_] & 0x0000ff00) << 8 | ($state[$_] & 0x00ff0000) >> 8 | ($state[$_] & 0xff000000) >> 24 ; } return wantarray ? @state : sprintf "%08x" x @state, @state; } sub mdFile { local ($ri, $block); $file = shift; open(FILE, $file) or return "error"; binmode FILE; $fSize = -s FILE; $ri = int $fSize / $blockLen; while ($ri--) { read FILE, $block, $blockLen; &md5roundz; } read FILE, $block, $blockLen; mdStr($block, $fSize); } sub mdStr { ($str, $strLen) = @_; $strLen = length $str if !$strLen; $str .= mdPadding($strLen); $strLen = length $str; $ri = int $strLen / $blockLen; for (0..$ri-1) { $block = substr $str, $blockLen* $_, $blockLen; &md5roundz; } } sub mdStrr # if ref shift { *pstr = shift; $strLen = length $pstr; $ri = int $strLen / $blockLen; for (0..$ri-1) { $block = substr $pstr, $blockLen* $_, $blockLen; &md5roundz; } $block = substr $pstr, -($strLen % $blockLen); mdStr($block, $strLen); } sub mdPadding { $len = shift; $md = $len % $blockLen; $padLen = 8; if ($md>= $blockLen- $padLen) { $md = $blockLen- ($md % $padLen); } else { $md = $blockLen- $padLen- $md; } $pad = "\x80". "\x00" x ($md-1); $len *= $padLen; $pad .= pack "V2", $len & 0xffffffff, $len / 0xffffffff; } sub md5roundz { @x = unpack "V16", $block; @tmpState = @state; for $n (0..63) { if ($n<16) { $tmp = ($state[1] & $state[2]) | (~$state[1] & $state[3]); } elsif ($n<32) { $tmp = ($state[1] & $state[3]) | ($state[2] & ~$state[3]); } elsif ($n<48) { $tmp = $state[1] ^ $state[2] ^ $state[3]; } elsif ($n<64) { $tmp = $state[2] ^ ($state[1] | ~$state[3]); } $tmp = ( $tmp + $x[ $k[$n] ] + $t[$n] + $state[0] )% 4294967296; $state[0] = ( $state[1] + (($tmp << $s[$n]) | ($tmp >> (32-$s[$n]))) )% 4294967296; @state = ($state[3], $state[0], $state[1], $state[2]); } $state[0] = ($state[0] + $tmpState[0])% 4294967296; $state[1] = ($state[1] + $tmpState[1])% 4294967296; $state[2] = ($state[2] + $tmpState[2])% 4294967296; $state[3] = ($state[3] + $tmpState[3])% 4294967296; } sub md5init { $blockLen = 64; @state = ( 0x67452301 , 0xefcdab89 , 0x98badcfe , 0x10325476 ); return if @k and @s and @t; @k = ( 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 1 , 6 , 11 , 0 , 5 , 10 , 15 , 4 , 9 , 14 , 3 , 8 , 13 , 2 , 7 , 12 , 5 , 8 , 11 , 14 , 1 , 4 , 7 , 10 , 13 , 0 , 3 , 6 , 9 , 12 , 15 , 2 , 0 , 7 , 14 , 5 , 12 , 3 , 10 , 1 , 8 , 15 , 6 , 13 , 4 , 11 , 2 , 9 , ); @s = ( 7 , 12 , 17 , 22 , 7 , 12 , 17 , 22 , 7 , 12 , 17 , 22 , 7 , 12 , 17 , 22 , 5 , 9 , 14 , 20 , 5 , 9 , 14 , 20 , 5 , 9 , 14 , 20 , 5 , 9 , 14 , 20 , 4 , 11 , 16 , 23 , 4 , 11 , 16 , 23 , 4 , 11 , 16 , 23 , 4 , 11 , 16 , 23 , 6 , 10 , 15 , 21 , 6 , 10 , 15 , 21 , 6 , 10 , 15 , 21 , 6 , 10 , 15 , 21 , ); @t = ( 0xd76aa478 , 0xe8c7b756 , 0x242070db , 0xc1bdceee , 0xf57c0faf , 0x4787c62a , 0xa8304613 , 0xfd469501 , 0x698098d8 , 0x8b44f7af , 0xffff5bb1 , 0x895cd7be , 0x6b901122 , 0xfd987193 , 0xa679438e , 0x49b40821 , 0xf61e2562 , 0xc040b340 , 0x265e5a51 , 0xe9b6c7aa , 0xd62f105d , 0x2441453 , 0xd8a1e681 , 0xe7d3fbc8 , 0x21e1cde6 , 0xc33707d6 , 0xf4d50d87 , 0x455a14ed , 0xa9e3e905 , 0xfcefa3f8 , 0x676f02d9 , 0x8d2a4c8a , 0xfffa3942 , 0x8771f681 , 0x6d9d6122 , 0xfde5380c , 0xa4beea44 , 0x4bdecfa9 , 0xf6bb4b60 , 0xbebfbc70 , 0x289b7ec6 , 0xeaa127fa , 0xd4ef3085 , 0x4881d05 , 0xd9d4d039 , 0xe6db99e5 , 0x1fa27cf8 , 0xc4ac5665 , 0xf4292244 , 0x432aff97 , 0xab9423a7 , 0xfc93a039 , 0x655b59c3 , 0x8f0ccc92 , 0xffeff47d , 0x85845dd1 , 0x6fa87e4f , 0xfe2ce6e0 , 0xa3014314 , 0x4e0811a1 , 0xf7537e82 , 0xbd3af235 , 0x2ad7d2bb , 0xeb86d391 , ); } &arg_check if @ARGV; sub arg_check { $switch = shift @ARGV; $switch_str = "/s"; $switch_file= "/f"; $maxLineLen = 40; $sltMsgTmpl = "%-6s : %s\n"; if ($switch =~ m{^/?(\?|help)$}i) { &arg_help; } elsif ($switch =~ m|^$switch_str$|i) { if (!@ARGV) { arg_help( 'ハッシュ値を得たい文字列を入力してください' ); } foreach (@ARGV) { if (length($_) > $maxLineLen) { $tmp = substr $_, 0, $maxLineLen-5; $tmp .= "....."; } else { $tmp = $_; } printf $sltMsgTmpl, "String", $tmp; printf $sltMsgTmpl, "MD5", $tmp = md5($_); printf "\n"; } } elsif ($switch =~ m|^$switch_file$|i) { if (!@ARGV) { arg_help( 'ハッシュ値を得たいファイルを入力してください' ); } foreach (@ARGV) { printf $sltMsgTmpl, "File", $_; $tmp = md5f($_); if ($tmp eq "error") { printf $sltMsgTmpl, "Error", 'ファイルを開けません'; } else { printf $sltMsgTmpl, "MD5", $tmp; } print "\n"; } } elsif ($switch =~ m|^(/.+)|) { arg_help( sprintf '"%s" というスイッチはありません', $1 ); } else { arg_help( '引数が変です' ); } } sub arg_help { if (@_) { printf "=========================================\n" . "* ERROR\n" . "%s\n" . "=========================================\n", shift; } print "Usage\n\n" . " .....\n\n" . "* switches\n\n"; printf " %-12s %-10s # %s\n", $switch_str, '"string"', '文字列のハッシュ値を計算'; printf " %-12s %-10s # %s\n", $switch_file, '"file"', 'ファイルのハッシュ値を計算'; printf " %-12s %-10s # %s\n", "/? or /help", "", '今読んでいるコレを表\示'; } 1;