Grow your CSS skills. Land your dream job.

Last updated on:

JavaScript MD5

var MD5 = function (string) {

   function RotateLeft(lValue, iShiftBits) {
           return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits));
   }

   function AddUnsigned(lX,lY) {
           var lX4,lY4,lX8,lY8,lResult;
           lX8 = (lX & 0x80000000);
           lY8 = (lY & 0x80000000);
           lX4 = (lX & 0x40000000);
           lY4 = (lY & 0x40000000);
           lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
           if (lX4 & lY4) {
                   return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
           }
           if (lX4 | lY4) {
                   if (lResult & 0x40000000) {
                           return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
                   } else {
                           return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
                   }
           } else {
                   return (lResult ^ lX8 ^ lY8);
           }
   }

   function F(x,y,z) { return (x & y) | ((~x) & z); }
   function G(x,y,z) { return (x & z) | (y & (~z)); }
   function H(x,y,z) { return (x ^ y ^ z); }
   function I(x,y,z) { return (y ^ (x | (~z))); }

   function FF(a,b,c,d,x,s,ac) {
           a = AddUnsigned(a, AddUnsigned(AddUnsigned(F(b, c, d), x), ac));
           return AddUnsigned(RotateLeft(a, s), b);
   };

   function GG(a,b,c,d,x,s,ac) {
           a = AddUnsigned(a, AddUnsigned(AddUnsigned(G(b, c, d), x), ac));
           return AddUnsigned(RotateLeft(a, s), b);
   };

   function HH(a,b,c,d,x,s,ac) {
           a = AddUnsigned(a, AddUnsigned(AddUnsigned(H(b, c, d), x), ac));
           return AddUnsigned(RotateLeft(a, s), b);
   };

   function II(a,b,c,d,x,s,ac) {
           a = AddUnsigned(a, AddUnsigned(AddUnsigned(I(b, c, d), x), ac));
           return AddUnsigned(RotateLeft(a, s), b);
   };

   function ConvertToWordArray(string) {
           var lWordCount;
           var lMessageLength = string.length;
           var lNumberOfWords_temp1=lMessageLength + 8;
           var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
           var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
           var lWordArray=Array(lNumberOfWords-1);
           var lBytePosition = 0;
           var lByteCount = 0;
           while ( lByteCount < lMessageLength ) {
                   lWordCount = (lByteCount-(lByteCount % 4))/4;
                   lBytePosition = (lByteCount % 4)*8;
                   lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount)<<lBytePosition));
                   lByteCount++;
           }
           lWordCount = (lByteCount-(lByteCount % 4))/4;
           lBytePosition = (lByteCount % 4)*8;
           lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
           lWordArray[lNumberOfWords-2] = lMessageLength<<3;
           lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
           return lWordArray;
   };

   function WordToHex(lValue) {
           var WordToHexValue="",WordToHexValue_temp="",lByte,lCount;
           for (lCount = 0;lCount<=3;lCount++) {
                   lByte = (lValue>>>(lCount*8)) & 255;
                   WordToHexValue_temp = "0" + lByte.toString(16);
                   WordToHexValue = WordToHexValue + WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2);
           }
           return WordToHexValue;
   };

   function Utf8Encode(string) {
           string = string.replace(/\r\n/g,"\n");
           var utftext = "";

           for (var n = 0; n < string.length; n++) {

                   var c = string.charCodeAt(n);

                   if (c < 128) {
                           utftext += String.fromCharCode(c);
                   }
                   else if((c > 127) && (c < 2048)) {
                           utftext += String.fromCharCode((c >> 6) | 192);
                           utftext += String.fromCharCode((c & 63) | 128);
                   }
                   else {
                           utftext += String.fromCharCode((c >> 12) | 224);
                           utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                           utftext += String.fromCharCode((c & 63) | 128);
                   }

           }

           return utftext;
   };

   var x=Array();
   var k,AA,BB,CC,DD,a,b,c,d;
   var S11=7, S12=12, S13=17, S14=22;
   var S21=5, S22=9 , S23=14, S24=20;
   var S31=4, S32=11, S33=16, S34=23;
   var S41=6, S42=10, S43=15, S44=21;

   string = Utf8Encode(string);

   x = ConvertToWordArray(string);

   a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;

   for (k=0;k<x.length;k+=16) {
           AA=a; BB=b; CC=c; DD=d;
           a=FF(a,b,c,d,x[k+0], S11,0xD76AA478);
           d=FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
           c=FF(c,d,a,b,x[k+2], S13,0x242070DB);
           b=FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
           a=FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
           d=FF(d,a,b,c,x[k+5], S12,0x4787C62A);
           c=FF(c,d,a,b,x[k+6], S13,0xA8304613);
           b=FF(b,c,d,a,x[k+7], S14,0xFD469501);
           a=FF(a,b,c,d,x[k+8], S11,0x698098D8);
           d=FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
           c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
           b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
           a=FF(a,b,c,d,x[k+12],S11,0x6B901122);
           d=FF(d,a,b,c,x[k+13],S12,0xFD987193);
           c=FF(c,d,a,b,x[k+14],S13,0xA679438E);
           b=FF(b,c,d,a,x[k+15],S14,0x49B40821);
           a=GG(a,b,c,d,x[k+1], S21,0xF61E2562);
           d=GG(d,a,b,c,x[k+6], S22,0xC040B340);
           c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);
           b=GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
           a=GG(a,b,c,d,x[k+5], S21,0xD62F105D);
           d=GG(d,a,b,c,x[k+10],S22,0x2441453);
           c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
           b=GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
           a=GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
           d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);
           c=GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
           b=GG(b,c,d,a,x[k+8], S24,0x455A14ED);
           a=GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
           d=GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
           c=GG(c,d,a,b,x[k+7], S23,0x676F02D9);
           b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
           a=HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
           d=HH(d,a,b,c,x[k+8], S32,0x8771F681);
           c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
           b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
           a=HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
           d=HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
           c=HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
           b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
           a=HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
           d=HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
           c=HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
           b=HH(b,c,d,a,x[k+6], S34,0x4881D05);
           a=HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
           d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
           c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
           b=HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
           a=II(a,b,c,d,x[k+0], S41,0xF4292244);
           d=II(d,a,b,c,x[k+7], S42,0x432AFF97);
           c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);
           b=II(b,c,d,a,x[k+5], S44,0xFC93A039);
           a=II(a,b,c,d,x[k+12],S41,0x655B59C3);
           d=II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
           c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
           b=II(b,c,d,a,x[k+1], S44,0x85845DD1);
           a=II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
           d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
           c=II(c,d,a,b,x[k+6], S43,0xA3014314);
           b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);
           a=II(a,b,c,d,x[k+4], S41,0xF7537E82);
           d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);
           c=II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
           b=II(b,c,d,a,x[k+9], S44,0xEB86D391);
           a=AddUnsigned(a,AA);
           b=AddUnsigned(b,BB);
           c=AddUnsigned(c,CC);
           d=AddUnsigned(d,DD);
   		}

   	var temp = WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);

   	return temp.toLowerCase();
}

Usage

MD5("whatever");

Like possibly snagging a Gravatar.

Comments

  1. Dyllon Fulgham
    Permalink to comment#

    Would it be a good or a bad idea to replace a password in a login form on submit to the md5 string instead of the actually password?

    I would figure it would create added security… Please correct me if I’m wrong..

    • I don’t think so. If the user has JavaScript disabled the password will still be sent in plain text and there is no way for the server to know if it was passed an md5 encrypted string or the users password.

    • Alexander Rath
      Permalink to comment#

      Yes, that’s a good idea.

      @Johnathan Barett:
      But the server could try both possibilities ;)
      (in PHP “$correct = $_GET[“pwd”] == $password || md5($_GET[“pwd”]) == $password;”)

  2. Kendall
    Permalink to comment#

    Why not just use the md5() mysql function?

    • Because he’s not using MySQL. I’m going to assume you mean the PHP MD5 function. The problem with this is how do you take a JavaScript input and run it through a PHP function? LIke grabbing a Gravatar, user types in email address, how do you pass that value to a PHP function without loading another page in the background to send the result back.

    • Kendall
      Permalink to comment#

      No I’m talking about the md5 MySQL function, which there is an equivalent function for SQL Server, or whatever database manager your using. If your encrypting passwords, I assume your storing in a database.

  3. Dyllon Fulgham
    Permalink to comment#

    I know exactly what you’re talking about, but it’s not about storing information, it’s about sending information through the browser.

  4. hey thanks guys for sharing this invaluable script.

  5. Permalink to comment#

    @Johnathan Barrett: There in fact a way for the server to know whether JavaScript was enabled or not in the client’s browser.
    To do so, add a hidden field named “hasjavascript” to your form with a default value of “false” and, with JavaScript, simply set the value of this field to “true”.
    Then, in the server-side code, checks for the value of the GET variable “hasjavascript”.

    Hashing the password with JavaScript’s only effect is that, if someone gets the submitted values, they won’t be able to know the plain-text one and will (hopefully) not be able to login with this password on other website.
    Note that he will still be able to login on your website by simply submitting the intercepted hashed password, as the browser would do.
    To prevent that, you would have to use an asymmetric encryption algorithm like RSA.

    Read more on this on: http://en.wikipedia.org/wiki/Public-key_cryptography

  6. Rick
    Permalink to comment#

    I’ve used this for websites where the client doesn’t want https (they’re crazy, I know). What I do is use challenge-authentication (Actually I stole it from Yahoo! mail :P ). It’s simple:

    1) Generate a random “salt” (generate a random string) and store it in the session. Send it to the browser.
    2) In the client, concatenate the salt and the password, and md5 it. send the result. Also send the salt.
    3) In the server, check if the salt is the same, and if md5(salt . password) match. If not, generate a NEW salt and repeat.

    If you need to encrypt the password on the server, do the same thing but instead of comparing the password, compare the encrypted password (obviously you need to replicate the database-pw-encryption process in the browser).

    Still, that’s not match for an HTTPS connection.

    As for detecting whether the client has javascript enabled, simply make the form unsubmittable unless the client has js enabled. Use something like action=”javascript:;” and then use onsubmit for the real submission (you’d need to make an invisible form).

  7. Michele
    Permalink to comment#

    great script

  8. ddlab
    Permalink to comment#

    @all and @ROMAC
    Hi, I see that the threads from above are not very actual ones, but may be somebody reads them in 2013 :-)
    I think it is a very interesting topic, to concern whether sensitive user data, as passwords are, will transferred over internet plain or encrypted / hashed, or not. Also, if they are saved in database encrypted / hashed or not.
    As I am very concerned on users data security I picked the following as my favorite way, setting up a website:
    1. – Given that nobody disables javascript today (he would never get a contemporary web experience, as there are almost no websites running without ) I assume, that users would totally agree, to use javascript to strengthen his or his datas security.
    2. – On register process, I require email address as first username and send it plain to server, and passwords as md5-hash (since a couple of months I am using sha256 for hashing).
    After successful registration, email verification and first login, he can set another username (or mobile number, see following point 6.)
    3. – There are different ways to check serverside, if the sent password is a hash (via enabled js) or not.
    … – a) use the solution of ROMAC above, set hidden field from “false” to “true” (or whatever known values),
    … – b) count length of string on server (who the f**k will use a 32 characters long password, or 64 with sha256 ?)
    … – c) create login form using js/jquery when page is loaded, instead of php/html (if js is disabled, no login form will appear)
    … – d) don´t include a type=submit button, but a type=button and send login form using js and onclick event, even it is created with php/html (without submit button ENTER key will not work for submitting form)
    4. – Serverside, incoming password hash will be hashed again using sha256 together with a random salt. The resulting hash and the salt are stored in database.
    5. – On login, the incoming password (assumed as a hash) will hashed again with stored salt, saved in a temp variable, which will be compared to the hash stored in database, if both are equal… everything fine.
    6. – Again considering ROMACs post (asymetric encryption like RSA): I prefer sms key, as some online banking institutes do.
    If the owner of a website agrees with it, as he has minimal knowledge of security and encryption, I book a sms-account for him (I am using german provider goyya.com, as I am German :-) ). For very sensitive user account data settings user has to trigger a sms code (mobile phone number required on registration) and he gets two codes: The salt from servers database, and a 4 digits random number, stored in session.
    Now the entire sensitive data traffic (and just this) will be sent AES encrypted, and will readable in local browser decrypted via jquery AES libraries. The key is never transmitted over internet, it equals to the hashed password from database, hashed again with the random sms key.
    It sounds horrible ? Hmm, may be. But it works nice. Once implemented its easy to handle and more safe than RSA or HTTPS, as asymmetric keys are not going through internet at all.
    Just one challenge is, when user lost or changed his mobile number… In users profile must be assigned one ore two reliable friends (mothers, fathers) mobile number(s), that one can use to change his own mobile number in user profile settings. This friend or minimum his mobile phone must be present at the moment, when user wants to login into his private area.
    In Premium tariff it costs 85 Euro for 1000 sms, which is much cheaper than a website HTTPS certificate, assuming that one doesn´t need to access his personal account settings everyday.

  9. Permalink to comment#

    @Rick, the reason for not using https is that recent browsers throw up a big red warning, “THIS IS AN UNTRUSTED SITE!” if you use a selfsigned cert.

    This effectively means that https can only be used on sites whose budget vustifies a Verisign cert, and on webspace where such a cert can be hosted. All others must send plaintext data. Call it counterproductive security.

Leave a Comment

Posting Code

Markdown is supported in the comment area, so you can write inline code in backticks like `this` or multiline blocks of code in in triple backtick fences like ```this```. You don't need to escape code in backticks, Markdown does that for you.

Sadly, it's kind of broken. WordPress only accepts a subset of HTML in comments, which makes sense, because certainly some HTML can't be allowed, like <script> tags. But this stripping happens before the comment is processed by Markdown (via Jetpack). It seems to me that would be reversed, because after Markdown processes code in backticks, it's escaped, thus safe. If you think you can fix this issue, get in touch!

If you need to make sure the code (typically HTML) you post absolutely posts correctly, escape it and put it within <pre><code> tags.

Current ye@r *

*May or may not contain any actual "CSS" or "Tricks".