#!/usr/local/bin/perl sub convert($){ use integer; my $s = join '',@_; my @round = ( [sub{($_[0] & $_[1]) | (~$_[0] & $_[2])},[ [ 0, 7,0xd76aa478],[ 1,12,0xe8c7b756],[ 2,17,0x242070db],[ 3,22,0xc1bdceee],[ 4, 7,0xf57c0faf],[ 5,12,0x4787c62a],[ 6,17,0xa8304613],[ 7,22,0xfd469501], [ 8, 7,0x698098d8],[ 9,12,0x8b44f7af],[10,17,0xffff5bb1],[11,22,0x895cd7be],[12, 7,0x6b901122],[13,12,0xfd987193],[14,17,0xa679438e],[15,22,0x49b40821] ]], [sub{($_[0] & $_[2]) | ($_[1] & ~$_[2])},[ [ 1, 5,0xf61e2562],[ 6, 9,0xc040b340],[11,14,0x265e5a51],[ 0,20,0xe9b6c7aa],[ 5, 5,0xd62f105d],[10, 9,0x02441453],[15,14,0xd8a1e681],[ 4,20,0xe7d3fbc8], [ 9, 5,0x21e1cde6],[14, 9,0xc33707d6],[ 3,14,0xf4d50d87],[ 8,20,0x455a14ed],[13, 5,0xa9e3e905],[ 2, 9,0xfcefa3f8],[ 7,14,0x676f02d9],[12,20,0x8d2a4c8a] ]], [sub{$_[0] ^ $_[1] ^ $_[2]},[ [ 5, 4,0xfffa3942],[ 8,11,0x8771f681],[11,16,0x6d9d6122],[14,23,0xfde5380c],[ 1, 4,0xa4beea44],[ 4,11,0x4bdecfa9],[ 7,16,0xf6bb4b60],[10,23,0xbebfbc70], [13, 4,0x289b7ec6],[ 0,11,0xeaa127fa],[ 3,16,0xd4ef3085],[ 6,23,0x04881d05],[ 9, 4,0xd9d4d039],[12,11,0xe6db99e5],[15,16,0x1fa27cf8],[ 2,23,0xc4ac5665] ]], [sub{$_[1] ^ ($_[0] | ~$_[2])},[ [ 0, 6,0xf4292244],[ 7,10,0x432aff97],[14,15,0xab9423a7],[ 5,21,0xfc93a039],[12, 6,0x655b59c3],[ 3,10,0x8f0ccc92],[10,15,0xffeff47d],[ 1,21,0x85845dd1], [ 8, 6,0x6fa87e4f],[15,10,0xfe2ce6e0],[ 6,15,0xa3014314],[13,21,0x4e0811a1],[ 4, 6,0xf7537e82],[11,10,0xbd3af235],[ 2,15,0x2ad7d2bb],[ 9,21,0xeb86d391] ]] ); my(@state,@abcd,@x,@s,$len,$index,$pad,$sub,$i,$n); @state = (0x67452301,0xefcdab89,0x98badcfe,0x10325476); @abcd = (0..3); $len = length $s; $index = $len & 0x3f; $pad = ($index<56?56:120)-$index-1; $s .= "\x80".("\0"x$pad) if $pad>=0; $s .= pack 'V2',$len*8; for($i=0;$i<$len;$i+=64){ @x = unpack 'V16',substr $s,$i,64; @s = @state; for(@round){ $f = ${$_}[0]; for(@{${$_}[1]}){ $n = ($s[$abcd[0]] + $x[${$_}[0]] + ${$_}[2] + &$f($s[$abcd[1]], $s[$abcd[2]], $s[$abcd[3]])) & 0xffffffff; $s[$abcd[0]] = ((($n<<${$_}[1]) | (($n>>(32-${$_}[1])) & ((1<<${$_}[1])-1)))+$s[$abcd[1]])&0xffffffff; unshift @abcd,pop @abcd; } } @state = map{($state[$_]+$s[$_])&0xffffffff}0..3; } pack 'V4',@state; } sub md5_crypt($$){ my $Magic = '$1$'; my($pass,$salt) = @_; my($final,$len,$ctx,$ctx1,$i); $salt =~ s|^\Q$Magic||; $salt =~ s|^(.*)\$.*$|$1|; $salt = substr $salt,0,8; $final = convert("$pass$salt$pass"); $ctx = "$pass$Magic$salt"; for ($len = length $pass; $len > 0; $len -= 16) { $ctx .= substr $final,0,$len > 16 ? 16 : $len; } for($i = length $pass;$i;$i >>= 1){ $ctx .= $i & 1 ? "\0" : substr $pass,0,1; } $final = convert($ctx); for ($i = 0;$i < 1000;$i++) { $ctx1 = ''; $ctx1 .= $i & 1 ? $pass : substr $final,0,16; $ctx1 .= $salt if $i % 3; $ctx1 .= $pass if $i % 7; $ctx1 .= $i & 1 ? substr $final,0,16 : $pass; $final = convert($ctx1); } my @to64 = ('.','/',0..9,A..Z,a..z); sub to64($$){ my($v,$n) = @_; my $ret; while(--$n >= 0){ $ret .= $to64[$v & 0x3f]; $v >>= 6; } $ret; } join '',$Magic,$salt,'$', to64(ord(substr $final, 0,1) << 16 | ord(substr $final, 6,1) << 8 | ord(substr $final,12,1),4), to64(ord(substr $final, 1,1) << 16 | ord(substr $final, 7,1) << 8 | ord(substr $final,13,1),4), to64(ord(substr $final, 2,1) << 16 | ord(substr $final, 8,1) << 8 | ord(substr $final,14,1),4), to64(ord(substr $final, 3,1) << 16 | ord(substr $final, 9,1) << 8 | ord(substr $final,15,1),4), to64(ord(substr $final, 4,1) << 16 | ord(substr $final,10,1) << 8 | ord(substr $final, 5,1),4), to64(ord(substr $final,11,1), 2); } $digest = unpack H32,convert("aaa:password:aaa"); print $digest;