Source: md4.js

  1. /**
  2. * [js-md4]{@link https://github.com/emn178/js-md4}
  3. *
  4. * @namespace md4
  5. * @version 0.3.2
  6. * @author Yi-Cyuan Chen [emn178@gmail.com]
  7. * @copyright Yi-Cyuan Chen 2015-2027
  8. * @license MIT
  9. */
  10. /*jslint bitwise: true */
  11. (function () {
  12. 'use strict';
  13. var root = typeof window === 'object' ? window : {};
  14. var NODE_JS = !root.JS_MD4_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node;
  15. if (NODE_JS) {
  16. root = global;
  17. }
  18. var COMMON_JS = !root.JS_MD4_NO_COMMON_JS && typeof module === 'object' && module.exports;
  19. var AMD = typeof define === 'function' && define.amd;
  20. var ARRAY_BUFFER = !root.JS_MD4_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined';
  21. var HEX_CHARS = '0123456789abcdef'.split('');
  22. var EXTRA = [128, 32768, 8388608, -2147483648];
  23. var SHIFT = [0, 8, 16, 24];
  24. var OUTPUT_TYPES = ['hex', 'array', 'digest', 'buffer', 'arrayBuffer'];
  25. var blocks = [], buffer8;
  26. if (ARRAY_BUFFER) {
  27. var buffer = new ArrayBuffer(68);
  28. buffer8 = new Uint8Array(buffer);
  29. blocks = new Uint32Array(buffer);
  30. }
  31. /**
  32. * @method hex
  33. * @memberof md4
  34. * @description Output hash as hex string
  35. * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
  36. * @returns {String} Hex string
  37. * @example
  38. * md4.hex('The quick brown fox jumps over the lazy dog');
  39. * // equal to
  40. * md4('The quick brown fox jumps over the lazy dog');
  41. */
  42. /**
  43. * @method digest
  44. * @memberof md4
  45. * @description Output hash as bytes array
  46. * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
  47. * @returns {Array} Bytes array
  48. * @example
  49. * md4.digest('The quick brown fox jumps over the lazy dog');
  50. */
  51. /**
  52. * @method array
  53. * @memberof md4
  54. * @description Output hash as bytes array
  55. * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
  56. * @returns {Array} Bytes array
  57. * @example
  58. * md4.array('The quick brown fox jumps over the lazy dog');
  59. */
  60. /**
  61. * @method buffer
  62. * @memberof md4
  63. * @description Output hash as ArrayBuffer
  64. * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
  65. * @returns {ArrayBuffer} ArrayBuffer
  66. * @example
  67. * md4.buffer('The quick brown fox jumps over the lazy dog');
  68. */
  69. var createOutputMethod = function (outputType) {
  70. return function(message) {
  71. return new Md4(true).update(message)[outputType]();
  72. }
  73. };
  74. /**
  75. * @method create
  76. * @memberof md4
  77. * @description Create Md4 object
  78. * @returns {Md4} MD4 object.
  79. * @example
  80. * var hash = md4.create();
  81. */
  82. /**
  83. * @method update
  84. * @memberof md4
  85. * @description Create and update Md4 object
  86. * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
  87. * @returns {Md4} MD4 object.
  88. * @example
  89. * var hash = md4.update('The quick brown fox jumps over the lazy dog');
  90. * // equal to
  91. * var hash = md4.create();
  92. * hash.update('The quick brown fox jumps over the lazy dog');
  93. */
  94. var createMethod = function () {
  95. var method = createOutputMethod('hex');
  96. if (NODE_JS) {
  97. method = nodeWrap(method);
  98. }
  99. method.create = function () {
  100. return new Md4();
  101. };
  102. method.update = function (message) {
  103. return method.create().update(message);
  104. };
  105. for (var i = 0; i < OUTPUT_TYPES.length; ++i) {
  106. var type = OUTPUT_TYPES[i];
  107. method[type] = createOutputMethod(type);
  108. }
  109. return method;
  110. };
  111. var nodeWrap = function (method) {
  112. var crypto = require('crypto');
  113. var Buffer = require('buffer').Buffer;
  114. var nodeMethod = function (message) {
  115. if (typeof message === 'string') {
  116. return crypto.createHash('md4').update(message, 'utf8').digest('hex');
  117. } else if (ARRAY_BUFFER && message instanceof ArrayBuffer) {
  118. message = new Uint8Array(message);
  119. } else if (message.length === undefined) {
  120. return method(message);
  121. }
  122. return crypto.createHash('md4').update(new Buffer(message)).digest('hex');
  123. };
  124. return nodeMethod;
  125. };
  126. /**
  127. * Md4 class
  128. * @class Md4
  129. * @description This is internal class.
  130. * @see {@link md4.create}
  131. */
  132. function Md4(sharedMemory) {
  133. if (sharedMemory) {
  134. blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] =
  135. blocks[4] = blocks[5] = blocks[6] = blocks[7] =
  136. blocks[8] = blocks[9] = blocks[10] = blocks[11] =
  137. blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
  138. this.blocks = blocks;
  139. this.buffer8 = buffer8;
  140. } else {
  141. if (ARRAY_BUFFER) {
  142. var buffer = new ArrayBuffer(68);
  143. this.buffer8 = new Uint8Array(buffer);
  144. this.blocks = new Uint32Array(buffer);
  145. } else {
  146. this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
  147. }
  148. }
  149. this.h0 = this.h1 = this.h2 = this.h3 = this.start = this.bytes = 0;
  150. this.finalized = this.hashed = false;
  151. this.first = true;
  152. }
  153. /**
  154. * @method update
  155. * @memberof Md4
  156. * @instance
  157. * @description Update hash
  158. * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
  159. * @returns {Md4} MD4 object.
  160. * @see {@link md4.update}
  161. */
  162. Md4.prototype.update = function (message) {
  163. if (this.finalized) {
  164. return;
  165. }
  166. var notString = typeof message !== 'string';
  167. if (notString && ARRAY_BUFFER && message instanceof ArrayBuffer) {
  168. message = new Uint8Array(message);
  169. }
  170. var code, index = 0, i, length = message.length || 0, blocks = this.blocks;
  171. var buffer8 = this.buffer8;
  172. while (index < length) {
  173. if (this.hashed) {
  174. this.hashed = false;
  175. blocks[0] = blocks[16];
  176. blocks[16] = blocks[1] = blocks[2] = blocks[3] =
  177. blocks[4] = blocks[5] = blocks[6] = blocks[7] =
  178. blocks[8] = blocks[9] = blocks[10] = blocks[11] =
  179. blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
  180. }
  181. if (notString) {
  182. if (ARRAY_BUFFER) {
  183. for (i = this.start; index < length && i < 64; ++index) {
  184. buffer8[i++] = message[index];
  185. }
  186. } else {
  187. for (i = this.start; index < length && i < 64; ++index) {
  188. blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];
  189. }
  190. }
  191. } else {
  192. if (ARRAY_BUFFER) {
  193. for (i = this.start; index < length && i < 64; ++index) {
  194. code = message.charCodeAt(index);
  195. if (code < 0x80) {
  196. buffer8[i++] = code;
  197. } else if (code < 0x800) {
  198. buffer8[i++] = 0xc0 | (code >> 6);
  199. buffer8[i++] = 0x80 | (code & 0x3f);
  200. } else if (code < 0xd800 || code >= 0xe000) {
  201. buffer8[i++] = 0xe0 | (code >> 12);
  202. buffer8[i++] = 0x80 | ((code >> 6) & 0x3f);
  203. buffer8[i++] = 0x80 | (code & 0x3f);
  204. } else {
  205. code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
  206. buffer8[i++] = 0xf0 | (code >> 18);
  207. buffer8[i++] = 0x80 | ((code >> 12) & 0x3f);
  208. buffer8[i++] = 0x80 | ((code >> 6) & 0x3f);
  209. buffer8[i++] = 0x80 | (code & 0x3f);
  210. }
  211. }
  212. } else {
  213. for (i = this.start; index < length && i < 64; ++index) {
  214. code = message.charCodeAt(index);
  215. if (code < 0x80) {
  216. blocks[i >> 2] |= code << SHIFT[i++ & 3];
  217. } else if (code < 0x800) {
  218. blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];
  219. blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
  220. } else if (code < 0xd800 || code >= 0xe000) {
  221. blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];
  222. blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
  223. blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
  224. } else {
  225. code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
  226. blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];
  227. blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];
  228. blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
  229. blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
  230. }
  231. }
  232. }
  233. }
  234. this.lastByteIndex = i;
  235. this.bytes += i - this.start;
  236. if (i >= 64) {
  237. this.start = i - 64;
  238. this.hash();
  239. this.hashed = true;
  240. } else {
  241. this.start = i;
  242. }
  243. }
  244. return this;
  245. };
  246. Md4.prototype.finalize = function () {
  247. if (this.finalized) {
  248. return;
  249. }
  250. this.finalized = true;
  251. var blocks = this.blocks, i = this.lastByteIndex;
  252. blocks[i >> 2] |= EXTRA[i & 3];
  253. if (i >= 56) {
  254. if (!this.hashed) {
  255. this.hash();
  256. }
  257. blocks[0] = blocks[16];
  258. blocks[16] = blocks[1] = blocks[2] = blocks[3] =
  259. blocks[4] = blocks[5] = blocks[6] = blocks[7] =
  260. blocks[8] = blocks[9] = blocks[10] = blocks[11] =
  261. blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
  262. }
  263. blocks[14] = this.bytes << 3;
  264. this.hash();
  265. };
  266. Md4.prototype.hash = function () {
  267. var a, b, c, d, ab, bc, cd, da, blocks = this.blocks;
  268. if (this.first) {
  269. a = blocks[0] - 1;
  270. a = (a << 3) | (a >>> 29);
  271. d = ((a & 0xefcdab89) | (~a & 0x98badcfe)) + blocks[1] + 271733878;
  272. d = (d << 7) | (d >>> 25);
  273. c = ((d & a) | (~d & 0xefcdab89)) + blocks[2] - 1732584194;
  274. c = (c << 11) | (c >>> 21);
  275. b = ((c & d) | (~c & a)) + blocks[3] - 271733879;
  276. b = (b << 19) | (b >>> 13);
  277. } else {
  278. a = this.h0;
  279. b = this.h1;
  280. c = this.h2;
  281. d = this.h3;
  282. a += ((b & c) | (~b & d)) + blocks[0];
  283. a = (a << 3) | (a >>> 29);
  284. d += ((a & b) | (~a & c)) + blocks[1];
  285. d = (d << 7) | (d >>> 25);
  286. c += ((d & a) | (~d & b)) + blocks[2];
  287. c = (c << 11) | (c >>> 21);
  288. b += ((c & d) | (~c & a)) + blocks[3];
  289. b = (b << 19) | (b >>> 13);
  290. }
  291. a += ((b & c) | (~b & d)) + blocks[4];
  292. a = (a << 3) | (a >>> 29);
  293. d += ((a & b) | (~a & c)) + blocks[5];
  294. d = (d << 7) | (d >>> 25);
  295. c += ((d & a) | (~d & b)) + blocks[6];
  296. c = (c << 11) | (c >>> 21);
  297. b += ((c & d) | (~c & a)) + blocks[7];
  298. b = (b << 19) | (b >>> 13);
  299. a += ((b & c) | (~b & d)) + blocks[8];
  300. a = (a << 3) | (a >>> 29);
  301. d += ((a & b) | (~a & c)) + blocks[9];
  302. d = (d << 7) | (d >>> 25);
  303. c += ((d & a) | (~d & b)) + blocks[10];
  304. c = (c << 11) | (c >>> 21);
  305. b += ((c & d) | (~c & a)) + blocks[11];
  306. b = (b << 19) | (b >>> 13);
  307. a += ((b & c) | (~b & d)) + blocks[12];
  308. a = (a << 3) | (a >>> 29);
  309. d += ((a & b) | (~a & c)) + blocks[13];
  310. d = (d << 7) | (d >>> 25);
  311. c += ((d & a) | (~d & b)) + blocks[14];
  312. c = (c << 11) | (c >>> 21);
  313. b += ((c & d) | (~c & a)) + blocks[15];
  314. b = (b << 19) | (b >>> 13);
  315. bc = b & c;
  316. a += (bc | (b & d) | (c & d)) + blocks[0] + 1518500249;
  317. a = (a << 3) | (a >>> 29);
  318. ab = a & b;
  319. d += (ab | (a & c) | bc) + blocks[4] + 1518500249;
  320. d = (d << 5) | (d >>> 27);
  321. da = d & a;
  322. c += (da | (d & b) | ab) + blocks[8] + 1518500249;
  323. c = (c << 9) | (c >>> 23);
  324. cd = c & d;
  325. b += (cd | (c & a) | da) + blocks[12] + 1518500249;
  326. b = (b << 13) | (b >>> 19);
  327. bc = b & c;
  328. a += (bc | (b & d) | cd) + blocks[1] + 1518500249;
  329. a = (a << 3) | (a >>> 29);
  330. ab = a & b;
  331. d += (ab | (a & c) | bc) + blocks[5] + 1518500249;
  332. d = (d << 5) | (d >>> 27);
  333. da = d & a;
  334. c += (da | (d & b) | ab) + blocks[9] + 1518500249;
  335. c = (c << 9) | (c >>> 23);
  336. cd = c & d;
  337. b += (cd | (c & a) | da) + blocks[13] + 1518500249;
  338. b = (b << 13) | (b >>> 19);
  339. bc = b & c;
  340. a += (bc | (b & d) | cd) + blocks[2] + 1518500249;
  341. a = (a << 3) | (a >>> 29);
  342. ab = a & b;
  343. d += (ab | (a & c) | bc) + blocks[6] + 1518500249;
  344. d = (d << 5) | (d >>> 27);
  345. da = d & a;
  346. c += (da | (d & b) | ab) + blocks[10] + 1518500249;
  347. c = (c << 9) | (c >>> 23);
  348. cd = c & d;
  349. b += (cd | (c & a) | da) + blocks[14] + 1518500249;
  350. b = (b << 13) | (b >>> 19);
  351. bc = b & c;
  352. a += (bc | (b & d) | cd) + blocks[3] + 1518500249;
  353. a = (a << 3) | (a >>> 29);
  354. ab = a & b;
  355. d += (ab | (a & c) | bc) + blocks[7] + 1518500249;
  356. d = (d << 5) | (d >>> 27);
  357. da = d & a;
  358. c += (da | (d & b) | ab) + blocks[11] + 1518500249;
  359. c = (c << 9) | (c >>> 23);
  360. b += ((c & d) | (c & a) | da) + blocks[15] + 1518500249;
  361. b = (b << 13) | (b >>> 19);
  362. bc = b ^ c;
  363. a += (bc ^ d) + blocks[0] + 1859775393;
  364. a = (a << 3) | (a >>> 29);
  365. d += (bc ^ a) + blocks[8] + 1859775393;
  366. d = (d << 9) | (d >>> 23);
  367. da = d ^ a;
  368. c += (da ^ b) + blocks[4] + 1859775393;
  369. c = (c << 11) | (c >>> 21);
  370. b += (da ^ c) + blocks[12] + 1859775393;
  371. b = (b << 15) | (b >>> 17);
  372. bc = b ^ c;
  373. a += (bc ^ d) + blocks[2] + 1859775393;
  374. a = (a << 3) | (a >>> 29);
  375. d += (bc ^ a) + blocks[10] + 1859775393;
  376. d = (d << 9) | (d >>> 23);
  377. da = d ^ a;
  378. c += (da ^ b) + blocks[6] + 1859775393;
  379. c = (c << 11) | (c >>> 21);
  380. b += (da ^ c) + blocks[14] + 1859775393;
  381. b = (b << 15) | (b >>> 17);
  382. bc = b ^ c;
  383. a += (bc ^ d) + blocks[1] + 1859775393;
  384. a = (a << 3) | (a >>> 29);
  385. d += (bc ^ a) + blocks[9] + 1859775393;
  386. d = (d << 9) | (d >>> 23);
  387. da = d ^ a;
  388. c += (da ^ b) + blocks[5] + 1859775393;
  389. c = (c << 11) | (c >>> 21);
  390. b += (da ^ c) + blocks[13] + 1859775393;
  391. b = (b << 15) | (b >>> 17);
  392. bc = b ^ c;
  393. a += (bc ^ d) + blocks[3] + 1859775393;
  394. a = (a << 3) | (a >>> 29);
  395. d += (bc ^ a) + blocks[11] + 1859775393;
  396. d = (d << 9) | (d >>> 23);
  397. da = d ^ a;
  398. c += (da ^ b) + blocks[7] + 1859775393;
  399. c = (c << 11) | (c >>> 21);
  400. b += (da ^ c) + blocks[15] + 1859775393;
  401. b = (b << 15) | (b >>> 17);
  402. if (this.first) {
  403. this.h0 = a + 1732584193 << 0;
  404. this.h1 = b - 271733879 << 0;
  405. this.h2 = c - 1732584194 << 0;
  406. this.h3 = d + 271733878 << 0;
  407. this.first = false;
  408. } else {
  409. this.h0 = this.h0 + a << 0;
  410. this.h1 = this.h1 + b << 0;
  411. this.h2 = this.h2 + c << 0;
  412. this.h3 = this.h3 + d << 0;
  413. }
  414. };
  415. /**
  416. * @method hex
  417. * @memberof Md4
  418. * @instance
  419. * @description Output hash as hex string
  420. * @returns {String} Hex string
  421. * @see {@link md4.hex}
  422. * @example
  423. * hash.hex();
  424. */
  425. Md4.prototype.hex = function () {
  426. this.finalize();
  427. var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3;
  428. return HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F] +
  429. HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F] +
  430. HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] +
  431. HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F] +
  432. HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F] +
  433. HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F] +
  434. HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F] +
  435. HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F] +
  436. HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F] +
  437. HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F] +
  438. HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F] +
  439. HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F] +
  440. HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F] +
  441. HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F] +
  442. HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F] +
  443. HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F];
  444. };
  445. /**
  446. * @method toString
  447. * @memberof Md4
  448. * @instance
  449. * @description Output hash as hex string
  450. * @returns {String} Hex string
  451. * @see {@link md4.hex}
  452. * @example
  453. * hash.toString();
  454. */
  455. Md4.prototype.toString = Md4.prototype.hex;
  456. /**
  457. * @method digest
  458. * @memberof Md4
  459. * @instance
  460. * @description Output hash as bytes array
  461. * @returns {Array} Bytes array
  462. * @see {@link md4.digest}
  463. * @example
  464. * hash.digest();
  465. */
  466. Md4.prototype.digest = function() {
  467. this.finalize();
  468. var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3;
  469. return [
  470. h0 & 0xFF, (h0 >> 8) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 24) & 0xFF,
  471. h1 & 0xFF, (h1 >> 8) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 24) & 0xFF,
  472. h2 & 0xFF, (h2 >> 8) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 24) & 0xFF,
  473. h3 & 0xFF, (h3 >> 8) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 24) & 0xFF
  474. ];
  475. };
  476. /**
  477. * @method array
  478. * @memberof Md4
  479. * @instance
  480. * @description Output hash as bytes array
  481. * @returns {Array} Bytes array
  482. * @see {@link md4.array}
  483. * @example
  484. * hash.array();
  485. */
  486. Md4.prototype.array = Md4.prototype.digest;
  487. /**
  488. * @method arrayBuffer
  489. * @memberof Md4
  490. * @instance
  491. * @description Output hash as ArrayBuffer
  492. * @returns {ArrayBuffer} ArrayBuffer
  493. * @see {@link md4.arrayBuffer}
  494. * @example
  495. * hash.arrayBuffer();
  496. */
  497. Md4.prototype.arrayBuffer = function() {
  498. this.finalize();
  499. var buffer = new ArrayBuffer(16);
  500. var blocks = new Uint32Array(buffer);
  501. blocks[0] = this.h0;
  502. blocks[1] = this.h1;
  503. blocks[2] = this.h2;
  504. blocks[3] = this.h3;
  505. return buffer;
  506. };
  507. /**
  508. * @method buffer
  509. * @deprecated This maybe confuse with Buffer in node.js. Please use arrayBuffer instead.
  510. * @memberof Md4
  511. * @instance
  512. * @description Output hash as ArrayBuffer
  513. * @returns {ArrayBuffer} ArrayBuffer
  514. * @see {@link md4.buffer}
  515. * @example
  516. * hash.buffer();
  517. */
  518. Md4.prototype.buffer = Md4.prototype.arrayBuffer;
  519. var exports = createMethod();
  520. if (COMMON_JS) {
  521. module.exports = exports;
  522. } else {
  523. /**
  524. * @method md4
  525. * @description MD4 hash function, export to global in browsers.
  526. * @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
  527. * @returns {String} md4 hashes
  528. * @example
  529. * md4(''); // 31d6cfe0d16ae931b73c59d7e0c089c0
  530. * md4('The quick brown fox jumps over the lazy dog'); // 1bee69a46ba811185c194762abaeae90
  531. * md4('The quick brown fox jumps over the lazy dog.'); // 2812c6c7136898c51f6f6739ad08750e
  532. *
  533. * // It also supports UTF-8 encoding
  534. * md4('中文'); // 223088bf7bd45a16436b15360c5fc5a0
  535. *
  536. * // It also supports byte `Array`, `Uint8Array`, `ArrayBuffer`
  537. * md4([]); // 31d6cfe0d16ae931b73c59d7e0c089c0
  538. * md4(new Uint8Array([])); // 31d6cfe0d16ae931b73c59d7e0c089c0
  539. */
  540. root.md4 = exports;
  541. if (AMD) {
  542. define(function () {
  543. return exports;
  544. });
  545. }
  546. }
  547. })();