Created
May 12, 2013 09:18
-
-
Save ForbesLindesay/5562935 to your computer and use it in GitHub Desktop.
Modified to only support data as a string
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Javascript MD5 library - version 0.4 | |
Coded (2011) by Luigi Galli - LG@4e71.org - http://faultylabs.com | |
Thanks to: Roberto Viola | |
The below code is PUBLIC DOMAIN - NO WARRANTY! | |
*/ | |
/* | |
MD5() | |
Computes the MD5 hash for the given input data | |
input : data as String - (Assumes Unicode code points are encoded as UTF-8. If you | |
attempt to digest Unicode strings using other encodings | |
you will get incorrect results!) | |
output: MD5 hash (as Hex Uppercase String) | |
*/ | |
function MD5(data) { | |
// convert number to (unsigned) 32 bit hex, zero filled string | |
function to_zerofilled_hex(n) { | |
var t1 = (n >>> 0).toString(16) | |
return "00000000".substr(0, 8 - t1.length) + t1 | |
} | |
// convert a 64 bit unsigned number to array of bytes. Little endian | |
function int64_to_bytes(num) { | |
var retval = [] | |
for (var i = 0; i < 8; i++) { | |
retval.push(num & 0xFF) | |
num = num >>> 8 | |
} | |
return retval | |
} | |
// 32 bit left-rotation | |
function rol(num, places) { | |
return ((num << places) & 0xFFFFFFFF) | (num >>> (32 - places)) | |
} | |
// The 4 MD5 functions | |
function fF(b, c, d) { | |
return (b & c) | (~b & d) | |
} | |
function fG(b, c, d) { | |
return (d & b) | (~d & c) | |
} | |
function fH(b, c, d) { | |
return b ^ c ^ d | |
} | |
function fI(b, c, d) { | |
return c ^ (b | ~d) | |
} | |
// pick 4 bytes at specified offset. Little-endian is assumed | |
function bytes_to_int32(arr, off) { | |
return (arr[off + 3] << 24) | (arr[off + 2] << 16) | (arr[off + 1] << 8) | (arr[off]) | |
} | |
/* | |
Conver string to array of bytes in UTF-8 encoding | |
See: | |
http://www.dangrossman.info/2007/05/25/handling-utf-8-in-javascript-php-and-non-utf8-databases/ | |
http://stackoverflow.com/questions/1240408/reading-bytes-from-a-javascript-string | |
How about a String.getBytes(<ENCODING>) for Javascript!? Isn't it time to add it? | |
*/ | |
function str_to_bytes(str) { | |
var retval = [ ] | |
for (var i = 0; i < str.length; i++) | |
if (str.charCodeAt(i) <= 0x7F) { | |
retval.push(str.charCodeAt(i)) | |
} else { | |
var tmp = encodeURIComponent(str.charAt(i)).substr(1).split('%') | |
for (var j = 0; j < tmp.length; j++) { | |
retval.push(parseInt(tmp[j], 0x10)) | |
} | |
} | |
return retval | |
} | |
// convert the 4 32-bit buffers to a 128 bit hex string. (Little-endian is assumed) | |
function int128le_to_hex(a, b, c, d) { | |
var ra = "" | |
var t = 0 | |
var ta = 0 | |
for (var i = 3; i >= 0; i--) { | |
ta = arguments[i] | |
t = (ta & 0xFF) | |
ta = ta >>> 8 | |
t = t << 8 | |
t = t | (ta & 0xFF) | |
ta = ta >>> 8 | |
t = t << 8 | |
t = t | (ta & 0xFF) | |
ta = ta >>> 8 | |
t = t << 8 | |
t = t | ta | |
ra = ra + to_zerofilled_hex(t) | |
} | |
return ra | |
} | |
// check input data type and perform conversions if needed | |
var databytes = str_to_bytes(data) | |
function _add(n1, n2) { | |
return 0x0FFFFFFFF & (n1 + n2) | |
} | |
return do_digest() | |
function do_digest() { | |
// function update partial state for each run | |
function updateRun(nf, sin32, dw32, b32) { | |
var temp = d | |
d = c | |
c = b | |
//b = b + rol(a + (nf + (sin32 + dw32)), b32) | |
b = _add(b, | |
rol( | |
_add(a, | |
_add(nf, _add(sin32, dw32)) | |
), b32 | |
) | |
) | |
a = temp | |
} | |
// save original length | |
var org_len = databytes.length | |
// first append the "1" + 7x "0" | |
databytes.push(0x80) | |
// determine required amount of padding | |
var tail = databytes.length % 64 | |
// no room for msg length? | |
if (tail > 56) { | |
// pad to next 512 bit block | |
for (var i = 0; i < (64 - tail); i++) { | |
databytes.push(0x0) | |
} | |
tail = databytes.length % 64 | |
} | |
for (i = 0; i < (56 - tail); i++) { | |
databytes.push(0x0) | |
} | |
// message length in bits mod 512 should now be 448 | |
// append 64 bit, little-endian original msg length (in *bits*!) | |
databytes = databytes.concat(int64_to_bytes(org_len * 8)) | |
// initialize 4x32 bit state | |
var h0 = 0x67452301 | |
var h1 = 0xEFCDAB89 | |
var h2 = 0x98BADCFE | |
var h3 = 0x10325476 | |
// temp buffers | |
var a = 0, b = 0, c = 0, d = 0 | |
// Digest message | |
for (i = 0; i < databytes.length / 64; i++) { | |
// initialize run | |
a = h0 | |
b = h1 | |
c = h2 | |
d = h3 | |
var ptr = i * 64 | |
// do 64 runs | |
updateRun(fF(b, c, d), 0xd76aa478, bytes_to_int32(databytes, ptr), 7) | |
updateRun(fF(b, c, d), 0xe8c7b756, bytes_to_int32(databytes, ptr + 4), 12) | |
updateRun(fF(b, c, d), 0x242070db, bytes_to_int32(databytes, ptr + 8), 17) | |
updateRun(fF(b, c, d), 0xc1bdceee, bytes_to_int32(databytes, ptr + 12), 22) | |
updateRun(fF(b, c, d), 0xf57c0faf, bytes_to_int32(databytes, ptr + 16), 7) | |
updateRun(fF(b, c, d), 0x4787c62a, bytes_to_int32(databytes, ptr + 20), 12) | |
updateRun(fF(b, c, d), 0xa8304613, bytes_to_int32(databytes, ptr + 24), 17) | |
updateRun(fF(b, c, d), 0xfd469501, bytes_to_int32(databytes, ptr + 28), 22) | |
updateRun(fF(b, c, d), 0x698098d8, bytes_to_int32(databytes, ptr + 32), 7) | |
updateRun(fF(b, c, d), 0x8b44f7af, bytes_to_int32(databytes, ptr + 36), 12) | |
updateRun(fF(b, c, d), 0xffff5bb1, bytes_to_int32(databytes, ptr + 40), 17) | |
updateRun(fF(b, c, d), 0x895cd7be, bytes_to_int32(databytes, ptr + 44), 22) | |
updateRun(fF(b, c, d), 0x6b901122, bytes_to_int32(databytes, ptr + 48), 7) | |
updateRun(fF(b, c, d), 0xfd987193, bytes_to_int32(databytes, ptr + 52), 12) | |
updateRun(fF(b, c, d), 0xa679438e, bytes_to_int32(databytes, ptr + 56), 17) | |
updateRun(fF(b, c, d), 0x49b40821, bytes_to_int32(databytes, ptr + 60), 22) | |
updateRun(fG(b, c, d), 0xf61e2562, bytes_to_int32(databytes, ptr + 4), 5) | |
updateRun(fG(b, c, d), 0xc040b340, bytes_to_int32(databytes, ptr + 24), 9) | |
updateRun(fG(b, c, d), 0x265e5a51, bytes_to_int32(databytes, ptr + 44), 14) | |
updateRun(fG(b, c, d), 0xe9b6c7aa, bytes_to_int32(databytes, ptr), 20) | |
updateRun(fG(b, c, d), 0xd62f105d, bytes_to_int32(databytes, ptr + 20), 5) | |
updateRun(fG(b, c, d), 0x2441453, bytes_to_int32(databytes, ptr + 40), 9) | |
updateRun(fG(b, c, d), 0xd8a1e681, bytes_to_int32(databytes, ptr + 60), 14) | |
updateRun(fG(b, c, d), 0xe7d3fbc8, bytes_to_int32(databytes, ptr + 16), 20) | |
updateRun(fG(b, c, d), 0x21e1cde6, bytes_to_int32(databytes, ptr + 36), 5) | |
updateRun(fG(b, c, d), 0xc33707d6, bytes_to_int32(databytes, ptr + 56), 9) | |
updateRun(fG(b, c, d), 0xf4d50d87, bytes_to_int32(databytes, ptr + 12), 14) | |
updateRun(fG(b, c, d), 0x455a14ed, bytes_to_int32(databytes, ptr + 32), 20) | |
updateRun(fG(b, c, d), 0xa9e3e905, bytes_to_int32(databytes, ptr + 52), 5) | |
updateRun(fG(b, c, d), 0xfcefa3f8, bytes_to_int32(databytes, ptr + 8), 9) | |
updateRun(fG(b, c, d), 0x676f02d9, bytes_to_int32(databytes, ptr + 28), 14) | |
updateRun(fG(b, c, d), 0x8d2a4c8a, bytes_to_int32(databytes, ptr + 48), 20) | |
updateRun(fH(b, c, d), 0xfffa3942, bytes_to_int32(databytes, ptr + 20), 4) | |
updateRun(fH(b, c, d), 0x8771f681, bytes_to_int32(databytes, ptr + 32), 11) | |
updateRun(fH(b, c, d), 0x6d9d6122, bytes_to_int32(databytes, ptr + 44), 16) | |
updateRun(fH(b, c, d), 0xfde5380c, bytes_to_int32(databytes, ptr + 56), 23) | |
updateRun(fH(b, c, d), 0xa4beea44, bytes_to_int32(databytes, ptr + 4), 4) | |
updateRun(fH(b, c, d), 0x4bdecfa9, bytes_to_int32(databytes, ptr + 16), 11) | |
updateRun(fH(b, c, d), 0xf6bb4b60, bytes_to_int32(databytes, ptr + 28), 16) | |
updateRun(fH(b, c, d), 0xbebfbc70, bytes_to_int32(databytes, ptr + 40), 23) | |
updateRun(fH(b, c, d), 0x289b7ec6, bytes_to_int32(databytes, ptr + 52), 4) | |
updateRun(fH(b, c, d), 0xeaa127fa, bytes_to_int32(databytes, ptr), 11) | |
updateRun(fH(b, c, d), 0xd4ef3085, bytes_to_int32(databytes, ptr + 12), 16) | |
updateRun(fH(b, c, d), 0x4881d05, bytes_to_int32(databytes, ptr + 24), 23) | |
updateRun(fH(b, c, d), 0xd9d4d039, bytes_to_int32(databytes, ptr + 36), 4) | |
updateRun(fH(b, c, d), 0xe6db99e5, bytes_to_int32(databytes, ptr + 48), 11) | |
updateRun(fH(b, c, d), 0x1fa27cf8, bytes_to_int32(databytes, ptr + 60), 16) | |
updateRun(fH(b, c, d), 0xc4ac5665, bytes_to_int32(databytes, ptr + 8), 23) | |
updateRun(fI(b, c, d), 0xf4292244, bytes_to_int32(databytes, ptr), 6) | |
updateRun(fI(b, c, d), 0x432aff97, bytes_to_int32(databytes, ptr + 28), 10) | |
updateRun(fI(b, c, d), 0xab9423a7, bytes_to_int32(databytes, ptr + 56), 15) | |
updateRun(fI(b, c, d), 0xfc93a039, bytes_to_int32(databytes, ptr + 20), 21) | |
updateRun(fI(b, c, d), 0x655b59c3, bytes_to_int32(databytes, ptr + 48), 6) | |
updateRun(fI(b, c, d), 0x8f0ccc92, bytes_to_int32(databytes, ptr + 12), 10) | |
updateRun(fI(b, c, d), 0xffeff47d, bytes_to_int32(databytes, ptr + 40), 15) | |
updateRun(fI(b, c, d), 0x85845dd1, bytes_to_int32(databytes, ptr + 4), 21) | |
updateRun(fI(b, c, d), 0x6fa87e4f, bytes_to_int32(databytes, ptr + 32), 6) | |
updateRun(fI(b, c, d), 0xfe2ce6e0, bytes_to_int32(databytes, ptr + 60), 10) | |
updateRun(fI(b, c, d), 0xa3014314, bytes_to_int32(databytes, ptr + 24), 15) | |
updateRun(fI(b, c, d), 0x4e0811a1, bytes_to_int32(databytes, ptr + 52), 21) | |
updateRun(fI(b, c, d), 0xf7537e82, bytes_to_int32(databytes, ptr + 16), 6) | |
updateRun(fI(b, c, d), 0xbd3af235, bytes_to_int32(databytes, ptr + 44), 10) | |
updateRun(fI(b, c, d), 0x2ad7d2bb, bytes_to_int32(databytes, ptr + 8), 15) | |
updateRun(fI(b, c, d), 0xeb86d391, bytes_to_int32(databytes, ptr + 36), 21) | |
// update buffers | |
h0 = _add(h0, a) | |
h1 = _add(h1, b) | |
h2 = _add(h2, c) | |
h3 = _add(h3, d) | |
} | |
// Done! Convert buffers to 128 bit (LE) | |
return int128le_to_hex(h3, h2, h1, h0).toUpperCase() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment