You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

289 lines
7.8 KiB

4 years ago
  1. /**
  2. * Message Digest Algorithm 5 with 128-bit digest (MD5) implementation.
  3. *
  4. * @author Dave Longley
  5. *
  6. * Copyright (c) 2010-2014 Digital Bazaar, Inc.
  7. */
  8. var forge = require('./forge');
  9. require('./md');
  10. require('./util');
  11. var md5 = module.exports = forge.md5 = forge.md5 || {};
  12. forge.md.md5 = forge.md.algorithms.md5 = md5;
  13. /**
  14. * Creates an MD5 message digest object.
  15. *
  16. * @return a message digest object.
  17. */
  18. md5.create = function() {
  19. // do initialization as necessary
  20. if(!_initialized) {
  21. _init();
  22. }
  23. // MD5 state contains four 32-bit integers
  24. var _state = null;
  25. // input buffer
  26. var _input = forge.util.createBuffer();
  27. // used for word storage
  28. var _w = new Array(16);
  29. // message digest object
  30. var md = {
  31. algorithm: 'md5',
  32. blockLength: 64,
  33. digestLength: 16,
  34. // 56-bit length of message so far (does not including padding)
  35. messageLength: 0,
  36. // true message length
  37. fullMessageLength: null,
  38. // size of message length in bytes
  39. messageLengthSize: 8
  40. };
  41. /**
  42. * Starts the digest.
  43. *
  44. * @return this digest object.
  45. */
  46. md.start = function() {
  47. // up to 56-bit message length for convenience
  48. md.messageLength = 0;
  49. // full message length (set md.messageLength64 for backwards-compatibility)
  50. md.fullMessageLength = md.messageLength64 = [];
  51. var int32s = md.messageLengthSize / 4;
  52. for(var i = 0; i < int32s; ++i) {
  53. md.fullMessageLength.push(0);
  54. }
  55. _input = forge.util.createBuffer();
  56. _state = {
  57. h0: 0x67452301,
  58. h1: 0xEFCDAB89,
  59. h2: 0x98BADCFE,
  60. h3: 0x10325476
  61. };
  62. return md;
  63. };
  64. // start digest automatically for first time
  65. md.start();
  66. /**
  67. * Updates the digest with the given message input. The given input can
  68. * treated as raw input (no encoding will be applied) or an encoding of
  69. * 'utf8' maybe given to encode the input using UTF-8.
  70. *
  71. * @param msg the message input to update with.
  72. * @param encoding the encoding to use (default: 'raw', other: 'utf8').
  73. *
  74. * @return this digest object.
  75. */
  76. md.update = function(msg, encoding) {
  77. if(encoding === 'utf8') {
  78. msg = forge.util.encodeUtf8(msg);
  79. }
  80. // update message length
  81. var len = msg.length;
  82. md.messageLength += len;
  83. len = [(len / 0x100000000) >>> 0, len >>> 0];
  84. for(var i = md.fullMessageLength.length - 1; i >= 0; --i) {
  85. md.fullMessageLength[i] += len[1];
  86. len[1] = len[0] + ((md.fullMessageLength[i] / 0x100000000) >>> 0);
  87. md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0;
  88. len[0] = (len[1] / 0x100000000) >>> 0;
  89. }
  90. // add bytes to input buffer
  91. _input.putBytes(msg);
  92. // process bytes
  93. _update(_state, _w, _input);
  94. // compact input buffer every 2K or if empty
  95. if(_input.read > 2048 || _input.length() === 0) {
  96. _input.compact();
  97. }
  98. return md;
  99. };
  100. /**
  101. * Produces the digest.
  102. *
  103. * @return a byte buffer containing the digest value.
  104. */
  105. md.digest = function() {
  106. /* Note: Here we copy the remaining bytes in the input buffer and
  107. add the appropriate MD5 padding. Then we do the final update
  108. on a copy of the state so that if the user wants to get
  109. intermediate digests they can do so. */
  110. /* Determine the number of bytes that must be added to the message
  111. to ensure its length is congruent to 448 mod 512. In other words,
  112. the data to be digested must be a multiple of 512 bits (or 128 bytes).
  113. This data includes the message, some padding, and the length of the
  114. message. Since the length of the message will be encoded as 8 bytes (64
  115. bits), that means that the last segment of the data must have 56 bytes
  116. (448 bits) of message and padding. Therefore, the length of the message
  117. plus the padding must be congruent to 448 mod 512 because
  118. 512 - 128 = 448.
  119. In order to fill up the message length it must be filled with
  120. padding that begins with 1 bit followed by all 0 bits. Padding
  121. must *always* be present, so if the message length is already
  122. congruent to 448 mod 512, then 512 padding bits must be added. */
  123. var finalBlock = forge.util.createBuffer();
  124. finalBlock.putBytes(_input.bytes());
  125. // compute remaining size to be digested (include message length size)
  126. var remaining = (
  127. md.fullMessageLength[md.fullMessageLength.length - 1] +
  128. md.messageLengthSize);
  129. // add padding for overflow blockSize - overflow
  130. // _padding starts with 1 byte with first bit is set (byte value 128), then
  131. // there may be up to (blockSize - 1) other pad bytes
  132. var overflow = remaining & (md.blockLength - 1);
  133. finalBlock.putBytes(_padding.substr(0, md.blockLength - overflow));
  134. // serialize message length in bits in little-endian order; since length
  135. // is stored in bytes we multiply by 8 and add carry
  136. var bits, carry = 0;
  137. for(var i = md.fullMessageLength.length - 1; i >= 0; --i) {
  138. bits = md.fullMessageLength[i] * 8 + carry;
  139. carry = (bits / 0x100000000) >>> 0;
  140. finalBlock.putInt32Le(bits >>> 0);
  141. }
  142. var s2 = {
  143. h0: _state.h0,
  144. h1: _state.h1,
  145. h2: _state.h2,
  146. h3: _state.h3
  147. };
  148. _update(s2, _w, finalBlock);
  149. var rval = forge.util.createBuffer();
  150. rval.putInt32Le(s2.h0);
  151. rval.putInt32Le(s2.h1);
  152. rval.putInt32Le(s2.h2);
  153. rval.putInt32Le(s2.h3);
  154. return rval;
  155. };
  156. return md;
  157. };
  158. // padding, constant tables for calculating md5
  159. var _padding = null;
  160. var _g = null;
  161. var _r = null;
  162. var _k = null;
  163. var _initialized = false;
  164. /**
  165. * Initializes the constant tables.
  166. */
  167. function _init() {
  168. // create padding
  169. _padding = String.fromCharCode(128);
  170. _padding += forge.util.fillString(String.fromCharCode(0x00), 64);
  171. // g values
  172. _g = [
  173. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
  174. 1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12,
  175. 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2,
  176. 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9];
  177. // rounds table
  178. _r = [
  179. 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
  180. 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
  181. 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
  182. 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21];
  183. // get the result of abs(sin(i + 1)) as a 32-bit integer
  184. _k = new Array(64);
  185. for(var i = 0; i < 64; ++i) {
  186. _k[i] = Math.floor(Math.abs(Math.sin(i + 1)) * 0x100000000);
  187. }
  188. // now initialized
  189. _initialized = true;
  190. }
  191. /**
  192. * Updates an MD5 state with the given byte buffer.
  193. *
  194. * @param s the MD5 state to update.
  195. * @param w the array to use to store words.
  196. * @param bytes the byte buffer to update with.
  197. */
  198. function _update(s, w, bytes) {
  199. // consume 512 bit (64 byte) chunks
  200. var t, a, b, c, d, f, r, i;
  201. var len = bytes.length();
  202. while(len >= 64) {
  203. // initialize hash value for this chunk
  204. a = s.h0;
  205. b = s.h1;
  206. c = s.h2;
  207. d = s.h3;
  208. // round 1
  209. for(i = 0; i < 16; ++i) {
  210. w[i] = bytes.getInt32Le();
  211. f = d ^ (b & (c ^ d));
  212. t = (a + f + _k[i] + w[i]);
  213. r = _r[i];
  214. a = d;
  215. d = c;
  216. c = b;
  217. b += (t << r) | (t >>> (32 - r));
  218. }
  219. // round 2
  220. for(; i < 32; ++i) {
  221. f = c ^ (d & (b ^ c));
  222. t = (a + f + _k[i] + w[_g[i]]);
  223. r = _r[i];
  224. a = d;
  225. d = c;
  226. c = b;
  227. b += (t << r) | (t >>> (32 - r));
  228. }
  229. // round 3
  230. for(; i < 48; ++i) {
  231. f = b ^ c ^ d;
  232. t = (a + f + _k[i] + w[_g[i]]);
  233. r = _r[i];
  234. a = d;
  235. d = c;
  236. c = b;
  237. b += (t << r) | (t >>> (32 - r));
  238. }
  239. // round 4
  240. for(; i < 64; ++i) {
  241. f = c ^ (b | ~d);
  242. t = (a + f + _k[i] + w[_g[i]]);
  243. r = _r[i];
  244. a = d;
  245. d = c;
  246. c = b;
  247. b += (t << r) | (t >>> (32 - r));
  248. }
  249. // update hash state
  250. s.h0 = (s.h0 + a) | 0;
  251. s.h1 = (s.h1 + b) | 0;
  252. s.h2 = (s.h2 + c) | 0;
  253. s.h3 = (s.h3 + d) | 0;
  254. len -= 64;
  255. }
  256. }