Created
February 20, 2013 21:10
-
-
Save 19h/4999648 to your computer and use it in GitHub Desktop.
A compact V8-ECMAScript ("Javascript") implementation of the Scrypt-hashing algorithm.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var j = void 0, | |
| k = require("crypto"); | |
| function m(a) { | |
| for (var b = a.length, c = Array(b), f = 0; f < b; f++) c[f] = a.charCodeAt(f); | |
| return c | |
| } | |
| var p, q, s; | |
| function t() { | |
| q = [1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225]; | |
| p = []; | |
| s = 0 | |
| } | |
| function A(a) { | |
| p = "string" == typeof a ? p.concat(m(a)) : p.concat(a); | |
| for (var b = 0; b + 64 <= p.length; b += 64) B(q, p.slice(b, b + 64)); | |
| p = p.slice(b); | |
| s += a.length | |
| } | |
| function C() { | |
| p[p.length] = 128; | |
| if (56 < p.length) { | |
| for (var a = p.length; 64 > a; a++) p[a] = 0; | |
| B(q, p); | |
| p.length = 0 | |
| } | |
| for (a = p.length; 59 > a; a++) p[a] = 0; | |
| p[59] = s >>> 29 & 255; | |
| p[60] = s >>> 21 & 255; | |
| p[61] = s >>> 13 & 255; | |
| p[62] = s >>> 5 & 255; | |
| p[63] = s << 3 & 255; | |
| B(q, p); | |
| for (var b = Array(32), a = 0; 8 > a; a++) b[4 * a + 0] = q[a] >>> 24, b[4 * a + 1] = q[a] >> 16 & 255, b[4 * a + 2] = q[a] >> 8 & 255, b[4 * a + 3] = q[a] & 255; | |
| delete q; | |
| delete p; | |
| delete s; | |
| return b | |
| } | |
| var D; | |
| SHA256_hexchars = "0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f".split(","); | |
| SHA256_K = [1116352408, 1899447441, 3049323471, 3921009573, 961987163, 1508970993, 2453635748, 2870763221, 3624381080, 310598401, 607225278, 1426881987, 1925078388, 2162078206, 2614888103, 3248222580, 3835390401, 4022224774, 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, 2554220882, 2821834349, 2952996808, 3210313671, 3336571891, 3584528711, 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, 1695183700, 1986661051, 2177026350, 2456956037, 2730485921, 2820302411, 3259730800, 3345764771, 3516065817, 3600352804, | |
| 4094571909, 275423344, 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, 1537002063, 1747873779, 1955562222, 2024104815, 2227730452, 2361852424, 2428436474, 2756734187, 3204031479, 3329325298]; | |
| function B(a, b) { | |
| for (var c = Array(16), f = 0; 16 > f; f++) c[f] = b[4 * f + 0] << 24 | b[4 * f + 1] << 16 | b[4 * f + 2] << 8 | b[4 * f + 3]; | |
| for (f = 16; 64 > f; f++) c[f] = ((c[f - 2] >>> 17 | c[f - 2] << 15) ^ (c[f - 2] >>> 19 | c[f - 2] << 13) ^ c[f - 2] >>> 10) + c[f - 7] + ((c[f - 15] >>> 7 | c[f - 15] << 25) ^ (c[f - 15] >>> 18 | c[f - 15] << 14) ^ c[f - 15] >>> 3) + c[f - 16] & 4294967295; | |
| for (var d = [].concat(a), f = 0; 64 > f; f++) { | |
| var i = d[7] + ((d[4] >>> 6 | d[4] << 26) ^ (d[4] >>> 11 | d[4] << 21) ^ (d[4] >>> 25 | d[4] << 7)) + (d[6] ^ d[4] & (d[5] ^ d[6])) + SHA256_K[f] + c[f], | |
| h = ((d[0] >>> 2 | d[0] << 30) ^ (d[0] >>> 13 | d[0] << 19) ^ (d[0] >>> 22 | d[0] << 10)) + (d[0] & d[1] ^ d[2] & (d[0] ^ d[1])); | |
| d.pop(); | |
| d.unshift(i + h & 4294967295); | |
| d[4] = d[4] + i & 4294967295 | |
| } | |
| for (f = 0; 8 > f; f++) a[f] = a[f] + d[f] & 4294967295 | |
| } | |
| sha256 = { | |
| n: function (a) { | |
| D = "string" == typeof a ? m(a) : [].concat(a); | |
| 64 < D.length && (t(), A(D), D = C()); | |
| for (a = D.length; 64 > a; a++) D[a] = 0; | |
| for (a = 0; 64 > a; a++) D[a] ^= 54; | |
| t(); | |
| A(D) | |
| }, | |
| update: function (a) { | |
| A(a) | |
| }, | |
| c: function () { | |
| for (var a = C(), b = 0; 64 > b; b++) D[b] ^= 106; | |
| t(); | |
| A(D); | |
| A(a); | |
| for (b = 0; 64 > b; b++) D[b] = 0; | |
| delete D; | |
| return C() | |
| } | |
| }; | |
| function E(a, b, c, f, d) { | |
| for (; d--;) c[f++] = a[b++] | |
| } | |
| PBKDF = function (a, b, c, f) { | |
| if (f > 32 * (Math.pow(2, 32) - 1)) throw Error("Requested key length too long"); | |
| var d = [], | |
| i = [], | |
| h = [], | |
| e = Math.ceil(f / 32), | |
| f = f - 32 * (e - 1); | |
| E(b, 0, h, 0, b.length); | |
| for (var g = 1; g <= e; g++) { | |
| h[b.length + 0] = g >> 24 & 255; | |
| h[b.length + 1] = g >> 16 & 255; | |
| h[b.length + 2] = g >> 8 & 255; | |
| h[b.length + 3] = g >> 0 & 255; | |
| sha256.n(a); | |
| sha256.update(h); | |
| d = sha256.c(); | |
| E(d, 0, i, 0, 32); | |
| for (var r = 1; 1 > r; r++) { | |
| sha256.update(d); | |
| for (var d = sha256.c(), l = 0; 32 > l; l++) i[l] ^= d[l] | |
| } | |
| E(i, 0, c, 32 * (g - 1), g == e ? f : 32) | |
| } | |
| }; | |
| function F() { | |
| this.toString = function () { | |
| return "BUG: " + this.message | |
| }; | |
| this.message = "random: addEntropy only supports number, array or string" | |
| } | |
| function G(a, b) { | |
| if (0 === a.length || 0 === b.length) return a.concat(b); | |
| var c = a[a.length - 1], | |
| f = H(c), | |
| d; | |
| if (32 === f) d = a.concat(b); | |
| else { | |
| d = b; | |
| var c = c | 0, | |
| i = a.slice(0, a.length - 1), | |
| h; | |
| for (i === j && (i = []); 32 <= f; f -= 32) i.push(c), c = 0; | |
| if (0 === f) d = i.concat(d); | |
| else { | |
| for (h = 0; h < d.length; h++) i.push(c | d[h] >>> f), c = d[h] << 32 - f; | |
| h = d.length ? d[d.length - 1] : 0; | |
| d = H(h); | |
| i.push(I(f + d & 31, 32 < f + d ? c : i.pop(), 1)); | |
| d = i | |
| } | |
| } | |
| return d | |
| } | |
| function I(a, b, c) { | |
| return 32 === a ? b : (c ? b | 0 : b << 32 - a) + 1099511627776 * a | |
| } | |
| function H(a) { | |
| return Math.round(a / 1099511627776) || 32 | |
| } | |
| function J(a) { | |
| this.e[0] || this.q(); | |
| a ? (this.d = a.d.slice(0), this.b = a.b.slice(0), this.a = a.a) : this.reset() | |
| } | |
| J.hash = function (a) { | |
| return (new J).update(a).c() | |
| }; | |
| J.prototype = { | |
| reset: function () { | |
| this.d = this.i.slice(0); | |
| this.b = []; | |
| this.a = 0; | |
| return this | |
| }, | |
| update: function (a) { | |
| if ("string" === typeof a) { | |
| var a = unescape(encodeURIComponent(a)), | |
| b = [], | |
| c, f = 0; | |
| for (c = 0; c < a.length; c++) f = f << 8 | a.charCodeAt(c), 3 === (c & 3) && (b.push(f), f = 0); | |
| c & 3 && b.push(I(8 * (c & 3), f)); | |
| a = b | |
| } | |
| c = this.b = G(this.b, a); | |
| b = this.a; | |
| f = a.length; | |
| a = this.a = b + (0 === f ? 0 : 32 * (f - 1) + H(a[f - 1])); | |
| for (b = 512 + b & -512; b <= a; b += 512) this.h(c.splice(0, 16)); | |
| return this | |
| }, | |
| c: function () { | |
| var a, b = this.b, | |
| c = this.d, | |
| b = G(b, [I(1, 1)]); | |
| for (a = b.length + 2; a & 15; a++) b.push(0); | |
| b.push(Math.floor(this.a / 4294967296)); | |
| for (b.push(this.a | 0); b.length;) this.h(b.splice(0, 16)); | |
| this.reset(); | |
| return c | |
| }, | |
| i: [], | |
| e: [], | |
| q: function () { | |
| var a = 0, | |
| b = 2, | |
| c; | |
| a: for (; 64 > a; b++) { | |
| for (c = 2; c * c <= b; c++) if (0 === b % c) continue a; | |
| 8 > a && (this.i[a] = 4294967296 * (Math.pow(b, 0.5) - Math.floor(Math.pow(b, 0.5))) | 0); | |
| this.e[a] = 4294967296 * (Math.pow(b, 1 / 3) - Math.floor(Math.pow(b, 1 / 3))) | 0; | |
| a++ | |
| } | |
| }, | |
| h: function (a) { | |
| for (var b, c, f = a.slice(0), d = this.d, i = this.e, h = d[0], e = d[1], g = d[2], r = d[3], l = d[4], w = d[5], n = d[6], x = d[7], a = 0; 64 > a; a++) 16 > a ? b = f[a] : (b = f[a + 1 & 15], c = f[a + 14 & 15], b = f[a & 15] = (b >>> 7 ^ b >>> 18 ^ b >>> 3 ^ b << 25 ^ b << 14) + (c >>> 17 ^ c >>> 19 ^ c >>> 10 ^ c << 15 ^ c << 13) + f[a & 15] + f[a + 9 & 15] | 0), b = b + x + (l >>> 6 ^ l >>> 11 ^ l >>> 25 ^ l << 26 ^ l << 21 ^ l << 7) + (n ^ l & (w ^ n)) + i[a], x = n, n = w, w = l, l = r + b | 0, r = g, g = e, e = h, h = b + (e & g ^ r & (e ^ g)) + (e >>> 2 ^ e >>> 13 ^ e >>> 22 ^ e << 30 ^ e << 19 ^ e << 10) | 0; | |
| d[0] = d[0] + h | 0; | |
| d[1] = d[1] + e | 0; | |
| d[2] = d[2] + g | 0; | |
| d[3] = d[3] + r | 0; | |
| d[4] = d[4] + l | 0; | |
| d[5] = d[5] + w | 0; | |
| d[6] = d[6] + n | 0; | |
| d[7] = d[7] + x | 0 | |
| } | |
| }; | |
| function K() { | |
| var a = L, | |
| b = 1024, | |
| c; | |
| c = "crypto['getRandomValues']"; | |
| var f, d, i = (new Date).valueOf(), | |
| h = this.g[c], | |
| e = this.o(); | |
| f = this.k[c]; | |
| f === j && (f = this.k[c] = this.r++); | |
| h === j && (h = this.g[c] = 0); | |
| this.g[c] = (this.g[c] + 1) % this.f.length; | |
| switch (typeof a) { | |
| case "number": | |
| break; | |
| case "object": | |
| if (b === j) for (c = b = 0; c < a.length; c++) for (d = a[c]; 0 < d;) b++, d >>>= 1; | |
| this.f[h].update([f, this.l++, 2, b, i, a.length].concat(a)); | |
| break; | |
| case "string": | |
| b === j && (b = a.length); | |
| this.f[h].update([f, this.l++, 3, b, i, a.length]); | |
| this.f[h].update(a); | |
| break; | |
| default: | |
| throw new F; | |
| } | |
| this.p[h] += b; | |
| this.j += b; | |
| 0 === e && (0 !== this.o() && this.m("seeded", Math.max(this.t, this.j)), this.m("progress", this.u())) | |
| } | |
| new J; | |
| try { | |
| var L = new Uint32Array(32); | |
| k.v(L); | |
| K() | |
| } catch (M) {} | |
| k = require("crypto"); | |
| require("util"); | |
| var N = 2147483647; | |
| function scrypt(a, b, c, f, d, i) { | |
| if (0 == c || 0 != (c & c - 1)) throw Error("N must be > 0 and a power of 2"); | |
| if (c > N / 128 / f) throw Error("Parameter N is too large"); | |
| if (f > N / 128 / d) throw Error("Parameter r is too large"); | |
| var h = [], | |
| e = [], | |
| g = [], | |
| r = []; | |
| PBKDF(a, new Buffer(b, encoding = "utf8"), e, 128 * d * f); | |
| for (b = 0; b < d; b++) { | |
| var l = e, | |
| w = 128 * b * f, | |
| n = f, | |
| x = c, | |
| O = r, | |
| o = g, | |
| u = 128 * n, | |
| y = j; | |
| E(l, w, o, 0, u); | |
| for (y = 0; y < x; y++) E(o, 0, O, y * u, u), Q(o, u, n); | |
| for (y = 0; y < x; y++) { | |
| var z = 0, | |
| v = j, | |
| z = z + 64 * (2 * n - 1), | |
| v = (o[z + 0] & 255) << 0, | |
| v = v | (o[z + 1] & 255) << 8, | |
| v = v | (o[z + 2] & 255) << 16, | |
| v = v | (o[z + 3] & 255) << 24; | |
| R(O, (v & x - 1) * u, o, u); | |
| Q(o, u, n) | |
| } | |
| E(o, 0, l, w, u) | |
| } | |
| PBKDF(a, e, h, i); | |
| return (new Buffer(h, "base64")).toString("base64") | |
| } | |
| function Q(a, b, c) { | |
| var f = [], | |
| d; | |
| S(a, 0 + 64 * (2 * c - 1), f, 0); | |
| for (d = 0; d < 2 * c; d++) { | |
| R(a, 64 * d, f, 64); | |
| for (var i = f, h = Array(32), e = Array(32), g = j, g = 0; 16 > g; g++) h[g] = (i[4 * g + 0] & 255) << 0, h[g] |= (i[4 * g + 1] & 255) << 8, h[g] |= (i[4 * g + 2] & 255) << 16, h[g] |= (i[4 * g + 3] & 255) << 24; | |
| E(h, 0, e, 0, 16); | |
| for (g = 8; 0 < g; g -= 2) e[4] ^= T(e[0] + e[12], 7), e[8] ^= T(e[4] + e[0], 9), e[12] ^= T(e[8] + e[4], 13), e[0] ^= T(e[12] + e[8], 18), e[9] ^= T(e[5] + e[1], 7), e[13] ^= T(e[9] + e[5], 9), e[1] ^= T(e[13] + e[9], 13), e[5] ^= T(e[1] + e[13], 18), e[14] ^= T(e[10] + e[6], 7), e[2] ^= T(e[14] + e[10], 9), e[6] ^= T(e[2] + e[14], 13), e[10] ^= T(e[6] + e[2], 18), e[3] ^= T(e[15] + e[11], 7), e[7] ^= T(e[3] + e[15], 9), e[11] ^= T(e[7] + e[3], 13), e[15] ^= T(e[11] + e[7], 18), e[1] ^= T(e[0] + e[3], 7), e[2] ^= T(e[1] + e[0], 9), e[3] ^= T(e[2] + e[1], 13), e[0] ^= T(e[3] + e[2], 18), e[6] ^= T(e[5] + e[4], 7), e[7] ^= T(e[6] + e[5], 9), e[4] ^= T(e[7] + e[6], 13), e[5] ^= T(e[4] + e[7], 18), e[11] ^= T(e[10] + e[9], 7), e[8] ^= T(e[11] + e[10], 9), e[9] ^= T(e[8] + e[11], 13), e[10] ^= T(e[9] + e[8], 18), e[12] ^= T(e[15] + e[14], 7), e[13] ^= T(e[12] + e[15], 9), e[14] ^= T(e[13] + e[12], 13), e[15] ^= T(e[14] + e[13], 18); | |
| for (g = 0; 16 > g; ++g) h[g] = e[g] + h[g]; | |
| for (g = 0; 16 > g; g++) e = 4 * g, i[e + 0] = h[g] >> 0 & 255, i[e + 1] = h[g] >> 8 & 255, i[e + 2] = h[g] >> 16 & 255, i[e + 3] = h[g] >> 24 & 255; | |
| S(f, 0, a, b + 64 * d) | |
| } | |
| for (d = 0; d < c; d++) S(a, b + 128 * d, a, 0 + 64 * d); | |
| for (d = 0; d < c; d++) S(a, b + 64 * (2 * d + 1), a, 0 + 64 * (d + c)) | |
| } | |
| function T(a, b) { | |
| return a << b | a >>> 32 - b | |
| } | |
| function R(a, b, c, f) { | |
| for (var d = 0, f = f >> 6; f--;) c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++], c[d++] ^= a[b++] | |
| } | |
| function E(a, b, c, f, d) { | |
| for (; d--;) c[f++] = a[b++] | |
| } | |
| function scrypt(a, b, c, f) { | |
| for (var d = 2; d--;) c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++], c[f++] = a[b++] | |
| } | |
| exports.scrypt = P; | |
| //scrypt("key", "salt", 32, 8, 4096, 32); // see |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment