scrypt-async-modern
Advanced tools
Comparing version 3.0.0 to 3.0.1
@@ -5,5 +5,5 @@ var scrypt = (function () { | ||
/*! | ||
* Fast "async" scrypt implementation in JavaScript. | ||
* Copyright (c) 2013-2016 Dmitry Chestnykh | BSD License | ||
* https://github.com/dchest/scrypt-async-js | ||
* Fast "async" scrypt implementation in modern JavaScript. | ||
* Copyright (c) 2018 Charles Crete | MIT License | ||
* https://github.com/Cretezy/scrypt-async-modern | ||
*/ | ||
@@ -42,659 +42,564 @@ | ||
*/ | ||
function scrypt(password, | ||
salt, | ||
{ N: n = 16384, logN, r = 8, p = 1, dkLen = 32, interruptStep = 0, encoding } = {}) { | ||
return new Promise((resolve, reject) => { | ||
function SHA256(m) { | ||
const K = [ | ||
0x428a2f98, | ||
0x71374491, | ||
0xb5c0fbcf, | ||
0xe9b5dba5, | ||
0x3956c25b, | ||
0x59f111f1, | ||
0x923f82a4, | ||
0xab1c5ed5, | ||
0xd807aa98, | ||
0x12835b01, | ||
0x243185be, | ||
0x550c7dc3, | ||
0x72be5d74, | ||
0x80deb1fe, | ||
0x9bdc06a7, | ||
0xc19bf174, | ||
0xe49b69c1, | ||
0xefbe4786, | ||
0x0fc19dc6, | ||
0x240ca1cc, | ||
0x2de92c6f, | ||
0x4a7484aa, | ||
0x5cb0a9dc, | ||
0x76f988da, | ||
0x983e5152, | ||
0xa831c66d, | ||
0xb00327c8, | ||
0xbf597fc7, | ||
0xc6e00bf3, | ||
0xd5a79147, | ||
0x06ca6351, | ||
0x14292967, | ||
0x27b70a85, | ||
0x2e1b2138, | ||
0x4d2c6dfc, | ||
0x53380d13, | ||
0x650a7354, | ||
0x766a0abb, | ||
0x81c2c92e, | ||
0x92722c85, | ||
0xa2bfe8a1, | ||
0xa81a664b, | ||
0xc24b8b70, | ||
0xc76c51a3, | ||
0xd192e819, | ||
0xd6990624, | ||
0xf40e3585, | ||
0x106aa070, | ||
0x19a4c116, | ||
0x1e376c08, | ||
0x2748774c, | ||
0x34b0bcb5, | ||
0x391c0cb3, | ||
0x4ed8aa4a, | ||
0x5b9cca4f, | ||
0x682e6ff3, | ||
0x748f82ee, | ||
0x78a5636f, | ||
0x84c87814, | ||
0x8cc70208, | ||
0x90befffa, | ||
0xa4506ceb, | ||
0xbef9a3f7, | ||
0xc67178f2 | ||
]; | ||
function scrypt(password, salt) { | ||
var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, | ||
_ref$N = _ref.N, | ||
N = _ref$N === void 0 ? 16384 : _ref$N, | ||
logN = _ref.logN, | ||
_ref$r = _ref.r, | ||
r = _ref$r === void 0 ? 8 : _ref$r, | ||
_ref$p = _ref.p, | ||
p = _ref$p === void 0 ? 1 : _ref$p, | ||
_ref$dkLen = _ref.dkLen, | ||
dkLen = _ref$dkLen === void 0 ? 32 : _ref$dkLen, | ||
_ref$interruptStep = _ref.interruptStep, | ||
interruptStep = _ref$interruptStep === void 0 ? 0 : _ref$interruptStep, | ||
encoding = _ref.encoding; | ||
let h0 = 0x6a09e667, | ||
h1 = 0xbb67ae85, | ||
h2 = 0x3c6ef372, | ||
h3 = 0xa54ff53a, | ||
h4 = 0x510e527f, | ||
h5 = 0x9b05688c, | ||
h6 = 0x1f83d9ab, | ||
h7 = 0x5be0cd19, | ||
w = new Array(64); | ||
return new Promise(function (resolve, reject) { | ||
if (!logN && !N) { | ||
return reject(new Error("scrypt: missing N or logN parameter")); | ||
} | ||
function blocks(p) { | ||
let off = 0, | ||
len = p.length; | ||
while (len >= 64) { | ||
let a = h0, | ||
b = h1, | ||
c = h2, | ||
d = h3, | ||
e = h4, | ||
f = h5, | ||
g = h6, | ||
h = h7, | ||
u, | ||
i, | ||
j, | ||
t1, | ||
t2; | ||
if (logN || logN === 0) { | ||
if (logN < 1 || logN > 31) { | ||
return reject(new Error("scrypt: logN must be between 1 and 31")); | ||
} | ||
for (i = 0; i < 16; i++) { | ||
j = off + i * 4; | ||
w[i] = | ||
((p[j] & 0xff) << 24) | | ||
((p[j + 1] & 0xff) << 16) | | ||
((p[j + 2] & 0xff) << 8) | | ||
(p[j + 3] & 0xff); | ||
} | ||
N = 1 << logN >>> 0; | ||
} else { | ||
if (N < 2 || N > MAX_UINT) { | ||
return reject(new Error("scrypt: N is out of range")); | ||
} else if ((N & N - 1) !== 0) { | ||
return reject(Error("scrypt: N is not a power of 2")); | ||
} | ||
} | ||
for (i = 16; i < 64; i++) { | ||
u = w[i - 2]; | ||
t1 = | ||
((u >>> 17) | (u << (32 - 17))) ^ | ||
((u >>> 19) | (u << (32 - 19))) ^ | ||
(u >>> 10); | ||
if (p < 1) { | ||
return reject(new Error("scrypt: invalid p")); | ||
} | ||
u = w[i - 15]; | ||
t2 = | ||
((u >>> 7) | (u << (32 - 7))) ^ | ||
((u >>> 18) | (u << (32 - 18))) ^ | ||
(u >>> 3); | ||
if (r <= 0) { | ||
return reject(new Error("scrypt: invalid r")); | ||
} | ||
w[i] = (((t1 + w[i - 7]) | 0) + ((t2 + w[i - 16]) | 0)) | 0; | ||
} | ||
run({ | ||
password: password, | ||
salt: salt, | ||
N: N, | ||
r: r, | ||
p: p, | ||
dkLen: dkLen, | ||
interruptStep: interruptStep, | ||
encoding: encoding | ||
}, resolve); | ||
}); | ||
} // Internal scrypt function | ||
for (i = 0; i < 64; i++) { | ||
t1 = | ||
((((((e >>> 6) | (e << (32 - 6))) ^ | ||
((e >>> 11) | (e << (32 - 11))) ^ | ||
((e >>> 25) | (e << (32 - 25)))) + | ||
((e & f) ^ (~e & g))) | | ||
0) + | ||
((h + ((K[i] + w[i]) | 0)) | 0)) | | ||
0; | ||
function run(_ref2, callback) { | ||
var password = _ref2.password, | ||
salt = _ref2.salt, | ||
N = _ref2.N, | ||
r = _ref2.r, | ||
p = _ref2.p, | ||
dkLen = _ref2.dkLen, | ||
interruptStep = _ref2.interruptStep, | ||
encoding = _ref2.encoding; | ||
t2 = | ||
((((a >>> 2) | (a << (32 - 2))) ^ | ||
((a >>> 13) | (a << (32 - 13))) ^ | ||
((a >>> 22) | (a << (32 - 22)))) + | ||
((a & b) ^ (a & c) ^ (b & c))) | | ||
0; | ||
function SHA256(m) { | ||
var K = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2]; | ||
var h0 = 0x6a09e667, | ||
h1 = 0xbb67ae85, | ||
h2 = 0x3c6ef372, | ||
h3 = 0xa54ff53a, | ||
h4 = 0x510e527f, | ||
h5 = 0x9b05688c, | ||
h6 = 0x1f83d9ab, | ||
h7 = 0x5be0cd19, | ||
w = new Array(64); | ||
h = g; | ||
g = f; | ||
f = e; | ||
e = (d + t1) | 0; | ||
d = c; | ||
c = b; | ||
b = a; | ||
a = (t1 + t2) | 0; | ||
} | ||
function blocks(p) { | ||
var off = 0, | ||
len = p.length; | ||
h0 = (h0 + a) | 0; | ||
h1 = (h1 + b) | 0; | ||
h2 = (h2 + c) | 0; | ||
h3 = (h3 + d) | 0; | ||
h4 = (h4 + e) | 0; | ||
h5 = (h5 + f) | 0; | ||
h6 = (h6 + g) | 0; | ||
h7 = (h7 + h) | 0; | ||
while (len >= 64) { | ||
var a = h0, | ||
b = h1, | ||
c = h2, | ||
d = h3, | ||
e = h4, | ||
f = h5, | ||
g = h6, | ||
h = h7, | ||
u = void 0, | ||
_i = void 0, | ||
j = void 0, | ||
t1 = void 0, | ||
t2 = void 0; | ||
off += 64; | ||
len -= 64; | ||
} | ||
} | ||
for (_i = 0; _i < 16; _i++) { | ||
j = off + _i * 4; | ||
w[_i] = (p[j] & 0xff) << 24 | (p[j + 1] & 0xff) << 16 | (p[j + 2] & 0xff) << 8 | p[j + 3] & 0xff; | ||
} | ||
blocks(m); | ||
for (_i = 16; _i < 64; _i++) { | ||
u = w[_i - 2]; | ||
t1 = (u >>> 17 | u << 32 - 17) ^ (u >>> 19 | u << 32 - 19) ^ u >>> 10; | ||
u = w[_i - 15]; | ||
t2 = (u >>> 7 | u << 32 - 7) ^ (u >>> 18 | u << 32 - 18) ^ u >>> 3; | ||
w[_i] = (t1 + w[_i - 7] | 0) + (t2 + w[_i - 16] | 0) | 0; | ||
} | ||
let i, | ||
bytesLeft = m.length % 64, | ||
bitLenHi = (m.length / 0x20000000) | 0, | ||
bitLenLo = m.length << 3, | ||
numZeros = bytesLeft < 56 ? 56 : 120, | ||
p = m.slice(m.length - bytesLeft, m.length); | ||
for (_i = 0; _i < 64; _i++) { | ||
t1 = (((e >>> 6 | e << 32 - 6) ^ (e >>> 11 | e << 32 - 11) ^ (e >>> 25 | e << 32 - 25)) + (e & f ^ ~e & g) | 0) + (h + (K[_i] + w[_i] | 0) | 0) | 0; | ||
t2 = ((a >>> 2 | a << 32 - 2) ^ (a >>> 13 | a << 32 - 13) ^ (a >>> 22 | a << 32 - 22)) + (a & b ^ a & c ^ b & c) | 0; | ||
h = g; | ||
g = f; | ||
f = e; | ||
e = d + t1 | 0; | ||
d = c; | ||
c = b; | ||
b = a; | ||
a = t1 + t2 | 0; | ||
} | ||
p.push(0x80); | ||
for (i = bytesLeft + 1; i < numZeros; i++) p.push(0); | ||
p.push((bitLenHi >>> 24) & 0xff); | ||
p.push((bitLenHi >>> 16) & 0xff); | ||
p.push((bitLenHi >>> 8) & 0xff); | ||
p.push((bitLenHi >>> 0) & 0xff); | ||
p.push((bitLenLo >>> 24) & 0xff); | ||
p.push((bitLenLo >>> 16) & 0xff); | ||
p.push((bitLenLo >>> 8) & 0xff); | ||
p.push((bitLenLo >>> 0) & 0xff); | ||
h0 = h0 + a | 0; | ||
h1 = h1 + b | 0; | ||
h2 = h2 + c | 0; | ||
h3 = h3 + d | 0; | ||
h4 = h4 + e | 0; | ||
h5 = h5 + f | 0; | ||
h6 = h6 + g | 0; | ||
h7 = h7 + h | 0; | ||
off += 64; | ||
len -= 64; | ||
} | ||
} | ||
blocks(p); | ||
blocks(m); | ||
var i, | ||
bytesLeft = m.length % 64, | ||
bitLenHi = m.length / 0x20000000 | 0, | ||
bitLenLo = m.length << 3, | ||
numZeros = bytesLeft < 56 ? 56 : 120, | ||
p = m.slice(m.length - bytesLeft, m.length); | ||
p.push(0x80); | ||
return [ | ||
(h0 >>> 24) & 0xff, | ||
(h0 >>> 16) & 0xff, | ||
(h0 >>> 8) & 0xff, | ||
(h0 >>> 0) & 0xff, | ||
(h1 >>> 24) & 0xff, | ||
(h1 >>> 16) & 0xff, | ||
(h1 >>> 8) & 0xff, | ||
(h1 >>> 0) & 0xff, | ||
(h2 >>> 24) & 0xff, | ||
(h2 >>> 16) & 0xff, | ||
(h2 >>> 8) & 0xff, | ||
(h2 >>> 0) & 0xff, | ||
(h3 >>> 24) & 0xff, | ||
(h3 >>> 16) & 0xff, | ||
(h3 >>> 8) & 0xff, | ||
(h3 >>> 0) & 0xff, | ||
(h4 >>> 24) & 0xff, | ||
(h4 >>> 16) & 0xff, | ||
(h4 >>> 8) & 0xff, | ||
(h4 >>> 0) & 0xff, | ||
(h5 >>> 24) & 0xff, | ||
(h5 >>> 16) & 0xff, | ||
(h5 >>> 8) & 0xff, | ||
(h5 >>> 0) & 0xff, | ||
(h6 >>> 24) & 0xff, | ||
(h6 >>> 16) & 0xff, | ||
(h6 >>> 8) & 0xff, | ||
(h6 >>> 0) & 0xff, | ||
(h7 >>> 24) & 0xff, | ||
(h7 >>> 16) & 0xff, | ||
(h7 >>> 8) & 0xff, | ||
(h7 >>> 0) & 0xff | ||
]; | ||
} | ||
for (i = bytesLeft + 1; i < numZeros; i++) { | ||
p.push(0); | ||
} | ||
function PBKDF2_HMAC_SHA256_OneIter(password, salt, dkLen) { | ||
// compress password if it's longer than hash block length | ||
password = password.length <= 64 ? password : SHA256(password); | ||
p.push(bitLenHi >>> 24 & 0xff); | ||
p.push(bitLenHi >>> 16 & 0xff); | ||
p.push(bitLenHi >>> 8 & 0xff); | ||
p.push(bitLenHi >>> 0 & 0xff); | ||
p.push(bitLenLo >>> 24 & 0xff); | ||
p.push(bitLenLo >>> 16 & 0xff); | ||
p.push(bitLenLo >>> 8 & 0xff); | ||
p.push(bitLenLo >>> 0 & 0xff); | ||
blocks(p); | ||
return [h0 >>> 24 & 0xff, h0 >>> 16 & 0xff, h0 >>> 8 & 0xff, h0 >>> 0 & 0xff, h1 >>> 24 & 0xff, h1 >>> 16 & 0xff, h1 >>> 8 & 0xff, h1 >>> 0 & 0xff, h2 >>> 24 & 0xff, h2 >>> 16 & 0xff, h2 >>> 8 & 0xff, h2 >>> 0 & 0xff, h3 >>> 24 & 0xff, h3 >>> 16 & 0xff, h3 >>> 8 & 0xff, h3 >>> 0 & 0xff, h4 >>> 24 & 0xff, h4 >>> 16 & 0xff, h4 >>> 8 & 0xff, h4 >>> 0 & 0xff, h5 >>> 24 & 0xff, h5 >>> 16 & 0xff, h5 >>> 8 & 0xff, h5 >>> 0 & 0xff, h6 >>> 24 & 0xff, h6 >>> 16 & 0xff, h6 >>> 8 & 0xff, h6 >>> 0 & 0xff, h7 >>> 24 & 0xff, h7 >>> 16 & 0xff, h7 >>> 8 & 0xff, h7 >>> 0 & 0xff]; | ||
} | ||
let i, | ||
innerLen = 64 + salt.length + 4, | ||
inner = new Array(innerLen), | ||
outerKey = new Array(64), | ||
dk = []; | ||
function PBKDF2_HMAC_SHA256_OneIter(password, salt, dkLen) { | ||
// compress password if it's longer than hash block length | ||
password = password.length <= 64 ? password : SHA256(password); | ||
var i, | ||
innerLen = 64 + salt.length + 4, | ||
inner = new Array(innerLen), | ||
outerKey = new Array(64), | ||
dk = []; // inner = (password ^ ipad) || salt || counter | ||
// inner = (password ^ ipad) || salt || counter | ||
for (i = 0; i < 64; i++) inner[i] = 0x36; | ||
for (i = 0; i < password.length; i++) inner[i] ^= password[i]; | ||
for (i = 0; i < salt.length; i++) inner[64 + i] = salt[i]; | ||
for (i = innerLen - 4; i < innerLen; i++) inner[i] = 0; | ||
for (i = 0; i < 64; i++) { | ||
inner[i] = 0x36; | ||
} | ||
// outerKey = password ^ opad | ||
for (i = 0; i < 64; i++) outerKey[i] = 0x5c; | ||
for (i = 0; i < password.length; i++) outerKey[i] ^= password[i]; | ||
for (i = 0; i < password.length; i++) { | ||
inner[i] ^= password[i]; | ||
} | ||
// increments counter inside inner | ||
function incrementCounter() { | ||
for (let i = innerLen - 1; i >= innerLen - 4; i--) { | ||
inner[i]++; | ||
if (inner[i] <= 0xff) return; | ||
inner[i] = 0; | ||
} | ||
} | ||
for (i = 0; i < salt.length; i++) { | ||
inner[64 + i] = salt[i]; | ||
} | ||
// output blocks = SHA256(outerKey || SHA256(inner)) ... | ||
while (dkLen >= 32) { | ||
incrementCounter(); | ||
dk = dk.concat(SHA256(outerKey.concat(SHA256(inner)))); | ||
dkLen -= 32; | ||
} | ||
if (dkLen > 0) { | ||
incrementCounter(); | ||
dk = dk.concat(SHA256(outerKey.concat(SHA256(inner))).slice(0, dkLen)); | ||
} | ||
return dk; | ||
} | ||
for (i = innerLen - 4; i < innerLen; i++) { | ||
inner[i] = 0; | ||
} // outerKey = password ^ opad | ||
function salsaXOR(tmp, B, bin, bout) { | ||
let j0 = tmp[0] ^ B[bin++], | ||
j1 = tmp[1] ^ B[bin++], | ||
j2 = tmp[2] ^ B[bin++], | ||
j3 = tmp[3] ^ B[bin++], | ||
j4 = tmp[4] ^ B[bin++], | ||
j5 = tmp[5] ^ B[bin++], | ||
j6 = tmp[6] ^ B[bin++], | ||
j7 = tmp[7] ^ B[bin++], | ||
j8 = tmp[8] ^ B[bin++], | ||
j9 = tmp[9] ^ B[bin++], | ||
j10 = tmp[10] ^ B[bin++], | ||
j11 = tmp[11] ^ B[bin++], | ||
j12 = tmp[12] ^ B[bin++], | ||
j13 = tmp[13] ^ B[bin++], | ||
j14 = tmp[14] ^ B[bin++], | ||
j15 = tmp[15] ^ B[bin++], | ||
u, | ||
i; | ||
let x0 = j0, | ||
x1 = j1, | ||
x2 = j2, | ||
x3 = j3, | ||
x4 = j4, | ||
x5 = j5, | ||
x6 = j6, | ||
x7 = j7, | ||
x8 = j8, | ||
x9 = j9, | ||
x10 = j10, | ||
x11 = j11, | ||
x12 = j12, | ||
x13 = j13, | ||
x14 = j14, | ||
x15 = j15; | ||
for (i = 0; i < 64; i++) { | ||
outerKey[i] = 0x5c; | ||
} | ||
for (i = 0; i < 8; i += 2) { | ||
u = x0 + x12; | ||
x4 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x4 + x0; | ||
x8 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x8 + x4; | ||
x12 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x12 + x8; | ||
x0 ^= (u << 18) | (u >>> (32 - 18)); | ||
for (i = 0; i < password.length; i++) { | ||
outerKey[i] ^= password[i]; | ||
} // increments counter inside inner | ||
u = x5 + x1; | ||
x9 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x9 + x5; | ||
x13 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x13 + x9; | ||
x1 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x1 + x13; | ||
x5 ^= (u << 18) | (u >>> (32 - 18)); | ||
u = x10 + x6; | ||
x14 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x14 + x10; | ||
x2 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x2 + x14; | ||
x6 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x6 + x2; | ||
x10 ^= (u << 18) | (u >>> (32 - 18)); | ||
function incrementCounter() { | ||
for (var _i2 = innerLen - 1; _i2 >= innerLen - 4; _i2--) { | ||
inner[_i2]++; | ||
if (inner[_i2] <= 0xff) return; | ||
inner[_i2] = 0; | ||
} | ||
} // output blocks = SHA256(outerKey || SHA256(inner)) ... | ||
u = x15 + x11; | ||
x3 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x3 + x15; | ||
x7 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x7 + x3; | ||
x11 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x11 + x7; | ||
x15 ^= (u << 18) | (u >>> (32 - 18)); | ||
u = x0 + x3; | ||
x1 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x1 + x0; | ||
x2 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x2 + x1; | ||
x3 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x3 + x2; | ||
x0 ^= (u << 18) | (u >>> (32 - 18)); | ||
while (dkLen >= 32) { | ||
incrementCounter(); | ||
dk = dk.concat(SHA256(outerKey.concat(SHA256(inner)))); | ||
dkLen -= 32; | ||
} | ||
u = x5 + x4; | ||
x6 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x6 + x5; | ||
x7 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x7 + x6; | ||
x4 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x4 + x7; | ||
x5 ^= (u << 18) | (u >>> (32 - 18)); | ||
if (dkLen > 0) { | ||
incrementCounter(); | ||
dk = dk.concat(SHA256(outerKey.concat(SHA256(inner))).slice(0, dkLen)); | ||
} | ||
u = x10 + x9; | ||
x11 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x11 + x10; | ||
x8 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x8 + x11; | ||
x9 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x9 + x8; | ||
x10 ^= (u << 18) | (u >>> (32 - 18)); | ||
return dk; | ||
} | ||
u = x15 + x14; | ||
x12 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x12 + x15; | ||
x13 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x13 + x12; | ||
x14 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x14 + x13; | ||
x15 ^= (u << 18) | (u >>> (32 - 18)); | ||
} | ||
function salsaXOR(tmp, B, bin, bout) { | ||
var j0 = tmp[0] ^ B[bin++], | ||
j1 = tmp[1] ^ B[bin++], | ||
j2 = tmp[2] ^ B[bin++], | ||
j3 = tmp[3] ^ B[bin++], | ||
j4 = tmp[4] ^ B[bin++], | ||
j5 = tmp[5] ^ B[bin++], | ||
j6 = tmp[6] ^ B[bin++], | ||
j7 = tmp[7] ^ B[bin++], | ||
j8 = tmp[8] ^ B[bin++], | ||
j9 = tmp[9] ^ B[bin++], | ||
j10 = tmp[10] ^ B[bin++], | ||
j11 = tmp[11] ^ B[bin++], | ||
j12 = tmp[12] ^ B[bin++], | ||
j13 = tmp[13] ^ B[bin++], | ||
j14 = tmp[14] ^ B[bin++], | ||
j15 = tmp[15] ^ B[bin++], | ||
u, | ||
i; | ||
var x0 = j0, | ||
x1 = j1, | ||
x2 = j2, | ||
x3 = j3, | ||
x4 = j4, | ||
x5 = j5, | ||
x6 = j6, | ||
x7 = j7, | ||
x8 = j8, | ||
x9 = j9, | ||
x10 = j10, | ||
x11 = j11, | ||
x12 = j12, | ||
x13 = j13, | ||
x14 = j14, | ||
x15 = j15; | ||
B[bout++] = tmp[0] = (x0 + j0) | 0; | ||
B[bout++] = tmp[1] = (x1 + j1) | 0; | ||
B[bout++] = tmp[2] = (x2 + j2) | 0; | ||
B[bout++] = tmp[3] = (x3 + j3) | 0; | ||
B[bout++] = tmp[4] = (x4 + j4) | 0; | ||
B[bout++] = tmp[5] = (x5 + j5) | 0; | ||
B[bout++] = tmp[6] = (x6 + j6) | 0; | ||
B[bout++] = tmp[7] = (x7 + j7) | 0; | ||
B[bout++] = tmp[8] = (x8 + j8) | 0; | ||
B[bout++] = tmp[9] = (x9 + j9) | 0; | ||
B[bout++] = tmp[10] = (x10 + j10) | 0; | ||
B[bout++] = tmp[11] = (x11 + j11) | 0; | ||
B[bout++] = tmp[12] = (x12 + j12) | 0; | ||
B[bout++] = tmp[13] = (x13 + j13) | 0; | ||
B[bout++] = tmp[14] = (x14 + j14) | 0; | ||
B[bout++] = tmp[15] = (x15 + j15) | 0; | ||
} | ||
for (i = 0; i < 8; i += 2) { | ||
u = x0 + x12; | ||
x4 ^= u << 7 | u >>> 32 - 7; | ||
u = x4 + x0; | ||
x8 ^= u << 9 | u >>> 32 - 9; | ||
u = x8 + x4; | ||
x12 ^= u << 13 | u >>> 32 - 13; | ||
u = x12 + x8; | ||
x0 ^= u << 18 | u >>> 32 - 18; | ||
u = x5 + x1; | ||
x9 ^= u << 7 | u >>> 32 - 7; | ||
u = x9 + x5; | ||
x13 ^= u << 9 | u >>> 32 - 9; | ||
u = x13 + x9; | ||
x1 ^= u << 13 | u >>> 32 - 13; | ||
u = x1 + x13; | ||
x5 ^= u << 18 | u >>> 32 - 18; | ||
u = x10 + x6; | ||
x14 ^= u << 7 | u >>> 32 - 7; | ||
u = x14 + x10; | ||
x2 ^= u << 9 | u >>> 32 - 9; | ||
u = x2 + x14; | ||
x6 ^= u << 13 | u >>> 32 - 13; | ||
u = x6 + x2; | ||
x10 ^= u << 18 | u >>> 32 - 18; | ||
u = x15 + x11; | ||
x3 ^= u << 7 | u >>> 32 - 7; | ||
u = x3 + x15; | ||
x7 ^= u << 9 | u >>> 32 - 9; | ||
u = x7 + x3; | ||
x11 ^= u << 13 | u >>> 32 - 13; | ||
u = x11 + x7; | ||
x15 ^= u << 18 | u >>> 32 - 18; | ||
u = x0 + x3; | ||
x1 ^= u << 7 | u >>> 32 - 7; | ||
u = x1 + x0; | ||
x2 ^= u << 9 | u >>> 32 - 9; | ||
u = x2 + x1; | ||
x3 ^= u << 13 | u >>> 32 - 13; | ||
u = x3 + x2; | ||
x0 ^= u << 18 | u >>> 32 - 18; | ||
u = x5 + x4; | ||
x6 ^= u << 7 | u >>> 32 - 7; | ||
u = x6 + x5; | ||
x7 ^= u << 9 | u >>> 32 - 9; | ||
u = x7 + x6; | ||
x4 ^= u << 13 | u >>> 32 - 13; | ||
u = x4 + x7; | ||
x5 ^= u << 18 | u >>> 32 - 18; | ||
u = x10 + x9; | ||
x11 ^= u << 7 | u >>> 32 - 7; | ||
u = x11 + x10; | ||
x8 ^= u << 9 | u >>> 32 - 9; | ||
u = x8 + x11; | ||
x9 ^= u << 13 | u >>> 32 - 13; | ||
u = x9 + x8; | ||
x10 ^= u << 18 | u >>> 32 - 18; | ||
u = x15 + x14; | ||
x12 ^= u << 7 | u >>> 32 - 7; | ||
u = x12 + x15; | ||
x13 ^= u << 9 | u >>> 32 - 9; | ||
u = x13 + x12; | ||
x14 ^= u << 13 | u >>> 32 - 13; | ||
u = x14 + x13; | ||
x15 ^= u << 18 | u >>> 32 - 18; | ||
} | ||
function blockCopy(dst, di, src, si, len) { | ||
while (len--) dst[di++] = src[si++]; | ||
} | ||
B[bout++] = tmp[0] = x0 + j0 | 0; | ||
B[bout++] = tmp[1] = x1 + j1 | 0; | ||
B[bout++] = tmp[2] = x2 + j2 | 0; | ||
B[bout++] = tmp[3] = x3 + j3 | 0; | ||
B[bout++] = tmp[4] = x4 + j4 | 0; | ||
B[bout++] = tmp[5] = x5 + j5 | 0; | ||
B[bout++] = tmp[6] = x6 + j6 | 0; | ||
B[bout++] = tmp[7] = x7 + j7 | 0; | ||
B[bout++] = tmp[8] = x8 + j8 | 0; | ||
B[bout++] = tmp[9] = x9 + j9 | 0; | ||
B[bout++] = tmp[10] = x10 + j10 | 0; | ||
B[bout++] = tmp[11] = x11 + j11 | 0; | ||
B[bout++] = tmp[12] = x12 + j12 | 0; | ||
B[bout++] = tmp[13] = x13 + j13 | 0; | ||
B[bout++] = tmp[14] = x14 + j14 | 0; | ||
B[bout++] = tmp[15] = x15 + j15 | 0; | ||
} | ||
function blockXOR(dst, di, src, si, len) { | ||
while (len--) dst[di++] ^= src[si++]; | ||
} | ||
function blockCopy(dst, di, src, si, len) { | ||
while (len--) { | ||
dst[di++] = src[si++]; | ||
} | ||
} | ||
function blockMix(tmp, B, bin, bout, r) { | ||
blockCopy(tmp, 0, B, bin + (2 * r - 1) * 16, 16); | ||
for (let i = 0; i < 2 * r; i += 2) { | ||
salsaXOR(tmp, B, bin + i * 16, bout + i * 8); | ||
salsaXOR(tmp, B, bin + i * 16 + 16, bout + i * 8 + r * 16); | ||
} | ||
} | ||
function blockXOR(dst, di, src, si, len) { | ||
while (len--) { | ||
dst[di++] ^= src[si++]; | ||
} | ||
} | ||
function integerify(B, bi, r) { | ||
return B[bi + (2 * r - 1) * 16]; | ||
} | ||
function blockMix(tmp, B, bin, bout, r) { | ||
blockCopy(tmp, 0, B, bin + (2 * r - 1) * 16, 16); | ||
function stringToUTF8Bytes(s) { | ||
const arr = []; | ||
for (let i = 0; i < s.length; i++) { | ||
let c = s.charCodeAt(i); | ||
if (c < 0x80) { | ||
arr.push(c); | ||
} else if (c < 0x800) { | ||
arr.push(0xc0 | (c >> 6)); | ||
arr.push(0x80 | (c & 0x3f)); | ||
} else if (c < 0xd800) { | ||
arr.push(0xe0 | (c >> 12)); | ||
arr.push(0x80 | ((c >> 6) & 0x3f)); | ||
arr.push(0x80 | (c & 0x3f)); | ||
} else { | ||
if (i >= s.length - 1) { | ||
throw new Error("invalid string"); | ||
} | ||
i++; // get one more character | ||
c = (c & 0x3ff) << 10; | ||
c |= s.charCodeAt(i) & 0x3ff; | ||
c += 0x10000; | ||
for (var i = 0; i < 2 * r; i += 2) { | ||
salsaXOR(tmp, B, bin + i * 16, bout + i * 8); | ||
salsaXOR(tmp, B, bin + i * 16 + 16, bout + i * 8 + r * 16); | ||
} | ||
} | ||
arr.push(0xf0 | (c >> 18)); | ||
arr.push(0x80 | ((c >> 12) & 0x3f)); | ||
arr.push(0x80 | ((c >> 6) & 0x3f)); | ||
arr.push(0x80 | (c & 0x3f)); | ||
} | ||
} | ||
return arr; | ||
} | ||
function integerify(B, bi, r) { | ||
return B[bi + (2 * r - 1) * 16]; | ||
} | ||
function bytesToHex(p) { | ||
const enc = "0123456789abcdef".split(""); | ||
function stringToUTF8Bytes(s) { | ||
var arr = []; | ||
const len = p.length, | ||
arr = []; | ||
for (var i = 0; i < s.length; i++) { | ||
var c = s.charCodeAt(i); | ||
for (let i = 0; i < len; i++) { | ||
arr.push(enc[(p[i] >>> 4) & 15]); | ||
arr.push(enc[(p[i] >>> 0) & 15]); | ||
} | ||
return arr.join(""); | ||
} | ||
if (c < 0x80) { | ||
arr.push(c); | ||
} else if (c < 0x800) { | ||
arr.push(0xc0 | c >> 6); | ||
arr.push(0x80 | c & 0x3f); | ||
} else if (c < 0xd800) { | ||
arr.push(0xe0 | c >> 12); | ||
arr.push(0x80 | c >> 6 & 0x3f); | ||
arr.push(0x80 | c & 0x3f); | ||
} else { | ||
if (i >= s.length - 1) { | ||
throw new Error("invalid string"); | ||
} | ||
function bytesToBase64(p) { | ||
/** @const */ | ||
const enc = ( | ||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789+/" | ||
).split(""); | ||
i++; // get one more character | ||
const len = p.length, | ||
arr = []; | ||
let i = 0, | ||
a, | ||
b, | ||
c, | ||
t; | ||
c = (c & 0x3ff) << 10; | ||
c |= s.charCodeAt(i) & 0x3ff; | ||
c += 0x10000; | ||
arr.push(0xf0 | c >> 18); | ||
arr.push(0x80 | c >> 12 & 0x3f); | ||
arr.push(0x80 | c >> 6 & 0x3f); | ||
arr.push(0x80 | c & 0x3f); | ||
} | ||
} | ||
while (i < len) { | ||
a = i < len ? p[i++] : 0; | ||
b = i < len ? p[i++] : 0; | ||
c = i < len ? p[i++] : 0; | ||
t = (a << 16) + (b << 8) + c; | ||
arr.push(enc[(t >>> (3 * 6)) & 63]); | ||
arr.push(enc[(t >>> (2 * 6)) & 63]); | ||
arr.push(enc[(t >>> (1 * 6)) & 63]); | ||
arr.push(enc[(t >>> (0 * 6)) & 63]); | ||
} | ||
if (len % 3 > 0) { | ||
arr[arr.length - 1] = "="; | ||
if (len % 3 === 1) arr[arr.length - 2] = "="; | ||
} | ||
return arr.join(""); | ||
} | ||
return arr; | ||
} | ||
// Generate key. | ||
function bytesToHex(p) { | ||
var enc = "0123456789abcdef".split(""); | ||
var len = p.length, | ||
arr = []; | ||
const MAX_UINT = -1 >>> 0; | ||
for (var i = 0; i < len; i++) { | ||
arr.push(enc[p[i] >>> 4 & 15]); | ||
arr.push(enc[p[i] >>> 0 & 15]); | ||
} | ||
if (!logN && !n) { | ||
return reject(new Error("scrypt: missing N or logN parameter")); | ||
} | ||
return arr.join(""); | ||
} | ||
let N; | ||
function bytesToBase64(p) { | ||
/** @const */ | ||
var enc = ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789+/").split(""); | ||
var len = p.length, | ||
arr = []; | ||
var i = 0, | ||
a, | ||
b, | ||
c, | ||
t; | ||
if (logN || logN === 0) { | ||
if (logN < 1 || logN > 31) { | ||
return reject(new Error("scrypt: logN must be between 1 and 31")); | ||
} | ||
while (i < len) { | ||
a = i < len ? p[i++] : 0; | ||
b = i < len ? p[i++] : 0; | ||
c = i < len ? p[i++] : 0; | ||
t = (a << 16) + (b << 8) + c; | ||
arr.push(enc[t >>> 3 * 6 & 63]); | ||
arr.push(enc[t >>> 2 * 6 & 63]); | ||
arr.push(enc[t >>> 1 * 6 & 63]); | ||
arr.push(enc[t >>> 0 * 6 & 63]); | ||
} | ||
N = (1 << logN) >>> 0; | ||
} else { | ||
if (n < 2 || n > MAX_UINT) { | ||
return reject(new Error("scrypt: N is out of range")); | ||
} else if ((n & (n - 1)) !== 0) { | ||
return reject(Error("scrypt: N is not a power of 2")); | ||
} | ||
if (len % 3 > 0) { | ||
arr[arr.length - 1] = "="; | ||
if (len % 3 === 1) arr[arr.length - 2] = "="; | ||
} | ||
N = n; | ||
} | ||
return arr.join(""); | ||
} | ||
if (p < 1) { | ||
return reject(new Error("scrypt: invalid p")); | ||
} | ||
var XY, V, B, tmp; | ||
if (r <= 0) { | ||
return reject(new Error("scrypt: invalid r")); | ||
} | ||
if (r * p >= 1 << 30 || r > MAX_UINT / 128 / p || r > MAX_UINT / 256 || N > MAX_UINT / 128 / r) { | ||
return reject(new Error("scrypt: parameters are too large")); | ||
} // Decode strings. | ||
let XY, V, B, tmp; | ||
if ( | ||
r * p >= 1 << 30 || | ||
r > MAX_UINT / 128 / p || | ||
r > MAX_UINT / 256 || | ||
N > MAX_UINT / 128 / r | ||
) { | ||
return reject(new Error("scrypt: parameters are too large")); | ||
} | ||
if (typeof password === "string") password = stringToUTF8Bytes(password); | ||
if (typeof salt === "string") salt = stringToUTF8Bytes(salt); | ||
// Decode strings. | ||
if (typeof password === "string") password = stringToUTF8Bytes(password); | ||
if (typeof salt === "string") salt = stringToUTF8Bytes(salt); | ||
if (typeof Int32Array !== "undefined") { | ||
//XXX We can use Uint32Array, but Int32Array is faster in Safari. | ||
XY = new Int32Array(64 * r); | ||
V = new Int32Array(32 * N * r); | ||
tmp = new Int32Array(16); | ||
} else { | ||
XY = []; | ||
V = []; | ||
tmp = new Array(16); | ||
} | ||
if (typeof Int32Array !== "undefined") { | ||
//XXX We can use Uint32Array, but Int32Array is faster in Safari. | ||
XY = new Int32Array(64 * r); | ||
V = new Int32Array(32 * N * r); | ||
tmp = new Int32Array(16); | ||
} else { | ||
XY = []; | ||
V = []; | ||
tmp = new Array(16); | ||
} | ||
B = PBKDF2_HMAC_SHA256_OneIter(password, salt, p * 128 * r); | ||
B = PBKDF2_HMAC_SHA256_OneIter(password, salt, p * 128 * r); | ||
var xi = 0, | ||
yi = 32 * r; | ||
const xi = 0, | ||
yi = 32 * r; | ||
function smixStart(pos) { | ||
for (var i = 0; i < 32 * r; i++) { | ||
var j = pos + i * 4; | ||
XY[xi + i] = (B[j + 3] & 0xff) << 24 | (B[j + 2] & 0xff) << 16 | (B[j + 1] & 0xff) << 8 | (B[j + 0] & 0xff) << 0; | ||
} | ||
} | ||
function smixStart(pos) { | ||
for (let i = 0; i < 32 * r; i++) { | ||
const j = pos + i * 4; | ||
XY[xi + i] = | ||
((B[j + 3] & 0xff) << 24) | | ||
((B[j + 2] & 0xff) << 16) | | ||
((B[j + 1] & 0xff) << 8) | | ||
((B[j + 0] & 0xff) << 0); | ||
} | ||
} | ||
function smixStep1(start, end) { | ||
for (var i = start; i < end; i += 2) { | ||
blockCopy(V, i * (32 * r), XY, xi, 32 * r); | ||
blockMix(tmp, XY, xi, yi, r); | ||
blockCopy(V, (i + 1) * (32 * r), XY, yi, 32 * r); | ||
blockMix(tmp, XY, yi, xi, r); | ||
} | ||
} | ||
function smixStep1(start, end) { | ||
for (let i = start; i < end; i += 2) { | ||
blockCopy(V, i * (32 * r), XY, xi, 32 * r); | ||
blockMix(tmp, XY, xi, yi, r); | ||
function smixStep2(start, end) { | ||
for (var i = start; i < end; i += 2) { | ||
var j = integerify(XY, xi, r) & N - 1; | ||
blockXOR(XY, xi, V, j * (32 * r), 32 * r); | ||
blockMix(tmp, XY, xi, yi, r); | ||
j = integerify(XY, yi, r) & N - 1; | ||
blockXOR(XY, yi, V, j * (32 * r), 32 * r); | ||
blockMix(tmp, XY, yi, xi, r); | ||
} | ||
} | ||
blockCopy(V, (i + 1) * (32 * r), XY, yi, 32 * r); | ||
blockMix(tmp, XY, yi, xi, r); | ||
} | ||
} | ||
function smixFinish(pos) { | ||
for (var i = 0; i < 32 * r; i++) { | ||
var j = XY[xi + i]; | ||
B[pos + i * 4 + 0] = j >>> 0 & 0xff; | ||
B[pos + i * 4 + 1] = j >>> 8 & 0xff; | ||
B[pos + i * 4 + 2] = j >>> 16 & 0xff; | ||
B[pos + i * 4 + 3] = j >>> 24 & 0xff; | ||
} | ||
} | ||
function smixStep2(start, end) { | ||
for (let i = start; i < end; i += 2) { | ||
let j = integerify(XY, xi, r) & (N - 1); | ||
blockXOR(XY, xi, V, j * (32 * r), 32 * r); | ||
blockMix(tmp, XY, xi, yi, r); | ||
var nextTick = typeof setImmediate !== "undefined" ? setImmediate : setTimeout; | ||
j = integerify(XY, yi, r) & (N - 1); | ||
blockXOR(XY, yi, V, j * (32 * r), 32 * r); | ||
blockMix(tmp, XY, yi, xi, r); | ||
} | ||
} | ||
function interruptedFor(start, end, step, fn, donefn) { | ||
(function performStep() { | ||
nextTick(function () { | ||
fn(start, start + step < end ? start + step : end); | ||
start += step; | ||
if (start < end) performStep();else donefn(); | ||
}); | ||
})(); | ||
} | ||
function smixFinish(pos) { | ||
for (let i = 0; i < 32 * r; i++) { | ||
const j = XY[xi + i]; | ||
B[pos + i * 4 + 0] = (j >>> 0) & 0xff; | ||
B[pos + i * 4 + 1] = (j >>> 8) & 0xff; | ||
B[pos + i * 4 + 2] = (j >>> 16) & 0xff; | ||
B[pos + i * 4 + 3] = (j >>> 24) & 0xff; | ||
} | ||
} | ||
function getResult(enc) { | ||
var result = PBKDF2_HMAC_SHA256_OneIter(password, B, dkLen); | ||
if (enc === "base64") return bytesToBase64(result);else if (enc === "hex") return bytesToHex(result);else if (enc === "binary") return new Uint8Array(result);else return result; | ||
} // Blocking variant. | ||
const nextTick = | ||
typeof setImmediate !== "undefined" ? setImmediate : setTimeout; | ||
function interruptedFor(start, end, step, fn, donefn) { | ||
(function performStep() { | ||
nextTick(function () { | ||
fn(start, start + step < end ? start + step : end); | ||
start += step; | ||
if (start < end) performStep(); | ||
else donefn(); | ||
}); | ||
})(); | ||
} | ||
function calculateSync() { | ||
for (var i = 0; i < p; i++) { | ||
smixStart(i * 128 * r); | ||
smixStep1(0, N); | ||
smixStep2(0, N); | ||
smixFinish(i * 128 * r); | ||
} | ||
function getResult(enc) { | ||
const result = PBKDF2_HMAC_SHA256_OneIter(password, B, dkLen); | ||
if (enc === "base64") return bytesToBase64(result); | ||
else if (enc === "hex") return bytesToHex(result); | ||
else if (enc === "binary") return new Uint8Array(result); | ||
else return result; | ||
} | ||
callback(getResult(encoding)); | ||
} // Async variant. | ||
// Blocking variant. | ||
function calculateSync() { | ||
for (let i = 0; i < p; i++) { | ||
smixStart(i * 128 * r); | ||
smixStep1(0, N); | ||
smixStep2(0, N); | ||
smixFinish(i * 128 * r); | ||
} | ||
resolve(getResult(encoding)); | ||
} | ||
// Async variant. | ||
function calculateAsync(i) { | ||
smixStart(i * 128 * r); | ||
interruptedFor(0, N, interruptStep * 2, smixStep1, function () { | ||
interruptedFor(0, N, interruptStep * 2, smixStep2, function () { | ||
smixFinish(i * 128 * r); | ||
if (i + 1 < p) { | ||
nextTick(function () { | ||
calculateAsync(i + 1); | ||
}); | ||
} else { | ||
resolve(getResult(encoding)); | ||
} | ||
}); | ||
}); | ||
} | ||
function calculateAsync(i) { | ||
smixStart(i * 128 * r); | ||
interruptedFor(0, N, interruptStep * 2, smixStep1, function () { | ||
interruptedFor(0, N, interruptStep * 2, smixStep2, function () { | ||
smixFinish(i * 128 * r); | ||
if (interruptStep <= 0) { | ||
calculateSync(); | ||
} else { | ||
calculateAsync(0); | ||
} | ||
}); | ||
if (i + 1 < p) { | ||
nextTick(function () { | ||
calculateAsync(i + 1); | ||
}); | ||
} else { | ||
callback(getResult(encoding)); | ||
} | ||
}); | ||
}); | ||
} | ||
if (interruptStep <= 0) { | ||
calculateSync(); | ||
} else { | ||
calculateAsync(0); | ||
} | ||
} | ||
var MAX_UINT = -1 >>> 0; | ||
return scrypt; | ||
}()); |
'use strict'; | ||
/*! | ||
* Fast "async" scrypt implementation in JavaScript. | ||
* Copyright (c) 2013-2016 Dmitry Chestnykh | BSD License | ||
* https://github.com/dchest/scrypt-async-js | ||
* Fast "async" scrypt implementation in modern JavaScript. | ||
* Copyright (c) 2018 Charles Crete | MIT License | ||
* https://github.com/Cretezy/scrypt-async-modern | ||
*/ | ||
@@ -40,657 +40,562 @@ | ||
*/ | ||
function scrypt(password, | ||
salt, | ||
{ N: n = 16384, logN, r = 8, p = 1, dkLen = 32, interruptStep = 0, encoding } = {}) { | ||
return new Promise((resolve, reject) => { | ||
function SHA256(m) { | ||
const K = [ | ||
0x428a2f98, | ||
0x71374491, | ||
0xb5c0fbcf, | ||
0xe9b5dba5, | ||
0x3956c25b, | ||
0x59f111f1, | ||
0x923f82a4, | ||
0xab1c5ed5, | ||
0xd807aa98, | ||
0x12835b01, | ||
0x243185be, | ||
0x550c7dc3, | ||
0x72be5d74, | ||
0x80deb1fe, | ||
0x9bdc06a7, | ||
0xc19bf174, | ||
0xe49b69c1, | ||
0xefbe4786, | ||
0x0fc19dc6, | ||
0x240ca1cc, | ||
0x2de92c6f, | ||
0x4a7484aa, | ||
0x5cb0a9dc, | ||
0x76f988da, | ||
0x983e5152, | ||
0xa831c66d, | ||
0xb00327c8, | ||
0xbf597fc7, | ||
0xc6e00bf3, | ||
0xd5a79147, | ||
0x06ca6351, | ||
0x14292967, | ||
0x27b70a85, | ||
0x2e1b2138, | ||
0x4d2c6dfc, | ||
0x53380d13, | ||
0x650a7354, | ||
0x766a0abb, | ||
0x81c2c92e, | ||
0x92722c85, | ||
0xa2bfe8a1, | ||
0xa81a664b, | ||
0xc24b8b70, | ||
0xc76c51a3, | ||
0xd192e819, | ||
0xd6990624, | ||
0xf40e3585, | ||
0x106aa070, | ||
0x19a4c116, | ||
0x1e376c08, | ||
0x2748774c, | ||
0x34b0bcb5, | ||
0x391c0cb3, | ||
0x4ed8aa4a, | ||
0x5b9cca4f, | ||
0x682e6ff3, | ||
0x748f82ee, | ||
0x78a5636f, | ||
0x84c87814, | ||
0x8cc70208, | ||
0x90befffa, | ||
0xa4506ceb, | ||
0xbef9a3f7, | ||
0xc67178f2 | ||
]; | ||
function scrypt(password, salt) { | ||
var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, | ||
_ref$N = _ref.N, | ||
N = _ref$N === void 0 ? 16384 : _ref$N, | ||
logN = _ref.logN, | ||
_ref$r = _ref.r, | ||
r = _ref$r === void 0 ? 8 : _ref$r, | ||
_ref$p = _ref.p, | ||
p = _ref$p === void 0 ? 1 : _ref$p, | ||
_ref$dkLen = _ref.dkLen, | ||
dkLen = _ref$dkLen === void 0 ? 32 : _ref$dkLen, | ||
_ref$interruptStep = _ref.interruptStep, | ||
interruptStep = _ref$interruptStep === void 0 ? 0 : _ref$interruptStep, | ||
encoding = _ref.encoding; | ||
let h0 = 0x6a09e667, | ||
h1 = 0xbb67ae85, | ||
h2 = 0x3c6ef372, | ||
h3 = 0xa54ff53a, | ||
h4 = 0x510e527f, | ||
h5 = 0x9b05688c, | ||
h6 = 0x1f83d9ab, | ||
h7 = 0x5be0cd19, | ||
w = new Array(64); | ||
return new Promise(function (resolve, reject) { | ||
if (!logN && !N) { | ||
return reject(new Error("scrypt: missing N or logN parameter")); | ||
} | ||
function blocks(p) { | ||
let off = 0, | ||
len = p.length; | ||
while (len >= 64) { | ||
let a = h0, | ||
b = h1, | ||
c = h2, | ||
d = h3, | ||
e = h4, | ||
f = h5, | ||
g = h6, | ||
h = h7, | ||
u, | ||
i, | ||
j, | ||
t1, | ||
t2; | ||
if (logN || logN === 0) { | ||
if (logN < 1 || logN > 31) { | ||
return reject(new Error("scrypt: logN must be between 1 and 31")); | ||
} | ||
for (i = 0; i < 16; i++) { | ||
j = off + i * 4; | ||
w[i] = | ||
((p[j] & 0xff) << 24) | | ||
((p[j + 1] & 0xff) << 16) | | ||
((p[j + 2] & 0xff) << 8) | | ||
(p[j + 3] & 0xff); | ||
} | ||
N = 1 << logN >>> 0; | ||
} else { | ||
if (N < 2 || N > MAX_UINT) { | ||
return reject(new Error("scrypt: N is out of range")); | ||
} else if ((N & N - 1) !== 0) { | ||
return reject(Error("scrypt: N is not a power of 2")); | ||
} | ||
} | ||
for (i = 16; i < 64; i++) { | ||
u = w[i - 2]; | ||
t1 = | ||
((u >>> 17) | (u << (32 - 17))) ^ | ||
((u >>> 19) | (u << (32 - 19))) ^ | ||
(u >>> 10); | ||
if (p < 1) { | ||
return reject(new Error("scrypt: invalid p")); | ||
} | ||
u = w[i - 15]; | ||
t2 = | ||
((u >>> 7) | (u << (32 - 7))) ^ | ||
((u >>> 18) | (u << (32 - 18))) ^ | ||
(u >>> 3); | ||
if (r <= 0) { | ||
return reject(new Error("scrypt: invalid r")); | ||
} | ||
w[i] = (((t1 + w[i - 7]) | 0) + ((t2 + w[i - 16]) | 0)) | 0; | ||
} | ||
run({ | ||
password: password, | ||
salt: salt, | ||
N: N, | ||
r: r, | ||
p: p, | ||
dkLen: dkLen, | ||
interruptStep: interruptStep, | ||
encoding: encoding | ||
}, resolve); | ||
}); | ||
} // Internal scrypt function | ||
for (i = 0; i < 64; i++) { | ||
t1 = | ||
((((((e >>> 6) | (e << (32 - 6))) ^ | ||
((e >>> 11) | (e << (32 - 11))) ^ | ||
((e >>> 25) | (e << (32 - 25)))) + | ||
((e & f) ^ (~e & g))) | | ||
0) + | ||
((h + ((K[i] + w[i]) | 0)) | 0)) | | ||
0; | ||
function run(_ref2, callback) { | ||
var password = _ref2.password, | ||
salt = _ref2.salt, | ||
N = _ref2.N, | ||
r = _ref2.r, | ||
p = _ref2.p, | ||
dkLen = _ref2.dkLen, | ||
interruptStep = _ref2.interruptStep, | ||
encoding = _ref2.encoding; | ||
t2 = | ||
((((a >>> 2) | (a << (32 - 2))) ^ | ||
((a >>> 13) | (a << (32 - 13))) ^ | ||
((a >>> 22) | (a << (32 - 22)))) + | ||
((a & b) ^ (a & c) ^ (b & c))) | | ||
0; | ||
function SHA256(m) { | ||
var K = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2]; | ||
var h0 = 0x6a09e667, | ||
h1 = 0xbb67ae85, | ||
h2 = 0x3c6ef372, | ||
h3 = 0xa54ff53a, | ||
h4 = 0x510e527f, | ||
h5 = 0x9b05688c, | ||
h6 = 0x1f83d9ab, | ||
h7 = 0x5be0cd19, | ||
w = new Array(64); | ||
h = g; | ||
g = f; | ||
f = e; | ||
e = (d + t1) | 0; | ||
d = c; | ||
c = b; | ||
b = a; | ||
a = (t1 + t2) | 0; | ||
} | ||
function blocks(p) { | ||
var off = 0, | ||
len = p.length; | ||
h0 = (h0 + a) | 0; | ||
h1 = (h1 + b) | 0; | ||
h2 = (h2 + c) | 0; | ||
h3 = (h3 + d) | 0; | ||
h4 = (h4 + e) | 0; | ||
h5 = (h5 + f) | 0; | ||
h6 = (h6 + g) | 0; | ||
h7 = (h7 + h) | 0; | ||
while (len >= 64) { | ||
var a = h0, | ||
b = h1, | ||
c = h2, | ||
d = h3, | ||
e = h4, | ||
f = h5, | ||
g = h6, | ||
h = h7, | ||
u = void 0, | ||
_i = void 0, | ||
j = void 0, | ||
t1 = void 0, | ||
t2 = void 0; | ||
off += 64; | ||
len -= 64; | ||
} | ||
} | ||
for (_i = 0; _i < 16; _i++) { | ||
j = off + _i * 4; | ||
w[_i] = (p[j] & 0xff) << 24 | (p[j + 1] & 0xff) << 16 | (p[j + 2] & 0xff) << 8 | p[j + 3] & 0xff; | ||
} | ||
blocks(m); | ||
for (_i = 16; _i < 64; _i++) { | ||
u = w[_i - 2]; | ||
t1 = (u >>> 17 | u << 32 - 17) ^ (u >>> 19 | u << 32 - 19) ^ u >>> 10; | ||
u = w[_i - 15]; | ||
t2 = (u >>> 7 | u << 32 - 7) ^ (u >>> 18 | u << 32 - 18) ^ u >>> 3; | ||
w[_i] = (t1 + w[_i - 7] | 0) + (t2 + w[_i - 16] | 0) | 0; | ||
} | ||
let i, | ||
bytesLeft = m.length % 64, | ||
bitLenHi = (m.length / 0x20000000) | 0, | ||
bitLenLo = m.length << 3, | ||
numZeros = bytesLeft < 56 ? 56 : 120, | ||
p = m.slice(m.length - bytesLeft, m.length); | ||
for (_i = 0; _i < 64; _i++) { | ||
t1 = (((e >>> 6 | e << 32 - 6) ^ (e >>> 11 | e << 32 - 11) ^ (e >>> 25 | e << 32 - 25)) + (e & f ^ ~e & g) | 0) + (h + (K[_i] + w[_i] | 0) | 0) | 0; | ||
t2 = ((a >>> 2 | a << 32 - 2) ^ (a >>> 13 | a << 32 - 13) ^ (a >>> 22 | a << 32 - 22)) + (a & b ^ a & c ^ b & c) | 0; | ||
h = g; | ||
g = f; | ||
f = e; | ||
e = d + t1 | 0; | ||
d = c; | ||
c = b; | ||
b = a; | ||
a = t1 + t2 | 0; | ||
} | ||
p.push(0x80); | ||
for (i = bytesLeft + 1; i < numZeros; i++) p.push(0); | ||
p.push((bitLenHi >>> 24) & 0xff); | ||
p.push((bitLenHi >>> 16) & 0xff); | ||
p.push((bitLenHi >>> 8) & 0xff); | ||
p.push((bitLenHi >>> 0) & 0xff); | ||
p.push((bitLenLo >>> 24) & 0xff); | ||
p.push((bitLenLo >>> 16) & 0xff); | ||
p.push((bitLenLo >>> 8) & 0xff); | ||
p.push((bitLenLo >>> 0) & 0xff); | ||
h0 = h0 + a | 0; | ||
h1 = h1 + b | 0; | ||
h2 = h2 + c | 0; | ||
h3 = h3 + d | 0; | ||
h4 = h4 + e | 0; | ||
h5 = h5 + f | 0; | ||
h6 = h6 + g | 0; | ||
h7 = h7 + h | 0; | ||
off += 64; | ||
len -= 64; | ||
} | ||
} | ||
blocks(p); | ||
blocks(m); | ||
var i, | ||
bytesLeft = m.length % 64, | ||
bitLenHi = m.length / 0x20000000 | 0, | ||
bitLenLo = m.length << 3, | ||
numZeros = bytesLeft < 56 ? 56 : 120, | ||
p = m.slice(m.length - bytesLeft, m.length); | ||
p.push(0x80); | ||
return [ | ||
(h0 >>> 24) & 0xff, | ||
(h0 >>> 16) & 0xff, | ||
(h0 >>> 8) & 0xff, | ||
(h0 >>> 0) & 0xff, | ||
(h1 >>> 24) & 0xff, | ||
(h1 >>> 16) & 0xff, | ||
(h1 >>> 8) & 0xff, | ||
(h1 >>> 0) & 0xff, | ||
(h2 >>> 24) & 0xff, | ||
(h2 >>> 16) & 0xff, | ||
(h2 >>> 8) & 0xff, | ||
(h2 >>> 0) & 0xff, | ||
(h3 >>> 24) & 0xff, | ||
(h3 >>> 16) & 0xff, | ||
(h3 >>> 8) & 0xff, | ||
(h3 >>> 0) & 0xff, | ||
(h4 >>> 24) & 0xff, | ||
(h4 >>> 16) & 0xff, | ||
(h4 >>> 8) & 0xff, | ||
(h4 >>> 0) & 0xff, | ||
(h5 >>> 24) & 0xff, | ||
(h5 >>> 16) & 0xff, | ||
(h5 >>> 8) & 0xff, | ||
(h5 >>> 0) & 0xff, | ||
(h6 >>> 24) & 0xff, | ||
(h6 >>> 16) & 0xff, | ||
(h6 >>> 8) & 0xff, | ||
(h6 >>> 0) & 0xff, | ||
(h7 >>> 24) & 0xff, | ||
(h7 >>> 16) & 0xff, | ||
(h7 >>> 8) & 0xff, | ||
(h7 >>> 0) & 0xff | ||
]; | ||
} | ||
for (i = bytesLeft + 1; i < numZeros; i++) { | ||
p.push(0); | ||
} | ||
function PBKDF2_HMAC_SHA256_OneIter(password, salt, dkLen) { | ||
// compress password if it's longer than hash block length | ||
password = password.length <= 64 ? password : SHA256(password); | ||
p.push(bitLenHi >>> 24 & 0xff); | ||
p.push(bitLenHi >>> 16 & 0xff); | ||
p.push(bitLenHi >>> 8 & 0xff); | ||
p.push(bitLenHi >>> 0 & 0xff); | ||
p.push(bitLenLo >>> 24 & 0xff); | ||
p.push(bitLenLo >>> 16 & 0xff); | ||
p.push(bitLenLo >>> 8 & 0xff); | ||
p.push(bitLenLo >>> 0 & 0xff); | ||
blocks(p); | ||
return [h0 >>> 24 & 0xff, h0 >>> 16 & 0xff, h0 >>> 8 & 0xff, h0 >>> 0 & 0xff, h1 >>> 24 & 0xff, h1 >>> 16 & 0xff, h1 >>> 8 & 0xff, h1 >>> 0 & 0xff, h2 >>> 24 & 0xff, h2 >>> 16 & 0xff, h2 >>> 8 & 0xff, h2 >>> 0 & 0xff, h3 >>> 24 & 0xff, h3 >>> 16 & 0xff, h3 >>> 8 & 0xff, h3 >>> 0 & 0xff, h4 >>> 24 & 0xff, h4 >>> 16 & 0xff, h4 >>> 8 & 0xff, h4 >>> 0 & 0xff, h5 >>> 24 & 0xff, h5 >>> 16 & 0xff, h5 >>> 8 & 0xff, h5 >>> 0 & 0xff, h6 >>> 24 & 0xff, h6 >>> 16 & 0xff, h6 >>> 8 & 0xff, h6 >>> 0 & 0xff, h7 >>> 24 & 0xff, h7 >>> 16 & 0xff, h7 >>> 8 & 0xff, h7 >>> 0 & 0xff]; | ||
} | ||
let i, | ||
innerLen = 64 + salt.length + 4, | ||
inner = new Array(innerLen), | ||
outerKey = new Array(64), | ||
dk = []; | ||
function PBKDF2_HMAC_SHA256_OneIter(password, salt, dkLen) { | ||
// compress password if it's longer than hash block length | ||
password = password.length <= 64 ? password : SHA256(password); | ||
var i, | ||
innerLen = 64 + salt.length + 4, | ||
inner = new Array(innerLen), | ||
outerKey = new Array(64), | ||
dk = []; // inner = (password ^ ipad) || salt || counter | ||
// inner = (password ^ ipad) || salt || counter | ||
for (i = 0; i < 64; i++) inner[i] = 0x36; | ||
for (i = 0; i < password.length; i++) inner[i] ^= password[i]; | ||
for (i = 0; i < salt.length; i++) inner[64 + i] = salt[i]; | ||
for (i = innerLen - 4; i < innerLen; i++) inner[i] = 0; | ||
for (i = 0; i < 64; i++) { | ||
inner[i] = 0x36; | ||
} | ||
// outerKey = password ^ opad | ||
for (i = 0; i < 64; i++) outerKey[i] = 0x5c; | ||
for (i = 0; i < password.length; i++) outerKey[i] ^= password[i]; | ||
for (i = 0; i < password.length; i++) { | ||
inner[i] ^= password[i]; | ||
} | ||
// increments counter inside inner | ||
function incrementCounter() { | ||
for (let i = innerLen - 1; i >= innerLen - 4; i--) { | ||
inner[i]++; | ||
if (inner[i] <= 0xff) return; | ||
inner[i] = 0; | ||
} | ||
} | ||
for (i = 0; i < salt.length; i++) { | ||
inner[64 + i] = salt[i]; | ||
} | ||
// output blocks = SHA256(outerKey || SHA256(inner)) ... | ||
while (dkLen >= 32) { | ||
incrementCounter(); | ||
dk = dk.concat(SHA256(outerKey.concat(SHA256(inner)))); | ||
dkLen -= 32; | ||
} | ||
if (dkLen > 0) { | ||
incrementCounter(); | ||
dk = dk.concat(SHA256(outerKey.concat(SHA256(inner))).slice(0, dkLen)); | ||
} | ||
return dk; | ||
} | ||
for (i = innerLen - 4; i < innerLen; i++) { | ||
inner[i] = 0; | ||
} // outerKey = password ^ opad | ||
function salsaXOR(tmp, B, bin, bout) { | ||
let j0 = tmp[0] ^ B[bin++], | ||
j1 = tmp[1] ^ B[bin++], | ||
j2 = tmp[2] ^ B[bin++], | ||
j3 = tmp[3] ^ B[bin++], | ||
j4 = tmp[4] ^ B[bin++], | ||
j5 = tmp[5] ^ B[bin++], | ||
j6 = tmp[6] ^ B[bin++], | ||
j7 = tmp[7] ^ B[bin++], | ||
j8 = tmp[8] ^ B[bin++], | ||
j9 = tmp[9] ^ B[bin++], | ||
j10 = tmp[10] ^ B[bin++], | ||
j11 = tmp[11] ^ B[bin++], | ||
j12 = tmp[12] ^ B[bin++], | ||
j13 = tmp[13] ^ B[bin++], | ||
j14 = tmp[14] ^ B[bin++], | ||
j15 = tmp[15] ^ B[bin++], | ||
u, | ||
i; | ||
let x0 = j0, | ||
x1 = j1, | ||
x2 = j2, | ||
x3 = j3, | ||
x4 = j4, | ||
x5 = j5, | ||
x6 = j6, | ||
x7 = j7, | ||
x8 = j8, | ||
x9 = j9, | ||
x10 = j10, | ||
x11 = j11, | ||
x12 = j12, | ||
x13 = j13, | ||
x14 = j14, | ||
x15 = j15; | ||
for (i = 0; i < 64; i++) { | ||
outerKey[i] = 0x5c; | ||
} | ||
for (i = 0; i < 8; i += 2) { | ||
u = x0 + x12; | ||
x4 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x4 + x0; | ||
x8 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x8 + x4; | ||
x12 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x12 + x8; | ||
x0 ^= (u << 18) | (u >>> (32 - 18)); | ||
for (i = 0; i < password.length; i++) { | ||
outerKey[i] ^= password[i]; | ||
} // increments counter inside inner | ||
u = x5 + x1; | ||
x9 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x9 + x5; | ||
x13 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x13 + x9; | ||
x1 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x1 + x13; | ||
x5 ^= (u << 18) | (u >>> (32 - 18)); | ||
u = x10 + x6; | ||
x14 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x14 + x10; | ||
x2 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x2 + x14; | ||
x6 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x6 + x2; | ||
x10 ^= (u << 18) | (u >>> (32 - 18)); | ||
function incrementCounter() { | ||
for (var _i2 = innerLen - 1; _i2 >= innerLen - 4; _i2--) { | ||
inner[_i2]++; | ||
if (inner[_i2] <= 0xff) return; | ||
inner[_i2] = 0; | ||
} | ||
} // output blocks = SHA256(outerKey || SHA256(inner)) ... | ||
u = x15 + x11; | ||
x3 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x3 + x15; | ||
x7 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x7 + x3; | ||
x11 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x11 + x7; | ||
x15 ^= (u << 18) | (u >>> (32 - 18)); | ||
u = x0 + x3; | ||
x1 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x1 + x0; | ||
x2 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x2 + x1; | ||
x3 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x3 + x2; | ||
x0 ^= (u << 18) | (u >>> (32 - 18)); | ||
while (dkLen >= 32) { | ||
incrementCounter(); | ||
dk = dk.concat(SHA256(outerKey.concat(SHA256(inner)))); | ||
dkLen -= 32; | ||
} | ||
u = x5 + x4; | ||
x6 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x6 + x5; | ||
x7 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x7 + x6; | ||
x4 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x4 + x7; | ||
x5 ^= (u << 18) | (u >>> (32 - 18)); | ||
if (dkLen > 0) { | ||
incrementCounter(); | ||
dk = dk.concat(SHA256(outerKey.concat(SHA256(inner))).slice(0, dkLen)); | ||
} | ||
u = x10 + x9; | ||
x11 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x11 + x10; | ||
x8 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x8 + x11; | ||
x9 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x9 + x8; | ||
x10 ^= (u << 18) | (u >>> (32 - 18)); | ||
return dk; | ||
} | ||
u = x15 + x14; | ||
x12 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x12 + x15; | ||
x13 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x13 + x12; | ||
x14 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x14 + x13; | ||
x15 ^= (u << 18) | (u >>> (32 - 18)); | ||
} | ||
function salsaXOR(tmp, B, bin, bout) { | ||
var j0 = tmp[0] ^ B[bin++], | ||
j1 = tmp[1] ^ B[bin++], | ||
j2 = tmp[2] ^ B[bin++], | ||
j3 = tmp[3] ^ B[bin++], | ||
j4 = tmp[4] ^ B[bin++], | ||
j5 = tmp[5] ^ B[bin++], | ||
j6 = tmp[6] ^ B[bin++], | ||
j7 = tmp[7] ^ B[bin++], | ||
j8 = tmp[8] ^ B[bin++], | ||
j9 = tmp[9] ^ B[bin++], | ||
j10 = tmp[10] ^ B[bin++], | ||
j11 = tmp[11] ^ B[bin++], | ||
j12 = tmp[12] ^ B[bin++], | ||
j13 = tmp[13] ^ B[bin++], | ||
j14 = tmp[14] ^ B[bin++], | ||
j15 = tmp[15] ^ B[bin++], | ||
u, | ||
i; | ||
var x0 = j0, | ||
x1 = j1, | ||
x2 = j2, | ||
x3 = j3, | ||
x4 = j4, | ||
x5 = j5, | ||
x6 = j6, | ||
x7 = j7, | ||
x8 = j8, | ||
x9 = j9, | ||
x10 = j10, | ||
x11 = j11, | ||
x12 = j12, | ||
x13 = j13, | ||
x14 = j14, | ||
x15 = j15; | ||
B[bout++] = tmp[0] = (x0 + j0) | 0; | ||
B[bout++] = tmp[1] = (x1 + j1) | 0; | ||
B[bout++] = tmp[2] = (x2 + j2) | 0; | ||
B[bout++] = tmp[3] = (x3 + j3) | 0; | ||
B[bout++] = tmp[4] = (x4 + j4) | 0; | ||
B[bout++] = tmp[5] = (x5 + j5) | 0; | ||
B[bout++] = tmp[6] = (x6 + j6) | 0; | ||
B[bout++] = tmp[7] = (x7 + j7) | 0; | ||
B[bout++] = tmp[8] = (x8 + j8) | 0; | ||
B[bout++] = tmp[9] = (x9 + j9) | 0; | ||
B[bout++] = tmp[10] = (x10 + j10) | 0; | ||
B[bout++] = tmp[11] = (x11 + j11) | 0; | ||
B[bout++] = tmp[12] = (x12 + j12) | 0; | ||
B[bout++] = tmp[13] = (x13 + j13) | 0; | ||
B[bout++] = tmp[14] = (x14 + j14) | 0; | ||
B[bout++] = tmp[15] = (x15 + j15) | 0; | ||
} | ||
for (i = 0; i < 8; i += 2) { | ||
u = x0 + x12; | ||
x4 ^= u << 7 | u >>> 32 - 7; | ||
u = x4 + x0; | ||
x8 ^= u << 9 | u >>> 32 - 9; | ||
u = x8 + x4; | ||
x12 ^= u << 13 | u >>> 32 - 13; | ||
u = x12 + x8; | ||
x0 ^= u << 18 | u >>> 32 - 18; | ||
u = x5 + x1; | ||
x9 ^= u << 7 | u >>> 32 - 7; | ||
u = x9 + x5; | ||
x13 ^= u << 9 | u >>> 32 - 9; | ||
u = x13 + x9; | ||
x1 ^= u << 13 | u >>> 32 - 13; | ||
u = x1 + x13; | ||
x5 ^= u << 18 | u >>> 32 - 18; | ||
u = x10 + x6; | ||
x14 ^= u << 7 | u >>> 32 - 7; | ||
u = x14 + x10; | ||
x2 ^= u << 9 | u >>> 32 - 9; | ||
u = x2 + x14; | ||
x6 ^= u << 13 | u >>> 32 - 13; | ||
u = x6 + x2; | ||
x10 ^= u << 18 | u >>> 32 - 18; | ||
u = x15 + x11; | ||
x3 ^= u << 7 | u >>> 32 - 7; | ||
u = x3 + x15; | ||
x7 ^= u << 9 | u >>> 32 - 9; | ||
u = x7 + x3; | ||
x11 ^= u << 13 | u >>> 32 - 13; | ||
u = x11 + x7; | ||
x15 ^= u << 18 | u >>> 32 - 18; | ||
u = x0 + x3; | ||
x1 ^= u << 7 | u >>> 32 - 7; | ||
u = x1 + x0; | ||
x2 ^= u << 9 | u >>> 32 - 9; | ||
u = x2 + x1; | ||
x3 ^= u << 13 | u >>> 32 - 13; | ||
u = x3 + x2; | ||
x0 ^= u << 18 | u >>> 32 - 18; | ||
u = x5 + x4; | ||
x6 ^= u << 7 | u >>> 32 - 7; | ||
u = x6 + x5; | ||
x7 ^= u << 9 | u >>> 32 - 9; | ||
u = x7 + x6; | ||
x4 ^= u << 13 | u >>> 32 - 13; | ||
u = x4 + x7; | ||
x5 ^= u << 18 | u >>> 32 - 18; | ||
u = x10 + x9; | ||
x11 ^= u << 7 | u >>> 32 - 7; | ||
u = x11 + x10; | ||
x8 ^= u << 9 | u >>> 32 - 9; | ||
u = x8 + x11; | ||
x9 ^= u << 13 | u >>> 32 - 13; | ||
u = x9 + x8; | ||
x10 ^= u << 18 | u >>> 32 - 18; | ||
u = x15 + x14; | ||
x12 ^= u << 7 | u >>> 32 - 7; | ||
u = x12 + x15; | ||
x13 ^= u << 9 | u >>> 32 - 9; | ||
u = x13 + x12; | ||
x14 ^= u << 13 | u >>> 32 - 13; | ||
u = x14 + x13; | ||
x15 ^= u << 18 | u >>> 32 - 18; | ||
} | ||
function blockCopy(dst, di, src, si, len) { | ||
while (len--) dst[di++] = src[si++]; | ||
} | ||
B[bout++] = tmp[0] = x0 + j0 | 0; | ||
B[bout++] = tmp[1] = x1 + j1 | 0; | ||
B[bout++] = tmp[2] = x2 + j2 | 0; | ||
B[bout++] = tmp[3] = x3 + j3 | 0; | ||
B[bout++] = tmp[4] = x4 + j4 | 0; | ||
B[bout++] = tmp[5] = x5 + j5 | 0; | ||
B[bout++] = tmp[6] = x6 + j6 | 0; | ||
B[bout++] = tmp[7] = x7 + j7 | 0; | ||
B[bout++] = tmp[8] = x8 + j8 | 0; | ||
B[bout++] = tmp[9] = x9 + j9 | 0; | ||
B[bout++] = tmp[10] = x10 + j10 | 0; | ||
B[bout++] = tmp[11] = x11 + j11 | 0; | ||
B[bout++] = tmp[12] = x12 + j12 | 0; | ||
B[bout++] = tmp[13] = x13 + j13 | 0; | ||
B[bout++] = tmp[14] = x14 + j14 | 0; | ||
B[bout++] = tmp[15] = x15 + j15 | 0; | ||
} | ||
function blockXOR(dst, di, src, si, len) { | ||
while (len--) dst[di++] ^= src[si++]; | ||
} | ||
function blockCopy(dst, di, src, si, len) { | ||
while (len--) { | ||
dst[di++] = src[si++]; | ||
} | ||
} | ||
function blockMix(tmp, B, bin, bout, r) { | ||
blockCopy(tmp, 0, B, bin + (2 * r - 1) * 16, 16); | ||
for (let i = 0; i < 2 * r; i += 2) { | ||
salsaXOR(tmp, B, bin + i * 16, bout + i * 8); | ||
salsaXOR(tmp, B, bin + i * 16 + 16, bout + i * 8 + r * 16); | ||
} | ||
} | ||
function blockXOR(dst, di, src, si, len) { | ||
while (len--) { | ||
dst[di++] ^= src[si++]; | ||
} | ||
} | ||
function integerify(B, bi, r) { | ||
return B[bi + (2 * r - 1) * 16]; | ||
} | ||
function blockMix(tmp, B, bin, bout, r) { | ||
blockCopy(tmp, 0, B, bin + (2 * r - 1) * 16, 16); | ||
function stringToUTF8Bytes(s) { | ||
const arr = []; | ||
for (let i = 0; i < s.length; i++) { | ||
let c = s.charCodeAt(i); | ||
if (c < 0x80) { | ||
arr.push(c); | ||
} else if (c < 0x800) { | ||
arr.push(0xc0 | (c >> 6)); | ||
arr.push(0x80 | (c & 0x3f)); | ||
} else if (c < 0xd800) { | ||
arr.push(0xe0 | (c >> 12)); | ||
arr.push(0x80 | ((c >> 6) & 0x3f)); | ||
arr.push(0x80 | (c & 0x3f)); | ||
} else { | ||
if (i >= s.length - 1) { | ||
throw new Error("invalid string"); | ||
} | ||
i++; // get one more character | ||
c = (c & 0x3ff) << 10; | ||
c |= s.charCodeAt(i) & 0x3ff; | ||
c += 0x10000; | ||
for (var i = 0; i < 2 * r; i += 2) { | ||
salsaXOR(tmp, B, bin + i * 16, bout + i * 8); | ||
salsaXOR(tmp, B, bin + i * 16 + 16, bout + i * 8 + r * 16); | ||
} | ||
} | ||
arr.push(0xf0 | (c >> 18)); | ||
arr.push(0x80 | ((c >> 12) & 0x3f)); | ||
arr.push(0x80 | ((c >> 6) & 0x3f)); | ||
arr.push(0x80 | (c & 0x3f)); | ||
} | ||
} | ||
return arr; | ||
} | ||
function integerify(B, bi, r) { | ||
return B[bi + (2 * r - 1) * 16]; | ||
} | ||
function bytesToHex(p) { | ||
const enc = "0123456789abcdef".split(""); | ||
function stringToUTF8Bytes(s) { | ||
var arr = []; | ||
const len = p.length, | ||
arr = []; | ||
for (var i = 0; i < s.length; i++) { | ||
var c = s.charCodeAt(i); | ||
for (let i = 0; i < len; i++) { | ||
arr.push(enc[(p[i] >>> 4) & 15]); | ||
arr.push(enc[(p[i] >>> 0) & 15]); | ||
} | ||
return arr.join(""); | ||
} | ||
if (c < 0x80) { | ||
arr.push(c); | ||
} else if (c < 0x800) { | ||
arr.push(0xc0 | c >> 6); | ||
arr.push(0x80 | c & 0x3f); | ||
} else if (c < 0xd800) { | ||
arr.push(0xe0 | c >> 12); | ||
arr.push(0x80 | c >> 6 & 0x3f); | ||
arr.push(0x80 | c & 0x3f); | ||
} else { | ||
if (i >= s.length - 1) { | ||
throw new Error("invalid string"); | ||
} | ||
function bytesToBase64(p) { | ||
/** @const */ | ||
const enc = ( | ||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789+/" | ||
).split(""); | ||
i++; // get one more character | ||
const len = p.length, | ||
arr = []; | ||
let i = 0, | ||
a, | ||
b, | ||
c, | ||
t; | ||
c = (c & 0x3ff) << 10; | ||
c |= s.charCodeAt(i) & 0x3ff; | ||
c += 0x10000; | ||
arr.push(0xf0 | c >> 18); | ||
arr.push(0x80 | c >> 12 & 0x3f); | ||
arr.push(0x80 | c >> 6 & 0x3f); | ||
arr.push(0x80 | c & 0x3f); | ||
} | ||
} | ||
while (i < len) { | ||
a = i < len ? p[i++] : 0; | ||
b = i < len ? p[i++] : 0; | ||
c = i < len ? p[i++] : 0; | ||
t = (a << 16) + (b << 8) + c; | ||
arr.push(enc[(t >>> (3 * 6)) & 63]); | ||
arr.push(enc[(t >>> (2 * 6)) & 63]); | ||
arr.push(enc[(t >>> (1 * 6)) & 63]); | ||
arr.push(enc[(t >>> (0 * 6)) & 63]); | ||
} | ||
if (len % 3 > 0) { | ||
arr[arr.length - 1] = "="; | ||
if (len % 3 === 1) arr[arr.length - 2] = "="; | ||
} | ||
return arr.join(""); | ||
} | ||
return arr; | ||
} | ||
// Generate key. | ||
function bytesToHex(p) { | ||
var enc = "0123456789abcdef".split(""); | ||
var len = p.length, | ||
arr = []; | ||
const MAX_UINT = -1 >>> 0; | ||
for (var i = 0; i < len; i++) { | ||
arr.push(enc[p[i] >>> 4 & 15]); | ||
arr.push(enc[p[i] >>> 0 & 15]); | ||
} | ||
if (!logN && !n) { | ||
return reject(new Error("scrypt: missing N or logN parameter")); | ||
} | ||
return arr.join(""); | ||
} | ||
let N; | ||
function bytesToBase64(p) { | ||
/** @const */ | ||
var enc = ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789+/").split(""); | ||
var len = p.length, | ||
arr = []; | ||
var i = 0, | ||
a, | ||
b, | ||
c, | ||
t; | ||
if (logN || logN === 0) { | ||
if (logN < 1 || logN > 31) { | ||
return reject(new Error("scrypt: logN must be between 1 and 31")); | ||
} | ||
while (i < len) { | ||
a = i < len ? p[i++] : 0; | ||
b = i < len ? p[i++] : 0; | ||
c = i < len ? p[i++] : 0; | ||
t = (a << 16) + (b << 8) + c; | ||
arr.push(enc[t >>> 3 * 6 & 63]); | ||
arr.push(enc[t >>> 2 * 6 & 63]); | ||
arr.push(enc[t >>> 1 * 6 & 63]); | ||
arr.push(enc[t >>> 0 * 6 & 63]); | ||
} | ||
N = (1 << logN) >>> 0; | ||
} else { | ||
if (n < 2 || n > MAX_UINT) { | ||
return reject(new Error("scrypt: N is out of range")); | ||
} else if ((n & (n - 1)) !== 0) { | ||
return reject(Error("scrypt: N is not a power of 2")); | ||
} | ||
if (len % 3 > 0) { | ||
arr[arr.length - 1] = "="; | ||
if (len % 3 === 1) arr[arr.length - 2] = "="; | ||
} | ||
N = n; | ||
} | ||
return arr.join(""); | ||
} | ||
if (p < 1) { | ||
return reject(new Error("scrypt: invalid p")); | ||
} | ||
var XY, V, B, tmp; | ||
if (r <= 0) { | ||
return reject(new Error("scrypt: invalid r")); | ||
} | ||
if (r * p >= 1 << 30 || r > MAX_UINT / 128 / p || r > MAX_UINT / 256 || N > MAX_UINT / 128 / r) { | ||
return reject(new Error("scrypt: parameters are too large")); | ||
} // Decode strings. | ||
let XY, V, B, tmp; | ||
if ( | ||
r * p >= 1 << 30 || | ||
r > MAX_UINT / 128 / p || | ||
r > MAX_UINT / 256 || | ||
N > MAX_UINT / 128 / r | ||
) { | ||
return reject(new Error("scrypt: parameters are too large")); | ||
} | ||
if (typeof password === "string") password = stringToUTF8Bytes(password); | ||
if (typeof salt === "string") salt = stringToUTF8Bytes(salt); | ||
// Decode strings. | ||
if (typeof password === "string") password = stringToUTF8Bytes(password); | ||
if (typeof salt === "string") salt = stringToUTF8Bytes(salt); | ||
if (typeof Int32Array !== "undefined") { | ||
//XXX We can use Uint32Array, but Int32Array is faster in Safari. | ||
XY = new Int32Array(64 * r); | ||
V = new Int32Array(32 * N * r); | ||
tmp = new Int32Array(16); | ||
} else { | ||
XY = []; | ||
V = []; | ||
tmp = new Array(16); | ||
} | ||
if (typeof Int32Array !== "undefined") { | ||
//XXX We can use Uint32Array, but Int32Array is faster in Safari. | ||
XY = new Int32Array(64 * r); | ||
V = new Int32Array(32 * N * r); | ||
tmp = new Int32Array(16); | ||
} else { | ||
XY = []; | ||
V = []; | ||
tmp = new Array(16); | ||
} | ||
B = PBKDF2_HMAC_SHA256_OneIter(password, salt, p * 128 * r); | ||
B = PBKDF2_HMAC_SHA256_OneIter(password, salt, p * 128 * r); | ||
var xi = 0, | ||
yi = 32 * r; | ||
const xi = 0, | ||
yi = 32 * r; | ||
function smixStart(pos) { | ||
for (var i = 0; i < 32 * r; i++) { | ||
var j = pos + i * 4; | ||
XY[xi + i] = (B[j + 3] & 0xff) << 24 | (B[j + 2] & 0xff) << 16 | (B[j + 1] & 0xff) << 8 | (B[j + 0] & 0xff) << 0; | ||
} | ||
} | ||
function smixStart(pos) { | ||
for (let i = 0; i < 32 * r; i++) { | ||
const j = pos + i * 4; | ||
XY[xi + i] = | ||
((B[j + 3] & 0xff) << 24) | | ||
((B[j + 2] & 0xff) << 16) | | ||
((B[j + 1] & 0xff) << 8) | | ||
((B[j + 0] & 0xff) << 0); | ||
} | ||
} | ||
function smixStep1(start, end) { | ||
for (var i = start; i < end; i += 2) { | ||
blockCopy(V, i * (32 * r), XY, xi, 32 * r); | ||
blockMix(tmp, XY, xi, yi, r); | ||
blockCopy(V, (i + 1) * (32 * r), XY, yi, 32 * r); | ||
blockMix(tmp, XY, yi, xi, r); | ||
} | ||
} | ||
function smixStep1(start, end) { | ||
for (let i = start; i < end; i += 2) { | ||
blockCopy(V, i * (32 * r), XY, xi, 32 * r); | ||
blockMix(tmp, XY, xi, yi, r); | ||
function smixStep2(start, end) { | ||
for (var i = start; i < end; i += 2) { | ||
var j = integerify(XY, xi, r) & N - 1; | ||
blockXOR(XY, xi, V, j * (32 * r), 32 * r); | ||
blockMix(tmp, XY, xi, yi, r); | ||
j = integerify(XY, yi, r) & N - 1; | ||
blockXOR(XY, yi, V, j * (32 * r), 32 * r); | ||
blockMix(tmp, XY, yi, xi, r); | ||
} | ||
} | ||
blockCopy(V, (i + 1) * (32 * r), XY, yi, 32 * r); | ||
blockMix(tmp, XY, yi, xi, r); | ||
} | ||
} | ||
function smixFinish(pos) { | ||
for (var i = 0; i < 32 * r; i++) { | ||
var j = XY[xi + i]; | ||
B[pos + i * 4 + 0] = j >>> 0 & 0xff; | ||
B[pos + i * 4 + 1] = j >>> 8 & 0xff; | ||
B[pos + i * 4 + 2] = j >>> 16 & 0xff; | ||
B[pos + i * 4 + 3] = j >>> 24 & 0xff; | ||
} | ||
} | ||
function smixStep2(start, end) { | ||
for (let i = start; i < end; i += 2) { | ||
let j = integerify(XY, xi, r) & (N - 1); | ||
blockXOR(XY, xi, V, j * (32 * r), 32 * r); | ||
blockMix(tmp, XY, xi, yi, r); | ||
var nextTick = typeof setImmediate !== "undefined" ? setImmediate : setTimeout; | ||
j = integerify(XY, yi, r) & (N - 1); | ||
blockXOR(XY, yi, V, j * (32 * r), 32 * r); | ||
blockMix(tmp, XY, yi, xi, r); | ||
} | ||
} | ||
function interruptedFor(start, end, step, fn, donefn) { | ||
(function performStep() { | ||
nextTick(function () { | ||
fn(start, start + step < end ? start + step : end); | ||
start += step; | ||
if (start < end) performStep();else donefn(); | ||
}); | ||
})(); | ||
} | ||
function smixFinish(pos) { | ||
for (let i = 0; i < 32 * r; i++) { | ||
const j = XY[xi + i]; | ||
B[pos + i * 4 + 0] = (j >>> 0) & 0xff; | ||
B[pos + i * 4 + 1] = (j >>> 8) & 0xff; | ||
B[pos + i * 4 + 2] = (j >>> 16) & 0xff; | ||
B[pos + i * 4 + 3] = (j >>> 24) & 0xff; | ||
} | ||
} | ||
function getResult(enc) { | ||
var result = PBKDF2_HMAC_SHA256_OneIter(password, B, dkLen); | ||
if (enc === "base64") return bytesToBase64(result);else if (enc === "hex") return bytesToHex(result);else if (enc === "binary") return new Uint8Array(result);else return result; | ||
} // Blocking variant. | ||
const nextTick = | ||
typeof setImmediate !== "undefined" ? setImmediate : setTimeout; | ||
function interruptedFor(start, end, step, fn, donefn) { | ||
(function performStep() { | ||
nextTick(function () { | ||
fn(start, start + step < end ? start + step : end); | ||
start += step; | ||
if (start < end) performStep(); | ||
else donefn(); | ||
}); | ||
})(); | ||
} | ||
function calculateSync() { | ||
for (var i = 0; i < p; i++) { | ||
smixStart(i * 128 * r); | ||
smixStep1(0, N); | ||
smixStep2(0, N); | ||
smixFinish(i * 128 * r); | ||
} | ||
function getResult(enc) { | ||
const result = PBKDF2_HMAC_SHA256_OneIter(password, B, dkLen); | ||
if (enc === "base64") return bytesToBase64(result); | ||
else if (enc === "hex") return bytesToHex(result); | ||
else if (enc === "binary") return new Uint8Array(result); | ||
else return result; | ||
} | ||
callback(getResult(encoding)); | ||
} // Async variant. | ||
// Blocking variant. | ||
function calculateSync() { | ||
for (let i = 0; i < p; i++) { | ||
smixStart(i * 128 * r); | ||
smixStep1(0, N); | ||
smixStep2(0, N); | ||
smixFinish(i * 128 * r); | ||
} | ||
resolve(getResult(encoding)); | ||
} | ||
// Async variant. | ||
function calculateAsync(i) { | ||
smixStart(i * 128 * r); | ||
interruptedFor(0, N, interruptStep * 2, smixStep1, function () { | ||
interruptedFor(0, N, interruptStep * 2, smixStep2, function () { | ||
smixFinish(i * 128 * r); | ||
if (i + 1 < p) { | ||
nextTick(function () { | ||
calculateAsync(i + 1); | ||
}); | ||
} else { | ||
resolve(getResult(encoding)); | ||
} | ||
}); | ||
}); | ||
} | ||
function calculateAsync(i) { | ||
smixStart(i * 128 * r); | ||
interruptedFor(0, N, interruptStep * 2, smixStep1, function () { | ||
interruptedFor(0, N, interruptStep * 2, smixStep2, function () { | ||
smixFinish(i * 128 * r); | ||
if (interruptStep <= 0) { | ||
calculateSync(); | ||
} else { | ||
calculateAsync(0); | ||
} | ||
}); | ||
if (i + 1 < p) { | ||
nextTick(function () { | ||
calculateAsync(i + 1); | ||
}); | ||
} else { | ||
callback(getResult(encoding)); | ||
} | ||
}); | ||
}); | ||
} | ||
if (interruptStep <= 0) { | ||
calculateSync(); | ||
} else { | ||
calculateAsync(0); | ||
} | ||
} | ||
var MAX_UINT = -1 >>> 0; | ||
module.exports = scrypt; |
1075
dist/es/index.js
/*! | ||
* Fast "async" scrypt implementation in JavaScript. | ||
* Copyright (c) 2013-2016 Dmitry Chestnykh | BSD License | ||
* https://github.com/dchest/scrypt-async-js | ||
* Fast "async" scrypt implementation in modern JavaScript. | ||
* Copyright (c) 2018 Charles Crete | MIT License | ||
* https://github.com/Cretezy/scrypt-async-modern | ||
*/ | ||
@@ -38,657 +38,562 @@ | ||
*/ | ||
function scrypt(password, | ||
salt, | ||
{ N: n = 16384, logN, r = 8, p = 1, dkLen = 32, interruptStep = 0, encoding } = {}) { | ||
return new Promise((resolve, reject) => { | ||
function SHA256(m) { | ||
const K = [ | ||
0x428a2f98, | ||
0x71374491, | ||
0xb5c0fbcf, | ||
0xe9b5dba5, | ||
0x3956c25b, | ||
0x59f111f1, | ||
0x923f82a4, | ||
0xab1c5ed5, | ||
0xd807aa98, | ||
0x12835b01, | ||
0x243185be, | ||
0x550c7dc3, | ||
0x72be5d74, | ||
0x80deb1fe, | ||
0x9bdc06a7, | ||
0xc19bf174, | ||
0xe49b69c1, | ||
0xefbe4786, | ||
0x0fc19dc6, | ||
0x240ca1cc, | ||
0x2de92c6f, | ||
0x4a7484aa, | ||
0x5cb0a9dc, | ||
0x76f988da, | ||
0x983e5152, | ||
0xa831c66d, | ||
0xb00327c8, | ||
0xbf597fc7, | ||
0xc6e00bf3, | ||
0xd5a79147, | ||
0x06ca6351, | ||
0x14292967, | ||
0x27b70a85, | ||
0x2e1b2138, | ||
0x4d2c6dfc, | ||
0x53380d13, | ||
0x650a7354, | ||
0x766a0abb, | ||
0x81c2c92e, | ||
0x92722c85, | ||
0xa2bfe8a1, | ||
0xa81a664b, | ||
0xc24b8b70, | ||
0xc76c51a3, | ||
0xd192e819, | ||
0xd6990624, | ||
0xf40e3585, | ||
0x106aa070, | ||
0x19a4c116, | ||
0x1e376c08, | ||
0x2748774c, | ||
0x34b0bcb5, | ||
0x391c0cb3, | ||
0x4ed8aa4a, | ||
0x5b9cca4f, | ||
0x682e6ff3, | ||
0x748f82ee, | ||
0x78a5636f, | ||
0x84c87814, | ||
0x8cc70208, | ||
0x90befffa, | ||
0xa4506ceb, | ||
0xbef9a3f7, | ||
0xc67178f2 | ||
]; | ||
function scrypt(password, salt) { | ||
var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, | ||
_ref$N = _ref.N, | ||
N = _ref$N === void 0 ? 16384 : _ref$N, | ||
logN = _ref.logN, | ||
_ref$r = _ref.r, | ||
r = _ref$r === void 0 ? 8 : _ref$r, | ||
_ref$p = _ref.p, | ||
p = _ref$p === void 0 ? 1 : _ref$p, | ||
_ref$dkLen = _ref.dkLen, | ||
dkLen = _ref$dkLen === void 0 ? 32 : _ref$dkLen, | ||
_ref$interruptStep = _ref.interruptStep, | ||
interruptStep = _ref$interruptStep === void 0 ? 0 : _ref$interruptStep, | ||
encoding = _ref.encoding; | ||
let h0 = 0x6a09e667, | ||
h1 = 0xbb67ae85, | ||
h2 = 0x3c6ef372, | ||
h3 = 0xa54ff53a, | ||
h4 = 0x510e527f, | ||
h5 = 0x9b05688c, | ||
h6 = 0x1f83d9ab, | ||
h7 = 0x5be0cd19, | ||
w = new Array(64); | ||
return new Promise(function (resolve, reject) { | ||
if (!logN && !N) { | ||
return reject(new Error("scrypt: missing N or logN parameter")); | ||
} | ||
function blocks(p) { | ||
let off = 0, | ||
len = p.length; | ||
while (len >= 64) { | ||
let a = h0, | ||
b = h1, | ||
c = h2, | ||
d = h3, | ||
e = h4, | ||
f = h5, | ||
g = h6, | ||
h = h7, | ||
u, | ||
i, | ||
j, | ||
t1, | ||
t2; | ||
if (logN || logN === 0) { | ||
if (logN < 1 || logN > 31) { | ||
return reject(new Error("scrypt: logN must be between 1 and 31")); | ||
} | ||
for (i = 0; i < 16; i++) { | ||
j = off + i * 4; | ||
w[i] = | ||
((p[j] & 0xff) << 24) | | ||
((p[j + 1] & 0xff) << 16) | | ||
((p[j + 2] & 0xff) << 8) | | ||
(p[j + 3] & 0xff); | ||
} | ||
N = 1 << logN >>> 0; | ||
} else { | ||
if (N < 2 || N > MAX_UINT) { | ||
return reject(new Error("scrypt: N is out of range")); | ||
} else if ((N & N - 1) !== 0) { | ||
return reject(Error("scrypt: N is not a power of 2")); | ||
} | ||
} | ||
for (i = 16; i < 64; i++) { | ||
u = w[i - 2]; | ||
t1 = | ||
((u >>> 17) | (u << (32 - 17))) ^ | ||
((u >>> 19) | (u << (32 - 19))) ^ | ||
(u >>> 10); | ||
if (p < 1) { | ||
return reject(new Error("scrypt: invalid p")); | ||
} | ||
u = w[i - 15]; | ||
t2 = | ||
((u >>> 7) | (u << (32 - 7))) ^ | ||
((u >>> 18) | (u << (32 - 18))) ^ | ||
(u >>> 3); | ||
if (r <= 0) { | ||
return reject(new Error("scrypt: invalid r")); | ||
} | ||
w[i] = (((t1 + w[i - 7]) | 0) + ((t2 + w[i - 16]) | 0)) | 0; | ||
} | ||
run({ | ||
password: password, | ||
salt: salt, | ||
N: N, | ||
r: r, | ||
p: p, | ||
dkLen: dkLen, | ||
interruptStep: interruptStep, | ||
encoding: encoding | ||
}, resolve); | ||
}); | ||
} // Internal scrypt function | ||
for (i = 0; i < 64; i++) { | ||
t1 = | ||
((((((e >>> 6) | (e << (32 - 6))) ^ | ||
((e >>> 11) | (e << (32 - 11))) ^ | ||
((e >>> 25) | (e << (32 - 25)))) + | ||
((e & f) ^ (~e & g))) | | ||
0) + | ||
((h + ((K[i] + w[i]) | 0)) | 0)) | | ||
0; | ||
function run(_ref2, callback) { | ||
var password = _ref2.password, | ||
salt = _ref2.salt, | ||
N = _ref2.N, | ||
r = _ref2.r, | ||
p = _ref2.p, | ||
dkLen = _ref2.dkLen, | ||
interruptStep = _ref2.interruptStep, | ||
encoding = _ref2.encoding; | ||
t2 = | ||
((((a >>> 2) | (a << (32 - 2))) ^ | ||
((a >>> 13) | (a << (32 - 13))) ^ | ||
((a >>> 22) | (a << (32 - 22)))) + | ||
((a & b) ^ (a & c) ^ (b & c))) | | ||
0; | ||
function SHA256(m) { | ||
var K = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2]; | ||
var h0 = 0x6a09e667, | ||
h1 = 0xbb67ae85, | ||
h2 = 0x3c6ef372, | ||
h3 = 0xa54ff53a, | ||
h4 = 0x510e527f, | ||
h5 = 0x9b05688c, | ||
h6 = 0x1f83d9ab, | ||
h7 = 0x5be0cd19, | ||
w = new Array(64); | ||
h = g; | ||
g = f; | ||
f = e; | ||
e = (d + t1) | 0; | ||
d = c; | ||
c = b; | ||
b = a; | ||
a = (t1 + t2) | 0; | ||
} | ||
function blocks(p) { | ||
var off = 0, | ||
len = p.length; | ||
h0 = (h0 + a) | 0; | ||
h1 = (h1 + b) | 0; | ||
h2 = (h2 + c) | 0; | ||
h3 = (h3 + d) | 0; | ||
h4 = (h4 + e) | 0; | ||
h5 = (h5 + f) | 0; | ||
h6 = (h6 + g) | 0; | ||
h7 = (h7 + h) | 0; | ||
while (len >= 64) { | ||
var a = h0, | ||
b = h1, | ||
c = h2, | ||
d = h3, | ||
e = h4, | ||
f = h5, | ||
g = h6, | ||
h = h7, | ||
u = void 0, | ||
_i = void 0, | ||
j = void 0, | ||
t1 = void 0, | ||
t2 = void 0; | ||
off += 64; | ||
len -= 64; | ||
} | ||
} | ||
for (_i = 0; _i < 16; _i++) { | ||
j = off + _i * 4; | ||
w[_i] = (p[j] & 0xff) << 24 | (p[j + 1] & 0xff) << 16 | (p[j + 2] & 0xff) << 8 | p[j + 3] & 0xff; | ||
} | ||
blocks(m); | ||
for (_i = 16; _i < 64; _i++) { | ||
u = w[_i - 2]; | ||
t1 = (u >>> 17 | u << 32 - 17) ^ (u >>> 19 | u << 32 - 19) ^ u >>> 10; | ||
u = w[_i - 15]; | ||
t2 = (u >>> 7 | u << 32 - 7) ^ (u >>> 18 | u << 32 - 18) ^ u >>> 3; | ||
w[_i] = (t1 + w[_i - 7] | 0) + (t2 + w[_i - 16] | 0) | 0; | ||
} | ||
let i, | ||
bytesLeft = m.length % 64, | ||
bitLenHi = (m.length / 0x20000000) | 0, | ||
bitLenLo = m.length << 3, | ||
numZeros = bytesLeft < 56 ? 56 : 120, | ||
p = m.slice(m.length - bytesLeft, m.length); | ||
for (_i = 0; _i < 64; _i++) { | ||
t1 = (((e >>> 6 | e << 32 - 6) ^ (e >>> 11 | e << 32 - 11) ^ (e >>> 25 | e << 32 - 25)) + (e & f ^ ~e & g) | 0) + (h + (K[_i] + w[_i] | 0) | 0) | 0; | ||
t2 = ((a >>> 2 | a << 32 - 2) ^ (a >>> 13 | a << 32 - 13) ^ (a >>> 22 | a << 32 - 22)) + (a & b ^ a & c ^ b & c) | 0; | ||
h = g; | ||
g = f; | ||
f = e; | ||
e = d + t1 | 0; | ||
d = c; | ||
c = b; | ||
b = a; | ||
a = t1 + t2 | 0; | ||
} | ||
p.push(0x80); | ||
for (i = bytesLeft + 1; i < numZeros; i++) p.push(0); | ||
p.push((bitLenHi >>> 24) & 0xff); | ||
p.push((bitLenHi >>> 16) & 0xff); | ||
p.push((bitLenHi >>> 8) & 0xff); | ||
p.push((bitLenHi >>> 0) & 0xff); | ||
p.push((bitLenLo >>> 24) & 0xff); | ||
p.push((bitLenLo >>> 16) & 0xff); | ||
p.push((bitLenLo >>> 8) & 0xff); | ||
p.push((bitLenLo >>> 0) & 0xff); | ||
h0 = h0 + a | 0; | ||
h1 = h1 + b | 0; | ||
h2 = h2 + c | 0; | ||
h3 = h3 + d | 0; | ||
h4 = h4 + e | 0; | ||
h5 = h5 + f | 0; | ||
h6 = h6 + g | 0; | ||
h7 = h7 + h | 0; | ||
off += 64; | ||
len -= 64; | ||
} | ||
} | ||
blocks(p); | ||
blocks(m); | ||
var i, | ||
bytesLeft = m.length % 64, | ||
bitLenHi = m.length / 0x20000000 | 0, | ||
bitLenLo = m.length << 3, | ||
numZeros = bytesLeft < 56 ? 56 : 120, | ||
p = m.slice(m.length - bytesLeft, m.length); | ||
p.push(0x80); | ||
return [ | ||
(h0 >>> 24) & 0xff, | ||
(h0 >>> 16) & 0xff, | ||
(h0 >>> 8) & 0xff, | ||
(h0 >>> 0) & 0xff, | ||
(h1 >>> 24) & 0xff, | ||
(h1 >>> 16) & 0xff, | ||
(h1 >>> 8) & 0xff, | ||
(h1 >>> 0) & 0xff, | ||
(h2 >>> 24) & 0xff, | ||
(h2 >>> 16) & 0xff, | ||
(h2 >>> 8) & 0xff, | ||
(h2 >>> 0) & 0xff, | ||
(h3 >>> 24) & 0xff, | ||
(h3 >>> 16) & 0xff, | ||
(h3 >>> 8) & 0xff, | ||
(h3 >>> 0) & 0xff, | ||
(h4 >>> 24) & 0xff, | ||
(h4 >>> 16) & 0xff, | ||
(h4 >>> 8) & 0xff, | ||
(h4 >>> 0) & 0xff, | ||
(h5 >>> 24) & 0xff, | ||
(h5 >>> 16) & 0xff, | ||
(h5 >>> 8) & 0xff, | ||
(h5 >>> 0) & 0xff, | ||
(h6 >>> 24) & 0xff, | ||
(h6 >>> 16) & 0xff, | ||
(h6 >>> 8) & 0xff, | ||
(h6 >>> 0) & 0xff, | ||
(h7 >>> 24) & 0xff, | ||
(h7 >>> 16) & 0xff, | ||
(h7 >>> 8) & 0xff, | ||
(h7 >>> 0) & 0xff | ||
]; | ||
} | ||
for (i = bytesLeft + 1; i < numZeros; i++) { | ||
p.push(0); | ||
} | ||
function PBKDF2_HMAC_SHA256_OneIter(password, salt, dkLen) { | ||
// compress password if it's longer than hash block length | ||
password = password.length <= 64 ? password : SHA256(password); | ||
p.push(bitLenHi >>> 24 & 0xff); | ||
p.push(bitLenHi >>> 16 & 0xff); | ||
p.push(bitLenHi >>> 8 & 0xff); | ||
p.push(bitLenHi >>> 0 & 0xff); | ||
p.push(bitLenLo >>> 24 & 0xff); | ||
p.push(bitLenLo >>> 16 & 0xff); | ||
p.push(bitLenLo >>> 8 & 0xff); | ||
p.push(bitLenLo >>> 0 & 0xff); | ||
blocks(p); | ||
return [h0 >>> 24 & 0xff, h0 >>> 16 & 0xff, h0 >>> 8 & 0xff, h0 >>> 0 & 0xff, h1 >>> 24 & 0xff, h1 >>> 16 & 0xff, h1 >>> 8 & 0xff, h1 >>> 0 & 0xff, h2 >>> 24 & 0xff, h2 >>> 16 & 0xff, h2 >>> 8 & 0xff, h2 >>> 0 & 0xff, h3 >>> 24 & 0xff, h3 >>> 16 & 0xff, h3 >>> 8 & 0xff, h3 >>> 0 & 0xff, h4 >>> 24 & 0xff, h4 >>> 16 & 0xff, h4 >>> 8 & 0xff, h4 >>> 0 & 0xff, h5 >>> 24 & 0xff, h5 >>> 16 & 0xff, h5 >>> 8 & 0xff, h5 >>> 0 & 0xff, h6 >>> 24 & 0xff, h6 >>> 16 & 0xff, h6 >>> 8 & 0xff, h6 >>> 0 & 0xff, h7 >>> 24 & 0xff, h7 >>> 16 & 0xff, h7 >>> 8 & 0xff, h7 >>> 0 & 0xff]; | ||
} | ||
let i, | ||
innerLen = 64 + salt.length + 4, | ||
inner = new Array(innerLen), | ||
outerKey = new Array(64), | ||
dk = []; | ||
function PBKDF2_HMAC_SHA256_OneIter(password, salt, dkLen) { | ||
// compress password if it's longer than hash block length | ||
password = password.length <= 64 ? password : SHA256(password); | ||
var i, | ||
innerLen = 64 + salt.length + 4, | ||
inner = new Array(innerLen), | ||
outerKey = new Array(64), | ||
dk = []; // inner = (password ^ ipad) || salt || counter | ||
// inner = (password ^ ipad) || salt || counter | ||
for (i = 0; i < 64; i++) inner[i] = 0x36; | ||
for (i = 0; i < password.length; i++) inner[i] ^= password[i]; | ||
for (i = 0; i < salt.length; i++) inner[64 + i] = salt[i]; | ||
for (i = innerLen - 4; i < innerLen; i++) inner[i] = 0; | ||
for (i = 0; i < 64; i++) { | ||
inner[i] = 0x36; | ||
} | ||
// outerKey = password ^ opad | ||
for (i = 0; i < 64; i++) outerKey[i] = 0x5c; | ||
for (i = 0; i < password.length; i++) outerKey[i] ^= password[i]; | ||
for (i = 0; i < password.length; i++) { | ||
inner[i] ^= password[i]; | ||
} | ||
// increments counter inside inner | ||
function incrementCounter() { | ||
for (let i = innerLen - 1; i >= innerLen - 4; i--) { | ||
inner[i]++; | ||
if (inner[i] <= 0xff) return; | ||
inner[i] = 0; | ||
} | ||
} | ||
for (i = 0; i < salt.length; i++) { | ||
inner[64 + i] = salt[i]; | ||
} | ||
// output blocks = SHA256(outerKey || SHA256(inner)) ... | ||
while (dkLen >= 32) { | ||
incrementCounter(); | ||
dk = dk.concat(SHA256(outerKey.concat(SHA256(inner)))); | ||
dkLen -= 32; | ||
} | ||
if (dkLen > 0) { | ||
incrementCounter(); | ||
dk = dk.concat(SHA256(outerKey.concat(SHA256(inner))).slice(0, dkLen)); | ||
} | ||
return dk; | ||
} | ||
for (i = innerLen - 4; i < innerLen; i++) { | ||
inner[i] = 0; | ||
} // outerKey = password ^ opad | ||
function salsaXOR(tmp, B, bin, bout) { | ||
let j0 = tmp[0] ^ B[bin++], | ||
j1 = tmp[1] ^ B[bin++], | ||
j2 = tmp[2] ^ B[bin++], | ||
j3 = tmp[3] ^ B[bin++], | ||
j4 = tmp[4] ^ B[bin++], | ||
j5 = tmp[5] ^ B[bin++], | ||
j6 = tmp[6] ^ B[bin++], | ||
j7 = tmp[7] ^ B[bin++], | ||
j8 = tmp[8] ^ B[bin++], | ||
j9 = tmp[9] ^ B[bin++], | ||
j10 = tmp[10] ^ B[bin++], | ||
j11 = tmp[11] ^ B[bin++], | ||
j12 = tmp[12] ^ B[bin++], | ||
j13 = tmp[13] ^ B[bin++], | ||
j14 = tmp[14] ^ B[bin++], | ||
j15 = tmp[15] ^ B[bin++], | ||
u, | ||
i; | ||
let x0 = j0, | ||
x1 = j1, | ||
x2 = j2, | ||
x3 = j3, | ||
x4 = j4, | ||
x5 = j5, | ||
x6 = j6, | ||
x7 = j7, | ||
x8 = j8, | ||
x9 = j9, | ||
x10 = j10, | ||
x11 = j11, | ||
x12 = j12, | ||
x13 = j13, | ||
x14 = j14, | ||
x15 = j15; | ||
for (i = 0; i < 64; i++) { | ||
outerKey[i] = 0x5c; | ||
} | ||
for (i = 0; i < 8; i += 2) { | ||
u = x0 + x12; | ||
x4 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x4 + x0; | ||
x8 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x8 + x4; | ||
x12 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x12 + x8; | ||
x0 ^= (u << 18) | (u >>> (32 - 18)); | ||
for (i = 0; i < password.length; i++) { | ||
outerKey[i] ^= password[i]; | ||
} // increments counter inside inner | ||
u = x5 + x1; | ||
x9 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x9 + x5; | ||
x13 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x13 + x9; | ||
x1 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x1 + x13; | ||
x5 ^= (u << 18) | (u >>> (32 - 18)); | ||
u = x10 + x6; | ||
x14 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x14 + x10; | ||
x2 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x2 + x14; | ||
x6 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x6 + x2; | ||
x10 ^= (u << 18) | (u >>> (32 - 18)); | ||
function incrementCounter() { | ||
for (var _i2 = innerLen - 1; _i2 >= innerLen - 4; _i2--) { | ||
inner[_i2]++; | ||
if (inner[_i2] <= 0xff) return; | ||
inner[_i2] = 0; | ||
} | ||
} // output blocks = SHA256(outerKey || SHA256(inner)) ... | ||
u = x15 + x11; | ||
x3 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x3 + x15; | ||
x7 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x7 + x3; | ||
x11 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x11 + x7; | ||
x15 ^= (u << 18) | (u >>> (32 - 18)); | ||
u = x0 + x3; | ||
x1 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x1 + x0; | ||
x2 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x2 + x1; | ||
x3 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x3 + x2; | ||
x0 ^= (u << 18) | (u >>> (32 - 18)); | ||
while (dkLen >= 32) { | ||
incrementCounter(); | ||
dk = dk.concat(SHA256(outerKey.concat(SHA256(inner)))); | ||
dkLen -= 32; | ||
} | ||
u = x5 + x4; | ||
x6 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x6 + x5; | ||
x7 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x7 + x6; | ||
x4 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x4 + x7; | ||
x5 ^= (u << 18) | (u >>> (32 - 18)); | ||
if (dkLen > 0) { | ||
incrementCounter(); | ||
dk = dk.concat(SHA256(outerKey.concat(SHA256(inner))).slice(0, dkLen)); | ||
} | ||
u = x10 + x9; | ||
x11 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x11 + x10; | ||
x8 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x8 + x11; | ||
x9 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x9 + x8; | ||
x10 ^= (u << 18) | (u >>> (32 - 18)); | ||
return dk; | ||
} | ||
u = x15 + x14; | ||
x12 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x12 + x15; | ||
x13 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x13 + x12; | ||
x14 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x14 + x13; | ||
x15 ^= (u << 18) | (u >>> (32 - 18)); | ||
} | ||
function salsaXOR(tmp, B, bin, bout) { | ||
var j0 = tmp[0] ^ B[bin++], | ||
j1 = tmp[1] ^ B[bin++], | ||
j2 = tmp[2] ^ B[bin++], | ||
j3 = tmp[3] ^ B[bin++], | ||
j4 = tmp[4] ^ B[bin++], | ||
j5 = tmp[5] ^ B[bin++], | ||
j6 = tmp[6] ^ B[bin++], | ||
j7 = tmp[7] ^ B[bin++], | ||
j8 = tmp[8] ^ B[bin++], | ||
j9 = tmp[9] ^ B[bin++], | ||
j10 = tmp[10] ^ B[bin++], | ||
j11 = tmp[11] ^ B[bin++], | ||
j12 = tmp[12] ^ B[bin++], | ||
j13 = tmp[13] ^ B[bin++], | ||
j14 = tmp[14] ^ B[bin++], | ||
j15 = tmp[15] ^ B[bin++], | ||
u, | ||
i; | ||
var x0 = j0, | ||
x1 = j1, | ||
x2 = j2, | ||
x3 = j3, | ||
x4 = j4, | ||
x5 = j5, | ||
x6 = j6, | ||
x7 = j7, | ||
x8 = j8, | ||
x9 = j9, | ||
x10 = j10, | ||
x11 = j11, | ||
x12 = j12, | ||
x13 = j13, | ||
x14 = j14, | ||
x15 = j15; | ||
B[bout++] = tmp[0] = (x0 + j0) | 0; | ||
B[bout++] = tmp[1] = (x1 + j1) | 0; | ||
B[bout++] = tmp[2] = (x2 + j2) | 0; | ||
B[bout++] = tmp[3] = (x3 + j3) | 0; | ||
B[bout++] = tmp[4] = (x4 + j4) | 0; | ||
B[bout++] = tmp[5] = (x5 + j5) | 0; | ||
B[bout++] = tmp[6] = (x6 + j6) | 0; | ||
B[bout++] = tmp[7] = (x7 + j7) | 0; | ||
B[bout++] = tmp[8] = (x8 + j8) | 0; | ||
B[bout++] = tmp[9] = (x9 + j9) | 0; | ||
B[bout++] = tmp[10] = (x10 + j10) | 0; | ||
B[bout++] = tmp[11] = (x11 + j11) | 0; | ||
B[bout++] = tmp[12] = (x12 + j12) | 0; | ||
B[bout++] = tmp[13] = (x13 + j13) | 0; | ||
B[bout++] = tmp[14] = (x14 + j14) | 0; | ||
B[bout++] = tmp[15] = (x15 + j15) | 0; | ||
} | ||
for (i = 0; i < 8; i += 2) { | ||
u = x0 + x12; | ||
x4 ^= u << 7 | u >>> 32 - 7; | ||
u = x4 + x0; | ||
x8 ^= u << 9 | u >>> 32 - 9; | ||
u = x8 + x4; | ||
x12 ^= u << 13 | u >>> 32 - 13; | ||
u = x12 + x8; | ||
x0 ^= u << 18 | u >>> 32 - 18; | ||
u = x5 + x1; | ||
x9 ^= u << 7 | u >>> 32 - 7; | ||
u = x9 + x5; | ||
x13 ^= u << 9 | u >>> 32 - 9; | ||
u = x13 + x9; | ||
x1 ^= u << 13 | u >>> 32 - 13; | ||
u = x1 + x13; | ||
x5 ^= u << 18 | u >>> 32 - 18; | ||
u = x10 + x6; | ||
x14 ^= u << 7 | u >>> 32 - 7; | ||
u = x14 + x10; | ||
x2 ^= u << 9 | u >>> 32 - 9; | ||
u = x2 + x14; | ||
x6 ^= u << 13 | u >>> 32 - 13; | ||
u = x6 + x2; | ||
x10 ^= u << 18 | u >>> 32 - 18; | ||
u = x15 + x11; | ||
x3 ^= u << 7 | u >>> 32 - 7; | ||
u = x3 + x15; | ||
x7 ^= u << 9 | u >>> 32 - 9; | ||
u = x7 + x3; | ||
x11 ^= u << 13 | u >>> 32 - 13; | ||
u = x11 + x7; | ||
x15 ^= u << 18 | u >>> 32 - 18; | ||
u = x0 + x3; | ||
x1 ^= u << 7 | u >>> 32 - 7; | ||
u = x1 + x0; | ||
x2 ^= u << 9 | u >>> 32 - 9; | ||
u = x2 + x1; | ||
x3 ^= u << 13 | u >>> 32 - 13; | ||
u = x3 + x2; | ||
x0 ^= u << 18 | u >>> 32 - 18; | ||
u = x5 + x4; | ||
x6 ^= u << 7 | u >>> 32 - 7; | ||
u = x6 + x5; | ||
x7 ^= u << 9 | u >>> 32 - 9; | ||
u = x7 + x6; | ||
x4 ^= u << 13 | u >>> 32 - 13; | ||
u = x4 + x7; | ||
x5 ^= u << 18 | u >>> 32 - 18; | ||
u = x10 + x9; | ||
x11 ^= u << 7 | u >>> 32 - 7; | ||
u = x11 + x10; | ||
x8 ^= u << 9 | u >>> 32 - 9; | ||
u = x8 + x11; | ||
x9 ^= u << 13 | u >>> 32 - 13; | ||
u = x9 + x8; | ||
x10 ^= u << 18 | u >>> 32 - 18; | ||
u = x15 + x14; | ||
x12 ^= u << 7 | u >>> 32 - 7; | ||
u = x12 + x15; | ||
x13 ^= u << 9 | u >>> 32 - 9; | ||
u = x13 + x12; | ||
x14 ^= u << 13 | u >>> 32 - 13; | ||
u = x14 + x13; | ||
x15 ^= u << 18 | u >>> 32 - 18; | ||
} | ||
function blockCopy(dst, di, src, si, len) { | ||
while (len--) dst[di++] = src[si++]; | ||
} | ||
B[bout++] = tmp[0] = x0 + j0 | 0; | ||
B[bout++] = tmp[1] = x1 + j1 | 0; | ||
B[bout++] = tmp[2] = x2 + j2 | 0; | ||
B[bout++] = tmp[3] = x3 + j3 | 0; | ||
B[bout++] = tmp[4] = x4 + j4 | 0; | ||
B[bout++] = tmp[5] = x5 + j5 | 0; | ||
B[bout++] = tmp[6] = x6 + j6 | 0; | ||
B[bout++] = tmp[7] = x7 + j7 | 0; | ||
B[bout++] = tmp[8] = x8 + j8 | 0; | ||
B[bout++] = tmp[9] = x9 + j9 | 0; | ||
B[bout++] = tmp[10] = x10 + j10 | 0; | ||
B[bout++] = tmp[11] = x11 + j11 | 0; | ||
B[bout++] = tmp[12] = x12 + j12 | 0; | ||
B[bout++] = tmp[13] = x13 + j13 | 0; | ||
B[bout++] = tmp[14] = x14 + j14 | 0; | ||
B[bout++] = tmp[15] = x15 + j15 | 0; | ||
} | ||
function blockXOR(dst, di, src, si, len) { | ||
while (len--) dst[di++] ^= src[si++]; | ||
} | ||
function blockCopy(dst, di, src, si, len) { | ||
while (len--) { | ||
dst[di++] = src[si++]; | ||
} | ||
} | ||
function blockMix(tmp, B, bin, bout, r) { | ||
blockCopy(tmp, 0, B, bin + (2 * r - 1) * 16, 16); | ||
for (let i = 0; i < 2 * r; i += 2) { | ||
salsaXOR(tmp, B, bin + i * 16, bout + i * 8); | ||
salsaXOR(tmp, B, bin + i * 16 + 16, bout + i * 8 + r * 16); | ||
} | ||
} | ||
function blockXOR(dst, di, src, si, len) { | ||
while (len--) { | ||
dst[di++] ^= src[si++]; | ||
} | ||
} | ||
function integerify(B, bi, r) { | ||
return B[bi + (2 * r - 1) * 16]; | ||
} | ||
function blockMix(tmp, B, bin, bout, r) { | ||
blockCopy(tmp, 0, B, bin + (2 * r - 1) * 16, 16); | ||
function stringToUTF8Bytes(s) { | ||
const arr = []; | ||
for (let i = 0; i < s.length; i++) { | ||
let c = s.charCodeAt(i); | ||
if (c < 0x80) { | ||
arr.push(c); | ||
} else if (c < 0x800) { | ||
arr.push(0xc0 | (c >> 6)); | ||
arr.push(0x80 | (c & 0x3f)); | ||
} else if (c < 0xd800) { | ||
arr.push(0xe0 | (c >> 12)); | ||
arr.push(0x80 | ((c >> 6) & 0x3f)); | ||
arr.push(0x80 | (c & 0x3f)); | ||
} else { | ||
if (i >= s.length - 1) { | ||
throw new Error("invalid string"); | ||
} | ||
i++; // get one more character | ||
c = (c & 0x3ff) << 10; | ||
c |= s.charCodeAt(i) & 0x3ff; | ||
c += 0x10000; | ||
for (var i = 0; i < 2 * r; i += 2) { | ||
salsaXOR(tmp, B, bin + i * 16, bout + i * 8); | ||
salsaXOR(tmp, B, bin + i * 16 + 16, bout + i * 8 + r * 16); | ||
} | ||
} | ||
arr.push(0xf0 | (c >> 18)); | ||
arr.push(0x80 | ((c >> 12) & 0x3f)); | ||
arr.push(0x80 | ((c >> 6) & 0x3f)); | ||
arr.push(0x80 | (c & 0x3f)); | ||
} | ||
} | ||
return arr; | ||
} | ||
function integerify(B, bi, r) { | ||
return B[bi + (2 * r - 1) * 16]; | ||
} | ||
function bytesToHex(p) { | ||
const enc = "0123456789abcdef".split(""); | ||
function stringToUTF8Bytes(s) { | ||
var arr = []; | ||
const len = p.length, | ||
arr = []; | ||
for (var i = 0; i < s.length; i++) { | ||
var c = s.charCodeAt(i); | ||
for (let i = 0; i < len; i++) { | ||
arr.push(enc[(p[i] >>> 4) & 15]); | ||
arr.push(enc[(p[i] >>> 0) & 15]); | ||
} | ||
return arr.join(""); | ||
} | ||
if (c < 0x80) { | ||
arr.push(c); | ||
} else if (c < 0x800) { | ||
arr.push(0xc0 | c >> 6); | ||
arr.push(0x80 | c & 0x3f); | ||
} else if (c < 0xd800) { | ||
arr.push(0xe0 | c >> 12); | ||
arr.push(0x80 | c >> 6 & 0x3f); | ||
arr.push(0x80 | c & 0x3f); | ||
} else { | ||
if (i >= s.length - 1) { | ||
throw new Error("invalid string"); | ||
} | ||
function bytesToBase64(p) { | ||
/** @const */ | ||
const enc = ( | ||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789+/" | ||
).split(""); | ||
i++; // get one more character | ||
const len = p.length, | ||
arr = []; | ||
let i = 0, | ||
a, | ||
b, | ||
c, | ||
t; | ||
c = (c & 0x3ff) << 10; | ||
c |= s.charCodeAt(i) & 0x3ff; | ||
c += 0x10000; | ||
arr.push(0xf0 | c >> 18); | ||
arr.push(0x80 | c >> 12 & 0x3f); | ||
arr.push(0x80 | c >> 6 & 0x3f); | ||
arr.push(0x80 | c & 0x3f); | ||
} | ||
} | ||
while (i < len) { | ||
a = i < len ? p[i++] : 0; | ||
b = i < len ? p[i++] : 0; | ||
c = i < len ? p[i++] : 0; | ||
t = (a << 16) + (b << 8) + c; | ||
arr.push(enc[(t >>> (3 * 6)) & 63]); | ||
arr.push(enc[(t >>> (2 * 6)) & 63]); | ||
arr.push(enc[(t >>> (1 * 6)) & 63]); | ||
arr.push(enc[(t >>> (0 * 6)) & 63]); | ||
} | ||
if (len % 3 > 0) { | ||
arr[arr.length - 1] = "="; | ||
if (len % 3 === 1) arr[arr.length - 2] = "="; | ||
} | ||
return arr.join(""); | ||
} | ||
return arr; | ||
} | ||
// Generate key. | ||
function bytesToHex(p) { | ||
var enc = "0123456789abcdef".split(""); | ||
var len = p.length, | ||
arr = []; | ||
const MAX_UINT = -1 >>> 0; | ||
for (var i = 0; i < len; i++) { | ||
arr.push(enc[p[i] >>> 4 & 15]); | ||
arr.push(enc[p[i] >>> 0 & 15]); | ||
} | ||
if (!logN && !n) { | ||
return reject(new Error("scrypt: missing N or logN parameter")); | ||
} | ||
return arr.join(""); | ||
} | ||
let N; | ||
function bytesToBase64(p) { | ||
/** @const */ | ||
var enc = ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789+/").split(""); | ||
var len = p.length, | ||
arr = []; | ||
var i = 0, | ||
a, | ||
b, | ||
c, | ||
t; | ||
if (logN || logN === 0) { | ||
if (logN < 1 || logN > 31) { | ||
return reject(new Error("scrypt: logN must be between 1 and 31")); | ||
} | ||
while (i < len) { | ||
a = i < len ? p[i++] : 0; | ||
b = i < len ? p[i++] : 0; | ||
c = i < len ? p[i++] : 0; | ||
t = (a << 16) + (b << 8) + c; | ||
arr.push(enc[t >>> 3 * 6 & 63]); | ||
arr.push(enc[t >>> 2 * 6 & 63]); | ||
arr.push(enc[t >>> 1 * 6 & 63]); | ||
arr.push(enc[t >>> 0 * 6 & 63]); | ||
} | ||
N = (1 << logN) >>> 0; | ||
} else { | ||
if (n < 2 || n > MAX_UINT) { | ||
return reject(new Error("scrypt: N is out of range")); | ||
} else if ((n & (n - 1)) !== 0) { | ||
return reject(Error("scrypt: N is not a power of 2")); | ||
} | ||
if (len % 3 > 0) { | ||
arr[arr.length - 1] = "="; | ||
if (len % 3 === 1) arr[arr.length - 2] = "="; | ||
} | ||
N = n; | ||
} | ||
return arr.join(""); | ||
} | ||
if (p < 1) { | ||
return reject(new Error("scrypt: invalid p")); | ||
} | ||
var XY, V, B, tmp; | ||
if (r <= 0) { | ||
return reject(new Error("scrypt: invalid r")); | ||
} | ||
if (r * p >= 1 << 30 || r > MAX_UINT / 128 / p || r > MAX_UINT / 256 || N > MAX_UINT / 128 / r) { | ||
return reject(new Error("scrypt: parameters are too large")); | ||
} // Decode strings. | ||
let XY, V, B, tmp; | ||
if ( | ||
r * p >= 1 << 30 || | ||
r > MAX_UINT / 128 / p || | ||
r > MAX_UINT / 256 || | ||
N > MAX_UINT / 128 / r | ||
) { | ||
return reject(new Error("scrypt: parameters are too large")); | ||
} | ||
if (typeof password === "string") password = stringToUTF8Bytes(password); | ||
if (typeof salt === "string") salt = stringToUTF8Bytes(salt); | ||
// Decode strings. | ||
if (typeof password === "string") password = stringToUTF8Bytes(password); | ||
if (typeof salt === "string") salt = stringToUTF8Bytes(salt); | ||
if (typeof Int32Array !== "undefined") { | ||
//XXX We can use Uint32Array, but Int32Array is faster in Safari. | ||
XY = new Int32Array(64 * r); | ||
V = new Int32Array(32 * N * r); | ||
tmp = new Int32Array(16); | ||
} else { | ||
XY = []; | ||
V = []; | ||
tmp = new Array(16); | ||
} | ||
if (typeof Int32Array !== "undefined") { | ||
//XXX We can use Uint32Array, but Int32Array is faster in Safari. | ||
XY = new Int32Array(64 * r); | ||
V = new Int32Array(32 * N * r); | ||
tmp = new Int32Array(16); | ||
} else { | ||
XY = []; | ||
V = []; | ||
tmp = new Array(16); | ||
} | ||
B = PBKDF2_HMAC_SHA256_OneIter(password, salt, p * 128 * r); | ||
B = PBKDF2_HMAC_SHA256_OneIter(password, salt, p * 128 * r); | ||
var xi = 0, | ||
yi = 32 * r; | ||
const xi = 0, | ||
yi = 32 * r; | ||
function smixStart(pos) { | ||
for (var i = 0; i < 32 * r; i++) { | ||
var j = pos + i * 4; | ||
XY[xi + i] = (B[j + 3] & 0xff) << 24 | (B[j + 2] & 0xff) << 16 | (B[j + 1] & 0xff) << 8 | (B[j + 0] & 0xff) << 0; | ||
} | ||
} | ||
function smixStart(pos) { | ||
for (let i = 0; i < 32 * r; i++) { | ||
const j = pos + i * 4; | ||
XY[xi + i] = | ||
((B[j + 3] & 0xff) << 24) | | ||
((B[j + 2] & 0xff) << 16) | | ||
((B[j + 1] & 0xff) << 8) | | ||
((B[j + 0] & 0xff) << 0); | ||
} | ||
} | ||
function smixStep1(start, end) { | ||
for (var i = start; i < end; i += 2) { | ||
blockCopy(V, i * (32 * r), XY, xi, 32 * r); | ||
blockMix(tmp, XY, xi, yi, r); | ||
blockCopy(V, (i + 1) * (32 * r), XY, yi, 32 * r); | ||
blockMix(tmp, XY, yi, xi, r); | ||
} | ||
} | ||
function smixStep1(start, end) { | ||
for (let i = start; i < end; i += 2) { | ||
blockCopy(V, i * (32 * r), XY, xi, 32 * r); | ||
blockMix(tmp, XY, xi, yi, r); | ||
function smixStep2(start, end) { | ||
for (var i = start; i < end; i += 2) { | ||
var j = integerify(XY, xi, r) & N - 1; | ||
blockXOR(XY, xi, V, j * (32 * r), 32 * r); | ||
blockMix(tmp, XY, xi, yi, r); | ||
j = integerify(XY, yi, r) & N - 1; | ||
blockXOR(XY, yi, V, j * (32 * r), 32 * r); | ||
blockMix(tmp, XY, yi, xi, r); | ||
} | ||
} | ||
blockCopy(V, (i + 1) * (32 * r), XY, yi, 32 * r); | ||
blockMix(tmp, XY, yi, xi, r); | ||
} | ||
} | ||
function smixFinish(pos) { | ||
for (var i = 0; i < 32 * r; i++) { | ||
var j = XY[xi + i]; | ||
B[pos + i * 4 + 0] = j >>> 0 & 0xff; | ||
B[pos + i * 4 + 1] = j >>> 8 & 0xff; | ||
B[pos + i * 4 + 2] = j >>> 16 & 0xff; | ||
B[pos + i * 4 + 3] = j >>> 24 & 0xff; | ||
} | ||
} | ||
function smixStep2(start, end) { | ||
for (let i = start; i < end; i += 2) { | ||
let j = integerify(XY, xi, r) & (N - 1); | ||
blockXOR(XY, xi, V, j * (32 * r), 32 * r); | ||
blockMix(tmp, XY, xi, yi, r); | ||
var nextTick = typeof setImmediate !== "undefined" ? setImmediate : setTimeout; | ||
j = integerify(XY, yi, r) & (N - 1); | ||
blockXOR(XY, yi, V, j * (32 * r), 32 * r); | ||
blockMix(tmp, XY, yi, xi, r); | ||
} | ||
} | ||
function interruptedFor(start, end, step, fn, donefn) { | ||
(function performStep() { | ||
nextTick(function () { | ||
fn(start, start + step < end ? start + step : end); | ||
start += step; | ||
if (start < end) performStep();else donefn(); | ||
}); | ||
})(); | ||
} | ||
function smixFinish(pos) { | ||
for (let i = 0; i < 32 * r; i++) { | ||
const j = XY[xi + i]; | ||
B[pos + i * 4 + 0] = (j >>> 0) & 0xff; | ||
B[pos + i * 4 + 1] = (j >>> 8) & 0xff; | ||
B[pos + i * 4 + 2] = (j >>> 16) & 0xff; | ||
B[pos + i * 4 + 3] = (j >>> 24) & 0xff; | ||
} | ||
} | ||
function getResult(enc) { | ||
var result = PBKDF2_HMAC_SHA256_OneIter(password, B, dkLen); | ||
if (enc === "base64") return bytesToBase64(result);else if (enc === "hex") return bytesToHex(result);else if (enc === "binary") return new Uint8Array(result);else return result; | ||
} // Blocking variant. | ||
const nextTick = | ||
typeof setImmediate !== "undefined" ? setImmediate : setTimeout; | ||
function interruptedFor(start, end, step, fn, donefn) { | ||
(function performStep() { | ||
nextTick(function () { | ||
fn(start, start + step < end ? start + step : end); | ||
start += step; | ||
if (start < end) performStep(); | ||
else donefn(); | ||
}); | ||
})(); | ||
} | ||
function calculateSync() { | ||
for (var i = 0; i < p; i++) { | ||
smixStart(i * 128 * r); | ||
smixStep1(0, N); | ||
smixStep2(0, N); | ||
smixFinish(i * 128 * r); | ||
} | ||
function getResult(enc) { | ||
const result = PBKDF2_HMAC_SHA256_OneIter(password, B, dkLen); | ||
if (enc === "base64") return bytesToBase64(result); | ||
else if (enc === "hex") return bytesToHex(result); | ||
else if (enc === "binary") return new Uint8Array(result); | ||
else return result; | ||
} | ||
callback(getResult(encoding)); | ||
} // Async variant. | ||
// Blocking variant. | ||
function calculateSync() { | ||
for (let i = 0; i < p; i++) { | ||
smixStart(i * 128 * r); | ||
smixStep1(0, N); | ||
smixStep2(0, N); | ||
smixFinish(i * 128 * r); | ||
} | ||
resolve(getResult(encoding)); | ||
} | ||
// Async variant. | ||
function calculateAsync(i) { | ||
smixStart(i * 128 * r); | ||
interruptedFor(0, N, interruptStep * 2, smixStep1, function () { | ||
interruptedFor(0, N, interruptStep * 2, smixStep2, function () { | ||
smixFinish(i * 128 * r); | ||
if (i + 1 < p) { | ||
nextTick(function () { | ||
calculateAsync(i + 1); | ||
}); | ||
} else { | ||
resolve(getResult(encoding)); | ||
} | ||
}); | ||
}); | ||
} | ||
function calculateAsync(i) { | ||
smixStart(i * 128 * r); | ||
interruptedFor(0, N, interruptStep * 2, smixStep1, function () { | ||
interruptedFor(0, N, interruptStep * 2, smixStep2, function () { | ||
smixFinish(i * 128 * r); | ||
if (interruptStep <= 0) { | ||
calculateSync(); | ||
} else { | ||
calculateAsync(0); | ||
} | ||
}); | ||
if (i + 1 < p) { | ||
nextTick(function () { | ||
calculateAsync(i + 1); | ||
}); | ||
} else { | ||
callback(getResult(encoding)); | ||
} | ||
}); | ||
}); | ||
} | ||
if (interruptStep <= 0) { | ||
calculateSync(); | ||
} else { | ||
calculateAsync(0); | ||
} | ||
} | ||
var MAX_UINT = -1 >>> 0; | ||
export default scrypt; |
{ | ||
"name": "scrypt-async-modern", | ||
"version": "3.0.0", | ||
"version": "3.0.1", | ||
"description": "Fast \"async\" scrypt implementation in modern JavaScript.", | ||
@@ -14,8 +14,10 @@ "main": "dist/cjs/index.js", | ||
"devDependencies": { | ||
"@babel/core": "^7.0.0-beta.38", | ||
"babel-core": "^7.0.0-0", | ||
"@babel/preset-env": "^7.0.0-beta.38", | ||
"jest": "^22.1.4", | ||
"@babel/core": "^7.0.0-beta.38", | ||
"babel-jest": "^22.1.0", | ||
"babel-preset-env": "^1.6.1", | ||
"prettier": "^1.10.2", | ||
"rollup": "^0.55.1" | ||
"rollup": "^0.55.1", | ||
"rollup-plugin-babel": "^4.0.0-beta.0", | ||
"prettier": "^1.10.2" | ||
}, | ||
@@ -22,0 +24,0 @@ "repository": { |
1140
src/index.js
/*! | ||
* Fast "async" scrypt implementation in JavaScript. | ||
* Copyright (c) 2013-2016 Dmitry Chestnykh | BSD License | ||
* https://github.com/dchest/scrypt-async-js | ||
* Fast "async" scrypt implementation in modern JavaScript. | ||
* Copyright (c) 2018 Charles Crete | MIT License | ||
* https://github.com/Cretezy/scrypt-async-modern | ||
*/ | ||
@@ -40,653 +40,653 @@ | ||
salt, | ||
{ N: n = 16384, logN, r = 8, p = 1, dkLen = 32, interruptStep = 0, encoding } = {}) { | ||
{ N = 16384, logN, r = 8, p = 1, dkLen = 32, interruptStep = 0, encoding } = {}) { | ||
return new Promise((resolve, reject) => { | ||
function SHA256(m) { | ||
const K = [ | ||
0x428a2f98, | ||
0x71374491, | ||
0xb5c0fbcf, | ||
0xe9b5dba5, | ||
0x3956c25b, | ||
0x59f111f1, | ||
0x923f82a4, | ||
0xab1c5ed5, | ||
0xd807aa98, | ||
0x12835b01, | ||
0x243185be, | ||
0x550c7dc3, | ||
0x72be5d74, | ||
0x80deb1fe, | ||
0x9bdc06a7, | ||
0xc19bf174, | ||
0xe49b69c1, | ||
0xefbe4786, | ||
0x0fc19dc6, | ||
0x240ca1cc, | ||
0x2de92c6f, | ||
0x4a7484aa, | ||
0x5cb0a9dc, | ||
0x76f988da, | ||
0x983e5152, | ||
0xa831c66d, | ||
0xb00327c8, | ||
0xbf597fc7, | ||
0xc6e00bf3, | ||
0xd5a79147, | ||
0x06ca6351, | ||
0x14292967, | ||
0x27b70a85, | ||
0x2e1b2138, | ||
0x4d2c6dfc, | ||
0x53380d13, | ||
0x650a7354, | ||
0x766a0abb, | ||
0x81c2c92e, | ||
0x92722c85, | ||
0xa2bfe8a1, | ||
0xa81a664b, | ||
0xc24b8b70, | ||
0xc76c51a3, | ||
0xd192e819, | ||
0xd6990624, | ||
0xf40e3585, | ||
0x106aa070, | ||
0x19a4c116, | ||
0x1e376c08, | ||
0x2748774c, | ||
0x34b0bcb5, | ||
0x391c0cb3, | ||
0x4ed8aa4a, | ||
0x5b9cca4f, | ||
0x682e6ff3, | ||
0x748f82ee, | ||
0x78a5636f, | ||
0x84c87814, | ||
0x8cc70208, | ||
0x90befffa, | ||
0xa4506ceb, | ||
0xbef9a3f7, | ||
0xc67178f2 | ||
]; | ||
let h0 = 0x6a09e667, | ||
h1 = 0xbb67ae85, | ||
h2 = 0x3c6ef372, | ||
h3 = 0xa54ff53a, | ||
h4 = 0x510e527f, | ||
h5 = 0x9b05688c, | ||
h6 = 0x1f83d9ab, | ||
h7 = 0x5be0cd19, | ||
w = new Array(64); | ||
if (!logN && !N) { | ||
return reject(new Error("scrypt: missing N or logN parameter")); | ||
} | ||
function blocks(p) { | ||
let off = 0, | ||
len = p.length; | ||
while (len >= 64) { | ||
let a = h0, | ||
b = h1, | ||
c = h2, | ||
d = h3, | ||
e = h4, | ||
f = h5, | ||
g = h6, | ||
h = h7, | ||
u, | ||
i, | ||
j, | ||
t1, | ||
t2; | ||
if (logN || logN === 0) { | ||
if (logN < 1 || logN > 31) { | ||
return reject(new Error("scrypt: logN must be between 1 and 31")); | ||
} | ||
for (i = 0; i < 16; i++) { | ||
j = off + i * 4; | ||
w[i] = | ||
((p[j] & 0xff) << 24) | | ||
((p[j + 1] & 0xff) << 16) | | ||
((p[j + 2] & 0xff) << 8) | | ||
(p[j + 3] & 0xff); | ||
} | ||
N = (1 << logN) >>> 0; | ||
} else { | ||
if (N < 2 || N > MAX_UINT) { | ||
return reject(new Error("scrypt: N is out of range")); | ||
} else if ((N & (N - 1)) !== 0) { | ||
return reject(Error("scrypt: N is not a power of 2")); | ||
} | ||
} | ||
for (i = 16; i < 64; i++) { | ||
u = w[i - 2]; | ||
t1 = | ||
((u >>> 17) | (u << (32 - 17))) ^ | ||
((u >>> 19) | (u << (32 - 19))) ^ | ||
(u >>> 10); | ||
if (p < 1) { | ||
return reject(new Error("scrypt: invalid p")); | ||
} | ||
u = w[i - 15]; | ||
t2 = | ||
((u >>> 7) | (u << (32 - 7))) ^ | ||
((u >>> 18) | (u << (32 - 18))) ^ | ||
(u >>> 3); | ||
if (r <= 0) { | ||
return reject(new Error("scrypt: invalid r")); | ||
} | ||
w[i] = (((t1 + w[i - 7]) | 0) + ((t2 + w[i - 16]) | 0)) | 0; | ||
} | ||
run({ password, salt, N, r, p, dkLen, interruptStep, encoding }, resolve); | ||
}); | ||
} | ||
for (i = 0; i < 64; i++) { | ||
t1 = | ||
((((((e >>> 6) | (e << (32 - 6))) ^ | ||
((e >>> 11) | (e << (32 - 11))) ^ | ||
((e >>> 25) | (e << (32 - 25)))) + | ||
((e & f) ^ (~e & g))) | | ||
0) + | ||
((h + ((K[i] + w[i]) | 0)) | 0)) | | ||
0; | ||
// Internal scrypt function | ||
function run({password, salt, N, r, p, dkLen, interruptStep, encoding }, callback) { | ||
function SHA256(m) { | ||
const K = [ | ||
0x428a2f98, | ||
0x71374491, | ||
0xb5c0fbcf, | ||
0xe9b5dba5, | ||
0x3956c25b, | ||
0x59f111f1, | ||
0x923f82a4, | ||
0xab1c5ed5, | ||
0xd807aa98, | ||
0x12835b01, | ||
0x243185be, | ||
0x550c7dc3, | ||
0x72be5d74, | ||
0x80deb1fe, | ||
0x9bdc06a7, | ||
0xc19bf174, | ||
0xe49b69c1, | ||
0xefbe4786, | ||
0x0fc19dc6, | ||
0x240ca1cc, | ||
0x2de92c6f, | ||
0x4a7484aa, | ||
0x5cb0a9dc, | ||
0x76f988da, | ||
0x983e5152, | ||
0xa831c66d, | ||
0xb00327c8, | ||
0xbf597fc7, | ||
0xc6e00bf3, | ||
0xd5a79147, | ||
0x06ca6351, | ||
0x14292967, | ||
0x27b70a85, | ||
0x2e1b2138, | ||
0x4d2c6dfc, | ||
0x53380d13, | ||
0x650a7354, | ||
0x766a0abb, | ||
0x81c2c92e, | ||
0x92722c85, | ||
0xa2bfe8a1, | ||
0xa81a664b, | ||
0xc24b8b70, | ||
0xc76c51a3, | ||
0xd192e819, | ||
0xd6990624, | ||
0xf40e3585, | ||
0x106aa070, | ||
0x19a4c116, | ||
0x1e376c08, | ||
0x2748774c, | ||
0x34b0bcb5, | ||
0x391c0cb3, | ||
0x4ed8aa4a, | ||
0x5b9cca4f, | ||
0x682e6ff3, | ||
0x748f82ee, | ||
0x78a5636f, | ||
0x84c87814, | ||
0x8cc70208, | ||
0x90befffa, | ||
0xa4506ceb, | ||
0xbef9a3f7, | ||
0xc67178f2 | ||
]; | ||
t2 = | ||
((((a >>> 2) | (a << (32 - 2))) ^ | ||
((a >>> 13) | (a << (32 - 13))) ^ | ||
((a >>> 22) | (a << (32 - 22)))) + | ||
((a & b) ^ (a & c) ^ (b & c))) | | ||
0; | ||
let h0 = 0x6a09e667, | ||
h1 = 0xbb67ae85, | ||
h2 = 0x3c6ef372, | ||
h3 = 0xa54ff53a, | ||
h4 = 0x510e527f, | ||
h5 = 0x9b05688c, | ||
h6 = 0x1f83d9ab, | ||
h7 = 0x5be0cd19, | ||
w = new Array(64); | ||
h = g; | ||
g = f; | ||
f = e; | ||
e = (d + t1) | 0; | ||
d = c; | ||
c = b; | ||
b = a; | ||
a = (t1 + t2) | 0; | ||
} | ||
function blocks(p) { | ||
let off = 0, | ||
len = p.length; | ||
while (len >= 64) { | ||
let a = h0, | ||
b = h1, | ||
c = h2, | ||
d = h3, | ||
e = h4, | ||
f = h5, | ||
g = h6, | ||
h = h7, | ||
u, | ||
i, | ||
j, | ||
t1, | ||
t2; | ||
h0 = (h0 + a) | 0; | ||
h1 = (h1 + b) | 0; | ||
h2 = (h2 + c) | 0; | ||
h3 = (h3 + d) | 0; | ||
h4 = (h4 + e) | 0; | ||
h5 = (h5 + f) | 0; | ||
h6 = (h6 + g) | 0; | ||
h7 = (h7 + h) | 0; | ||
off += 64; | ||
len -= 64; | ||
for (i = 0; i < 16; i++) { | ||
j = off + i * 4; | ||
w[i] = | ||
((p[j] & 0xff) << 24) | | ||
((p[j + 1] & 0xff) << 16) | | ||
((p[j + 2] & 0xff) << 8) | | ||
(p[j + 3] & 0xff); | ||
} | ||
} | ||
blocks(m); | ||
for (i = 16; i < 64; i++) { | ||
u = w[i - 2]; | ||
t1 = | ||
((u >>> 17) | (u << (32 - 17))) ^ | ||
((u >>> 19) | (u << (32 - 19))) ^ | ||
(u >>> 10); | ||
let i, | ||
bytesLeft = m.length % 64, | ||
bitLenHi = (m.length / 0x20000000) | 0, | ||
bitLenLo = m.length << 3, | ||
numZeros = bytesLeft < 56 ? 56 : 120, | ||
p = m.slice(m.length - bytesLeft, m.length); | ||
u = w[i - 15]; | ||
t2 = | ||
((u >>> 7) | (u << (32 - 7))) ^ | ||
((u >>> 18) | (u << (32 - 18))) ^ | ||
(u >>> 3); | ||
p.push(0x80); | ||
for (i = bytesLeft + 1; i < numZeros; i++) p.push(0); | ||
p.push((bitLenHi >>> 24) & 0xff); | ||
p.push((bitLenHi >>> 16) & 0xff); | ||
p.push((bitLenHi >>> 8) & 0xff); | ||
p.push((bitLenHi >>> 0) & 0xff); | ||
p.push((bitLenLo >>> 24) & 0xff); | ||
p.push((bitLenLo >>> 16) & 0xff); | ||
p.push((bitLenLo >>> 8) & 0xff); | ||
p.push((bitLenLo >>> 0) & 0xff); | ||
w[i] = (((t1 + w[i - 7]) | 0) + ((t2 + w[i - 16]) | 0)) | 0; | ||
} | ||
blocks(p); | ||
for (i = 0; i < 64; i++) { | ||
t1 = | ||
((((((e >>> 6) | (e << (32 - 6))) ^ | ||
((e >>> 11) | (e << (32 - 11))) ^ | ||
((e >>> 25) | (e << (32 - 25)))) + | ||
((e & f) ^ (~e & g))) | | ||
0) + | ||
((h + ((K[i] + w[i]) | 0)) | 0)) | | ||
0; | ||
return [ | ||
(h0 >>> 24) & 0xff, | ||
(h0 >>> 16) & 0xff, | ||
(h0 >>> 8) & 0xff, | ||
(h0 >>> 0) & 0xff, | ||
(h1 >>> 24) & 0xff, | ||
(h1 >>> 16) & 0xff, | ||
(h1 >>> 8) & 0xff, | ||
(h1 >>> 0) & 0xff, | ||
(h2 >>> 24) & 0xff, | ||
(h2 >>> 16) & 0xff, | ||
(h2 >>> 8) & 0xff, | ||
(h2 >>> 0) & 0xff, | ||
(h3 >>> 24) & 0xff, | ||
(h3 >>> 16) & 0xff, | ||
(h3 >>> 8) & 0xff, | ||
(h3 >>> 0) & 0xff, | ||
(h4 >>> 24) & 0xff, | ||
(h4 >>> 16) & 0xff, | ||
(h4 >>> 8) & 0xff, | ||
(h4 >>> 0) & 0xff, | ||
(h5 >>> 24) & 0xff, | ||
(h5 >>> 16) & 0xff, | ||
(h5 >>> 8) & 0xff, | ||
(h5 >>> 0) & 0xff, | ||
(h6 >>> 24) & 0xff, | ||
(h6 >>> 16) & 0xff, | ||
(h6 >>> 8) & 0xff, | ||
(h6 >>> 0) & 0xff, | ||
(h7 >>> 24) & 0xff, | ||
(h7 >>> 16) & 0xff, | ||
(h7 >>> 8) & 0xff, | ||
(h7 >>> 0) & 0xff | ||
]; | ||
} | ||
t2 = | ||
((((a >>> 2) | (a << (32 - 2))) ^ | ||
((a >>> 13) | (a << (32 - 13))) ^ | ||
((a >>> 22) | (a << (32 - 22)))) + | ||
((a & b) ^ (a & c) ^ (b & c))) | | ||
0; | ||
function PBKDF2_HMAC_SHA256_OneIter(password, salt, dkLen) { | ||
// compress password if it's longer than hash block length | ||
password = password.length <= 64 ? password : SHA256(password); | ||
h = g; | ||
g = f; | ||
f = e; | ||
e = (d + t1) | 0; | ||
d = c; | ||
c = b; | ||
b = a; | ||
a = (t1 + t2) | 0; | ||
} | ||
let i, | ||
innerLen = 64 + salt.length + 4, | ||
inner = new Array(innerLen), | ||
outerKey = new Array(64), | ||
dk = []; | ||
h0 = (h0 + a) | 0; | ||
h1 = (h1 + b) | 0; | ||
h2 = (h2 + c) | 0; | ||
h3 = (h3 + d) | 0; | ||
h4 = (h4 + e) | 0; | ||
h5 = (h5 + f) | 0; | ||
h6 = (h6 + g) | 0; | ||
h7 = (h7 + h) | 0; | ||
// inner = (password ^ ipad) || salt || counter | ||
for (i = 0; i < 64; i++) inner[i] = 0x36; | ||
for (i = 0; i < password.length; i++) inner[i] ^= password[i]; | ||
for (i = 0; i < salt.length; i++) inner[64 + i] = salt[i]; | ||
for (i = innerLen - 4; i < innerLen; i++) inner[i] = 0; | ||
// outerKey = password ^ opad | ||
for (i = 0; i < 64; i++) outerKey[i] = 0x5c; | ||
for (i = 0; i < password.length; i++) outerKey[i] ^= password[i]; | ||
// increments counter inside inner | ||
function incrementCounter() { | ||
for (let i = innerLen - 1; i >= innerLen - 4; i--) { | ||
inner[i]++; | ||
if (inner[i] <= 0xff) return; | ||
inner[i] = 0; | ||
} | ||
off += 64; | ||
len -= 64; | ||
} | ||
// output blocks = SHA256(outerKey || SHA256(inner)) ... | ||
while (dkLen >= 32) { | ||
incrementCounter(); | ||
dk = dk.concat(SHA256(outerKey.concat(SHA256(inner)))); | ||
dkLen -= 32; | ||
} | ||
if (dkLen > 0) { | ||
incrementCounter(); | ||
dk = dk.concat(SHA256(outerKey.concat(SHA256(inner))).slice(0, dkLen)); | ||
} | ||
return dk; | ||
} | ||
function salsaXOR(tmp, B, bin, bout) { | ||
let j0 = tmp[0] ^ B[bin++], | ||
j1 = tmp[1] ^ B[bin++], | ||
j2 = tmp[2] ^ B[bin++], | ||
j3 = tmp[3] ^ B[bin++], | ||
j4 = tmp[4] ^ B[bin++], | ||
j5 = tmp[5] ^ B[bin++], | ||
j6 = tmp[6] ^ B[bin++], | ||
j7 = tmp[7] ^ B[bin++], | ||
j8 = tmp[8] ^ B[bin++], | ||
j9 = tmp[9] ^ B[bin++], | ||
j10 = tmp[10] ^ B[bin++], | ||
j11 = tmp[11] ^ B[bin++], | ||
j12 = tmp[12] ^ B[bin++], | ||
j13 = tmp[13] ^ B[bin++], | ||
j14 = tmp[14] ^ B[bin++], | ||
j15 = tmp[15] ^ B[bin++], | ||
u, | ||
i; | ||
blocks(m); | ||
let x0 = j0, | ||
x1 = j1, | ||
x2 = j2, | ||
x3 = j3, | ||
x4 = j4, | ||
x5 = j5, | ||
x6 = j6, | ||
x7 = j7, | ||
x8 = j8, | ||
x9 = j9, | ||
x10 = j10, | ||
x11 = j11, | ||
x12 = j12, | ||
x13 = j13, | ||
x14 = j14, | ||
x15 = j15; | ||
let i, | ||
bytesLeft = m.length % 64, | ||
bitLenHi = (m.length / 0x20000000) | 0, | ||
bitLenLo = m.length << 3, | ||
numZeros = bytesLeft < 56 ? 56 : 120, | ||
p = m.slice(m.length - bytesLeft, m.length); | ||
for (i = 0; i < 8; i += 2) { | ||
u = x0 + x12; | ||
x4 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x4 + x0; | ||
x8 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x8 + x4; | ||
x12 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x12 + x8; | ||
x0 ^= (u << 18) | (u >>> (32 - 18)); | ||
p.push(0x80); | ||
for (i = bytesLeft + 1; i < numZeros; i++) p.push(0); | ||
p.push((bitLenHi >>> 24) & 0xff); | ||
p.push((bitLenHi >>> 16) & 0xff); | ||
p.push((bitLenHi >>> 8) & 0xff); | ||
p.push((bitLenHi >>> 0) & 0xff); | ||
p.push((bitLenLo >>> 24) & 0xff); | ||
p.push((bitLenLo >>> 16) & 0xff); | ||
p.push((bitLenLo >>> 8) & 0xff); | ||
p.push((bitLenLo >>> 0) & 0xff); | ||
u = x5 + x1; | ||
x9 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x9 + x5; | ||
x13 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x13 + x9; | ||
x1 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x1 + x13; | ||
x5 ^= (u << 18) | (u >>> (32 - 18)); | ||
blocks(p); | ||
u = x10 + x6; | ||
x14 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x14 + x10; | ||
x2 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x2 + x14; | ||
x6 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x6 + x2; | ||
x10 ^= (u << 18) | (u >>> (32 - 18)); | ||
return [ | ||
(h0 >>> 24) & 0xff, | ||
(h0 >>> 16) & 0xff, | ||
(h0 >>> 8) & 0xff, | ||
(h0 >>> 0) & 0xff, | ||
(h1 >>> 24) & 0xff, | ||
(h1 >>> 16) & 0xff, | ||
(h1 >>> 8) & 0xff, | ||
(h1 >>> 0) & 0xff, | ||
(h2 >>> 24) & 0xff, | ||
(h2 >>> 16) & 0xff, | ||
(h2 >>> 8) & 0xff, | ||
(h2 >>> 0) & 0xff, | ||
(h3 >>> 24) & 0xff, | ||
(h3 >>> 16) & 0xff, | ||
(h3 >>> 8) & 0xff, | ||
(h3 >>> 0) & 0xff, | ||
(h4 >>> 24) & 0xff, | ||
(h4 >>> 16) & 0xff, | ||
(h4 >>> 8) & 0xff, | ||
(h4 >>> 0) & 0xff, | ||
(h5 >>> 24) & 0xff, | ||
(h5 >>> 16) & 0xff, | ||
(h5 >>> 8) & 0xff, | ||
(h5 >>> 0) & 0xff, | ||
(h6 >>> 24) & 0xff, | ||
(h6 >>> 16) & 0xff, | ||
(h6 >>> 8) & 0xff, | ||
(h6 >>> 0) & 0xff, | ||
(h7 >>> 24) & 0xff, | ||
(h7 >>> 16) & 0xff, | ||
(h7 >>> 8) & 0xff, | ||
(h7 >>> 0) & 0xff | ||
]; | ||
} | ||
u = x15 + x11; | ||
x3 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x3 + x15; | ||
x7 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x7 + x3; | ||
x11 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x11 + x7; | ||
x15 ^= (u << 18) | (u >>> (32 - 18)); | ||
function PBKDF2_HMAC_SHA256_OneIter(password, salt, dkLen) { | ||
// compress password if it's longer than hash block length | ||
password = password.length <= 64 ? password : SHA256(password); | ||
u = x0 + x3; | ||
x1 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x1 + x0; | ||
x2 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x2 + x1; | ||
x3 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x3 + x2; | ||
x0 ^= (u << 18) | (u >>> (32 - 18)); | ||
let i, | ||
innerLen = 64 + salt.length + 4, | ||
inner = new Array(innerLen), | ||
outerKey = new Array(64), | ||
dk = []; | ||
u = x5 + x4; | ||
x6 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x6 + x5; | ||
x7 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x7 + x6; | ||
x4 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x4 + x7; | ||
x5 ^= (u << 18) | (u >>> (32 - 18)); | ||
// inner = (password ^ ipad) || salt || counter | ||
for (i = 0; i < 64; i++) inner[i] = 0x36; | ||
for (i = 0; i < password.length; i++) inner[i] ^= password[i]; | ||
for (i = 0; i < salt.length; i++) inner[64 + i] = salt[i]; | ||
for (i = innerLen - 4; i < innerLen; i++) inner[i] = 0; | ||
u = x10 + x9; | ||
x11 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x11 + x10; | ||
x8 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x8 + x11; | ||
x9 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x9 + x8; | ||
x10 ^= (u << 18) | (u >>> (32 - 18)); | ||
// outerKey = password ^ opad | ||
for (i = 0; i < 64; i++) outerKey[i] = 0x5c; | ||
for (i = 0; i < password.length; i++) outerKey[i] ^= password[i]; | ||
u = x15 + x14; | ||
x12 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x12 + x15; | ||
x13 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x13 + x12; | ||
x14 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x14 + x13; | ||
x15 ^= (u << 18) | (u >>> (32 - 18)); | ||
// increments counter inside inner | ||
function incrementCounter() { | ||
for (let i = innerLen - 1; i >= innerLen - 4; i--) { | ||
inner[i]++; | ||
if (inner[i] <= 0xff) return; | ||
inner[i] = 0; | ||
} | ||
B[bout++] = tmp[0] = (x0 + j0) | 0; | ||
B[bout++] = tmp[1] = (x1 + j1) | 0; | ||
B[bout++] = tmp[2] = (x2 + j2) | 0; | ||
B[bout++] = tmp[3] = (x3 + j3) | 0; | ||
B[bout++] = tmp[4] = (x4 + j4) | 0; | ||
B[bout++] = tmp[5] = (x5 + j5) | 0; | ||
B[bout++] = tmp[6] = (x6 + j6) | 0; | ||
B[bout++] = tmp[7] = (x7 + j7) | 0; | ||
B[bout++] = tmp[8] = (x8 + j8) | 0; | ||
B[bout++] = tmp[9] = (x9 + j9) | 0; | ||
B[bout++] = tmp[10] = (x10 + j10) | 0; | ||
B[bout++] = tmp[11] = (x11 + j11) | 0; | ||
B[bout++] = tmp[12] = (x12 + j12) | 0; | ||
B[bout++] = tmp[13] = (x13 + j13) | 0; | ||
B[bout++] = tmp[14] = (x14 + j14) | 0; | ||
B[bout++] = tmp[15] = (x15 + j15) | 0; | ||
} | ||
function blockCopy(dst, di, src, si, len) { | ||
while (len--) dst[di++] = src[si++]; | ||
// output blocks = SHA256(outerKey || SHA256(inner)) ... | ||
while (dkLen >= 32) { | ||
incrementCounter(); | ||
dk = dk.concat(SHA256(outerKey.concat(SHA256(inner)))); | ||
dkLen -= 32; | ||
} | ||
function blockXOR(dst, di, src, si, len) { | ||
while (len--) dst[di++] ^= src[si++]; | ||
if (dkLen > 0) { | ||
incrementCounter(); | ||
dk = dk.concat(SHA256(outerKey.concat(SHA256(inner))).slice(0, dkLen)); | ||
} | ||
return dk; | ||
} | ||
function blockMix(tmp, B, bin, bout, r) { | ||
blockCopy(tmp, 0, B, bin + (2 * r - 1) * 16, 16); | ||
for (let i = 0; i < 2 * r; i += 2) { | ||
salsaXOR(tmp, B, bin + i * 16, bout + i * 8); | ||
salsaXOR(tmp, B, bin + i * 16 + 16, bout + i * 8 + r * 16); | ||
} | ||
} | ||
function salsaXOR(tmp, B, bin, bout) { | ||
let j0 = tmp[0] ^ B[bin++], | ||
j1 = tmp[1] ^ B[bin++], | ||
j2 = tmp[2] ^ B[bin++], | ||
j3 = tmp[3] ^ B[bin++], | ||
j4 = tmp[4] ^ B[bin++], | ||
j5 = tmp[5] ^ B[bin++], | ||
j6 = tmp[6] ^ B[bin++], | ||
j7 = tmp[7] ^ B[bin++], | ||
j8 = tmp[8] ^ B[bin++], | ||
j9 = tmp[9] ^ B[bin++], | ||
j10 = tmp[10] ^ B[bin++], | ||
j11 = tmp[11] ^ B[bin++], | ||
j12 = tmp[12] ^ B[bin++], | ||
j13 = tmp[13] ^ B[bin++], | ||
j14 = tmp[14] ^ B[bin++], | ||
j15 = tmp[15] ^ B[bin++], | ||
u, | ||
i; | ||
function integerify(B, bi, r) { | ||
return B[bi + (2 * r - 1) * 16]; | ||
} | ||
let x0 = j0, | ||
x1 = j1, | ||
x2 = j2, | ||
x3 = j3, | ||
x4 = j4, | ||
x5 = j5, | ||
x6 = j6, | ||
x7 = j7, | ||
x8 = j8, | ||
x9 = j9, | ||
x10 = j10, | ||
x11 = j11, | ||
x12 = j12, | ||
x13 = j13, | ||
x14 = j14, | ||
x15 = j15; | ||
function stringToUTF8Bytes(s) { | ||
const arr = []; | ||
for (let i = 0; i < s.length; i++) { | ||
let c = s.charCodeAt(i); | ||
if (c < 0x80) { | ||
arr.push(c); | ||
} else if (c < 0x800) { | ||
arr.push(0xc0 | (c >> 6)); | ||
arr.push(0x80 | (c & 0x3f)); | ||
} else if (c < 0xd800) { | ||
arr.push(0xe0 | (c >> 12)); | ||
arr.push(0x80 | ((c >> 6) & 0x3f)); | ||
arr.push(0x80 | (c & 0x3f)); | ||
} else { | ||
if (i >= s.length - 1) { | ||
throw new Error("invalid string"); | ||
} | ||
i++; // get one more character | ||
c = (c & 0x3ff) << 10; | ||
c |= s.charCodeAt(i) & 0x3ff; | ||
c += 0x10000; | ||
for (i = 0; i < 8; i += 2) { | ||
u = x0 + x12; | ||
x4 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x4 + x0; | ||
x8 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x8 + x4; | ||
x12 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x12 + x8; | ||
x0 ^= (u << 18) | (u >>> (32 - 18)); | ||
arr.push(0xf0 | (c >> 18)); | ||
arr.push(0x80 | ((c >> 12) & 0x3f)); | ||
arr.push(0x80 | ((c >> 6) & 0x3f)); | ||
arr.push(0x80 | (c & 0x3f)); | ||
} | ||
} | ||
return arr; | ||
} | ||
u = x5 + x1; | ||
x9 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x9 + x5; | ||
x13 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x13 + x9; | ||
x1 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x1 + x13; | ||
x5 ^= (u << 18) | (u >>> (32 - 18)); | ||
function bytesToHex(p) { | ||
const enc = "0123456789abcdef".split(""); | ||
u = x10 + x6; | ||
x14 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x14 + x10; | ||
x2 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x2 + x14; | ||
x6 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x6 + x2; | ||
x10 ^= (u << 18) | (u >>> (32 - 18)); | ||
const len = p.length, | ||
arr = []; | ||
u = x15 + x11; | ||
x3 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x3 + x15; | ||
x7 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x7 + x3; | ||
x11 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x11 + x7; | ||
x15 ^= (u << 18) | (u >>> (32 - 18)); | ||
for (let i = 0; i < len; i++) { | ||
arr.push(enc[(p[i] >>> 4) & 15]); | ||
arr.push(enc[(p[i] >>> 0) & 15]); | ||
} | ||
return arr.join(""); | ||
} | ||
u = x0 + x3; | ||
x1 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x1 + x0; | ||
x2 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x2 + x1; | ||
x3 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x3 + x2; | ||
x0 ^= (u << 18) | (u >>> (32 - 18)); | ||
function bytesToBase64(p) { | ||
/** @const */ | ||
const enc = ( | ||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789+/" | ||
).split(""); | ||
u = x5 + x4; | ||
x6 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x6 + x5; | ||
x7 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x7 + x6; | ||
x4 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x4 + x7; | ||
x5 ^= (u << 18) | (u >>> (32 - 18)); | ||
const len = p.length, | ||
arr = []; | ||
let i = 0, | ||
a, | ||
b, | ||
c, | ||
t; | ||
u = x10 + x9; | ||
x11 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x11 + x10; | ||
x8 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x8 + x11; | ||
x9 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x9 + x8; | ||
x10 ^= (u << 18) | (u >>> (32 - 18)); | ||
while (i < len) { | ||
a = i < len ? p[i++] : 0; | ||
b = i < len ? p[i++] : 0; | ||
c = i < len ? p[i++] : 0; | ||
t = (a << 16) + (b << 8) + c; | ||
arr.push(enc[(t >>> (3 * 6)) & 63]); | ||
arr.push(enc[(t >>> (2 * 6)) & 63]); | ||
arr.push(enc[(t >>> (1 * 6)) & 63]); | ||
arr.push(enc[(t >>> (0 * 6)) & 63]); | ||
} | ||
if (len % 3 > 0) { | ||
arr[arr.length - 1] = "="; | ||
if (len % 3 === 1) arr[arr.length - 2] = "="; | ||
} | ||
return arr.join(""); | ||
u = x15 + x14; | ||
x12 ^= (u << 7) | (u >>> (32 - 7)); | ||
u = x12 + x15; | ||
x13 ^= (u << 9) | (u >>> (32 - 9)); | ||
u = x13 + x12; | ||
x14 ^= (u << 13) | (u >>> (32 - 13)); | ||
u = x14 + x13; | ||
x15 ^= (u << 18) | (u >>> (32 - 18)); | ||
} | ||
// Generate key. | ||
B[bout++] = tmp[0] = (x0 + j0) | 0; | ||
B[bout++] = tmp[1] = (x1 + j1) | 0; | ||
B[bout++] = tmp[2] = (x2 + j2) | 0; | ||
B[bout++] = tmp[3] = (x3 + j3) | 0; | ||
B[bout++] = tmp[4] = (x4 + j4) | 0; | ||
B[bout++] = tmp[5] = (x5 + j5) | 0; | ||
B[bout++] = tmp[6] = (x6 + j6) | 0; | ||
B[bout++] = tmp[7] = (x7 + j7) | 0; | ||
B[bout++] = tmp[8] = (x8 + j8) | 0; | ||
B[bout++] = tmp[9] = (x9 + j9) | 0; | ||
B[bout++] = tmp[10] = (x10 + j10) | 0; | ||
B[bout++] = tmp[11] = (x11 + j11) | 0; | ||
B[bout++] = tmp[12] = (x12 + j12) | 0; | ||
B[bout++] = tmp[13] = (x13 + j13) | 0; | ||
B[bout++] = tmp[14] = (x14 + j14) | 0; | ||
B[bout++] = tmp[15] = (x15 + j15) | 0; | ||
} | ||
const MAX_UINT = -1 >>> 0; | ||
function blockCopy(dst, di, src, si, len) { | ||
while (len--) dst[di++] = src[si++]; | ||
} | ||
if (!logN && !n) { | ||
return reject(new Error("scrypt: missing N or logN parameter")); | ||
function blockXOR(dst, di, src, si, len) { | ||
while (len--) dst[di++] ^= src[si++]; | ||
} | ||
function blockMix(tmp, B, bin, bout, r) { | ||
blockCopy(tmp, 0, B, bin + (2 * r - 1) * 16, 16); | ||
for (let i = 0; i < 2 * r; i += 2) { | ||
salsaXOR(tmp, B, bin + i * 16, bout + i * 8); | ||
salsaXOR(tmp, B, bin + i * 16 + 16, bout + i * 8 + r * 16); | ||
} | ||
} | ||
let N; | ||
function integerify(B, bi, r) { | ||
return B[bi + (2 * r - 1) * 16]; | ||
} | ||
if (logN || logN === 0) { | ||
if (logN < 1 || logN > 31) { | ||
return reject(new Error("scrypt: logN must be between 1 and 31")); | ||
} | ||
function stringToUTF8Bytes(s) { | ||
const arr = []; | ||
for (let i = 0; i < s.length; i++) { | ||
let c = s.charCodeAt(i); | ||
if (c < 0x80) { | ||
arr.push(c); | ||
} else if (c < 0x800) { | ||
arr.push(0xc0 | (c >> 6)); | ||
arr.push(0x80 | (c & 0x3f)); | ||
} else if (c < 0xd800) { | ||
arr.push(0xe0 | (c >> 12)); | ||
arr.push(0x80 | ((c >> 6) & 0x3f)); | ||
arr.push(0x80 | (c & 0x3f)); | ||
} else { | ||
if (i >= s.length - 1) { | ||
throw new Error("invalid string"); | ||
} | ||
i++; // get one more character | ||
c = (c & 0x3ff) << 10; | ||
c |= s.charCodeAt(i) & 0x3ff; | ||
c += 0x10000; | ||
N = (1 << logN) >>> 0; | ||
} else { | ||
if (n < 2 || n > MAX_UINT) { | ||
return reject(new Error("scrypt: N is out of range")); | ||
} else if ((n & (n - 1)) !== 0) { | ||
return reject(Error("scrypt: N is not a power of 2")); | ||
arr.push(0xf0 | (c >> 18)); | ||
arr.push(0x80 | ((c >> 12) & 0x3f)); | ||
arr.push(0x80 | ((c >> 6) & 0x3f)); | ||
arr.push(0x80 | (c & 0x3f)); | ||
} | ||
N = n; | ||
} | ||
return arr; | ||
} | ||
if (p < 1) { | ||
return reject(new Error("scrypt: invalid p")); | ||
} | ||
function bytesToHex(p) { | ||
const enc = "0123456789abcdef".split(""); | ||
if (r <= 0) { | ||
return reject(new Error("scrypt: invalid r")); | ||
const len = p.length, | ||
arr = []; | ||
for (let i = 0; i < len; i++) { | ||
arr.push(enc[(p[i] >>> 4) & 15]); | ||
arr.push(enc[(p[i] >>> 0) & 15]); | ||
} | ||
return arr.join(""); | ||
} | ||
let XY, V, B, tmp; | ||
function bytesToBase64(p) { | ||
/** @const */ | ||
const enc = ( | ||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789+/" | ||
).split(""); | ||
if ( | ||
r * p >= 1 << 30 || | ||
r > MAX_UINT / 128 / p || | ||
r > MAX_UINT / 256 || | ||
N > MAX_UINT / 128 / r | ||
) { | ||
return reject(new Error("scrypt: parameters are too large")); | ||
const len = p.length, | ||
arr = []; | ||
let i = 0, | ||
a, | ||
b, | ||
c, | ||
t; | ||
while (i < len) { | ||
a = i < len ? p[i++] : 0; | ||
b = i < len ? p[i++] : 0; | ||
c = i < len ? p[i++] : 0; | ||
t = (a << 16) + (b << 8) + c; | ||
arr.push(enc[(t >>> (3 * 6)) & 63]); | ||
arr.push(enc[(t >>> (2 * 6)) & 63]); | ||
arr.push(enc[(t >>> (1 * 6)) & 63]); | ||
arr.push(enc[(t >>> (0 * 6)) & 63]); | ||
} | ||
if (len % 3 > 0) { | ||
arr[arr.length - 1] = "="; | ||
if (len % 3 === 1) arr[arr.length - 2] = "="; | ||
} | ||
return arr.join(""); | ||
} | ||
// Decode strings. | ||
if (typeof password === "string") password = stringToUTF8Bytes(password); | ||
if (typeof salt === "string") salt = stringToUTF8Bytes(salt); | ||
let XY, V, B, tmp; | ||
if (typeof Int32Array !== "undefined") { | ||
//XXX We can use Uint32Array, but Int32Array is faster in Safari. | ||
XY = new Int32Array(64 * r); | ||
V = new Int32Array(32 * N * r); | ||
tmp = new Int32Array(16); | ||
} else { | ||
XY = []; | ||
V = []; | ||
tmp = new Array(16); | ||
} | ||
B = PBKDF2_HMAC_SHA256_OneIter(password, salt, p * 128 * r); | ||
if ( | ||
r * p >= 1 << 30 || | ||
r > MAX_UINT / 128 / p || | ||
r > MAX_UINT / 256 || | ||
N > MAX_UINT / 128 / r | ||
) { | ||
return reject(new Error("scrypt: parameters are too large")); | ||
} | ||
const xi = 0, | ||
yi = 32 * r; | ||
// Decode strings. | ||
if (typeof password === "string") password = stringToUTF8Bytes(password); | ||
if (typeof salt === "string") salt = stringToUTF8Bytes(salt); | ||
function smixStart(pos) { | ||
for (let i = 0; i < 32 * r; i++) { | ||
const j = pos + i * 4; | ||
XY[xi + i] = | ||
((B[j + 3] & 0xff) << 24) | | ||
((B[j + 2] & 0xff) << 16) | | ||
((B[j + 1] & 0xff) << 8) | | ||
((B[j + 0] & 0xff) << 0); | ||
} | ||
if (typeof Int32Array !== "undefined") { | ||
//XXX We can use Uint32Array, but Int32Array is faster in Safari. | ||
XY = new Int32Array(64 * r); | ||
V = new Int32Array(32 * N * r); | ||
tmp = new Int32Array(16); | ||
} else { | ||
XY = []; | ||
V = []; | ||
tmp = new Array(16); | ||
} | ||
B = PBKDF2_HMAC_SHA256_OneIter(password, salt, p * 128 * r); | ||
const xi = 0, | ||
yi = 32 * r; | ||
function smixStart(pos) { | ||
for (let i = 0; i < 32 * r; i++) { | ||
const j = pos + i * 4; | ||
XY[xi + i] = | ||
((B[j + 3] & 0xff) << 24) | | ||
((B[j + 2] & 0xff) << 16) | | ||
((B[j + 1] & 0xff) << 8) | | ||
((B[j + 0] & 0xff) << 0); | ||
} | ||
} | ||
function smixStep1(start, end) { | ||
for (let i = start; i < end; i += 2) { | ||
blockCopy(V, i * (32 * r), XY, xi, 32 * r); | ||
blockMix(tmp, XY, xi, yi, r); | ||
function smixStep1(start, end) { | ||
for (let i = start; i < end; i += 2) { | ||
blockCopy(V, i * (32 * r), XY, xi, 32 * r); | ||
blockMix(tmp, XY, xi, yi, r); | ||
blockCopy(V, (i + 1) * (32 * r), XY, yi, 32 * r); | ||
blockMix(tmp, XY, yi, xi, r); | ||
} | ||
blockCopy(V, (i + 1) * (32 * r), XY, yi, 32 * r); | ||
blockMix(tmp, XY, yi, xi, r); | ||
} | ||
} | ||
function smixStep2(start, end) { | ||
for (let i = start; i < end; i += 2) { | ||
let j = integerify(XY, xi, r) & (N - 1); | ||
blockXOR(XY, xi, V, j * (32 * r), 32 * r); | ||
blockMix(tmp, XY, xi, yi, r); | ||
function smixStep2(start, end) { | ||
for (let i = start; i < end; i += 2) { | ||
let j = integerify(XY, xi, r) & (N - 1); | ||
blockXOR(XY, xi, V, j * (32 * r), 32 * r); | ||
blockMix(tmp, XY, xi, yi, r); | ||
j = integerify(XY, yi, r) & (N - 1); | ||
blockXOR(XY, yi, V, j * (32 * r), 32 * r); | ||
blockMix(tmp, XY, yi, xi, r); | ||
} | ||
j = integerify(XY, yi, r) & (N - 1); | ||
blockXOR(XY, yi, V, j * (32 * r), 32 * r); | ||
blockMix(tmp, XY, yi, xi, r); | ||
} | ||
} | ||
function smixFinish(pos) { | ||
for (let i = 0; i < 32 * r; i++) { | ||
const j = XY[xi + i]; | ||
B[pos + i * 4 + 0] = (j >>> 0) & 0xff; | ||
B[pos + i * 4 + 1] = (j >>> 8) & 0xff; | ||
B[pos + i * 4 + 2] = (j >>> 16) & 0xff; | ||
B[pos + i * 4 + 3] = (j >>> 24) & 0xff; | ||
} | ||
function smixFinish(pos) { | ||
for (let i = 0; i < 32 * r; i++) { | ||
const j = XY[xi + i]; | ||
B[pos + i * 4 + 0] = (j >>> 0) & 0xff; | ||
B[pos + i * 4 + 1] = (j >>> 8) & 0xff; | ||
B[pos + i * 4 + 2] = (j >>> 16) & 0xff; | ||
B[pos + i * 4 + 3] = (j >>> 24) & 0xff; | ||
} | ||
} | ||
const nextTick = | ||
typeof setImmediate !== "undefined" ? setImmediate : setTimeout; | ||
const nextTick = | ||
typeof setImmediate !== "undefined" ? setImmediate : setTimeout; | ||
function interruptedFor(start, end, step, fn, donefn) { | ||
(function performStep() { | ||
nextTick(function () { | ||
fn(start, start + step < end ? start + step : end); | ||
start += step; | ||
if (start < end) performStep(); | ||
else donefn(); | ||
}); | ||
})(); | ||
} | ||
function interruptedFor(start, end, step, fn, donefn) { | ||
(function performStep() { | ||
nextTick(function () { | ||
fn(start, start + step < end ? start + step : end); | ||
start += step; | ||
if (start < end) performStep(); | ||
else donefn(); | ||
}); | ||
})(); | ||
} | ||
function getResult(enc) { | ||
const result = PBKDF2_HMAC_SHA256_OneIter(password, B, dkLen); | ||
if (enc === "base64") return bytesToBase64(result); | ||
else if (enc === "hex") return bytesToHex(result); | ||
else if (enc === "binary") return new Uint8Array(result); | ||
else return result; | ||
function getResult(enc) { | ||
const result = PBKDF2_HMAC_SHA256_OneIter(password, B, dkLen); | ||
if (enc === "base64") return bytesToBase64(result); | ||
else if (enc === "hex") return bytesToHex(result); | ||
else if (enc === "binary") return new Uint8Array(result); | ||
else return result; | ||
} | ||
// Blocking variant. | ||
function calculateSync() { | ||
for (let i = 0; i < p; i++) { | ||
smixStart(i * 128 * r); | ||
smixStep1(0, N); | ||
smixStep2(0, N); | ||
smixFinish(i * 128 * r); | ||
} | ||
callback(getResult(encoding)); | ||
} | ||
// Blocking variant. | ||
function calculateSync() { | ||
for (let i = 0; i < p; i++) { | ||
smixStart(i * 128 * r); | ||
smixStep1(0, N); | ||
smixStep2(0, N); | ||
// Async variant. | ||
function calculateAsync(i) { | ||
smixStart(i * 128 * r); | ||
interruptedFor(0, N, interruptStep * 2, smixStep1, () => { | ||
interruptedFor(0, N, interruptStep * 2, smixStep2, () => { | ||
smixFinish(i * 128 * r); | ||
} | ||
resolve(getResult(encoding)); | ||
} | ||
// Async variant. | ||
function calculateAsync(i) { | ||
smixStart(i * 128 * r); | ||
interruptedFor(0, N, interruptStep * 2, smixStep1, function () { | ||
interruptedFor(0, N, interruptStep * 2, smixStep2, function () { | ||
smixFinish(i * 128 * r); | ||
if (i + 1 < p) { | ||
nextTick(function () { | ||
calculateAsync(i + 1); | ||
}); | ||
} else { | ||
resolve(getResult(encoding)); | ||
} | ||
}); | ||
if (i + 1 < p) { | ||
nextTick(() => { | ||
calculateAsync(i + 1); | ||
}); | ||
} else { | ||
callback(getResult(encoding)); | ||
} | ||
}); | ||
} | ||
}); | ||
} | ||
if (interruptStep <= 0) { | ||
calculateSync(); | ||
} else { | ||
calculateAsync(0); | ||
} | ||
}); | ||
if (interruptStep <= 0) { | ||
calculateSync(); | ||
} else { | ||
calculateAsync(0); | ||
} | ||
} | ||
const MAX_UINT = -1 >>> 0; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
73164
8
2202