=readme charset shift-jis LastModified : 2005-08/20 /_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ SHA-1 [RFC 3174] ftp://ftp.isi.edu/in-notes/rfc3174.txt SHA-256 [FIPS 180-2] http://csrc.nist.gov/cryptval/shs.html Written by kerry http://202.248.69.143/~goma/ /_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ 当ライブラリはモジュールが使えない環境用に書かれたコードです。 # ファイルの SHA-1 を得る $fileSHA1 = sha'sha1f( $file ); # 文字列の SHA-1 を得る $strSHA1 = sha'sha1( $str ); # ファイルの SHA-256 を得る $fileSHA256 = sha'sha256f( $file ); # 文字列の SHA-256 を得る $strSHA25 = sha'sha256( $str ); ------------------------------------------------------------------------- * 返り値 通常は以下( 16進数に整形されたハッシュ値が返ってくる) $hexHash = sha'sha1( $str ); 整形前の値が欲しい時は配列で受け取れる @decHashz = sha'sha1f( $file ); # e.g. $sha1bin = pack("N5", @decHashz); ファイルを開けなかった場合は "error" という文字列が返る /_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ =cut package sha; sub sha1f { &sha1init; shaFormat( shaFile(shift) ) } sub sha1 { &sha1init; shaFormat( shaStr( shift) ) } sub sha1r { &sha1init; shaFormat( shaStrr(shift) ) } sub sha256f { &sha256init; shaFormat( shaFile(shift) ) } sub sha256 { &sha256init; shaFormat( shaStr( shift) ) } sub sha256r { &sha256init; shaFormat( shaStrr(shift) ) } sub shaFile { $file = shift; open(FILE, $file) or return "error"; binmode FILE; $fSize = -s FILE; $ri = int $fSize/ $blockLen; while ($ri--) { read FILE, $block, $blockLen; &round; } read FILE, $block, $blockLen; close FILE; shaStr($block, $fSize); } sub shaStr { local ($str, $strLen) = @_; $strLen = length $str if !$strLen; $str .= padding($strLen); $ri = length ($str) / $blockLen; for (0..$ri-1) { $block = substr $str, $blockLen* $_, $blockLen; &round; } } sub shaStrr { *pstr = shift; $strLen = length $pstr; $ri = int $strLen / $blockLen; for (0..$ri-1) { $block = substr $pstr, $blockLen* $_, $blockLen; &round; } if ($strLen % $blockLen) { $block = substr $pstr, -($strLen % $blockLen); } else { $block = ""; } shaStr($block, $strLen); } sub padding { $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("N2", $len / 0xffffffff , $len % 0xffffffff); } sub sha1roundz { @tmpState = @state; @x = unpack "N16", $block; for $n (16..79) { $x[$n] = rotl($x[$n-3] ^ $x[$n-8] ^ $x[$n-14] ^ $x[$n-16], 1); } for $n (0..79) { if ($n<20) { $tmp = ch(@state[1..3]) + $k[0]; } elsif ($n<40) { $tmp = parity(@state[1..3]) + $k[1]; } elsif ($n<60) { $tmp = maj(@state[1..3]) + $k[2]; } elsif ($n<80) { $tmp = parity(@state[1..3]) + $k[3]; } $tmp = mod($tmp + rotl($state[0], 5) + $x[$n] + $state[4]); $state[4] = $state[3]; $state[3] = $state[2]; $state[2] = rotl($state[1], 30); $state[1] = $state[0]; $state[0] = $tmp; } $state[$_] = mod($state[$_] + $tmpState[$_]) for 0..$#state; } sub sha256roundz { @tmpState = @state; @x = unpack "N16", $block; for $n (16..63) { $x[$n] = mod(s1($x[ $n-2 ]) + $x[ $n-7 ] + s0($x[ $n-15 ]) + $x[ $n-16 ]); } for $n (0..63) { $tmp1 = $state[7] + S1($state[4]) + ch(@state[4..6]) + $k[$n] + $x[$n]; $tmp2 = S0($state[0]) + maj(@state[0..2]); $state[7] = $state[6]; $state[6] = $state[5]; $state[5] = $state[4]; $state[4] = mod($state[3] + $tmp1); $state[3] = $state[2]; $state[2] = $state[1]; $state[1] = $state[0]; $state[0] = mod($tmp1 + $tmp2); } $state[$_] = mod($state[$_] + $tmpState[$_]) for 0..$#state; } sub shaFormat { if ($_[0] eq "error") { return wantarray ? @_ : shift; } return wantarray ? @state : sprintf "%08x" x@state, @state; } sub mod { $_[0] % 4294967296 } sub rotr { ($_[0] >> $_[1]) | ($_[0] << (32 - $_[1])) } sub rotl { ($_[0] << $_[1]) | ($_[0] >> (32 - $_[1])) } sub S0 { rotr($_[0], 2) ^ rotr($_[0], 13) ^ rotr($_[0], 22) } sub S1 { rotr($_[0], 6) ^ rotr($_[0], 11) ^ rotr($_[0], 25) } sub s0 { rotr($_[0], 7) ^ rotr($_[0], 18) ^ ($_[0] >> 3) } sub s1 { rotr($_[0], 17) ^ rotr($_[0], 19) ^ ($_[0] >> 10) } sub ch { ($_[0] & $_[1] ) ^ (~$_[0] & $_[2]) } sub maj { ($_[0] & $_[1] ) ^ ($_[0] & $_[2]) ^ ($_[1] & $_[2]) } sub parity { $_[0] ^ $_[1] ^ $_[2] } sub sha1init { *round = *sha1roundz; $blockLen = 64; @state = ( 0x67452301 , 0xefcdab89 , 0x98badcfe , 0x10325476 , 0xc3d2e1f0 ); @k = ( 0x5a827999 , 0x6ed9eba1 , 0x8f1bbcdc , 0xca62c1d6 ); } sub sha256init { *round = *sha256roundz; $blockLen = 64; @state = ( 0x6a09e667 , 0xbb67ae85 , 0x3c6ef372 , 0xa54ff53a , 0x510e527f , 0x9b05688c , 0x1f83d9ab , 0x5be0cd19 , ); @k = ( 0x428a2f98 , 0x71374491 , 0xb5c0fbcf , 0xe9b5dba5 , 0x3956c25b , 0x59f111f1 , 0x923f82a4 , 0xab1c5ed5 , 0xd807aa98 , 0x12835b01 , 0x243185be , 0x550c7dc3 , 0x72be5d74 , 0x80deb1fe , 0x9bdc06a7 , 0xc19bf174 , 0xe49b69c1 , 0xefbe4786 , 0x0fc19dc6 , 0x240ca1cc , 0x2de92c6f , 0x4a7484aa , 0x5cb0a9dc , 0x76f988da , 0x983e5152 , 0xa831c66d , 0xb00327c8 , 0xbf597fc7 , 0xc6e00bf3 , 0xd5a79147 , 0x06ca6351 , 0x14292967 , 0x27b70a85 , 0x2e1b2138 , 0x4d2c6dfc , 0x53380d13 , 0x650a7354 , 0x766a0abb , 0x81c2c92e , 0x92722c85 , 0xa2bfe8a1 , 0xa81a664b , 0xc24b8b70 , 0xc76c51a3 , 0xd192e819 , 0xd6990624 , 0xf40e3585 , 0x106aa070 , 0x19a4c116 , 0x1e376c08 , 0x2748774c , 0x34b0bcb5 , 0x391c0cb3 , 0x4ed8aa4a , 0x5b9cca4f , 0x682e6ff3 , 0x748f82ee , 0x78a5636f , 0x84c87814 , 0x8cc70208 , 0x90befffa , 0xa4506ceb , 0xbef9a3f7 , 0xc67178f2 , ); } &arg_check if @ARGV; sub arg_check { $| = 1; $switch = shift @ARGV; $switch_str1 = "/1s"; $switch_file1 = "/1f"; $switch_str256 = "/256s"; $switch_file256 = "/256f"; $maxLineLen = 40; $sltMsgTmpl = "%-6s : %s\n"; if ($switch =~ m{^/?(\?|help)$}i) { &arg_help; } elsif ($switch =~ m{^($switch_str1|$switch_str256)$}i) { if (!@ARGV) { arg_help( 'ハッシュ値を得たい文字列を入力してください' ); } ($bit_w) = $switch =~ /(\d+)/; foreach (@ARGV) { if (length($_) > $maxLineLen) { $tmp = substr $_, 0, $maxLineLen-5; $tmp .= "....."; } else { $tmp = $_; } printf $sltMsgTmpl, "String", $tmp; printf $sltMsgTmpl, "SHA-$bit_w", $tmp = &{"sha${bit_w}"}($_); printf "\n"; } } elsif ($switch =~ m{^($switch_file1|$switch_file256)$}i) { if (!@ARGV) { arg_help( 'ハッシュ値を得たいファイルを入力してください' ); } ($bit_w) = $switch =~ /(\d+)/; foreach (@ARGV) { printf $sltMsgTmpl, "File", $_; $tmp = &{"sha${bit_w}f"}($_); if ($tmp eq "error") { printf $sltMsgTmpl, "Error", 'ファイルを開けません'; } else { printf $sltMsgTmpl, "SHA-$bit_w", $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_str1, '"string"', '文字列のSHA-1を計算'; printf " %-12s %-10s # %s\n", $switch_file1, '"file"', 'ファイルのSHA-1を計算'; printf " %-12s %-10s # %s\n", $switch_str256, '"string"', '文字列のSHA-256を計算'; printf " %-12s %-10s # %s\n", $switch_file256, '"file"', 'ファイルのSHA-256を計算'; printf " %-12s %-10s # %s\n", "/? or /help", "", '今読んでいるコレを表\示'; } 1;