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.

327 lines
9.3 KiB

4 years ago
  1. /**
  2. * Secure Hash Algorithm with 256-bit digest (SHA-256) implementation.
  3. *
  4. * See FIPS 180-2 for details.
  5. *
  6. * @author Dave Longley
  7. *
  8. * Copyright (c) 2010-2015 Digital Bazaar, Inc.
  9. */
  10. var forge = require('./forge');
  11. require('./md');
  12. require('./util');
  13. var sha256 = module.exports = forge.sha256 = forge.sha256 || {};
  14. forge.md.sha256 = forge.md.algorithms.sha256 = sha256;
  15. /**
  16. * Creates a SHA-256 message digest object.
  17. *
  18. * @return a message digest object.
  19. */
  20. sha256.create = function() {
  21. // do initialization as necessary
  22. if(!_initialized) {
  23. _init();
  24. }
  25. // SHA-256 state contains eight 32-bit integers
  26. var _state = null;
  27. // input buffer
  28. var _input = forge.util.createBuffer();
  29. // used for word storage
  30. var _w = new Array(64);
  31. // message digest object
  32. var md = {
  33. algorithm: 'sha256',
  34. blockLength: 64,
  35. digestLength: 32,
  36. // 56-bit length of message so far (does not including padding)
  37. messageLength: 0,
  38. // true message length
  39. fullMessageLength: null,
  40. // size of message length in bytes
  41. messageLengthSize: 8
  42. };
  43. /**
  44. * Starts the digest.
  45. *
  46. * @return this digest object.
  47. */
  48. md.start = function() {
  49. // up to 56-bit message length for convenience
  50. md.messageLength = 0;
  51. // full message length (set md.messageLength64 for backwards-compatibility)
  52. md.fullMessageLength = md.messageLength64 = [];
  53. var int32s = md.messageLengthSize / 4;
  54. for(var i = 0; i < int32s; ++i) {
  55. md.fullMessageLength.push(0);
  56. }
  57. _input = forge.util.createBuffer();
  58. _state = {
  59. h0: 0x6A09E667,
  60. h1: 0xBB67AE85,
  61. h2: 0x3C6EF372,
  62. h3: 0xA54FF53A,
  63. h4: 0x510E527F,
  64. h5: 0x9B05688C,
  65. h6: 0x1F83D9AB,
  66. h7: 0x5BE0CD19
  67. };
  68. return md;
  69. };
  70. // start digest automatically for first time
  71. md.start();
  72. /**
  73. * Updates the digest with the given message input. The given input can
  74. * treated as raw input (no encoding will be applied) or an encoding of
  75. * 'utf8' maybe given to encode the input using UTF-8.
  76. *
  77. * @param msg the message input to update with.
  78. * @param encoding the encoding to use (default: 'raw', other: 'utf8').
  79. *
  80. * @return this digest object.
  81. */
  82. md.update = function(msg, encoding) {
  83. if(encoding === 'utf8') {
  84. msg = forge.util.encodeUtf8(msg);
  85. }
  86. // update message length
  87. var len = msg.length;
  88. md.messageLength += len;
  89. len = [(len / 0x100000000) >>> 0, len >>> 0];
  90. for(var i = md.fullMessageLength.length - 1; i >= 0; --i) {
  91. md.fullMessageLength[i] += len[1];
  92. len[1] = len[0] + ((md.fullMessageLength[i] / 0x100000000) >>> 0);
  93. md.fullMessageLength[i] = md.fullMessageLength[i] >>> 0;
  94. len[0] = ((len[1] / 0x100000000) >>> 0);
  95. }
  96. // add bytes to input buffer
  97. _input.putBytes(msg);
  98. // process bytes
  99. _update(_state, _w, _input);
  100. // compact input buffer every 2K or if empty
  101. if(_input.read > 2048 || _input.length() === 0) {
  102. _input.compact();
  103. }
  104. return md;
  105. };
  106. /**
  107. * Produces the digest.
  108. *
  109. * @return a byte buffer containing the digest value.
  110. */
  111. md.digest = function() {
  112. /* Note: Here we copy the remaining bytes in the input buffer and
  113. add the appropriate SHA-256 padding. Then we do the final update
  114. on a copy of the state so that if the user wants to get
  115. intermediate digests they can do so. */
  116. /* Determine the number of bytes that must be added to the message
  117. to ensure its length is congruent to 448 mod 512. In other words,
  118. the data to be digested must be a multiple of 512 bits (or 128 bytes).
  119. This data includes the message, some padding, and the length of the
  120. message. Since the length of the message will be encoded as 8 bytes (64
  121. bits), that means that the last segment of the data must have 56 bytes
  122. (448 bits) of message and padding. Therefore, the length of the message
  123. plus the padding must be congruent to 448 mod 512 because
  124. 512 - 128 = 448.
  125. In order to fill up the message length it must be filled with
  126. padding that begins with 1 bit followed by all 0 bits. Padding
  127. must *always* be present, so if the message length is already
  128. congruent to 448 mod 512, then 512 padding bits must be added. */
  129. var finalBlock = forge.util.createBuffer();
  130. finalBlock.putBytes(_input.bytes());
  131. // compute remaining size to be digested (include message length size)
  132. var remaining = (
  133. md.fullMessageLength[md.fullMessageLength.length - 1] +
  134. md.messageLengthSize);
  135. // add padding for overflow blockSize - overflow
  136. // _padding starts with 1 byte with first bit is set (byte value 128), then
  137. // there may be up to (blockSize - 1) other pad bytes
  138. var overflow = remaining & (md.blockLength - 1);
  139. finalBlock.putBytes(_padding.substr(0, md.blockLength - overflow));
  140. // serialize message length in bits in big-endian order; since length
  141. // is stored in bytes we multiply by 8 and add carry from next int
  142. var next, carry;
  143. var bits = md.fullMessageLength[0] * 8;
  144. for(var i = 0; i < md.fullMessageLength.length - 1; ++i) {
  145. next = md.fullMessageLength[i + 1] * 8;
  146. carry = (next / 0x100000000) >>> 0;
  147. bits += carry;
  148. finalBlock.putInt32(bits >>> 0);
  149. bits = next >>> 0;
  150. }
  151. finalBlock.putInt32(bits);
  152. var s2 = {
  153. h0: _state.h0,
  154. h1: _state.h1,
  155. h2: _state.h2,
  156. h3: _state.h3,
  157. h4: _state.h4,
  158. h5: _state.h5,
  159. h6: _state.h6,
  160. h7: _state.h7
  161. };
  162. _update(s2, _w, finalBlock);
  163. var rval = forge.util.createBuffer();
  164. rval.putInt32(s2.h0);
  165. rval.putInt32(s2.h1);
  166. rval.putInt32(s2.h2);
  167. rval.putInt32(s2.h3);
  168. rval.putInt32(s2.h4);
  169. rval.putInt32(s2.h5);
  170. rval.putInt32(s2.h6);
  171. rval.putInt32(s2.h7);
  172. return rval;
  173. };
  174. return md;
  175. };
  176. // sha-256 padding bytes not initialized yet
  177. var _padding = null;
  178. var _initialized = false;
  179. // table of constants
  180. var _k = null;
  181. /**
  182. * Initializes the constant tables.
  183. */
  184. function _init() {
  185. // create padding
  186. _padding = String.fromCharCode(128);
  187. _padding += forge.util.fillString(String.fromCharCode(0x00), 64);
  188. // create K table for SHA-256
  189. _k = [
  190. 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
  191. 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
  192. 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
  193. 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
  194. 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
  195. 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
  196. 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
  197. 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
  198. 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
  199. 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
  200. 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
  201. 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
  202. 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
  203. 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
  204. 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
  205. 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2];
  206. // now initialized
  207. _initialized = true;
  208. }
  209. /**
  210. * Updates a SHA-256 state with the given byte buffer.
  211. *
  212. * @param s the SHA-256 state to update.
  213. * @param w the array to use to store words.
  214. * @param bytes the byte buffer to update with.
  215. */
  216. function _update(s, w, bytes) {
  217. // consume 512 bit (64 byte) chunks
  218. var t1, t2, s0, s1, ch, maj, i, a, b, c, d, e, f, g, h;
  219. var len = bytes.length();
  220. while(len >= 64) {
  221. // the w array will be populated with sixteen 32-bit big-endian words
  222. // and then extended into 64 32-bit words according to SHA-256
  223. for(i = 0; i < 16; ++i) {
  224. w[i] = bytes.getInt32();
  225. }
  226. for(; i < 64; ++i) {
  227. // XOR word 2 words ago rot right 17, rot right 19, shft right 10
  228. t1 = w[i - 2];
  229. t1 =
  230. ((t1 >>> 17) | (t1 << 15)) ^
  231. ((t1 >>> 19) | (t1 << 13)) ^
  232. (t1 >>> 10);
  233. // XOR word 15 words ago rot right 7, rot right 18, shft right 3
  234. t2 = w[i - 15];
  235. t2 =
  236. ((t2 >>> 7) | (t2 << 25)) ^
  237. ((t2 >>> 18) | (t2 << 14)) ^
  238. (t2 >>> 3);
  239. // sum(t1, word 7 ago, t2, word 16 ago) modulo 2^32
  240. w[i] = (t1 + w[i - 7] + t2 + w[i - 16]) | 0;
  241. }
  242. // initialize hash value for this chunk
  243. a = s.h0;
  244. b = s.h1;
  245. c = s.h2;
  246. d = s.h3;
  247. e = s.h4;
  248. f = s.h5;
  249. g = s.h6;
  250. h = s.h7;
  251. // round function
  252. for(i = 0; i < 64; ++i) {
  253. // Sum1(e)
  254. s1 =
  255. ((e >>> 6) | (e << 26)) ^
  256. ((e >>> 11) | (e << 21)) ^
  257. ((e >>> 25) | (e << 7));
  258. // Ch(e, f, g) (optimized the same way as SHA-1)
  259. ch = g ^ (e & (f ^ g));
  260. // Sum0(a)
  261. s0 =
  262. ((a >>> 2) | (a << 30)) ^
  263. ((a >>> 13) | (a << 19)) ^
  264. ((a >>> 22) | (a << 10));
  265. // Maj(a, b, c) (optimized the same way as SHA-1)
  266. maj = (a & b) | (c & (a ^ b));
  267. // main algorithm
  268. t1 = h + s1 + ch + _k[i] + w[i];
  269. t2 = s0 + maj;
  270. h = g;
  271. g = f;
  272. f = e;
  273. // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug
  274. // can't truncate with `| 0`
  275. e = (d + t1) >>> 0;
  276. d = c;
  277. c = b;
  278. b = a;
  279. // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug
  280. // can't truncate with `| 0`
  281. a = (t1 + t2) >>> 0;
  282. }
  283. // update hash state
  284. s.h0 = (s.h0 + a) | 0;
  285. s.h1 = (s.h1 + b) | 0;
  286. s.h2 = (s.h2 + c) | 0;
  287. s.h3 = (s.h3 + d) | 0;
  288. s.h4 = (s.h4 + e) | 0;
  289. s.h5 = (s.h5 + f) | 0;
  290. s.h6 = (s.h6 + g) | 0;
  291. s.h7 = (s.h7 + h) | 0;
  292. len -= 64;
  293. }
  294. }