Rusha

A JavaScript implementation of the Secure Hash Algorithm, SHA-1

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.cn-greasyfork.org/scripts/13017/79803/Rusha.js

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