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 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