#!/bin/bash
# MD5 implementation in Bash
# - Vidar 'koala_man' Holen
#
# 2006-04-12 http://www.vidarholen.net

S11=7
S12=12
S13=17
S14=22
S21=5
S22=9
S23=14
S24=20
S31=4
S32=11
S33=16
S34=23
S41=6
S42=10
S43=15
S44=21
HEXDIGITS=(0 1 2 3 4 5 6 7 8 9 a b c d e f)



SA=$((0x67452301))
SB=$((0xefcdab89))
SC=$((0x98badcfe))
SD=$((0x10325476))
SDATA=()
SBUFFER=()
SBUFFERPOS=0
SNUM=0


F() {
	XV=$1; YV=$2; ZV=$3;
	echo $(((XV&YV)|((~XV)&ZV)))
}
G() {
	XV=$1; YV=$2; ZV=$3;
	echo $(((XV&ZV)|(YV&(~ZV))))
}
H() {
	XV=$1; YV=$2; ZV=$3;
	echo $((XV^YV^ZV))
}
I() {
	XV=$1; YV=$2; ZV=$3;
	echo $((YV^(XV|(~ZV))))
}

ROL() {
	XV=$1; SV=$2;
	echo $((((XV<<SV)|(XV>>(32-SV)))&((1<<32)-1)))
}

FF() {
	A=$1; B=$2; C=$3; D=$4; X=$5; S=$6; T=$7;
	TMP=$(F $B $C $D)
	TMP=$(((A+TMP+X+T)&((1<<32)-1)))
	TMP=$(ROL $TMP $S)
	echo $((B+TMP))
}
GG() {
	A=$1; B=$2; C=$3; D=$4; X=$5; S=$6; T=$7;
	TMP=$(G $B $C $D)
	TMP=$(((A+TMP+X+T)&((1<<32)-1)))
	TMP=$(ROL $TMP $S)
	echo $((B+TMP))
}
HH() {
	A=$1; B=$2; C=$3; D=$4; X=$5; S=$6; T=$7;
	TMP=$(H $B $C $D)
	TMP=$(((A+TMP+X+T)&((1<<32)-1)))
	TMP=$(ROL $TMP $S)
	echo $((B+TMP))
}
II() {
	A=$1; B=$2; C=$3; D=$4; X=$5; S=$6; T=$7;
	TMP=$(I $B $C $D)
	TMP=$(((A+TMP+X+T)&((1<<32)-1)))
	TMP=$(ROL $TMP $S)
	echo $((B+TMP))
}

TRANSFORM() {
	TA=$SA
	TB=$SB
	TC=$SC
	TD=$SD

	TA=$(FF $TA $TB $TC $TD ${SDATA[ 0]} $S11 $((0xd76aa478)) )
	TD=$(FF $TD $TA $TB $TC ${SDATA[ 1]} $S12 $((0xe8c7b756)) )
	TC=$(FF $TC $TD $TA $TB ${SDATA[ 2]} $S13 $((0x242070db)) )
	TB=$(FF $TB $TC $TD $TA ${SDATA[ 3]} $S14 $((0xc1bdceee)) )
	TA=$(FF $TA $TB $TC $TD ${SDATA[ 4]} $S11 $((0xf57c0faf)) )
	TD=$(FF $TD $TA $TB $TC ${SDATA[ 5]} $S12 $((0x4787c62a)) )
	TC=$(FF $TC $TD $TA $TB ${SDATA[ 6]} $S13 $((0xa8304613)) )
	TB=$(FF $TB $TC $TD $TA ${SDATA[ 7]} $S14 $((0xfd469501)) )
	TA=$(FF $TA $TB $TC $TD ${SDATA[ 8]} $S11 $((0x698098d8)) )
	TD=$(FF $TD $TA $TB $TC ${SDATA[ 9]} $S12 $((0x8b44f7af)) )
	TC=$(FF $TC $TD $TA $TB ${SDATA[10]} $S13 $((0xffff5bb1)) )
	TB=$(FF $TB $TC $TD $TA ${SDATA[11]} $S14 $((0x895cd7be)) )
	TA=$(FF $TA $TB $TC $TD ${SDATA[12]} $S11 $((0x6b901122)) )
	TD=$(FF $TD $TA $TB $TC ${SDATA[13]} $S12 $((0xfd987193)) )
	TC=$(FF $TC $TD $TA $TB ${SDATA[14]} $S13 $((0xa679438e)) )
	TB=$(FF $TB $TC $TD $TA ${SDATA[15]} $S14 $((0x49b40821)) )


	TA=$(GG $TA $TB $TC $TD ${SDATA[ 1]} $S21 $((0xf61e2562)) )
	TD=$(GG $TD $TA $TB $TC ${SDATA[ 6]} $S22 $((0xc040b340)) )
	TC=$(GG $TC $TD $TA $TB ${SDATA[11]} $S23 $((0x265e5a51)) )
	TB=$(GG $TB $TC $TD $TA ${SDATA[ 0]} $S24 $((0xe9b6c7aa)) )
	TA=$(GG $TA $TB $TC $TD ${SDATA[ 5]} $S21 $((0xd62f105d)) )
	TD=$(GG $TD $TA $TB $TC ${SDATA[10]} $S22  $((0x2441453)) )
	TC=$(GG $TC $TD $TA $TB ${SDATA[15]} $S23 $((0xd8a1e681)) )
	TB=$(GG $TB $TC $TD $TA ${SDATA[ 4]} $S24 $((0xe7d3fbc8)) )
	TA=$(GG $TA $TB $TC $TD ${SDATA[ 9]} $S21 $((0x21e1cde6)) )
	TD=$(GG $TD $TA $TB $TC ${SDATA[14]} $S22 $((0xc33707d6)) )
	TC=$(GG $TC $TD $TA $TB ${SDATA[ 3]} $S23 $((0xf4d50d87)) )
	TB=$(GG $TB $TC $TD $TA ${SDATA[ 8]} $S24 $((0x455a14ed)) )
	TA=$(GG $TA $TB $TC $TD ${SDATA[13]} $S21 $((0xa9e3e905)) )
	TD=$(GG $TD $TA $TB $TC ${SDATA[ 2]} $S22 $((0xfcefa3f8)) )
	TC=$(GG $TC $TD $TA $TB ${SDATA[ 7]} $S23 $((0x676f02d9)) )
	TB=$(GG $TB $TC $TD $TA ${SDATA[12]} $S24 $((0x8d2a4c8a)) )


	TA=$(HH $TA $TB $TC $TD ${SDATA[ 5]} $S31 $((0xfffa3942)) )
	TD=$(HH $TD $TA $TB $TC ${SDATA[ 8]} $S32 $((0x8771f681)) )
	TC=$(HH $TC $TD $TA $TB ${SDATA[11]} $S33 $((0x6d9d6122)) )
	TB=$(HH $TB $TC $TD $TA ${SDATA[14]} $S34 $((0xfde5380c)) )
	TA=$(HH $TA $TB $TC $TD ${SDATA[ 1]} $S31 $((0xa4beea44)) )
	TD=$(HH $TD $TA $TB $TC ${SDATA[ 4]} $S32 $((0x4bdecfa9)) )
	TC=$(HH $TC $TD $TA $TB ${SDATA[ 7]} $S33 $((0xf6bb4b60)) )
	TB=$(HH $TB $TC $TD $TA ${SDATA[10]} $S34 $((0xbebfbc70)) )
	TA=$(HH $TA $TB $TC $TD ${SDATA[13]} $S31 $((0x289b7ec6)) )
	TD=$(HH $TD $TA $TB $TC ${SDATA[ 0]} $S32 $((0xeaa127fa)) )
	TC=$(HH $TC $TD $TA $TB ${SDATA[ 3]} $S33 $((0xd4ef3085)) )
	TB=$(HH $TB $TC $TD $TA ${SDATA[ 6]} $S34  $((0x4881d05)) )
	TA=$(HH $TA $TB $TC $TD ${SDATA[ 9]} $S31 $((0xd9d4d039)) )
	TD=$(HH $TD $TA $TB $TC ${SDATA[12]} $S32 $((0xe6db99e5)) )
	TC=$(HH $TC $TD $TA $TB ${SDATA[15]} $S33 $((0x1fa27cf8)) )
	TB=$(HH $TB $TC $TD $TA ${SDATA[ 2]} $S34 $((0xc4ac5665)) )


	TA=$(II $TA $TB $TC $TD ${SDATA[ 0]} $S41 $((0xf4292244)) )
	TD=$(II $TD $TA $TB $TC ${SDATA[ 7]} $S42 $((0x432aff97)) )
	TC=$(II $TC $TD $TA $TB ${SDATA[14]} $S43 $((0xab9423a7)) )
	TB=$(II $TB $TC $TD $TA ${SDATA[ 5]} $S44 $((0xfc93a039)) )
	TA=$(II $TA $TB $TC $TD ${SDATA[12]} $S41 $((0x655b59c3)) )
	TD=$(II $TD $TA $TB $TC ${SDATA[ 3]} $S42 $((0x8f0ccc92)) )
	TC=$(II $TC $TD $TA $TB ${SDATA[10]} $S43 $((0xffeff47d)) )
	TB=$(II $TB $TC $TD $TA ${SDATA[ 1]} $S44 $((0x85845dd1)) )
	TA=$(II $TA $TB $TC $TD ${SDATA[ 8]} $S41 $((0x6fa87e4f)) )
	TD=$(II $TD $TA $TB $TC ${SDATA[15]} $S42 $((0xfe2ce6e0)) )
	TC=$(II $TC $TD $TA $TB ${SDATA[ 6]} $S43 $((0xa3014314)) )
	TB=$(II $TB $TC $TD $TA ${SDATA[13]} $S44 $((0x4e0811a1)) )
	TA=$(II $TA $TB $TC $TD ${SDATA[ 4]} $S41 $((0xf7537e82)) )
	TD=$(II $TD $TA $TB $TC ${SDATA[11]} $S42 $((0xbd3af235)) )
	TC=$(II $TC $TD $TA $TB ${SDATA[ 2]} $S43 $((0x2ad7d2bb)) )
	TB=$(II $TB $TC $TD $TA ${SDATA[ 9]} $S44 $((0xeb86d391)) )

	SA=$(((SA+TA)&((1<<32)-1)))
	SB=$(((SB+TB)&((1<<32)-1)))
	SC=$(((SC+TC)&((1<<32)-1)))
	SD=$(((SD+TD)&((1<<32)-1)))

}

LEHEX() {
	N=$1
	S=""
	for((i=0; i<4; i++)) {
		B=$((N&255))
		U=$((B>>4))
		L=$((B&15))
		S="${S}${HEXDIGITS[U]}${HEXDIGITS[L]}"
		N=$((N>>8))
	}
	echo $S
}

HEXFORMAT() {
	echo "$(LEHEX $SA)$(LEHEX $SB)$(LEHEX $SC)$(LEHEX $SD)"
}

UPDATE() {
	while [[ $# -gt 0 ]]
	do
		SBUFFER[SBUFFERPOS]=$1
		let SBUFFERPOS++
		shift

		if [[ $SBUFFERPOS == 64 ]] 
		then
			SDATAPOS=0;
			for((I=0; I<64; I+=4))
			do
				SDATA[SDATAPOS]=$((0x${SBUFFER[I]} | (0x${SBUFFER[I+1]}<<8) | (0x${SBUFFER[I+2]}<<16) | (0x${SBUFFER[I+3]}<<24)))
				let SDATAPOS++
			done
			TRANSFORM
			SBUFFERPOS=0
		fi
		let SNUM++
	done
}

FINALIZE() {
	N=$((SNUM*8))
	UPDATE 80
	while [[ $SBUFFERPOS != 56 ]]
	do
		UPDATE 00
	done

	S=""
	for((I=0; I<8; I++))
	do
		B=$((N&255))
		U=$((B>>4))
		L=$((B&15))
		S="${S} ${HEXDIGITS[U]}${HEXDIGITS[L]}"
		N=$((N>>8))
	done
	UPDATE $S
}


exec < <(od -v -t x1)

while read ADDR BYTES
do
	UPDATE $BYTES
done
FINALIZE
HEXFORMAT


