PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/weave/sha.js

https://bitbucket.org/philikon/weaveclient-chromium/
JavaScript | 482 lines | 341 code | 48 blank | 93 comment | 43 complexity | d2e34248cf078e5b1697b52ffa86d09c MD5 | raw file
  1. /*
  2. * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
  3. * in FIPS 180-1
  4. * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined
  5. * in FIPS 180-2
  6. * Version 2.2 Copyright Paul Johnston 2000 - 2009.
  7. * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
  8. * Distributed under the BSD License
  9. * See http://pajhome.org.uk/crypt/md5 for details.
  10. * Also http://anmar.eu.org/projects/jssha2/
  11. */
  12. Weave.Util.SHA = function () {
  13. /*
  14. * Configurable variables. You may need to tweak these to be compatible with
  15. * the server-side, but the defaults work in most cases.
  16. */
  17. var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
  18. var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
  19. /*
  20. * These are the functions you'll usually want to call
  21. * They take string arguments and return either hex or base-64 encoded strings
  22. */
  23. function hex_sha1(s) { return rstr2hex(rstr_sha1(str2rstr_utf8(s))); }
  24. function b64_sha1(s) { return rstr2b64(rstr_sha1(str2rstr_utf8(s))); }
  25. function any_sha1(s, e) { return rstr2any(rstr_sha1(str2rstr_utf8(s)), e); }
  26. function hex_hmac_sha1(k, d)
  27. { return rstr2hex(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d))); }
  28. function b64_hmac_sha1(k, d)
  29. { return rstr2b64(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d))); }
  30. function any_hmac_sha1(k, d, e)
  31. { return rstr2any(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
  32. function hex_sha256(s) { return rstr2hex(rstr_sha256(str2rstr_utf8(s))); }
  33. function b64_sha256(s) { return rstr2b64(rstr_sha256(str2rstr_utf8(s))); }
  34. function any_sha256(s, e) { return rstr2any(rstr_sha256(str2rstr_utf8(s)), e); }
  35. function hex_hmac_sha256(k, d)
  36. { return rstr2hex(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d))); }
  37. function b64_hmac_sha256(k, d)
  38. { return rstr2b64(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d))); }
  39. function any_hmac_sha256(k, d, e)
  40. { return rstr2any(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
  41. /*
  42. * Perform a simple self-test to see if the VM is working
  43. */
  44. function sha1_vm_test()
  45. {
  46. return hex_sha1("abc").toLowerCase() == "a9993e364706816aba3e25717850c26c9cd0d89d";
  47. }
  48. /*
  49. * Calculate the SHA1 of a raw string
  50. */
  51. function rstr_sha1(s)
  52. {
  53. return binb2rstr(binb_sha1(rstr2binb(s), s.length * 8));
  54. }
  55. /*
  56. * Calculate the HMAC-SHA1 of a key and some data (raw strings)
  57. */
  58. function rstr_hmac_sha1(key, data)
  59. {
  60. var bkey = rstr2binb(key);
  61. if(bkey.length > 16) bkey = binb_sha1(bkey, key.length * 8);
  62. var ipad = Array(16), opad = Array(16);
  63. for(var i = 0; i < 16; i++)
  64. {
  65. ipad[i] = bkey[i] ^ 0x36363636;
  66. opad[i] = bkey[i] ^ 0x5C5C5C5C;
  67. }
  68. var hash = binb_sha1(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
  69. return binb2rstr(binb_sha1(opad.concat(hash), 512 + 160));
  70. }
  71. /*
  72. * Perform a simple self-test to see if the VM is working
  73. */
  74. function sha256_vm_test()
  75. {
  76. return hex_sha256("abc").toLowerCase() ==
  77. "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
  78. }
  79. /*
  80. * Calculate the sha256 of a raw string
  81. */
  82. function rstr_sha256(s)
  83. {
  84. return binb2rstr(binb_sha256(rstr2binb(s), s.length * 8));
  85. }
  86. /*
  87. * Calculate the HMAC-sha256 of a key and some data (raw strings)
  88. */
  89. function rstr_hmac_sha256(key, data)
  90. {
  91. var bkey = rstr2binb(key);
  92. if(bkey.length > 16) bkey = binb_sha256(bkey, key.length * 8);
  93. var ipad = Array(16), opad = Array(16);
  94. for(var i = 0; i < 16; i++)
  95. {
  96. ipad[i] = bkey[i] ^ 0x36363636;
  97. opad[i] = bkey[i] ^ 0x5C5C5C5C;
  98. }
  99. var hash = binb_sha256(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
  100. return binb2rstr(binb_sha256(opad.concat(hash), 512 + 256));
  101. }
  102. /*
  103. * Convert a raw string to a hex string
  104. */
  105. function rstr2hex(input)
  106. {
  107. try { hexcase } catch(e) { hexcase=0; }
  108. var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  109. var output = "";
  110. var x;
  111. for(var i = 0; i < input.length; i++)
  112. {
  113. x = input.charCodeAt(i);
  114. output += hex_tab.charAt((x >>> 4) & 0x0F)
  115. + hex_tab.charAt( x & 0x0F);
  116. }
  117. return output;
  118. }
  119. /*
  120. * Convert a raw string to a base-64 string
  121. */
  122. function rstr2b64(input)
  123. {
  124. try { b64pad } catch(e) { b64pad=''; }
  125. var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  126. var output = "";
  127. var len = input.length;
  128. for(var i = 0; i < len; i += 3)
  129. {
  130. var triplet = (input.charCodeAt(i) << 16)
  131. | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
  132. | (i + 2 < len ? input.charCodeAt(i+2) : 0);
  133. for(var j = 0; j < 4; j++)
  134. {
  135. if(i * 8 + j * 6 > input.length * 8) output += b64pad;
  136. else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
  137. }
  138. }
  139. return output;
  140. }
  141. /*
  142. * Convert a raw string to an arbitrary string encoding
  143. */
  144. function rstr2any(input, encoding)
  145. {
  146. var divisor = encoding.length;
  147. var remainders = Array();
  148. var i, q, x, quotient;
  149. /* Convert to an array of 16-bit big-endian values, forming the dividend */
  150. var dividend = Array(Math.ceil(input.length / 2));
  151. for(i = 0; i < dividend.length; i++)
  152. {
  153. dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
  154. }
  155. /*
  156. * Repeatedly perform a long division. The binary array forms the dividend,
  157. * the length of the encoding is the divisor. Once computed, the quotient
  158. * forms the dividend for the next step. We stop when the dividend is zero.
  159. * All remainders are stored for later use.
  160. */
  161. while(dividend.length > 0)
  162. {
  163. quotient = Array();
  164. x = 0;
  165. for(i = 0; i < dividend.length; i++)
  166. {
  167. x = (x << 16) + dividend[i];
  168. q = Math.floor(x / divisor);
  169. x -= q * divisor;
  170. if(quotient.length > 0 || q > 0)
  171. quotient[quotient.length] = q;
  172. }
  173. remainders[remainders.length] = x;
  174. dividend = quotient;
  175. }
  176. /* Convert the remainders to the output string */
  177. var output = "";
  178. for(i = remainders.length - 1; i >= 0; i--)
  179. output += encoding.charAt(remainders[i]);
  180. /* Append leading zero equivalents */
  181. var full_length = Math.ceil(input.length * 8 /
  182. (Math.log(encoding.length) / Math.log(2)))
  183. for(i = output.length; i < full_length; i++)
  184. output = encoding[0] + output;
  185. return output;
  186. }
  187. /*
  188. * Encode a string as utf-8.
  189. * For efficiency, this assumes the input is valid utf-16.
  190. */
  191. function str2rstr_utf8(input)
  192. {
  193. var output = "";
  194. var i = -1;
  195. var x, y;
  196. while(++i < input.length)
  197. {
  198. /* Decode utf-16 surrogate pairs */
  199. x = input.charCodeAt(i);
  200. y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
  201. if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
  202. {
  203. x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
  204. i++;
  205. }
  206. /* Encode output as utf-8 */
  207. if(x <= 0x7F)
  208. output += String.fromCharCode(x);
  209. else if(x <= 0x7FF)
  210. output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
  211. 0x80 | ( x & 0x3F));
  212. else if(x <= 0xFFFF)
  213. output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
  214. 0x80 | ((x >>> 6 ) & 0x3F),
  215. 0x80 | ( x & 0x3F));
  216. else if(x <= 0x1FFFFF)
  217. output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
  218. 0x80 | ((x >>> 12) & 0x3F),
  219. 0x80 | ((x >>> 6 ) & 0x3F),
  220. 0x80 | ( x & 0x3F));
  221. }
  222. return output;
  223. }
  224. /*
  225. * Encode a string as utf-16
  226. */
  227. function str2rstr_utf16le(input)
  228. {
  229. var output = "";
  230. for(var i = 0; i < input.length; i++)
  231. output += String.fromCharCode( input.charCodeAt(i) & 0xFF,
  232. (input.charCodeAt(i) >>> 8) & 0xFF);
  233. return output;
  234. }
  235. function str2rstr_utf16be(input)
  236. {
  237. var output = "";
  238. for(var i = 0; i < input.length; i++)
  239. output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
  240. input.charCodeAt(i) & 0xFF);
  241. return output;
  242. }
  243. /*
  244. * Convert a raw string to an array of big-endian words
  245. * Characters >255 have their high-byte silently ignored.
  246. */
  247. function rstr2binb(input)
  248. {
  249. var output = Array(input.length >> 2);
  250. for(var i = 0; i < output.length; i++)
  251. output[i] = 0;
  252. for(var i = 0; i < input.length * 8; i += 8)
  253. output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
  254. return output;
  255. }
  256. /*
  257. * Convert an array of big-endian words to a string
  258. */
  259. function binb2rstr(input)
  260. {
  261. var output = "";
  262. for(var i = 0; i < input.length * 32; i += 8)
  263. output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF);
  264. return output;
  265. }
  266. /*
  267. * Calculate the SHA-1 of an array of big-endian words, and a bit length
  268. */
  269. function binb_sha1(x, len)
  270. {
  271. /* append padding */
  272. x[len >> 5] |= 0x80 << (24 - len % 32);
  273. x[((len + 64 >> 9) << 4) + 15] = len;
  274. var w = Array(80);
  275. var a = 1732584193;
  276. var b = -271733879;
  277. var c = -1732584194;
  278. var d = 271733878;
  279. var e = -1009589776;
  280. for(var i = 0; i < x.length; i += 16)
  281. {
  282. var olda = a;
  283. var oldb = b;
  284. var oldc = c;
  285. var oldd = d;
  286. var olde = e;
  287. for(var j = 0; j < 80; j++)
  288. {
  289. if(j < 16) w[j] = x[i + j];
  290. else w[j] = bit_rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
  291. var t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)),
  292. safe_add(safe_add(e, w[j]), sha1_kt(j)));
  293. e = d;
  294. d = c;
  295. c = bit_rol(b, 30);
  296. b = a;
  297. a = t;
  298. }
  299. a = safe_add(a, olda);
  300. b = safe_add(b, oldb);
  301. c = safe_add(c, oldc);
  302. d = safe_add(d, oldd);
  303. e = safe_add(e, olde);
  304. }
  305. return Array(a, b, c, d, e);
  306. }
  307. /*
  308. * Perform the appropriate triplet combination function for the current
  309. * iteration
  310. */
  311. function sha1_ft(t, b, c, d)
  312. {
  313. if(t < 20) return (b & c) | ((~b) & d);
  314. if(t < 40) return b ^ c ^ d;
  315. if(t < 60) return (b & c) | (b & d) | (c & d);
  316. return b ^ c ^ d;
  317. }
  318. /*
  319. * Determine the appropriate additive constant for the current iteration
  320. */
  321. function sha1_kt(t)
  322. {
  323. return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
  324. (t < 60) ? -1894007588 : -899497514;
  325. }
  326. /*
  327. * Main sha256 function, with its support functions
  328. */
  329. function sha256_S (X, n) {return ( X >>> n ) | (X << (32 - n));}
  330. function sha256_R (X, n) {return ( X >>> n );}
  331. function sha256_Ch(x, y, z) {return ((x & y) ^ ((~x) & z));}
  332. function sha256_Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}
  333. function sha256_Sigma0256(x) {return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));}
  334. function sha256_Sigma1256(x) {return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));}
  335. function sha256_Gamma0256(x) {return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));}
  336. function sha256_Gamma1256(x) {return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));}
  337. function sha256_Sigma0512(x) {return (sha256_S(x, 28) ^ sha256_S(x, 34) ^ sha256_S(x, 39));}
  338. function sha256_Sigma1512(x) {return (sha256_S(x, 14) ^ sha256_S(x, 18) ^ sha256_S(x, 41));}
  339. function sha256_Gamma0512(x) {return (sha256_S(x, 1) ^ sha256_S(x, 8) ^ sha256_R(x, 7));}
  340. function sha256_Gamma1512(x) {return (sha256_S(x, 19) ^ sha256_S(x, 61) ^ sha256_R(x, 6));}
  341. var sha256_K = new Array
  342. (
  343. 1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993,
  344. -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987,
  345. 1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522,
  346. 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986,
  347. -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585,
  348. 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291,
  349. 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885,
  350. -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344,
  351. 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218,
  352. 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872,
  353. -1866530822, -1538233109, -1090935817, -965641998
  354. );
  355. function binb_sha256(m, l)
  356. {
  357. var HASH = new Array(1779033703, -1150833019, 1013904242, -1521486534,
  358. 1359893119, -1694144372, 528734635, 1541459225);
  359. var W = new Array(64);
  360. var a, b, c, d, e, f, g, h;
  361. var i, j, T1, T2;
  362. /* append padding */
  363. m[l >> 5] |= 0x80 << (24 - l % 32);
  364. m[((l + 64 >> 9) << 4) + 15] = l;
  365. for(i = 0; i < m.length; i += 16)
  366. {
  367. a = HASH[0];
  368. b = HASH[1];
  369. c = HASH[2];
  370. d = HASH[3];
  371. e = HASH[4];
  372. f = HASH[5];
  373. g = HASH[6];
  374. h = HASH[7];
  375. for(j = 0; j < 64; j++)
  376. {
  377. if (j < 16) W[j] = m[j + i];
  378. else W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]),
  379. sha256_Gamma0256(W[j - 15])), W[j - 16]);
  380. T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)),
  381. sha256_K[j]), W[j]);
  382. T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
  383. h = g;
  384. g = f;
  385. f = e;
  386. e = safe_add(d, T1);
  387. d = c;
  388. c = b;
  389. b = a;
  390. a = safe_add(T1, T2);
  391. }
  392. HASH[0] = safe_add(a, HASH[0]);
  393. HASH[1] = safe_add(b, HASH[1]);
  394. HASH[2] = safe_add(c, HASH[2]);
  395. HASH[3] = safe_add(d, HASH[3]);
  396. HASH[4] = safe_add(e, HASH[4]);
  397. HASH[5] = safe_add(f, HASH[5]);
  398. HASH[6] = safe_add(g, HASH[6]);
  399. HASH[7] = safe_add(h, HASH[7]);
  400. }
  401. return HASH;
  402. }
  403. /*
  404. * Add integers, wrapping at 2^32. This uses 16-bit operations internally
  405. * to work around bugs in some JS interpreters.
  406. */
  407. function safe_add(x, y)
  408. {
  409. var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  410. var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  411. return (msw << 16) | (lsw & 0xFFFF);
  412. }
  413. /*
  414. * Bitwise rotate a 32-bit number to the left.
  415. */
  416. function bit_rol(num, cnt)
  417. {
  418. return (num << cnt) | (num >>> (32 - cnt));
  419. }
  420. return {
  421. digest1: hex_sha1,
  422. digest1_str: rstr_sha1,
  423. digest1_b64: b64_sha1,
  424. hmac1: hex_hmac_sha1,
  425. hmac1_str: rstr_hmac_sha1,
  426. hmac1_b64: b64_hmac_sha1,
  427. digest256: hex_sha256,
  428. digest256_str: rstr_sha256,
  429. digest256_b64: b64_sha256,
  430. hmac256: hex_hmac_sha256,
  431. hmac256_str: rstr_hmac_sha256,
  432. hmac256_b64: b64_hmac_sha256
  433. };
  434. }();