Custom code for MD5 in js I wanted to write my own code for md5 in javascript and learn its inner mechanics. (I know it is not trusted anymore, deprecated, ... but I'm just learning).
I didn't want to just copy the code that uses these like 60 repeated lines and over-complicated functions (like here), so I started writing my own implementation:
(Although I have just written this pseudocode in js)

function myMD5(string){
    /*bit rotation*/
    var rot = function(word, shift){return word &lt;&lt; shift | word &gt;&gt;&gt; (32 - shift);};
    /*unsigning also cuts to 32bit words*/
    var us = function(word){return word &gt;&gt;&gt; 0;};
    /*function for unsigned adding words mod 2**32*/
    var add = function(wordsarr){
        var res = 0;
        for(var wr = 0; wr &lt; wordsarr.length; wr++)
            res = us(res + us(wordsarr[wr]));
        return res;
    };
    /*converting string to utf8encoded string to bytes to 32bit-words to 512bit padded blocks*/
    var bytes = [];
    string = unescape(encodeURIComponent(string));
    for(var char = 0; char &lt; string.length; char++)
        bytes[char] = string.charCodeAt(char);
    bytes.push(0x80);
    var words = [];
    for(var byte = 0; byte &lt; bytes.length; byte += 4)
        words.push(bytes[byte + 3] &lt;&lt; 24 | bytes[byte + 2] &lt;&lt; 16 | bytes[byte + 1] &lt;&lt; 8 | bytes[byte]);
    while(words.length % 16 != 14)
        words.push(0);
    words.push((bytes.length - 1) &lt;&lt; 3);
    words.push((bytes.length - 1) &gt;&gt;&gt; 29);
    /*initialization of the constants*/
    var K = [];
    for(var i = 1; i &lt;= 64; i++)
        K.push(Math.floor(0x100000000 * Math.abs(Math.sin(i))));
    var shif = [0x07, 0x0c, 0x11, 0x16, 0x07, 0x0c, 0x11, 0x16, 0x07, 0x0c, 0x11, 0x16, 0x07, 0x0c, 0x11, 0x16,
                0x05, 0x09, 0x0e, 0x14, 0x05, 0x09, 0x0e, 0x14, 0x05, 0x09, 0x0e, 0x14, 0x05, 0x09, 0x0e, 0x14,
                0x04, 0x0b, 0x10, 0x17, 0x04, 0x0b, 0x10, 0x17, 0x04, 0x0b, 0x10, 0x17, 0x04, 0x0b, 0x10, 0x17,
                0x06, 0x0a, 0x0f, 0x15, 0x06, 0x0a, 0x0f, 0x15, 0x06, 0x0a, 0x0f, 0x15, 0x06, 0x0a, 0x0f, 0x15];
    var a0 = 0x67452301,
        b0 = 0xefcdab89,
        c0 = 0x98badcfe,
        d0 = 0x10325476;
    var F, ix;
    var chunk;
    var A, B, C, D;
    for(var pos = 0; pos &lt; words.length; pos += 16){
        /*chunk = current 512bit block*/
        var chunk = words.slice(pos, pos + 16);
        A = a0;
        B = b0;
        C = c0;
        D = d0;
        for(var rnd = 0; rnd &lt; 64; rnd++){
            /*round type*/
            if(rnd &lt; 16){
                F = (B &amp; C) | (~B &amp; D);
                ix = rnd;
            }
            else if(rnd &lt; 32){
                F = (B &amp; D) | (C &amp; ~D);
                ix = (5 * rnd + 1) % 16;
            }
            else if(rnd &lt; 48){
                F = B ^ C ^ D;
                ix = (3 * rnd + 5) % 16;
            }
            else{
                F = C ^ (B | ~D);
                ix = (7 * rnd) % 16;
            }
            /*prepare for the next round, compute the temporary F*/
            F = add([F, A, K[rnd], chunk[ix]]);
            A = D;
            D = C;
            C = B;
            B = add([B, rot(F, shif[rnd])]);
        }
        /*add to the current state mod 2**32*/
        a0 = add([a0, A]);
        b0 = add([b0, B]);
        c0 = add([c0, C]);
        d0 = add([d0, D]);
    }
    /*return the state words as 16 bytes*/
    return [a0 &gt;&gt;&gt; 24, a0 &gt;&gt;&gt; 16 &amp; 0xff, a0 &gt;&gt;&gt; 8 &amp; 0xff, a0 &amp; 0xff,
            b0 &gt;&gt;&gt; 24, b0 &gt;&gt;&gt; 16 &amp; 0xff, b0 &gt;&gt;&gt; 8 &amp; 0xff, b0 &amp; 0xff,
            c0 &gt;&gt;&gt; 24, c0 &gt;&gt;&gt; 16 &amp; 0xff, c0 &gt;&gt;&gt; 8 &amp; 0xff, c0 &amp; 0xff,
            d0 &gt;&gt;&gt; 24, d0 &gt;&gt;&gt; 16 &amp; 0xff, d0 &gt;&gt;&gt; 8 &amp; 0xff, d0 &amp; 0xff];
};


However, It doesn't work as it should...
I already fixed some mistakes, but now I can't find anything wrong!
Could someone help me troubleshooting?
function myMD5(string){


MD5 itself acts on bits or - for most runtimes - bytes. All string manipulation should take place outside any MD5 function.

/*unsigning also works cuts to 32bit words*/


That's not clear to me. Two verbs in a row...

string = unescape(encodeURIComponent(string));


Oh dear, that throws the principle of least surprise in the blender. Do not suddenly change the string without warning the user.

The you first copy the complete message to bytes, and then to words. This uses a lot of unnecessary memory. There is a reason why most implementations (well, outside of those of JavaScript) use multiple update method and a final digest method. It is to handle larger messages, or messages that are actually split over multiple locations.

for(var i = 1; i &lt;= 64; i++)
    K.push(Math.floor(0x100000000 * Math.abs(Math.sin(i))));


This makes the code smaller, of course, but do you really want to perform that calculation for each MD5 invocation?

var A, B, C, D;


When using variable names that are specific to a specification, then please provide a link to the specification. Otherwise other devs are going to wonder about the special variable names (such as shif).

if(rnd &lt; 16){


Branching is relatively slow on modern processors. This is why you see the unrolled loops that you've coiled up again. To get speed, you want to perform operations chunks by buffering a chunk at a time. Then you want to have the code run as fast as possible.

Fortunately you are using else if which makes it ever so slightly more performant. Over a few runs, the branching should become predictable and a good runtime should make it run faster.

You are returning the result as bytes, which is how it should be. Don't forget to test your code against the official test vectors, and add tests for your own edge cases or your MD5 may still result in a wrong value.

Your code looks fine if you just want to get a feel of what MD5 - a relatively simple crypto hash - looks like. It's good practice. But now you may want to proceed and see what it takes to make it efficient - and unroll your own code yourself.