Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: lib/rusha.js

Issue 29354773: Issue 4465 - Move rsa module from adblockpluschrome (Closed)
Patch Set: Add btoa and navigator stub Created Sept. 25, 2016, 1:17 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/rsa.js ('k') | test/signatures.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 (function () {
2 var /*
3 * Rusha, a JavaScript implementation of the Secure Hash Algorithm, SHA-1,
4 * as defined in FIPS PUB 180-1, tuned for high performance with large inputs.
5 * (http://github.com/srijs/rusha)
6 *
7 * Inspired by Paul Johnstons implementation (http://pajhome.org.uk/crypt/md5).
8 *
9 * Copyright (c) 2013 Sam Rijs (http://awesam.de).
10 * Released under the terms of the MIT license as follows:
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28 * IN THE SOFTWARE.
29 */
30 util = {
31 getDataType: function (data) {
32 if (typeof data === 'string') {
33 return 'string';
34 }
35 if (data instanceof Array) {
36 return 'array';
37 }
38 if (typeof global !== 'undefined' && global.Buffer && global.Buffer. isBuffer(data)) {
39 return 'buffer';
40 }
41 if (data instanceof ArrayBuffer) {
42 return 'arraybuffer';
43 }
44 if (data.buffer instanceof ArrayBuffer) {
45 return 'view';
46 }
47 if (data instanceof Blob) {
48 return 'blob';
49 }
50 throw new Error('Unsupported data type.');
51 }
52 };
53 function Rusha(chunkSize) {
54 'use strict';
55 var // Private object structure.
56 self$2 = { fill: 0 };
57 var // Calculate the length of buffer that the sha1 routine uses
58 // including the padding.
59 padlen = function (len) {
60 for (len += 9; len % 64 > 0; len += 1);
61 return len;
62 };
63 var padZeroes = function (bin, len) {
64 for (var i$2 = len >> 2; i$2 < bin.length; i$2++)
65 bin[i$2] = 0;
66 };
67 var padData = function (bin, chunkLen, msgLen) {
68 bin[chunkLen >> 2] |= 128 << 24 - (chunkLen % 4 << 3);
69 // To support msgLen >= 2 GiB, use a float division when computing t he
70 // high 32-bits of the big-endian message length in bits.
71 bin[((chunkLen >> 2) + 2 & ~15) + 14] = msgLen / (1 << 29) | 0;
72 bin[((chunkLen >> 2) + 2 & ~15) + 15] = msgLen << 3;
73 };
74 var // Convert a binary string and write it to the heap.
75 // A binary string is expected to only contain char codes < 256.
76 convStr = function (H8, H32, start, len, off) {
77 var str = this, i$2, om = off % 4, lm = len % 4, j = len - lm;
78 if (j > 0) {
79 switch (om) {
80 case 0:
81 H8[off + 3 | 0] = str.charCodeAt(start);
82 case 1:
83 H8[off + 2 | 0] = str.charCodeAt(start + 1);
84 case 2:
85 H8[off + 1 | 0] = str.charCodeAt(start + 2);
86 case 3:
87 H8[off | 0] = str.charCodeAt(start + 3);
88 }
89 }
90 for (i$2 = om; i$2 < j; i$2 = i$2 + 4 | 0) {
91 H32[off + i$2 >> 2] = str.charCodeAt(start + i$2) << 24 | str.ch arCodeAt(start + i$2 + 1) << 16 | str.charCodeAt(start + i$2 + 2) << 8 | str.cha rCodeAt(start + i$2 + 3);
92 }
93 switch (lm) {
94 case 3:
95 H8[off + j + 1 | 0] = str.charCodeAt(start + j + 2);
96 case 2:
97 H8[off + j + 2 | 0] = str.charCodeAt(start + j + 1);
98 case 1:
99 H8[off + j + 3 | 0] = str.charCodeAt(start + j);
100 }
101 };
102 var // Convert a buffer or array and write it to the heap.
103 // The buffer or array is expected to only contain elements < 256.
104 convBuf = function (H8, H32, start, len, off) {
105 var buf = this, i$2, om = off % 4, lm = len % 4, j = len - lm;
106 if (j > 0) {
107 switch (om) {
108 case 0:
109 H8[off + 3 | 0] = buf[start];
110 case 1:
111 H8[off + 2 | 0] = buf[start + 1];
112 case 2:
113 H8[off + 1 | 0] = buf[start + 2];
114 case 3:
115 H8[off | 0] = buf[start + 3];
116 }
117 }
118 for (i$2 = 4 - om; i$2 < j; i$2 = i$2 += 4 | 0) {
119 H32[off + i$2 >> 2] = buf[start + i$2] << 24 | buf[start + i$2 + 1] << 16 | buf[start + i$2 + 2] << 8 | buf[start + i$2 + 3];
120 }
121 switch (lm) {
122 case 3:
123 H8[off + j + 1 | 0] = buf[start + j + 2];
124 case 2:
125 H8[off + j + 2 | 0] = buf[start + j + 1];
126 case 1:
127 H8[off + j + 3 | 0] = buf[start + j];
128 }
129 };
130 var convBlob = function (H8, H32, start, len, off) {
131 var blob = this, i$2, om = off % 4, lm = len % 4, j = len - lm;
132 var buf = new Uint8Array(reader.readAsArrayBuffer(blob.slice(start, start + len)));
133 if (j > 0) {
134 switch (om) {
135 case 0:
136 H8[off + 3 | 0] = buf[0];
137 case 1:
138 H8[off + 2 | 0] = buf[1];
139 case 2:
140 H8[off + 1 | 0] = buf[2];
141 case 3:
142 H8[off | 0] = buf[3];
143 }
144 }
145 for (i$2 = 4 - om; i$2 < j; i$2 = i$2 += 4 | 0) {
146 H32[off + i$2 >> 2] = buf[i$2] << 24 | buf[i$2 + 1] << 16 | buf[ i$2 + 2] << 8 | buf[i$2 + 3];
147 }
148 switch (lm) {
149 case 3:
150 H8[off + j + 1 | 0] = buf[j + 2];
151 case 2:
152 H8[off + j + 2 | 0] = buf[j + 1];
153 case 1:
154 H8[off + j + 3 | 0] = buf[j];
155 }
156 };
157 var convFn = function (data) {
158 switch (util.getDataType(data)) {
159 case 'string':
160 return convStr.bind(data);
161 case 'array':
162 return convBuf.bind(data);
163 case 'buffer':
164 return convBuf.bind(data);
165 case 'arraybuffer':
166 return convBuf.bind(new Uint8Array(data));
167 case 'view':
168 return convBuf.bind(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));
169 case 'blob':
170 return convBlob.bind(data);
171 }
172 };
173 var slice = function (data, offset) {
174 switch (util.getDataType(data)) {
175 case 'string':
176 return data.slice(offset);
177 case 'array':
178 return data.slice(offset);
179 case 'buffer':
180 return data.slice(offset);
181 case 'arraybuffer':
182 return data.slice(offset);
183 case 'view':
184 return data.buffer.slice(offset);
185 }
186 };
187 var // Precompute 00 - ff strings
188 precomputedHex = new Array(256);
189 for (var i = 0; i < 256; i++) {
190 precomputedHex[i] = (i < 16 ? '0' : '') + i.toString(16);
191 }
192 var // Convert an ArrayBuffer into its hexadecimal string representation .
193 hex = function (arrayBuffer) {
194 var binarray = new Uint8Array(arrayBuffer);
195 var res = new Array(arrayBuffer.byteLength);
196 for (var i$2 = 0; i$2 < res.length; i$2++) {
197 res[i$2] = precomputedHex[binarray[i$2]];
198 }
199 return res.join('');
200 };
201 var ceilHeapSize = function (v) {
202 // The asm.js spec says:
203 // The heap object's byteLength must be either
204 // 2^n for n in [12, 24) or 2^24 * n for n ≥ 1.
205 // Also, byteLengths smaller than 2^16 are deprecated.
206 var p;
207 if (// If v is smaller than 2^16, the smallest possible solution
208 // is 2^16.
209 v <= 65536)
210 return 65536;
211 if (// If v < 2^24, we round up to 2^n,
212 // otherwise we round up to 2^24 * n.
213 v < 16777216) {
214 for (p = 1; p < v; p = p << 1);
215 } else {
216 for (p = 16777216; p < v; p += 16777216);
217 }
218 return p;
219 };
220 var // Initialize the internal data structures to a new capacity.
221 init = function (size) {
222 if (size % 64 > 0) {
223 throw new Error('Chunk size must be a multiple of 128 bit');
224 }
225 self$2.maxChunkLen = size;
226 self$2.padMaxChunkLen = padlen(size);
227 // The size of the heap is the sum of:
228 // 1. The padded input message size
229 // 2. The extended space the algorithm needs (320 byte)
230 // 3. The 160 bit state the algoritm uses
231 self$2.heap = new ArrayBuffer(ceilHeapSize(self$2.padMaxChunkLen + 3 20 + 20));
232 self$2.h32 = new Int32Array(self$2.heap);
233 self$2.h8 = new Int8Array(self$2.heap);
234 self$2.core = new Rusha._core({
235 Int32Array: Int32Array,
236 DataView: DataView
237 }, {}, self$2.heap);
238 self$2.buffer = null;
239 };
240 // Iinitializethe datastructures according
241 // to a chunk siyze.
242 init(chunkSize || 64 * 1024);
243 var initState = function (heap, padMsgLen) {
244 var io = new Int32Array(heap, padMsgLen + 320, 5);
245 io[0] = 1732584193;
246 io[1] = -271733879;
247 io[2] = -1732584194;
248 io[3] = 271733878;
249 io[4] = -1009589776;
250 };
251 var padChunk = function (chunkLen, msgLen) {
252 var padChunkLen = padlen(chunkLen);
253 var view = new Int32Array(self$2.heap, 0, padChunkLen >> 2);
254 padZeroes(view, chunkLen);
255 padData(view, chunkLen, msgLen);
256 return padChunkLen;
257 };
258 var // Write data to the heap.
259 write = function (data, chunkOffset, chunkLen) {
260 convFn(data)(self$2.h8, self$2.h32, chunkOffset, chunkLen, 0);
261 };
262 var // Initialize and call the RushaCore,
263 // assuming an input buffer of length len * 4.
264 coreCall = function (data, chunkOffset, chunkLen, msgLen, finalize) {
265 var padChunkLen = chunkLen;
266 if (finalize) {
267 padChunkLen = padChunk(chunkLen, msgLen);
268 }
269 write(data, chunkOffset, chunkLen);
270 self$2.core.hash(padChunkLen, self$2.padMaxChunkLen);
271 };
272 var getRawDigest = function (heap, padMaxChunkLen) {
273 var io = new Int32Array(heap, padMaxChunkLen + 320, 5);
274 var out = new Int32Array(5);
275 var arr = new DataView(out.buffer);
276 arr.setInt32(0, io[0], false);
277 arr.setInt32(4, io[1], false);
278 arr.setInt32(8, io[2], false);
279 arr.setInt32(12, io[3], false);
280 arr.setInt32(16, io[4], false);
281 return out;
282 };
283 var // Calculate the hash digest as an array of 5 32bit integers.
284 rawDigest = this.rawDigest = function (str) {
285 var msgLen = str.byteLength || str.length || str.size || 0;
286 initState(self$2.heap, self$2.padMaxChunkLen);
287 var chunkOffset = 0, chunkLen = self$2.maxChunkLen, last;
288 for (chunkOffset = 0; msgLen > chunkOffset + chunkLen; chunkOffset + = chunkLen) {
289 coreCall(str, chunkOffset, chunkLen, msgLen, false);
290 }
291 coreCall(str, chunkOffset, msgLen - chunkOffset, msgLen, true);
292 return getRawDigest(self$2.heap, self$2.padMaxChunkLen);
293 };
294 // The digest and digestFrom* interface returns the hash digest
295 // as a hex string.
296 this.digest = this.digestFromString = this.digestFromBuffer = this.diges tFromArrayBuffer = function (str) {
297 return hex(rawDigest(str).buffer);
298 };
299 }
300 ;
301 // The low-level RushCore module provides the heart of Rusha,
302 // a high-speed sha1 implementation working on an Int32Array heap.
303 // At first glance, the implementation seems complicated, however
304 // with the SHA1 spec at hand, it is obvious this almost a textbook
305 // implementation that has a few functions hand-inlined and a few loops
306 // hand-unrolled.
307 Rusha._core = function RushaCore(stdlib, foreign, heap) {
308 'use asm';
309 var H = new stdlib.Int32Array(heap);
310 function hash(k, x) {
311 // k in bytes
312 k = k | 0;
313 x = x | 0;
314 var i = 0, j = 0, y0 = 0, z0 = 0, y1 = 0, z1 = 0, y2 = 0, z2 = 0, y3 = 0, z3 = 0, y4 = 0, z4 = 0, t0 = 0, t1 = 0;
315 y0 = H[x + 320 >> 2] | 0;
316 y1 = H[x + 324 >> 2] | 0;
317 y2 = H[x + 328 >> 2] | 0;
318 y3 = H[x + 332 >> 2] | 0;
319 y4 = H[x + 336 >> 2] | 0;
320 for (i = 0; (i | 0) < (k | 0); i = i + 64 | 0) {
321 z0 = y0;
322 z1 = y1;
323 z2 = y2;
324 z3 = y3;
325 z4 = y4;
326 for (j = 0; (j | 0) < 64; j = j + 4 | 0) {
327 t1 = H[i + j >> 2] | 0;
328 t0 = ((y0 << 5 | y0 >>> 27) + (y1 & y2 | ~y1 & y3) | 0) + (( t1 + y4 | 0) + 1518500249 | 0) | 0;
329 y4 = y3;
330 y3 = y2;
331 y2 = y1 << 30 | y1 >>> 2;
332 y1 = y0;
333 y0 = t0;
334 H[k + j >> 2] = t1;
335 }
336 for (j = k + 64 | 0; (j | 0) < (k + 80 | 0); j = j + 4 | 0) {
337 t1 = (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) << 1 | (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) >>> 31;
338 t0 = ((y0 << 5 | y0 >>> 27) + (y1 & y2 | ~y1 & y3) | 0) + (( t1 + y4 | 0) + 1518500249 | 0) | 0;
339 y4 = y3;
340 y3 = y2;
341 y2 = y1 << 30 | y1 >>> 2;
342 y1 = y0;
343 y0 = t0;
344 H[j >> 2] = t1;
345 }
346 for (j = k + 80 | 0; (j | 0) < (k + 160 | 0); j = j + 4 | 0) {
347 t1 = (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) << 1 | (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) >>> 31;
348 t0 = ((y0 << 5 | y0 >>> 27) + (y1 ^ y2 ^ y3) | 0) + ((t1 + y 4 | 0) + 1859775393 | 0) | 0;
349 y4 = y3;
350 y3 = y2;
351 y2 = y1 << 30 | y1 >>> 2;
352 y1 = y0;
353 y0 = t0;
354 H[j >> 2] = t1;
355 }
356 for (j = k + 160 | 0; (j | 0) < (k + 240 | 0); j = j + 4 | 0) {
357 t1 = (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) << 1 | (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) >>> 31;
358 t0 = ((y0 << 5 | y0 >>> 27) + (y1 & y2 | y1 & y3 | y2 & y3) | 0) + ((t1 + y4 | 0) - 1894007588 | 0) | 0;
359 y4 = y3;
360 y3 = y2;
361 y2 = y1 << 30 | y1 >>> 2;
362 y1 = y0;
363 y0 = t0;
364 H[j >> 2] = t1;
365 }
366 for (j = k + 240 | 0; (j | 0) < (k + 320 | 0); j = j + 4 | 0) {
367 t1 = (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) << 1 | (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) >>> 31;
368 t0 = ((y0 << 5 | y0 >>> 27) + (y1 ^ y2 ^ y3) | 0) + ((t1 + y 4 | 0) - 899497514 | 0) | 0;
369 y4 = y3;
370 y3 = y2;
371 y2 = y1 << 30 | y1 >>> 2;
372 y1 = y0;
373 y0 = t0;
374 H[j >> 2] = t1;
375 }
376 y0 = y0 + z0 | 0;
377 y1 = y1 + z1 | 0;
378 y2 = y2 + z2 | 0;
379 y3 = y3 + z3 | 0;
380 y4 = y4 + z4 | 0;
381 }
382 H[x + 320 >> 2] = y0;
383 H[x + 324 >> 2] = y1;
384 H[x + 328 >> 2] = y2;
385 H[x + 332 >> 2] = y3;
386 H[x + 336 >> 2] = y4;
387 }
388 return { hash: hash };
389 };
390 exports = Rusha;
391 if (// If we'e running in Node.JS, export a module.
392 typeof module !== 'undefined') {
393 module.exports = Rusha;
394 } else {// If we're running in Adblock Plus, export a module.
395 exports = Rusha;
396 }
397 if (// If we're running in a webworker, accept
398 // messages containing a jobid and a buffer
399 // or blob object, and return the hash result.
400 typeof FileReaderSync !== 'undefined') {
401 var reader = new FileReaderSync(), hasher = new Rusha(4 * 1024 * 1024);
402 self.onmessage = function onMessage(event) {
403 var hash, data = event.data.data;
404 try {
405 hash = hasher.digest(data);
406 self.postMessage({
407 id: event.data.id,
408 hash: hash
409 });
410 } catch (e) {
411 self.postMessage({
412 id: event.data.id,
413 error: e.name
414 });
415 }
416 };
417 }
418 }());
OLDNEW
« no previous file with comments | « lib/rsa.js ('k') | test/signatures.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld