317

There are many MD5 JavaScript implementations out there. Does anybody know which one is the most advanced, most bugfixed and fastest?

I need it for this tool.

10
  • 4
    Why do you need a "fast" MD5 implementation? Commented Oct 31, 2009 at 22:39
  • 12
    @AnthonyWJones is there a need for any other type of md5 function? It's not like a "slow" md5 function really serves any purpose.. does it? Commented Mar 2, 2013 at 21:31
  • 6
    @LeeOlayvar The slower a cryptography function is, the longer it would take to bruteforce a given hash using that function. Commented May 7, 2013 at 13:00
  • 58
    @MathiasBynens Yes but by design, md5 is a fast hash. That is to say, it's designed to consume large amounts of data and output a hash very, very fast. This is essentially the last thing you want for storing secure data such as passwords/etc, and is better suited/designed for identifying data. Slow hashes on the otherhand, are designed to be slow from the ground up. Brute forcing a slow hash, with a large work value, is not an easy task. As such, slow hashes are ideal for passwords. MD5 is bad for passwords in many (most?) cases. I'm not an expert in this field, so take this with salt. :) Commented May 7, 2013 at 16:55
  • 21
    Yes, but as there is a spec that mandates what an MD5 hash looks like, it does not matter whether you compute it quickly or slowly. The end result is the same and will be equally as difficult / easy to bruteforce. So it does make sense to use the fastest implementation. Commented Jul 19, 2014 at 19:46

21 Answers 21

207

I've heard Joseph's Myers implementation is quite fast. Additionally, he has a lengthy article on Javascript optimization describing what he learned while writing his implementation. It's a good read for anyone interested in performant javascript.

http://www.webreference.com/programming/javascript/jkm3/

His MD5 implementation can be found here

7
  • 13
    A demonstration of this md5 library can be found here: jsfiddle.net/v28gq Commented Jan 21, 2013 at 13:10
  • 20
    What is the licence for Myers' code? He doesn't indicate that it is licenced (or not) on his website as far as I can tell.
    – JeroenHoek
    Commented Jul 11, 2013 at 15:36
  • 30
    It bothers me that this implementation creates a bunch of global functions, so I wrapped the whole thing in a closure, made each function a variable and assigned the md5 function to the window object. This is obviously assuming there is a window object, but it will keep all of the supporting functions private. I'm not sure how ( if at all ) this will effect performance, but it should be much safer for use in large applications. gist.github.com/jhoff/7680711
    – jhoff
    Commented Nov 27, 2013 at 18:27
  • 4
    Agree with jhoff. It also bothers me that this implementation fails jshint miserably, has incorrect indentation and throws errors in strict mode. Aside from the extra hour cleaning up the mess, this implementation performs well Commented May 13, 2014 at 22:03
  • 6
    @jhoff Your Gist has been forked and improved a couple times, I also think that the var add32 on line 185 should be just add32 so I found the best fork I could and updated it to this new version: gist.github.com/MichaelPote/3f0cefaaa9578d7e30be
    – Mikepote
    Commented Dec 3, 2015 at 10:36
91

I would suggest you use CryptoJS in this case.

Basically CryptoJS is a growing collection of standard and secure cryptographic algorithms implemented in JavaScript using best practices and patterns. They are fast, and they have a consistent and simple interface.

So if you want to calculate the MD5 hash of your password string then do as follows:

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/core.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/md5.js"></script>
<script>
    var passhash = CryptoJS.MD5(password).toString();

    $.post(
      'includes/login.php', 
      { user: username, pass: passhash },
      onLogin, 
      'json' );
</script>

So this script will post the hash of your password string to the server.

For further info and support on other hash calculating algorithms you can visit:

http://code.google.com/p/crypto-js/

9
  • 87
    You should not be using md5 for passwords. Commented Feb 28, 2015 at 10:04
  • 4
    Looks like this will be orphaned before long, still on "google code". No one maintaining?
    – MrYellow
    Commented Jun 21, 2015 at 22:41
  • 3
    md5 is fast and if someone cracks your site and your db & code is leaked you can always generate db with hashes and decode passwords. Give me your live database with 10M users & code. I will have fun with that and post on the internet my decoded results. Cheers. Commented Dec 27, 2015 at 22:46
  • 2
    The link leads to a 404 Page now Commented Aug 12, 2016 at 21:32
  • 3
64

My favorite md5

This one is 42 lines long, fits in 120 characters horizontally, and looks good. Is it fast? Well - it's fast enough and it's approximately the same as all other JS implementations. But it's just oddly satisfying to look at all those nicely aligned columns. Don't deny.

NOTE: input should be a string
In practice, numbers and arrays will work (since 2023 feb 20, thank you Andreas Riedmüller), but objects will always return the same md5 every time. To support objects, add a line with JSON.stringify; I didn't because md5 is designed for strings.

//  Formatted version of a popular md5 implementation
//  Original copyright (c) Paul Johnston & Greg Holt.
//  The function itself is now 42 lines long.

function md5(inputString) {
    var hc="0123456789abcdef";
    function rh(n) {var j,s="";for(j=0;j<=3;j++) s+=hc.charAt((n>>(j*8+4))&0x0F)+hc.charAt((n>>(j*8))&0x0F);return s;}
    function ad(x,y) {var l=(x&0xFFFF)+(y&0xFFFF);var m=(x>>16)+(y>>16)+(l>>16);return (m<<16)|(l&0xFFFF);}
    function rl(n,c)            {return (n<<c)|(n>>>(32-c));}
    function cm(q,a,b,x,s,t)    {return ad(rl(ad(ad(a,q),ad(x,t)),s),b);}
    function ff(a,b,c,d,x,s,t)  {return cm((b&c)|((~b)&d),a,b,x,s,t);}
    function gg(a,b,c,d,x,s,t)  {return cm((b&d)|(c&(~d)),a,b,x,s,t);}
    function hh(a,b,c,d,x,s,t)  {return cm(b^c^d,a,b,x,s,t);}
    function ii(a,b,c,d,x,s,t)  {return cm(c^(b|(~d)),a,b,x,s,t);}
    function sb(x) {
        var i;var nblk=((x.length+8)>>6)+1;var blks=new Array(nblk*16);for(i=0;i<nblk*16;i++) blks[i]=0;
        for(i=0;i<x.length;i++) blks[i>>2]|=x.charCodeAt(i)<<((i%4)*8);
        blks[i>>2]|=0x80<<((i%4)*8);blks[nblk*16-2]=x.length*8;return blks;
    }
    var i,x=sb(""+inputString),a=1732584193,b=-271733879,c=-1732584194,d=271733878,olda,oldb,oldc,oldd;
    for(i=0;i<x.length;i+=16) {olda=a;oldb=b;oldc=c;oldd=d;
        a=ff(a,b,c,d,x[i+ 0], 7, -680876936);d=ff(d,a,b,c,x[i+ 1],12, -389564586);c=ff(c,d,a,b,x[i+ 2],17,  606105819);
        b=ff(b,c,d,a,x[i+ 3],22,-1044525330);a=ff(a,b,c,d,x[i+ 4], 7, -176418897);d=ff(d,a,b,c,x[i+ 5],12, 1200080426);
        c=ff(c,d,a,b,x[i+ 6],17,-1473231341);b=ff(b,c,d,a,x[i+ 7],22,  -45705983);a=ff(a,b,c,d,x[i+ 8], 7, 1770035416);
        d=ff(d,a,b,c,x[i+ 9],12,-1958414417);c=ff(c,d,a,b,x[i+10],17,     -42063);b=ff(b,c,d,a,x[i+11],22,-1990404162);
        a=ff(a,b,c,d,x[i+12], 7, 1804603682);d=ff(d,a,b,c,x[i+13],12,  -40341101);c=ff(c,d,a,b,x[i+14],17,-1502002290);
        b=ff(b,c,d,a,x[i+15],22, 1236535329);a=gg(a,b,c,d,x[i+ 1], 5, -165796510);d=gg(d,a,b,c,x[i+ 6], 9,-1069501632);
        c=gg(c,d,a,b,x[i+11],14,  643717713);b=gg(b,c,d,a,x[i+ 0],20, -373897302);a=gg(a,b,c,d,x[i+ 5], 5, -701558691);
        d=gg(d,a,b,c,x[i+10], 9,   38016083);c=gg(c,d,a,b,x[i+15],14, -660478335);b=gg(b,c,d,a,x[i+ 4],20, -405537848);
        a=gg(a,b,c,d,x[i+ 9], 5,  568446438);d=gg(d,a,b,c,x[i+14], 9,-1019803690);c=gg(c,d,a,b,x[i+ 3],14, -187363961);
        b=gg(b,c,d,a,x[i+ 8],20, 1163531501);a=gg(a,b,c,d,x[i+13], 5,-1444681467);d=gg(d,a,b,c,x[i+ 2], 9,  -51403784);
        c=gg(c,d,a,b,x[i+ 7],14, 1735328473);b=gg(b,c,d,a,x[i+12],20,-1926607734);a=hh(a,b,c,d,x[i+ 5], 4,    -378558);
        d=hh(d,a,b,c,x[i+ 8],11,-2022574463);c=hh(c,d,a,b,x[i+11],16, 1839030562);b=hh(b,c,d,a,x[i+14],23,  -35309556);
        a=hh(a,b,c,d,x[i+ 1], 4,-1530992060);d=hh(d,a,b,c,x[i+ 4],11, 1272893353);c=hh(c,d,a,b,x[i+ 7],16, -155497632);
        b=hh(b,c,d,a,x[i+10],23,-1094730640);a=hh(a,b,c,d,x[i+13], 4,  681279174);d=hh(d,a,b,c,x[i+ 0],11, -358537222);
        c=hh(c,d,a,b,x[i+ 3],16, -722521979);b=hh(b,c,d,a,x[i+ 6],23,   76029189);a=hh(a,b,c,d,x[i+ 9], 4, -640364487);
        d=hh(d,a,b,c,x[i+12],11, -421815835);c=hh(c,d,a,b,x[i+15],16,  530742520);b=hh(b,c,d,a,x[i+ 2],23, -995338651);
        a=ii(a,b,c,d,x[i+ 0], 6, -198630844);d=ii(d,a,b,c,x[i+ 7],10, 1126891415);c=ii(c,d,a,b,x[i+14],15,-1416354905);
        b=ii(b,c,d,a,x[i+ 5],21,  -57434055);a=ii(a,b,c,d,x[i+12], 6, 1700485571);d=ii(d,a,b,c,x[i+ 3],10,-1894986606);
        c=ii(c,d,a,b,x[i+10],15,   -1051523);b=ii(b,c,d,a,x[i+ 1],21,-2054922799);a=ii(a,b,c,d,x[i+ 8], 6, 1873313359);
        d=ii(d,a,b,c,x[i+15],10,  -30611744);c=ii(c,d,a,b,x[i+ 6],15,-1560198380);b=ii(b,c,d,a,x[i+13],21, 1309151649);
        a=ii(a,b,c,d,x[i+ 4], 6, -145523070);d=ii(d,a,b,c,x[i+11],10,-1120210379);c=ii(c,d,a,b,x[i+ 2],15,  718787259);
        b=ii(b,c,d,a,x[i+ 9],21, -343485551);a=ad(a,olda);b=ad(b,oldb);c=ad(c,oldc);d=ad(d,oldd);
    }
    return rh(a)+rh(b)+rh(c)+rh(d);
}

Another absolutely irrelevant fact: it's 4000 bytes long. It may seem pointless but it feels good to just know. You look at it and you know. You belong to the secret club of Those Who Just Know. Life will never be the same. Trust me.

Also, thank you Paul Johnston and Greg Holt.
And Douglas Adams, for all the fish.

Stackblitz demo

7
  • 2
    @dkelner Cool. I'd like to copy/paste your function to use in my app. Please could you grant a licence
    – pinoyyid
    Commented Jun 20, 2020 at 10:03
  • 3
    There's no need, it's absolutely free to use, it's a derived work from another free implementation. So just use it and maybe comment the authors like I did.
    – dkellner
    Commented Jun 20, 2020 at 10:14
  • 1
    Hoep you don't mind but I added a Stackblitz demo link to your answer
    – Eonasdan
    Commented Jul 8, 2022 at 13:03
  • 1
    Here's Typescript class translation, linted, with a unit test jsfiddle.net/y3sh/653ejsqL/2 Commented Aug 18, 2022 at 20:32
  • 1
    Just a heads up: If you pass a Number you will always get the same hash no matter what number you use. Be sure to make it a string first! Commented Feb 17, 2023 at 13:11
61

Node.js has built-in support

const crypto = require('crypto')
crypto.createHash('md5').update('hello world').digest('hex')

Code snippet above computes MD5 hex string for string hello world

The advantage of this solution is you don't need to install additional library.

I think built in solution should be the fastest. If not, we should create issue/PR for the Node.js project.

5
  • 2
    This should be higher up. Commented Jan 12, 2022 at 12:06
  • 1
    The problem is that this solution throws Uncaught ReferenceError: require is not defined in browser consoles so it does not really work..
    – Taureon
    Commented Nov 6, 2022 at 22:59
  • 3
    @Taureon, the answer was written for Node.js. To use this feature in browser, I believe you can take advantage of webpack, to bundle the Node.js code for browser.
    – Tyler Liu
    Commented Nov 7, 2022 at 19:31
  • @TylerLiu but is there a solution that does not require webpack?
    – Taureon
    Commented Nov 10, 2022 at 19:34
  • 1
    @Taureon the solution I posted is for Node.js. I am unaware of a way to make it work in browser easily.
    – Tyler Liu
    Commented Nov 10, 2022 at 22:47
38

While selecting library it's also important to see if it supports modern frameworks such as Bower, passes jslint, supports plugin model for JQuery or module systems such as AMD/RequireJS in addition to being in active development and have more than 1 contributors. There are couple of options that satisfies some or all of these additional criteria:

  • CryptoJS: This is perhaps the most expansive library where each algorithm can be used separately without adding fat in to your JS code. Plus it as encoder/decoders for UTF8, UTF16 and Base64. I maintain github repository that is registered as Bower package plus instructions on how to use it with RequireJS.
  • Spark MD5: This is based on JKM code that other answer mentions which is also the faster implementation. However in addition, Spark implementation adds AMD support, passes jslint plus has incremental mode. It doesn't have Base64 o/p but it does have raw o/p (i.e. array of 32-bit int insead of string).
  • JQuery MD5 plugin: Very simple down to earth but doesn't seem to have raw mode.
  • JavaScript-MD5: Not as fancy or fast as Spark but simpler.

Example from CryptoJS:

//just include md5.js from the CryptoJS rollups folder
var hash = CryptoJS.MD5("Message");
console.log(hash.toString()); 

There is a performance comparison between above libraries at http://jsperf.com/md5-shootout/7. On my machine current tests (which are admittedly old) shows that if you are looking for speed Spark MD5 is your best bet (and so is plain JKM code). However if you looking for more comprehensive library then CryptoJS is your best bet although it is 79% slower than Spark MD5. However I would imagine CryptoJS would eventually achieve same speed as it is bit more active project.

2
  • The link to "jQuery MD5 plugin" leads me to a malware site. Eep!
    – Raffi
    Commented Oct 17, 2017 at 21:46
  • 1
    Looks like original website for jQuery MD5 plugin got shutdown and its now redirects to generic domain seller. I've updated to plugin hosted in GitHub now. Commented Oct 20, 2017 at 20:25
31

As of 2020 the fastest MD5 implementation is probably written in WASM (Web Assembly).

hash-wasm is a library that implements MD5 hash in WASM.

You can find the benchmarks here.

You can either install it with npm:

npm i hash-wasm

or just add a script tag

<script src="https://cdn.jsdelivr.net/npm/hash-wasm"></script>

then use the hashwasm global variable.

Example:

async function run() {
  console.log('MD5:', await hashwasm.md5('The quick brown fox jumps over the lazy dog'));
}

run();

outputs

MD5: 9e107d9d372bb6826bd81d3542a419d6

async function run() {
  console.log('MD5:', await hashwasm.md5('The quick brown fox jumps over the lazy dog'));
}

run();
<script src="https://cdn.jsdelivr.net/npm/hash-wasm"></script>

1
27

I really can't remember where did I get this from.. I searched everywhere on the net and the only references I find are from this post. Strange. If anyone has infos about this implementation origin, let me know.

Or you can try this new one which is 25% faster: https://stackoverflow.com/a/74186696/236062 :D

MD5 = function(e) {
    function h(a, b) {
        var c, d, e, f, g;
        e = a & 2147483648;
        f = b & 2147483648;
        c = a & 1073741824;
        d = b & 1073741824;
        g = (a & 1073741823) + (b & 1073741823);
        return c & d ? g ^ 2147483648 ^ e ^ f : c | d ? g & 1073741824 ? g ^ 3221225472 ^ e ^ f : g ^ 1073741824 ^ e ^ f : g ^ e ^ f
    }

    function k(a, b, c, d, e, f, g) {
        a = h(a, h(h(b & c | ~b & d, e), g));
        return h(a << f | a >>> 32 - f, b)
    }

    function l(a, b, c, d, e, f, g) {
        a = h(a, h(h(b & d | c & ~d, e), g));
        return h(a << f | a >>> 32 - f, b)
    }

    function m(a, b, d, c, e, f, g) {
        a = h(a, h(h(b ^ d ^ c, e), g));
        return h(a << f | a >>> 32 - f, b)
    }

    function n(a, b, d, c, e, f, g) {
        a = h(a, h(h(d ^ (b | ~c), e), g));
        return h(a << f | a >>> 32 - f, b)
    }

    function p(a) {
        var b = "",
            d = "",
            c;
        for (c = 0; 3 >= c; c++) d = a >>> 8 * c & 255, d = "0" + d.toString(16), b += d.substr(d.length - 2, 2);
        return b
    }
    var f = [],
        q, r, s, t, a, b, c, d;
    e = function(a) {
        a = a.replace(/\r\n/g, "\n");
        for (var b = "", d = 0; d < a.length; d++) {
            var c = a.charCodeAt(d);
            128 > c ? b += String.fromCharCode(c) : (127 < c && 2048 > c ? b += String.fromCharCode(c >> 6 | 192) : (b += String.fromCharCode(c >> 12 | 224), b += String.fromCharCode(c >> 6 & 63 | 128)), b += String.fromCharCode(c & 63 | 128))
        }
        return b
    }(e);
    f = function(b) {
        var a, c = b.length;
        a = c + 8;
        for (var d = 16 * ((a - a % 64) / 64 + 1), e = Array(d - 1), f = 0, g = 0; g < c;) a = (g - g % 4) / 4, f = g % 4 * 8, e[a] |= b.charCodeAt(g) << f, g++;
        a = (g - g % 4) / 4;
        e[a] |= 128 << g % 4 * 8;
        e[d - 2] = c << 3;
        e[d - 1] = c >>> 29;
        return e
    }(e);
    a = 1732584193;
    b = 4023233417;
    c = 2562383102;
    d = 271733878;
    for (e = 0; e < f.length; e += 16) q = a, r = b, s = c, t = d, a = k(a, b, c, d, f[e + 0], 7, 3614090360), d = k(d, a, b, c, f[e + 1], 12, 3905402710), c = k(c, d, a, b, f[e + 2], 17, 606105819), b = k(b, c, d, a, f[e + 3], 22, 3250441966), a = k(a, b, c, d, f[e + 4], 7, 4118548399), d = k(d, a, b, c, f[e + 5], 12, 1200080426), c = k(c, d, a, b, f[e + 6], 17, 2821735955), b = k(b, c, d, a, f[e + 7], 22, 4249261313), a = k(a, b, c, d, f[e + 8], 7, 1770035416), d = k(d, a, b, c, f[e + 9], 12, 2336552879), c = k(c, d, a, b, f[e + 10], 17, 4294925233), b = k(b, c, d, a, f[e + 11], 22, 2304563134), a = k(a, b, c, d, f[e + 12], 7, 1804603682), d = k(d, a, b, c, f[e + 13], 12, 4254626195), c = k(c, d, a, b, f[e + 14], 17, 2792965006), b = k(b, c, d, a, f[e + 15], 22, 1236535329), a = l(a, b, c, d, f[e + 1], 5, 4129170786), d = l(d, a, b, c, f[e + 6], 9, 3225465664), c = l(c, d, a, b, f[e + 11], 14, 643717713), b = l(b, c, d, a, f[e + 0], 20, 3921069994), a = l(a, b, c, d, f[e + 5], 5, 3593408605), d = l(d, a, b, c, f[e + 10], 9, 38016083), c = l(c, d, a, b, f[e + 15], 14, 3634488961), b = l(b, c, d, a, f[e + 4], 20, 3889429448), a = l(a, b, c, d, f[e + 9], 5, 568446438), d = l(d, a, b, c, f[e + 14], 9, 3275163606), c = l(c, d, a, b, f[e + 3], 14, 4107603335), b = l(b, c, d, a, f[e + 8], 20, 1163531501), a = l(a, b, c, d, f[e + 13], 5, 2850285829), d = l(d, a, b, c, f[e + 2], 9, 4243563512), c = l(c, d, a, b, f[e + 7], 14, 1735328473), b = l(b, c, d, a, f[e + 12], 20, 2368359562), a = m(a, b, c, d, f[e + 5], 4, 4294588738), d = m(d, a, b, c, f[e + 8], 11, 2272392833), c = m(c, d, a, b, f[e + 11], 16, 1839030562), b = m(b, c, d, a, f[e + 14], 23, 4259657740), a = m(a, b, c, d, f[e + 1], 4, 2763975236), d = m(d, a, b, c, f[e + 4], 11, 1272893353), c = m(c, d, a, b, f[e + 7], 16, 4139469664), b = m(b, c, d, a, f[e + 10], 23, 3200236656), a = m(a, b, c, d, f[e + 13], 4, 681279174), d = m(d, a, b, c, f[e + 0], 11, 3936430074), c = m(c, d, a, b, f[e + 3], 16, 3572445317), b = m(b, c, d, a, f[e + 6], 23, 76029189), a = m(a, b, c, d, f[e + 9], 4, 3654602809), d = m(d, a, b, c, f[e + 12], 11, 3873151461), c = m(c, d, a, b, f[e + 15], 16, 530742520), b = m(b, c, d, a, f[e + 2], 23, 3299628645), a = n(a, b, c, d, f[e + 0], 6, 4096336452), d = n(d, a, b, c, f[e + 7], 10, 1126891415), c = n(c, d, a, b, f[e + 14], 15, 2878612391), b = n(b, c, d, a, f[e + 5], 21, 4237533241), a = n(a, b, c, d, f[e + 12], 6, 1700485571), d = n(d, a, b, c, f[e + 3], 10, 2399980690), c = n(c, d, a, b, f[e + 10], 15, 4293915773), b = n(b, c, d, a, f[e + 1], 21, 2240044497), a = n(a, b, c, d, f[e + 8], 6, 1873313359), d = n(d, a, b, c, f[e + 15], 10, 4264355552), c = n(c, d, a, b, f[e + 6], 15, 2734768916), b = n(b, c, d, a, f[e + 13], 21, 1309151649), a = n(a, b, c, d, f[e + 4], 6, 4149444226), d = n(d, a, b, c, f[e + 11], 10, 3174756917), c = n(c, d, a, b, f[e + 2], 15, 718787259), b = n(b, c, d, a, f[e + 9], 21, 3951481745), a = h(a, q), b = h(b, r), c = h(c, s), d = h(d, t);
    return (p(a) + p(b) + p(c) + p(d)).toLowerCase()
};
<!DOCTYPE html>
<html>
<body onload="md5.value=MD5(a.value);">

<form oninput="md5.value=MD5(a.value)">Enter String:
<input type="string" id="a" name="a" value="https://www.zibri.org"></br></br>MD5:<output id="md5" name="md5" for="a"></output>
</form>

</body>
</html>

7
  • but it seems the fastest implementation is this one: myersdaily.org/joseph/javascript/jkm-md5.js
    – Zibri
    Commented Jun 2, 2019 at 8:23
  • this link doesn't work myersdaily.org/joseph/javascript/jkm-md5.js
    – Giggs
    Commented Jan 8, 2020 at 8:32
  • 1
    @Giggs just use google and you will find it: pajhome.org.uk/crypt/md5/contrib/jkm-md5.js
    – Zibri
    Commented Jan 9, 2020 at 9:27
  • Thanks man. This works really efficiently. However, I'm sure if am the only one who isn' t getting this right. How do I decrypt? Commented Aug 31, 2021 at 10:04
  • 3
    @MpwanyiSamuel yes, you are. MD5 is a hashing algorythm. you don't "decrypt it"
    – Zibri
    Commented Aug 31, 2021 at 16:33
7

I only need to support HTML5 browsers that support typed arrays (DataView, ArrayBuffer, etc.) I think I took the Joseph Myers code and modified it to support passing in a Uint8Array. I did not catch all the improvements, and there are still probably some char() array artifacts that can be improved on. I needed this for adding to the PouchDB project.

var PouchUtils = {};
PouchUtils.Crypto = {};
(function () {
    PouchUtils.Crypto.MD5 = function (uint8Array) {
        function md5cycle(x, k) {
            var a = x[0], b = x[1], c = x[2], d = x[3];

            a = ff(a, b, c, d, k[0], 7, -680876936);
            d = ff(d, a, b, c, k[1], 12, -389564586);
            c = ff(c, d, a, b, k[2], 17, 606105819);
            b = ff(b, c, d, a, k[3], 22, -1044525330);
            a = ff(a, b, c, d, k[4], 7, -176418897);
            d = ff(d, a, b, c, k[5], 12, 1200080426);
            c = ff(c, d, a, b, k[6], 17, -1473231341);
            b = ff(b, c, d, a, k[7], 22, -45705983);
            a = ff(a, b, c, d, k[8], 7, 1770035416);
            d = ff(d, a, b, c, k[9], 12, -1958414417);
            c = ff(c, d, a, b, k[10], 17, -42063);
            b = ff(b, c, d, a, k[11], 22, -1990404162);
            a = ff(a, b, c, d, k[12], 7, 1804603682);
            d = ff(d, a, b, c, k[13], 12, -40341101);
            c = ff(c, d, a, b, k[14], 17, -1502002290);
            b = ff(b, c, d, a, k[15], 22, 1236535329);

            a = gg(a, b, c, d, k[1], 5, -165796510);
            d = gg(d, a, b, c, k[6], 9, -1069501632);
            c = gg(c, d, a, b, k[11], 14, 643717713);
            b = gg(b, c, d, a, k[0], 20, -373897302);
            a = gg(a, b, c, d, k[5], 5, -701558691);
            d = gg(d, a, b, c, k[10], 9, 38016083);
            c = gg(c, d, a, b, k[15], 14, -660478335);
            b = gg(b, c, d, a, k[4], 20, -405537848);
            a = gg(a, b, c, d, k[9], 5, 568446438);
            d = gg(d, a, b, c, k[14], 9, -1019803690);
            c = gg(c, d, a, b, k[3], 14, -187363961);
            b = gg(b, c, d, a, k[8], 20, 1163531501);
            a = gg(a, b, c, d, k[13], 5, -1444681467);
            d = gg(d, a, b, c, k[2], 9, -51403784);
            c = gg(c, d, a, b, k[7], 14, 1735328473);
            b = gg(b, c, d, a, k[12], 20, -1926607734);

            a = hh(a, b, c, d, k[5], 4, -378558);
            d = hh(d, a, b, c, k[8], 11, -2022574463);
            c = hh(c, d, a, b, k[11], 16, 1839030562);
            b = hh(b, c, d, a, k[14], 23, -35309556);
            a = hh(a, b, c, d, k[1], 4, -1530992060);
            d = hh(d, a, b, c, k[4], 11, 1272893353);
            c = hh(c, d, a, b, k[7], 16, -155497632);
            b = hh(b, c, d, a, k[10], 23, -1094730640);
            a = hh(a, b, c, d, k[13], 4, 681279174);
            d = hh(d, a, b, c, k[0], 11, -358537222);
            c = hh(c, d, a, b, k[3], 16, -722521979);
            b = hh(b, c, d, a, k[6], 23, 76029189);
            a = hh(a, b, c, d, k[9], 4, -640364487);
            d = hh(d, a, b, c, k[12], 11, -421815835);
            c = hh(c, d, a, b, k[15], 16, 530742520);
            b = hh(b, c, d, a, k[2], 23, -995338651);

            a = ii(a, b, c, d, k[0], 6, -198630844);
            d = ii(d, a, b, c, k[7], 10, 1126891415);
            c = ii(c, d, a, b, k[14], 15, -1416354905);
            b = ii(b, c, d, a, k[5], 21, -57434055);
            a = ii(a, b, c, d, k[12], 6, 1700485571);
            d = ii(d, a, b, c, k[3], 10, -1894986606);
            c = ii(c, d, a, b, k[10], 15, -1051523);
            b = ii(b, c, d, a, k[1], 21, -2054922799);
            a = ii(a, b, c, d, k[8], 6, 1873313359);
            d = ii(d, a, b, c, k[15], 10, -30611744);
            c = ii(c, d, a, b, k[6], 15, -1560198380);
            b = ii(b, c, d, a, k[13], 21, 1309151649);
            a = ii(a, b, c, d, k[4], 6, -145523070);
            d = ii(d, a, b, c, k[11], 10, -1120210379);
            c = ii(c, d, a, b, k[2], 15, 718787259);
            b = ii(b, c, d, a, k[9], 21, -343485551);

            x[0] = add32(a, x[0]);
            x[1] = add32(b, x[1]);
            x[2] = add32(c, x[2]);
            x[3] = add32(d, x[3]);

        }

        function cmn(q, a, b, x, s, t) {
            a = add32(add32(a, q), add32(x, t));
            return add32((a << s) | (a >>> (32 - s)), b);
        }

        function ff(a, b, c, d, x, s, t) {
            return cmn((b & c) | ((~b) & d), a, b, x, s, t);
        }

        function gg(a, b, c, d, x, s, t) {
            return cmn((b & d) | (c & (~d)), a, b, x, s, t);
        }

        function hh(a, b, c, d, x, s, t) {
            return cmn(b ^ c ^ d, a, b, x, s, t);
        }

        function ii(a, b, c, d, x, s, t) {
            return cmn(c ^ (b | (~d)), a, b, x, s, t);
        }

        function md51(s) {
            txt = '';
            var n = s.length,
            state = [1732584193, -271733879, -1732584194, 271733878], i;
            for (i = 64; i <= s.length; i += 64) {
                md5cycle(state, md5blk(s.subarray(i - 64, i)));
            }
            s = s.subarray(i - 64);
            var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
            for (i = 0; i < s.length; i++)
                tail[i >> 2] |= s[i] << ((i % 4) << 3);
            tail[i >> 2] |= 0x80 << ((i % 4) << 3);
            if (i > 55) {
                md5cycle(state, tail);
                for (i = 0; i < 16; i++) tail[i] = 0;
            }
            tail[14] = n * 8;
            md5cycle(state, tail);
            return state;
        }

        /* there needs to be support for Unicode here,
         * unless we pretend that we can redefine the MD-5
         * algorithm for multi-byte characters (perhaps
         * by adding every four 16-bit characters and
         * shortening the sum to 32 bits). Otherwise
         * I suggest performing MD-5 as if every character
         * was two bytes--e.g., 0040 0025 = @%--but then
         * how will an ordinary MD-5 sum be matched?
         * There is no way to standardize text to something
         * like UTF-8 before transformation; speed cost is
         * utterly prohibitive. The JavaScript standard
         * itself needs to look at this: it should start
         * providing access to strings as preformed UTF-8
         * 8-bit unsigned value arrays.
         */
        function md5blk(s) { /* I figured global was faster.   */
            var md5blks = [], i; /* Andy King said do it this way. */
            for (i = 0; i < 64; i += 4) {
                md5blks[i >> 2] = s[i]
                + (s[i + 1] << 8)
                + (s[i + 2] << 16)
                + (s[i + 3] << 24);
            }
            return md5blks;
        }

        var hex_chr = '0123456789abcdef'.split('');

        function rhex(n) {
            var s = '', j = 0;
            for (; j < 4; j++)
                s += hex_chr[(n >> (j * 8 + 4)) & 0x0F]
                + hex_chr[(n >> (j * 8)) & 0x0F];
            return s;
        }

        function hex(x) {
            for (var i = 0; i < x.length; i++)
                x[i] = rhex(x[i]);
            return x.join('');
        }

        function md5(s) {
            return hex(md51(s));
        }

        function add32(a, b) {
            return (a + b) & 0xFFFFFFFF;
        }

        return md5(uint8Array);
    };
})();
2
  • 1
    I am interested in total system performance, So my demo includes xhr2 downloads and PouchDB (IDB) stores. You can try it and see the performance results at codepen.io/DrYSG/pen/kdzft . What I would like a MD5 algorithm person to look at is the add32() and md5blks() functions and see if they can't be sped up by binary typed arrays Uint32Array()
    – Dr.YSG
    Commented Aug 21, 2013 at 11:55
  • 1
    What txt = '' does actually mean? Commented Nov 24, 2016 at 13:43
6

Currently the fastest implementation of md5 (based on Joseph Myers' code):

https://github.com/iReal/FastMD5

jsPerf comparaison: http://jsperf.com/md5-shootout/63

1
  • 3
    link is not found (404)
    – Mechanic
    Commented Aug 20, 2020 at 22:24
6

I wrote tests to compare several JavaScript hash implementations, including most MD5 implementations mentioned here. To run the tests, go to http://brillout.github.io/test-javascript-hash-implementations/ and wait a bit.

It seems that the YaMD5 implementation of R. Hill's answer is the fastest.

1
  • Thank you for the great benchmark!! YaMD5 with wide characters seems slow, so I will stick to FastMD5 for generic usage. Commented Apr 9, 2017 at 11:31
4

It bothered me that I could not find an implementation which is both fast and support Unicode strings.

So I made one which supports Unicode strings and still shows as faster (at time of writing) than the currently fastest ascii-only-strings implementations:

https://github.com/gorhill/yamd5.js

Based on Joseph Myers' code, but uses TypedArrays, plus other improvements.

1
  • Kudos to you. This is actually the only so far I found that yields the exact same hash as the md5 utility on a Unix server. Well done indeed.
    – Jacques
    Commented Nov 23, 2018 at 10:37
3

Here we go with another one which is 25% faster than my previous one :D

function MD5(r) {
var o, e, n, f = [ -680876936, -389564586, 606105819, -1044525330, -176418897, 1200080426, -1473231341, -45705983, 1770035416, -1958414417, -42063, -1990404162, 1804603682, -40341101, -1502002290, 1236535329, -165796510, -1069501632, 643717713, -373897302, -701558691, 38016083, -660478335, -405537848, 568446438, -1019803690, -187363961, 1163531501, -1444681467, -51403784, 1735328473, -1926607734, -378558, -2022574463, 1839030562, -35309556, -1530992060, 1272893353, -155497632, -1094730640, 681279174, -358537222, -722521979, 76029189, -640364487, -421815835, 530742520, -995338651, -198630844, 1126891415, -1416354905, -57434055, 1700485571, -1894986606, -1051523, -2054922799, 1873313359, -30611744, -1560198380, 1309151649, -145523070, -1120210379, 718787259, -343485551 ], t = [ o = 1732584193, e = 4023233417, ~o, ~e ], c = [], a = unescape(encodeURI(r)) + "\u0080", d = a.length;
for (r = --d / 4 + 2 | 15, c[--r] = 8 * d; ~d; ) c[d >> 2] |= a.charCodeAt(d) << 8 * d--;
for (i = a = 0; i < r; i += 16) {
    for (d = t; 64 > a; d = [ n = d[3], o + ((n = d[0] + [ o & e | ~o & n, n & o | ~n & e, o ^ e ^ n, e ^ (o | ~n) ][d = a >> 4] + f[a] + ~~c[i | 15 & [ a, 5 * a + 1, 3 * a + 5, 7 * a ][d]]) << (d = [ 7, 12, 17, 22, 5, 9, 14, 20, 4, 11, 16, 23, 6, 10, 15, 21 ][4 * d + a++ % 4]) | n >>> -d), o, e ]) o = 0 | d[1], 
    e = d[2];
    for (a = 4; a; ) t[--a] += d[a];
}
for (r = ""; 32 > a; ) r += (t[a >> 3] >> 4 * (1 ^ a++) & 15).toString(16);
return r;
}
<!DOCTYPE html>
<html>
<body onload="md5.value=MD5(a.value);">

<form oninput="md5.value=MD5(a.value)">Enter String:
<input type="string" id="a" name="a" value="https://www.zibri.org"></br></br>MD5:<output id="md5" name="md5" for="a"></output>
</form>

</body>
</html>

2

js-md5 supports UTF-8 string, array, ArrayBuffer, AMD....

and fast. jsperf

2

Here's the ES6 version of the md5 implementation by @dkellner and @Eonasdan:

const md5 = inputString => {
   const hc = '0123456789abcdef';
   const rh = n => {let j,s='';for(j=0;j<=3;j++) s+=hc.charAt((n>>(j*8+4))&0x0F)+hc.charAt((n>>(j*8))&0x0F);return s;}
   const ad = (x,y) => {let l=(x&0xFFFF)+(y&0xFFFF);let m=(x>>16)+(y>>16)+(l>>16);return (m<<16)|(l&0xFFFF);}
   const rl = (n,c) => (n<<c)|(n>>>(32-c));
   const cm = (q,a,b,x,s,t) => ad(rl(ad(ad(a,q),ad(x,t)),s),b);
   const ff = (a,b,c,d,x,s,t) => cm((b&c)|((~b)&d),a,b,x,s,t);
   const gg = (a,b,c,d,x,s,t) => cm((b&d)|(c&(~d)),a,b,x,s,t);
   const hh = (a,b,c,d,x,s,t) => cm(b^c^d,a,b,x,s,t);
   const ii = (a,b,c,d,x,s,t) => cm(c^(b|(~d)),a,b,x,s,t);
   const sb = x => {
      let i;const nblk=((x.length+8)>>6)+1;const blks=[];for(i=0;i<nblk*16;i++) { blks[i]=0 };
      for(i=0;i<x.length;i++) {blks[i>>2]|=x.charCodeAt(i)<<((i%4)*8);}
      blks[i>>2]|=0x80<<((i%4)*8);blks[nblk*16-2]=x.length*8;return blks;
   }
   let i,x=sb(inputString),a=1732584193,b=-271733879,c=-1732584194,d=271733878,olda,oldb,oldc,oldd;
   for(i=0;i<x.length;i+=16) {olda=a;oldb=b;oldc=c;oldd=d;
      a=ff(a,b,c,d,x[i+ 0], 7, -680876936);d=ff(d,a,b,c,x[i+ 1],12, -389564586);c=ff(c,d,a,b,x[i+ 2],17,  606105819);
      b=ff(b,c,d,a,x[i+ 3],22,-1044525330);a=ff(a,b,c,d,x[i+ 4], 7, -176418897);d=ff(d,a,b,c,x[i+ 5],12, 1200080426);
      c=ff(c,d,a,b,x[i+ 6],17,-1473231341);b=ff(b,c,d,a,x[i+ 7],22,  -45705983);a=ff(a,b,c,d,x[i+ 8], 7, 1770035416);
      d=ff(d,a,b,c,x[i+ 9],12,-1958414417);c=ff(c,d,a,b,x[i+10],17,     -42063);b=ff(b,c,d,a,x[i+11],22,-1990404162);
      a=ff(a,b,c,d,x[i+12], 7, 1804603682);d=ff(d,a,b,c,x[i+13],12,  -40341101);c=ff(c,d,a,b,x[i+14],17,-1502002290);
      b=ff(b,c,d,a,x[i+15],22, 1236535329);a=gg(a,b,c,d,x[i+ 1], 5, -165796510);d=gg(d,a,b,c,x[i+ 6], 9,-1069501632);
      c=gg(c,d,a,b,x[i+11],14,  643717713);b=gg(b,c,d,a,x[i+ 0],20, -373897302);a=gg(a,b,c,d,x[i+ 5], 5, -701558691);
      d=gg(d,a,b,c,x[i+10], 9,   38016083);c=gg(c,d,a,b,x[i+15],14, -660478335);b=gg(b,c,d,a,x[i+ 4],20, -405537848);
      a=gg(a,b,c,d,x[i+ 9], 5,  568446438);d=gg(d,a,b,c,x[i+14], 9,-1019803690);c=gg(c,d,a,b,x[i+ 3],14, -187363961);
      b=gg(b,c,d,a,x[i+ 8],20, 1163531501);a=gg(a,b,c,d,x[i+13], 5,-1444681467);d=gg(d,a,b,c,x[i+ 2], 9,  -51403784);
      c=gg(c,d,a,b,x[i+ 7],14, 1735328473);b=gg(b,c,d,a,x[i+12],20,-1926607734);a=hh(a,b,c,d,x[i+ 5], 4,    -378558);
      d=hh(d,a,b,c,x[i+ 8],11,-2022574463);c=hh(c,d,a,b,x[i+11],16, 1839030562);b=hh(b,c,d,a,x[i+14],23,  -35309556);
      a=hh(a,b,c,d,x[i+ 1], 4,-1530992060);d=hh(d,a,b,c,x[i+ 4],11, 1272893353);c=hh(c,d,a,b,x[i+ 7],16, -155497632);
      b=hh(b,c,d,a,x[i+10],23,-1094730640);a=hh(a,b,c,d,x[i+13], 4,  681279174);d=hh(d,a,b,c,x[i+ 0],11, -358537222);
      c=hh(c,d,a,b,x[i+ 3],16, -722521979);b=hh(b,c,d,a,x[i+ 6],23,   76029189);a=hh(a,b,c,d,x[i+ 9], 4, -640364487);
      d=hh(d,a,b,c,x[i+12],11, -421815835);c=hh(c,d,a,b,x[i+15],16,  530742520);b=hh(b,c,d,a,x[i+ 2],23, -995338651);
      a=ii(a,b,c,d,x[i+ 0], 6, -198630844);d=ii(d,a,b,c,x[i+ 7],10, 1126891415);c=ii(c,d,a,b,x[i+14],15,-1416354905);
      b=ii(b,c,d,a,x[i+ 5],21,  -57434055);a=ii(a,b,c,d,x[i+12], 6, 1700485571);d=ii(d,a,b,c,x[i+ 3],10,-1894986606);
      c=ii(c,d,a,b,x[i+10],15,   -1051523);b=ii(b,c,d,a,x[i+ 1],21,-2054922799);a=ii(a,b,c,d,x[i+ 8], 6, 1873313359);
      d=ii(d,a,b,c,x[i+15],10,  -30611744);c=ii(c,d,a,b,x[i+ 6],15,-1560198380);b=ii(b,c,d,a,x[i+13],21, 1309151649);
      a=ii(a,b,c,d,x[i+ 4], 6, -145523070);d=ii(d,a,b,c,x[i+11],10,-1120210379);c=ii(c,d,a,b,x[i+ 2],15,  718787259);
      b=ii(b,c,d,a,x[i+ 9],21, -343485551);a=ad(a,olda);b=ad(b,oldb);c=ad(c,oldc);d=ad(d,oldd);
   }
   return rh(a)+rh(b)+rh(c)+rh(d);
}
1

Maybe this package was useful
https://www.npmjs.com/package/pure-md5

console.time('latin');
const latin = md5('hello');
console.timeEnd('latin');

console.log('Привет: ', md5('Привет'));
console.log('嘿: ', md5('嘿'));
<script src="https://unpkg.com/pure-md5@latest/lib/index.js"></script>

0

Why not try http://phpjs.org/functions/md5/?

Unfortunately performance is limited with any emulated script, however this can render real md5 hash. Although I would advice against using md5 for passwords, as it is a fast-rendered hash.

0

Much faster hashing should be possible by calculating on graphic card (implement hashing algorithm in WebGL), as discussed there about SHA256: Is it possible to calculate sha256 hashes in the browser using the user's video card, eg. by using WebGL or Flash?

-1

Strongly recommend the SparkMD5, which is support many different type of data to get the md5 and with good performance in most situation. And it has the highest weekly downloads compare to other md5 libs.

Blob data for example:

import SparkMD5 from 'spark-md5'

export async function computeMd5(data: Blob): Promise<string> {
  const buffer = await readAsArrayBuffer(data)
  const spark = new SparkMD5.ArrayBuffer()
  spark.append(buffer)
  return spark.end()
}

In the Chrome v117, better than the js-md5.

1
  • 1
    As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
    – Community Bot
    Commented Sep 23, 2023 at 2:21
-3

You could also check my md5 implementation. It should be approx. the same as the other posted above. Unfortunately, the performance is limited by the inner loop which is impossible to optimize more.

0
-3

The winner for the MD5 benchmark is Javascript-MD5

Test it on https://jsben.ch/imzpt or see on jsfiddle.net/w731ed58/

Benchmark Results

1
  • 1
    No it's not: jsben.ch/Cl5Lc mine is 10% faster :P
    – Zibri
    Commented Oct 25, 2022 at 13:44
-4

If the performance of your application is limited by a Javascript implementation of MD5, then you're really doing something wrong. Consider an architectural change (Hint: use MD5 less often)

1
  • 3
    Im not using MD5 in an "native" application with JS, its a online MD5 check tool: bruechner.de/md5file/js no need of native app for MD5 anymore ;)
    – powtac
    Commented Oct 27, 2011 at 18:08

Not the answer you're looking for? Browse other questions tagged or ask your own question.