Implement the MD5 algorithm!

-5

Your challenge is to output the MD5 hash of your input. The specification of MD5 can be found here. Crypto builtins are NOT allowed. Shortest code wins. Psuedocode:

//Note: All variables are unsigned 32 bit and wrap modulo 2^32 when calculating
var int[64] s, K

//s specifies the per-round shift amounts
s[ 0..15] := { 7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22,  7, 12, 17, 22 }
s[16..31] := { 5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20,  5,  9, 14, 20 }
s[32..47] := { 4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23,  4, 11, 16, 23 }
s[48..63] := { 6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21,  6, 10, 15, 21 }

//Use binary integer part of the sines of integers (Radians) as constants:
for i from 0 to 63
    K[i] := floor(232 × abs(sin(i + 1)))
end for
//(Or just use the following precomputed table):
K[ 0.. 3] := { 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee }
K[ 4.. 7] := { 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501 }
K[ 8..11] := { 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be }
K[12..15] := { 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 }
K[16..19] := { 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa }
K[20..23] := { 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8 }
K[24..27] := { 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed }
K[28..31] := { 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a }
K[32..35] := { 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c }
K[36..39] := { 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70 }
K[40..43] := { 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05 }
K[44..47] := { 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665 }
K[48..51] := { 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039 }
K[52..55] := { 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1 }
K[56..59] := { 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1 }
K[60..63] := { 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 }

//Initialize variables:
var int a0 := 0x67452301   //A
var int b0 := 0xefcdab89   //B
var int c0 := 0x98badcfe   //C
var int d0 := 0x10325476   //D

//Pre-processing: adding a single 1 bit
append "1" bit to message    
// Notice: the input bytes are considered as bits strings,
//  where the first bit is the most significant bit of the byte.[49]


//Pre-processing: padding with zeros
append "0" bit until message length in bits ≡ 448 (mod 512)
append original length in bits mod (2 pow 64) to message


//Process the message in successive 512-bit chunks:
for each 512-bit chunk of message
    break chunk into sixteen 32-bit words M[j], 0 ≤ j ≤ 15
//Initialize hash value for this chunk:
    var int A := a0
    var int B := b0
    var int C := c0
    var int D := d0
//Main loop:
    for i from 0 to 63
        if 0 ≤ i ≤ 15 then
            F := (B and C) or ((not B) and D)
            g := i
        else if 16 ≤ i ≤ 31
            F := (D and B) or ((not D) and C)
            g := (5×i + 1) mod 16
        else if 32 ≤ i ≤ 47
            F := B xor C xor D
            g := (3×i + 5) mod 16
        else if 48 ≤ i ≤ 63
            F := C xor (B or (not D))
            g := (7×i) mod 16
//Be wary of the below definitions of a,b,c,d
        dTemp := D
        D := C
        C := B
        B := B + leftrotate((A + F + K[i] + M[g]), s[i])
        A := dTemp
    end for
//Add this chunk's hash to result so far:
    a0 := a0 + A
    b0 := b0 + B
    c0 := c0 + C
    d0 := d0 + D
end for

var char digest[16] := a0 append b0 append c0 append d0 //(Output is in little-endian)

//leftrotate function definition
leftrotate (x, c)
    return (x << c) binary or (x >> (32-c));

programmer5000

Posted 2017-06-11T20:20:00.990

Reputation: 7 828

Question was closed 2019-03-24T00:20:22.717

4

Linking to an RFC isn't really sufficient, see the relevant sha256 question.

– FryAmTheEggman – 2017-06-11T20:30:31.620

3I don't particularly like this challenge, simply because it decays to "Which language has the shortest built-in for MD5 hashing?" Although the general consensus in the past has been not to bar built-ins, I think in this case a better question would prohibit crypto builtins. – musicman523 – 2017-06-11T20:40:26.723

7Ok, that's cool, just change the restrictions, invalidating 4 answers. – Conor O'Brien – 2017-06-11T20:42:02.507

7This is the type of feedback that should be caught in the Sandbox – musicman523 – 2017-06-11T20:44:24.413

4It is unadvisable to make a trivial challenge and then change the specifications. Having a challenge that is literally "give me the shortest MD5 builtin" is bound to get many answers very quickly, and then changing the specifications and invalidating all of them is not a good idea. Additionally, this sort of stuff would have been caught in the Sandbox; even if the Sandbox seems very obselete now, linking it into chat and having a few people see it would have been enough to get this feedback. – HyperNeutrino – 2017-06-11T20:55:18.653

I'm voting to close; "md5 builtin" does not have an exact definition – MilkyWay90 – 2019-03-22T22:40:02.017

I now have a reasonably well-golfed answer to this in Jelly. If this is reopened, it's 327 bytes and is at BitLy link because TIO one too long for a comment.

– Nick Kennedy – 2019-03-24T23:42:25.880

Answers

2

PHP, 3012 bytes

removing unnessary Whitespaces and short some variables and function names and replacing string with non existing constants

function MD($s){$A=$a="67452301";$B=$b=efcdab89;$C=$c="98badcfe";$D=$d="10325476";$words=str2blks_MD5($s);$z=[A,B,C,D];$it=[7,12,17,22,5,9,14,20,4,11,16,23,6,10,15,21];$funcs=[F,G,H,I];$moduls=[0,1,1,5,5,3,0,7];$acs=[d76aa478,e8c7b756,"242070db",c1bdceee,f57c0faf,"4787c62a",a8304613,fd469501,"698098d8","8b44f7af",ffff5bb1,"895cd7be","6b901122",fd987193,a679438e,"49b40821",f61e2562,c040b340,"265e5a51",e9b6c7aa,d62f105d,"2441453",d8a1e681,e7d3fbc8,"21e1cde6",c33707d6,f4d50d87,"455a14ed",a9e3e905,fcefa3f8,"676f02d9","8d2a4c8a",fffa3942,"8771f681","6d9d6122",fde5380c,a4beea44,"4bdecfa9",f6bb4b60,bebfbc70,"289b7ec6",eaa127fa,d4ef3085,"4881d05",d9d4d039,e6db99e5,"1fa27cf8",c4ac5665, f4292244,"432aff97",ab9423a7,fc93a039,"655b59c3","8f0ccc92",ffeff47d,"85845dd1","6fa87e4f",fe2ce6e0,a3014314,"4e0811a1",f7537e82,bd3af235,"2ad7d2bb",eb86d391];for($i=0;$i<count($words)/16;$i++){$a=$A;$b=$B;$c=$C;$d=$D;$n=0;for($rot3=0;$rot3<4;$rot3++){$minit=$moduls[$rot3*2];$madd=$moduls[$rot3*2+1];for($rot2=0;$rot2<4;$rot2++){for ($rot=0;$rot<4;$rot++){$word=$words[$minit+($i*16)];$nit=$it[$rot+4*$rot3];FGHI(${"$z[0]"},${"$z[1]"},${"$z[2]"},${"$z[3]"},$word,$nit,$acs[$n],$funcs[$rot3]);array_unshift($z,$z[3]);array_pop($z);$minit=($minit+$madd)%16;++$n;}}}$A=_A(_X($A),_X($a));$B=_A(_X($B),_X($b));$C=_A(_X($C),_X($c));$D=_A(_X($D),_X($d));}return _W($A)._W($B)._W($C)._W($D);}function _W($lValue){$_WValue="";for($lCount=0;$lCount<4;$lCount++){$lByte=_X($lValue)>>($lCount*8)&255;$_WValue.=sprintf("%02x",$lByte);}return$_WValue;}function FGHI(&$A,$B,$C,$D,$M,$s,$t,$func){$Level1=_X(_A(FGHI2($B,$C,$D,$func),bindec($M)));$level2=_X(_A($Level1, _X($t)));$A=_X(_A(_X($A),$level2));$A=rotate($A,$s);$A=_A($A,_X($B));}function FGHI2($X,$Y,$Z,$func){$X=_X($X);$Y=_X($Y);$Z=_X($Z);switch($func){case F:$calc=(($X&$Y)|((~$X)&$Z));break;case G:$calc=(($X&$Z)|($Y&(~$Z)));break;case H:$calc=($X^$Y^$Z);break;case I:$calc=($Y^($X|(~$Z)));}return$calc;}function dectohex($res){if($res<0)return'-'.dechex(abs($res));return dechex($res);}function _X($hex){if($hex[0]=="-")return doubleval('-'.hexdec(str_replace("-","",$hex)));return hexdec($hex);}function _A($lX,$lY){ $lX8=($lX&0x80000000);$lY8=($lY&0x80000000);$lX4=($lX&0x40000000);$lY4=($lY&0x40000000);$lResult=($lX&0x3FFFFFFF)+($lY&0x3FFFFFFF);$res=$lResult^$lX8^$lY8;if($lX4&$lY4)return dectohex($res^0x80000000);if($lX4|$lY4){if($lResult&0x40000000)return dectohex($res^0xC0000000);else return dectohex($res^0x40000000);}return dectohex($res);}function rotate($_d,$bits){return(($_d<<$bits)|shiftright($_d,(32-$bits))&0xffffffff);}function shiftright($_d,$right){$shift=$_d>>$right;if($_d>=0)return$shift;return bindec(substr(decbin($shift),$right));}function str2blks_MD5($s){$nblk=((strlen($s)+8)>>6)+1;$blks=[$nblk*16];for($i=0;$i<$nblk*16;$i++)$blks[$i]=0;for($i=0;$i<strlen($s);$i++)$blks[$i>>2]|=ord($s[$i])<<(($i%4)*8);$blks[$i>>2]|=0x80<<(($i%4)*8);$blks[$nblk*16-2]=strlen($s)*8;for($i=0;$i<$nblk*16;$i++)$blks[$i]=decbin($blks[$i]);return$blks;}echo MD($argn);

Try it online!

PHP, 5307 bytes

copy and paste from here

function MD($string)
    {
    $A = $a = "67452301";
    $B = $b = "efcdab89";
    $C = $c = "98badcfe";
    $D = $d = "10325476";

    $words = str2blks_MD5($string);   

    $torot=array("A","B","C","D");    
    $it=array(7,12,17,22,5,9,14,20,4,11,16,23,6,10,15,21);
    $funcs=array("F","G","H","I");    

    $moduls=array(0,1,1,5,5,3,0,7);

    $acs=array(     "d76aa478","e8c7b756","242070db","c1bdceee",
                    "f57c0faf","4787c62a","a8304613","fd469501",
                    "698098d8","8b44f7af","ffff5bb1","895cd7be",
                    "6b901122","fd987193","a679438e","49b40821",

                    "f61e2562","c040b340","265e5a51","e9b6c7aa",
                    "d62f105d","2441453","d8a1e681","e7d3fbc8",
                    "21e1cde6","c33707d6","f4d50d87","455a14ed",
                    "a9e3e905","fcefa3f8","676f02d9","8d2a4c8a",

                    "fffa3942","8771f681","6d9d6122","fde5380c",
                    "a4beea44","4bdecfa9","f6bb4b60","bebfbc70",
                    "289b7ec6","eaa127fa","d4ef3085","4881d05",
                    "d9d4d039","e6db99e5","1fa27cf8","c4ac5665",  

                    "f4292244","432aff97","ab9423a7","fc93a039",
                    "655b59c3","8f0ccc92","ffeff47d","85845dd1",
                    "6fa87e4f","fe2ce6e0","a3014314","4e0811a1",
                    "f7537e82","bd3af235","2ad7d2bb","eb86d391"); 

    for($i = 0; $i < count($words)/16; $i++)
        {
            $a  = $A;
            $b  = $B;
            $c  = $C;
            $d  = $D;
            $n  = 0; 

        for ($rot3=0;$rot3<4;$rot3++)
            {
            $minit=$moduls[$rot3*2];
        $madd=$moduls[$rot3*2+1];   

            for ($rot2=0;$rot2<4;$rot2++)
                {
                for ($rot=0;$rot<4;$rot++)
                {
                $word=$words[$minit + ($i * 16)];
                $nit=$it[$rot+4*$rot3];

                FGHI (${"$torot[0]"}, ${"$torot[1]"}, ${"$torot[2]"}, ${"$torot[3]"}, $word, $nit, $acs[$n],$funcs[$rot3]); 

                    array_unshift($torot,$torot[3]);
                    array_pop($torot);

                $minit=($minit+$madd)%16;
                ++$n;
                }       
                 }
            }

            $A=AddUnsigned(hexdec2($A),hexdec2($a));
            $B=AddUnsigned(hexdec2($B),hexdec2($b));
            $C=AddUnsigned(hexdec2($C),hexdec2($c));
            $D=AddUnsigned(hexdec2($D),hexdec2($d));    
            }
    return WordToHex($A).WordToHex($B).WordToHex($C).WordToHex($D);
    }
function WordToHex($lValue) 
   { 
    $WordToHexValue = "";
    for ($lCount = 0;$lCount<4;$lCount++) 
        { 
        $lByte = hexdec2($lValue)>>($lCount*8) & 255; 
        $WordToHexValue.= sprintf("%02x",$lByte);
        }
    return $WordToHexValue;
    }
function FGHI(&$A, $B, $C, $D, $M, $s, $t, $func)
        {
        $Level1 = hexdec2(AddUnsigned(FGHI2($B, $C, $D, $func) , bindec($M) ));
        $level2 = hexdec2(AddUnsigned($Level1, hexdec2($t)));  
        $A = hexdec2(AddUnsigned(hexdec2($A),$level2));
        $A = rotate($A, $s); 
        $A = AddUnsigned($A , hexdec2($B)) ; 
        }
function FGHI2($X, $Y, $Z,$func)
        {    
        $X = hexdec2($X); 
        $Y = hexdec2($Y);
        $Z = hexdec2($Z);

    switch ($func)
        {
        case "F":
                $calc = (($X & $Y) | ((~ $X) & $Z));break;
        case "G":
            $calc = (($X & $Z) | ($Y & (~ $Z)));break;
        case "H":
            $calc = ($X ^ $Y ^ $Z);break;
        case "I":
            $calc = ($Y ^ ($X | (~ $Z)));
        }
        return  $calc; 
    }
function dectohex($res)
    {
        if($res < 0)
            return '-'.dechex(abs($res));
        return dechex($res);    
    }

function hexdec2($hex)
    {  
    if($hex[0] == "-")   
        return doubleval('-'.hexdec(str_replace("-", "", $hex )));

    return hexdec($hex);
    }

function AddUnsigned($lX,$lY) 
   { 
    $lX8 = ($lX & 0x80000000);
    $lY8 = ($lY & 0x80000000);
    $lX4 = ($lX & 0x40000000);
    $lY4 = ($lY & 0x40000000);

    $lResult = ($lX & 0x3FFFFFFF)+($lY & 0x3FFFFFFF);

    $res=$lResult ^ $lX8 ^ $lY8;

    if ($lX4 & $lY4)                       return dectohex($res ^ 0x80000000);   
    if ($lX4 | $lY4) 
    {
        if ($lResult & 0x40000000)         return dectohex($res ^ 0xC0000000);
        else                               return dectohex($res ^ 0x40000000);       
        }                                  return dectohex($res);
    }
function rotate ($decimal, $bits) 
    { 
    return  (($decimal << $bits) |  shiftright($decimal, (32 - $bits))  & 0xffffffff);
    }
function shiftright($decimal , $right)
    { 
    $shift=$decimal >> $right;

    if($decimal >= 0) return $shift;
    return bindec(substr(decbin($shift),$right));
    }

function str2blks_MD5($str)
  {
  $nblk = ((strlen($str) + 8) >> 6) + 1;

  $blks = array($nblk * 16);

  for($i = 0; $i < $nblk * 16; $i++) 
                $blks[$i] = 0;

  for($i = 0; $i < strlen($str); $i++)
            $blks[$i >> 2] |= ord($str[$i]) << (($i % 4) * 8);

  $blks[$i >> 2] |= 0x80 << (($i % 4) * 8);

  $blks[$nblk * 16 - 2] = strlen($str) * 8;

  for ($i=0; $i < $nblk * 16; $i++)             
        $blks[$i] = decbin($blks[$i]);

  return $blks;
  }

echo MD($argn);

Try it online!

Jörg Hülsermann

Posted 2017-06-11T20:20:00.990

Reputation: 13 026