src/firefoxos/hashes/md4.js

Mon, 22 Apr 2013 22:00:43 +0200

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Mon, 22 Apr 2013 22:00:43 +0200
changeset 0
6a0957738c54
permissions
-rw-r--r--

Import pristine sources of new project OTPWCalc.

michael@0 1 /*
michael@0 2 * A JavaScript implementation of the RSA Data Security, Inc. MD4 Message
michael@0 3 * Digest Algorithm, as defined in RFC 1320.
michael@0 4 * Version 2.1 Copyright (C) Jerrad Pierce, Paul Johnston 1999 - 2002.
michael@0 5 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
michael@0 6 * Distributed under the BSD License
michael@0 7 * See http://pajhome.org.uk/crypt/md5 for more info.
michael@0 8 */
michael@0 9
michael@0 10 /*
michael@0 11 * Configurable variables. You may need to tweak these to be compatible with
michael@0 12 * the server-side, but the defaults work in most cases.
michael@0 13 */
michael@0 14 var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
michael@0 15 var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
michael@0 16 var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
michael@0 17
michael@0 18 /*
michael@0 19 * These are the functions you'll usually want to call
michael@0 20 */
michael@0 21 function hexmd4(s){ return binl2hex(coremd4(str2binl(s), s.length * chrsz));}
michael@0 22 function b64md4(s){ return binl2b64(coremd4(str2binl(s), s.length * chrsz));}
michael@0 23 function strmd4(s){ return binl2str(coremd4(str2binl(s), s.length * chrsz));}
michael@0 24 function hexhmacmd4(key, data) { return binl2hex(corehmacmd4(key, data)); }
michael@0 25 function b64hmacmd4(key, data) { return binl2b64(corehmacmd4(key, data)); }
michael@0 26 function strhmacmd4(key, data) { return binl2str(corehmacmd4(key, data)); }
michael@0 27
michael@0 28 /*
michael@0 29 * Perform a simple self-test to see if the VM is working
michael@0 30 */
michael@0 31 function md4vmtest()
michael@0 32 {
michael@0 33 return hexmd4("abc") == "a448017aaf21d8525fc10ae87aa6729d";
michael@0 34 }
michael@0 35
michael@0 36 /*
michael@0 37 * Calculate the MD4 of an array of little-endian words, and a bit length
michael@0 38 */
michael@0 39 function coremd4(x, len)
michael@0 40 {
michael@0 41 /* append padding */
michael@0 42 x[len >> 5] |= 0x80 << (len % 32);
michael@0 43 x[(((len + 64) >>> 9) << 4) + 14] = len;
michael@0 44
michael@0 45 var a = 1732584193;
michael@0 46 var b = -271733879;
michael@0 47 var c = -1732584194;
michael@0 48 var d = 271733878;
michael@0 49
michael@0 50 for(var i = 0; i < x.length; i += 16)
michael@0 51 {
michael@0 52 var olda = a;
michael@0 53 var oldb = b;
michael@0 54 var oldc = c;
michael@0 55 var oldd = d;
michael@0 56
michael@0 57 a = md4ff(a, b, c, d, x[i+ 0], 3 );
michael@0 58 d = md4ff(d, a, b, c, x[i+ 1], 7 );
michael@0 59 c = md4ff(c, d, a, b, x[i+ 2], 11);
michael@0 60 b = md4ff(b, c, d, a, x[i+ 3], 19);
michael@0 61 a = md4ff(a, b, c, d, x[i+ 4], 3 );
michael@0 62 d = md4ff(d, a, b, c, x[i+ 5], 7 );
michael@0 63 c = md4ff(c, d, a, b, x[i+ 6], 11);
michael@0 64 b = md4ff(b, c, d, a, x[i+ 7], 19);
michael@0 65 a = md4ff(a, b, c, d, x[i+ 8], 3 );
michael@0 66 d = md4ff(d, a, b, c, x[i+ 9], 7 );
michael@0 67 c = md4ff(c, d, a, b, x[i+10], 11);
michael@0 68 b = md4ff(b, c, d, a, x[i+11], 19);
michael@0 69 a = md4ff(a, b, c, d, x[i+12], 3 );
michael@0 70 d = md4ff(d, a, b, c, x[i+13], 7 );
michael@0 71 c = md4ff(c, d, a, b, x[i+14], 11);
michael@0 72 b = md4ff(b, c, d, a, x[i+15], 19);
michael@0 73
michael@0 74 a = md4gg(a, b, c, d, x[i+ 0], 3 );
michael@0 75 d = md4gg(d, a, b, c, x[i+ 4], 5 );
michael@0 76 c = md4gg(c, d, a, b, x[i+ 8], 9 );
michael@0 77 b = md4gg(b, c, d, a, x[i+12], 13);
michael@0 78 a = md4gg(a, b, c, d, x[i+ 1], 3 );
michael@0 79 d = md4gg(d, a, b, c, x[i+ 5], 5 );
michael@0 80 c = md4gg(c, d, a, b, x[i+ 9], 9 );
michael@0 81 b = md4gg(b, c, d, a, x[i+13], 13);
michael@0 82 a = md4gg(a, b, c, d, x[i+ 2], 3 );
michael@0 83 d = md4gg(d, a, b, c, x[i+ 6], 5 );
michael@0 84 c = md4gg(c, d, a, b, x[i+10], 9 );
michael@0 85 b = md4gg(b, c, d, a, x[i+14], 13);
michael@0 86 a = md4gg(a, b, c, d, x[i+ 3], 3 );
michael@0 87 d = md4gg(d, a, b, c, x[i+ 7], 5 );
michael@0 88 c = md4gg(c, d, a, b, x[i+11], 9 );
michael@0 89 b = md4gg(b, c, d, a, x[i+15], 13);
michael@0 90
michael@0 91 a = md4hh(a, b, c, d, x[i+ 0], 3 );
michael@0 92 d = md4hh(d, a, b, c, x[i+ 8], 9 );
michael@0 93 c = md4hh(c, d, a, b, x[i+ 4], 11);
michael@0 94 b = md4hh(b, c, d, a, x[i+12], 15);
michael@0 95 a = md4hh(a, b, c, d, x[i+ 2], 3 );
michael@0 96 d = md4hh(d, a, b, c, x[i+10], 9 );
michael@0 97 c = md4hh(c, d, a, b, x[i+ 6], 11);
michael@0 98 b = md4hh(b, c, d, a, x[i+14], 15);
michael@0 99 a = md4hh(a, b, c, d, x[i+ 1], 3 );
michael@0 100 d = md4hh(d, a, b, c, x[i+ 9], 9 );
michael@0 101 c = md4hh(c, d, a, b, x[i+ 5], 11);
michael@0 102 b = md4hh(b, c, d, a, x[i+13], 15);
michael@0 103 a = md4hh(a, b, c, d, x[i+ 3], 3 );
michael@0 104 d = md4hh(d, a, b, c, x[i+11], 9 );
michael@0 105 c = md4hh(c, d, a, b, x[i+ 7], 11);
michael@0 106 b = md4hh(b, c, d, a, x[i+15], 15);
michael@0 107
michael@0 108 a = safeadd(a, olda);
michael@0 109 b = safeadd(b, oldb);
michael@0 110 c = safeadd(c, oldc);
michael@0 111 d = safeadd(d, oldd);
michael@0 112
michael@0 113 }
michael@0 114 return Array(a, b, c, d);
michael@0 115
michael@0 116 }
michael@0 117
michael@0 118 /*
michael@0 119 * These functions implement the basic operation for each round of the
michael@0 120 * algorithm.
michael@0 121 */
michael@0 122 function md4cmn(q, a, b, x, s, t)
michael@0 123 {
michael@0 124 return safeadd(rol(safeadd(safeadd(a, q), safeadd(x, t)), s), b);
michael@0 125 }
michael@0 126 function md4ff(a, b, c, d, x, s)
michael@0 127 {
michael@0 128 return md4cmn((b & c) | ((~b) & d), a, 0, x, s, 0);
michael@0 129 }
michael@0 130 function md4gg(a, b, c, d, x, s)
michael@0 131 {
michael@0 132 return md4cmn((b & c) | (b & d) | (c & d), a, 0, x, s, 1518500249);
michael@0 133 }
michael@0 134 function md4hh(a, b, c, d, x, s)
michael@0 135 {
michael@0 136 return md4cmn(b ^ c ^ d, a, 0, x, s, 1859775393);
michael@0 137 }
michael@0 138
michael@0 139 /*
michael@0 140 * Calculate the HMAC-MD4, of a key and some data
michael@0 141 */
michael@0 142 function corehmacmd4(key, data)
michael@0 143 {
michael@0 144 var bkey = str2binl(key);
michael@0 145 if(bkey.length > 16) bkey = coremd4(bkey, key.length * chrsz);
michael@0 146
michael@0 147 var ipad = Array(16), opad = Array(16);
michael@0 148 for(var i = 0; i < 16; i++)
michael@0 149 {
michael@0 150 ipad[i] = bkey[i] ^ 0x36363636;
michael@0 151 opad[i] = bkey[i] ^ 0x5C5C5C5C;
michael@0 152 }
michael@0 153
michael@0 154 var hash = coremd4(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
michael@0 155 return coremd4(opad.concat(hash), 512 + 128);
michael@0 156 }
michael@0 157
michael@0 158 /*
michael@0 159 * Add integers, wrapping at 2^32. This uses 16-bit operations internally
michael@0 160 * to work around bugs in some JS interpreters.
michael@0 161 */
michael@0 162 function safeadd(x, y)
michael@0 163 {
michael@0 164 var lsw = (x & 0xFFFF) + (y & 0xFFFF);
michael@0 165 var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
michael@0 166 return (msw << 16) | (lsw & 0xFFFF);
michael@0 167 }
michael@0 168
michael@0 169 /*
michael@0 170 * Bitwise rotate a 32-bit number to the left.
michael@0 171 */
michael@0 172 function rol(num, cnt)
michael@0 173 {
michael@0 174 return (num << cnt) | (num >>> (32 - cnt));
michael@0 175 }
michael@0 176
michael@0 177 /*
michael@0 178 * Convert a string to an array of little-endian words
michael@0 179 * If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
michael@0 180 */
michael@0 181 function str2binl(str)
michael@0 182 {
michael@0 183 var bin = Array();
michael@0 184 var mask = (1 << chrsz) - 1;
michael@0 185 for(var i = 0; i < str.length * chrsz; i += chrsz)
michael@0 186 bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
michael@0 187 return bin;
michael@0 188 }
michael@0 189
michael@0 190 /*
michael@0 191 * Convert an array of little-endian words to a string
michael@0 192 */
michael@0 193 function binl2str(bin)
michael@0 194 {
michael@0 195 var str = "";
michael@0 196 var mask = (1 << chrsz) - 1;
michael@0 197 for(var i = 0; i < bin.length * 32; i += chrsz)
michael@0 198 str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
michael@0 199 return str;
michael@0 200 }
michael@0 201
michael@0 202 /*
michael@0 203 * Convert an array of little-endian words to a hex string.
michael@0 204 */
michael@0 205 function binl2hex(binarray)
michael@0 206 {
michael@0 207 var hextab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
michael@0 208 var str = "";
michael@0 209 for(var i = 0; i < binarray.length * 4; i++)
michael@0 210 {
michael@0 211 str += hextab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
michael@0 212 hextab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
michael@0 213 }
michael@0 214 return str;
michael@0 215 }
michael@0 216
michael@0 217 /*
michael@0 218 * Convert an array of little-endian words to a base-64 string
michael@0 219 */
michael@0 220 function binl2b64(binarray)
michael@0 221 {
michael@0 222 var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
michael@0 223 var str = "";
michael@0 224 for(var i = 0; i < binarray.length * 4; i += 3)
michael@0 225 {
michael@0 226 var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16)
michael@0 227 | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
michael@0 228 | ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
michael@0 229 for(var j = 0; j < 4; j++)
michael@0 230 {
michael@0 231 if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
michael@0 232 else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
michael@0 233 }
michael@0 234 }
michael@0 235 return str;
michael@0 236 }

mercurial