browserSha256.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. var Buffer = require('buffer/').Buffer;
  2. var hashUtils = require('./browserHashUtils');
  3. var BLOCK_SIZE = 64;
  4. var DIGEST_LENGTH = 32;
  5. var KEY = new Uint32Array([
  6. 0x428a2f98,
  7. 0x71374491,
  8. 0xb5c0fbcf,
  9. 0xe9b5dba5,
  10. 0x3956c25b,
  11. 0x59f111f1,
  12. 0x923f82a4,
  13. 0xab1c5ed5,
  14. 0xd807aa98,
  15. 0x12835b01,
  16. 0x243185be,
  17. 0x550c7dc3,
  18. 0x72be5d74,
  19. 0x80deb1fe,
  20. 0x9bdc06a7,
  21. 0xc19bf174,
  22. 0xe49b69c1,
  23. 0xefbe4786,
  24. 0x0fc19dc6,
  25. 0x240ca1cc,
  26. 0x2de92c6f,
  27. 0x4a7484aa,
  28. 0x5cb0a9dc,
  29. 0x76f988da,
  30. 0x983e5152,
  31. 0xa831c66d,
  32. 0xb00327c8,
  33. 0xbf597fc7,
  34. 0xc6e00bf3,
  35. 0xd5a79147,
  36. 0x06ca6351,
  37. 0x14292967,
  38. 0x27b70a85,
  39. 0x2e1b2138,
  40. 0x4d2c6dfc,
  41. 0x53380d13,
  42. 0x650a7354,
  43. 0x766a0abb,
  44. 0x81c2c92e,
  45. 0x92722c85,
  46. 0xa2bfe8a1,
  47. 0xa81a664b,
  48. 0xc24b8b70,
  49. 0xc76c51a3,
  50. 0xd192e819,
  51. 0xd6990624,
  52. 0xf40e3585,
  53. 0x106aa070,
  54. 0x19a4c116,
  55. 0x1e376c08,
  56. 0x2748774c,
  57. 0x34b0bcb5,
  58. 0x391c0cb3,
  59. 0x4ed8aa4a,
  60. 0x5b9cca4f,
  61. 0x682e6ff3,
  62. 0x748f82ee,
  63. 0x78a5636f,
  64. 0x84c87814,
  65. 0x8cc70208,
  66. 0x90befffa,
  67. 0xa4506ceb,
  68. 0xbef9a3f7,
  69. 0xc67178f2
  70. ]);
  71. var INIT = [
  72. 0x6a09e667,
  73. 0xbb67ae85,
  74. 0x3c6ef372,
  75. 0xa54ff53a,
  76. 0x510e527f,
  77. 0x9b05688c,
  78. 0x1f83d9ab,
  79. 0x5be0cd19,
  80. ];
  81. var MAX_HASHABLE_LENGTH = Math.pow(2, 53) - 1;
  82. /**
  83. * @private
  84. */
  85. function Sha256() {
  86. this.state = [
  87. 0x6a09e667,
  88. 0xbb67ae85,
  89. 0x3c6ef372,
  90. 0xa54ff53a,
  91. 0x510e527f,
  92. 0x9b05688c,
  93. 0x1f83d9ab,
  94. 0x5be0cd19,
  95. ];
  96. this.temp = new Int32Array(64);
  97. this.buffer = new Uint8Array(64);
  98. this.bufferLength = 0;
  99. this.bytesHashed = 0;
  100. /**
  101. * @private
  102. */
  103. this.finished = false;
  104. }
  105. /**
  106. * @api private
  107. */
  108. module.exports = exports = Sha256;
  109. Sha256.BLOCK_SIZE = BLOCK_SIZE;
  110. Sha256.prototype.update = function (data) {
  111. if (this.finished) {
  112. throw new Error('Attempted to update an already finished hash.');
  113. }
  114. if (hashUtils.isEmptyData(data)) {
  115. return this;
  116. }
  117. data = hashUtils.convertToBuffer(data);
  118. var position = 0;
  119. var byteLength = data.byteLength;
  120. this.bytesHashed += byteLength;
  121. if (this.bytesHashed * 8 > MAX_HASHABLE_LENGTH) {
  122. throw new Error('Cannot hash more than 2^53 - 1 bits');
  123. }
  124. while (byteLength > 0) {
  125. this.buffer[this.bufferLength++] = data[position++];
  126. byteLength--;
  127. if (this.bufferLength === BLOCK_SIZE) {
  128. this.hashBuffer();
  129. this.bufferLength = 0;
  130. }
  131. }
  132. return this;
  133. };
  134. Sha256.prototype.digest = function (encoding) {
  135. if (!this.finished) {
  136. var bitsHashed = this.bytesHashed * 8;
  137. var bufferView = new DataView(this.buffer.buffer, this.buffer.byteOffset, this.buffer.byteLength);
  138. var undecoratedLength = this.bufferLength;
  139. bufferView.setUint8(this.bufferLength++, 0x80);
  140. // Ensure the final block has enough room for the hashed length
  141. if (undecoratedLength % BLOCK_SIZE >= BLOCK_SIZE - 8) {
  142. for (var i = this.bufferLength; i < BLOCK_SIZE; i++) {
  143. bufferView.setUint8(i, 0);
  144. }
  145. this.hashBuffer();
  146. this.bufferLength = 0;
  147. }
  148. for (var i = this.bufferLength; i < BLOCK_SIZE - 8; i++) {
  149. bufferView.setUint8(i, 0);
  150. }
  151. bufferView.setUint32(BLOCK_SIZE - 8, Math.floor(bitsHashed / 0x100000000), true);
  152. bufferView.setUint32(BLOCK_SIZE - 4, bitsHashed);
  153. this.hashBuffer();
  154. this.finished = true;
  155. }
  156. // The value in state is little-endian rather than big-endian, so flip
  157. // each word into a new Uint8Array
  158. var out = new Buffer(DIGEST_LENGTH);
  159. for (var i = 0; i < 8; i++) {
  160. out[i * 4] = (this.state[i] >>> 24) & 0xff;
  161. out[i * 4 + 1] = (this.state[i] >>> 16) & 0xff;
  162. out[i * 4 + 2] = (this.state[i] >>> 8) & 0xff;
  163. out[i * 4 + 3] = (this.state[i] >>> 0) & 0xff;
  164. }
  165. return encoding ? out.toString(encoding) : out;
  166. };
  167. Sha256.prototype.hashBuffer = function () {
  168. var _a = this,
  169. buffer = _a.buffer,
  170. state = _a.state;
  171. var state0 = state[0],
  172. state1 = state[1],
  173. state2 = state[2],
  174. state3 = state[3],
  175. state4 = state[4],
  176. state5 = state[5],
  177. state6 = state[6],
  178. state7 = state[7];
  179. for (var i = 0; i < BLOCK_SIZE; i++) {
  180. if (i < 16) {
  181. this.temp[i] = (((buffer[i * 4] & 0xff) << 24) |
  182. ((buffer[(i * 4) + 1] & 0xff) << 16) |
  183. ((buffer[(i * 4) + 2] & 0xff) << 8) |
  184. (buffer[(i * 4) + 3] & 0xff));
  185. }
  186. else {
  187. var u = this.temp[i - 2];
  188. var t1_1 = (u >>> 17 | u << 15) ^
  189. (u >>> 19 | u << 13) ^
  190. (u >>> 10);
  191. u = this.temp[i - 15];
  192. var t2_1 = (u >>> 7 | u << 25) ^
  193. (u >>> 18 | u << 14) ^
  194. (u >>> 3);
  195. this.temp[i] = (t1_1 + this.temp[i - 7] | 0) +
  196. (t2_1 + this.temp[i - 16] | 0);
  197. }
  198. var t1 = (((((state4 >>> 6 | state4 << 26) ^
  199. (state4 >>> 11 | state4 << 21) ^
  200. (state4 >>> 25 | state4 << 7))
  201. + ((state4 & state5) ^ (~state4 & state6))) | 0)
  202. + ((state7 + ((KEY[i] + this.temp[i]) | 0)) | 0)) | 0;
  203. var t2 = (((state0 >>> 2 | state0 << 30) ^
  204. (state0 >>> 13 | state0 << 19) ^
  205. (state0 >>> 22 | state0 << 10)) + ((state0 & state1) ^ (state0 & state2) ^ (state1 & state2))) | 0;
  206. state7 = state6;
  207. state6 = state5;
  208. state5 = state4;
  209. state4 = (state3 + t1) | 0;
  210. state3 = state2;
  211. state2 = state1;
  212. state1 = state0;
  213. state0 = (t1 + t2) | 0;
  214. }
  215. state[0] += state0;
  216. state[1] += state1;
  217. state[2] += state2;
  218. state[3] += state3;
  219. state[4] += state4;
  220. state[5] += state5;
  221. state[6] += state6;
  222. state[7] += state7;
  223. };