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