Skip to content

Commit 0ce7a5c

Browse files
committed
Make use of JS Promises
- Least invasive changes at first - Redundant tests were removed
1 parent 1723f1f commit 0ce7a5c

File tree

2 files changed

+50
-110
lines changed

2 files changed

+50
-110
lines changed

scrypt-async.js

+10-40
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*!
2-
* Fast "async" scrypt implementation in JavaScript.
2+
* Fast scrypt implementation in JavaScript, using Promises.
33
* Copyright (c) 2013-2015 Dmitry Chestnykh | BSD License
44
* https://github.com/dchest/scrypt-async-js
55
*/
@@ -9,29 +9,23 @@
99
*/
1010

1111
/**
12-
* scrypt(password, salt, logN, r, dkLen, [interruptStep], callback, [encoding])
12+
* scrypt(password, salt, logN, r, dkLen, [encoding])
1313
*
14-
* Derives a key from password and salt and calls callback
14+
* Derives a key from password and salt and returns a Promise
1515
* with derived key as the only argument.
1616
*
17-
* Calculations are interrupted with setImmediate (or zero setTimeout) at the
18-
* given interruptSteps to avoid freezing the browser. If interruptStep is not
19-
* given, it defaults to 1000. If it's zero, the callback is called immediately
20-
* after the calculation, avoiding setImmediate.
21-
*
2217
* @param {string|Array.<number>} password Password.
2318
* @param {string|Array.<number>} salt Salt.
2419
* @param {number} logN CPU/memory cost parameter (1 to 31).
2520
* @param {number} r Block size parameter.
2621
* @param {number} dkLen Length of derived key.
27-
* @param {number?} interruptStep (optional) Steps to split calculation with timeouts (default 1000).
28-
* @param {function(string|Array.<number>)} callback Callback function.
2922
* @param {string?} encoding (optional) Result encoding ("base64", "hex", or null).
3023
*
3124
*/
32-
function scrypt(password, salt, logN, r, dkLen, interruptStep, callback, encoding) {
25+
function scrypt(password, salt, logN, r, dkLen, encoding) {
3326
'use strict';
3427

28+
return new Promise(function (callback, reject) {
3529
function SHA256(m) {
3630
/** @const */ var K = [
3731
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
@@ -351,17 +345,17 @@ function scrypt(password, salt, logN, r, dkLen, interruptStep, callback, encodin
351345
var p = 1;
352346

353347
if (r <= 0)
354-
throw new Error('scrypt: invalid r');
348+
return reject('scrypt: invalid r');
355349

356350
if (logN < 1 || logN > 31)
357-
throw new Error('scrypt: logN not be between 1 and 31');
351+
return reject('scrypt: logN not be between 1 and 31');
358352

359353
var MAX_INT = (1<<31)>>>0,
360354
N = (1<<logN)>>>0,
361355
XY, V, B, tmp;
362356

363357
if (r*p >= 1<<30 || r > MAX_INT/128/p || r > MAX_INT/256 || N > MAX_INT/128/r)
364-
throw new Error('scrypt: parameters are too large');
358+
return reject('scrypt: parameters are too large');
365359

366360
// Decode strings.
367361
if (typeof password === 'string')
@@ -448,36 +442,12 @@ function scrypt(password, salt, logN, r, dkLen, interruptStep, callback, encodin
448442
return result;
449443
}
450444

451-
if (typeof interruptStep === 'function') {
452-
// Called as: scrypt(..., callback, [encoding])
453-
// shifting: scrypt(..., interruptStep, callback, [encoding])
454-
encoding = callback;
455-
callback = interruptStep;
456-
interruptStep = 1000;
457-
}
458-
459-
if (interruptStep <= 0) {
460-
//
461-
// Blocking async variant, calls callback.
462-
//
463445
smixStart();
464446
smixStep1(0, N);
465447
smixStep2(0, N);
466448
smixFinish();
467-
callback(getResult(encoding));
468-
469-
} else {
470-
//
471-
// Async variant with interruptions, calls callback.
472-
//
473-
smixStart();
474-
interruptedFor(0, N, interruptStep*2, smixStep1, function() {
475-
interruptedFor(0, N, interruptStep*2, smixStep2, function () {
476-
smixFinish();
477-
callback(getResult(encoding));
478-
});
479-
});
480-
}
449+
return callback(getResult(encoding));
450+
});
481451
}
482452

483453
if (typeof module !== 'undefined') module.exports = scrypt;

test/unittests.js

+40-70
Original file line numberDiff line numberDiff line change
@@ -255,28 +255,32 @@ var shortInput = {
255255
describe('limits test', function() {
256256
var v = shortInput;
257257

258-
it('should throw with too small logN', function() {
259-
assert.throws(function() {
260-
scrypt(v.password, v.salt, 0, v.r, v.dkLen);
261-
}, Error);
258+
it('should reject with too small logN', function() {
259+
scrypt(v.password, v.salt, 0, v.r, v.dkLen)
260+
.catch(function (err) {
261+
assert.equal('should reject with too small logN', err);
262+
});
262263
});
263264

264-
it('should throw with too big logN', function() {
265-
assert.throws(function() {
266-
scrypt(v.password, v.salt, 32, v.r, v.dkLen);
267-
}, Error);
265+
it('should reject with too big logN', function() {
266+
scrypt(v.password, v.salt, 32, v.r, v.dkLen)
267+
.catch(function (err) {
268+
assert.equal('should reject with too big logN', err);
269+
});
268270
});
269271

270-
it('should throw with too large parameters', function() {
271-
assert.throws(function() {
272-
scrypt(v.password, v.salt, v.logN, 1<<31, v.dkLen);
273-
}, Error);
272+
it('should reject with too large parameters', function() {
273+
scrypt(v.password, v.salt, v.logN, 1<<31, v.dkLen)
274+
.catch(function (err) {
275+
assert.equal('should reject with too large parameters', err);
276+
});
274277
});
275278

276-
it('should throw when r = 0', function() {
277-
assert.throws(function() {
278-
scrypt(v.password, v.salt, v.logN, 0, v.dkLen);
279-
}, Error);
279+
it('should reject when r = 0', function() {
280+
scrypt(v.password, v.salt, v.logN, 0, v.dkLen)
281+
.catch(function (err) {
282+
assert.equal('should reject when r = 0', err);
283+
});
280284
});
281285

282286
});
@@ -287,101 +291,67 @@ describe('argument order test', function() {
287291
var v = shortInput;
288292

289293
it('all arguments', function(done) {
290-
scrypt(v.password, v.salt, v.logN, v.r, v.dkLen, 1000, function(out) {
294+
scrypt(v.password, v.salt, v.logN, v.r, v.dkLen, "hex")
295+
.then(function (out) {
291296
assert.equal(v.hexResult, out);
292297
done();
293-
}, "hex");
294-
});
295-
296-
it('all arguments, zero interruptStep', function(done) {
297-
scrypt(v.password, v.salt, v.logN, v.r, v.dkLen, 0, function(out) {
298-
assert.equal(v.hexResult, out);
299-
done();
300-
}, "hex");
298+
});
301299
});
302300

303301
it('drop encoding', function(done) {
304-
scrypt(v.password, v.salt, v.logN, v.r, v.dkLen, 1000, function(out) {
302+
scrypt(v.password, v.salt, v.logN, v.r, v.dkLen)
303+
.then(function (out) {
305304
assert.deepEqual(v.result, out);
306305
done();
307306
});
308307
});
309308

310-
it('drop interruptStep, keep encoding', function(done) {
311-
scrypt(v.password, v.salt, v.logN, v.r, v.dkLen, function(out) {
312-
assert.equal(v.hexResult, out);
313-
done();
314-
}, 'hex');
315-
});
316-
317309
});
318310

319-
function async_test(i, interruptStep, done) {
311+
function async_test(i, done) {
320312
var v = inputs[i];
321-
scrypt(v.password, v.salt, v.logN, v.r, v.dkLen, interruptStep, function(out) {
313+
scrypt(v.password, v.salt, v.logN, v.r, v.dkLen, v.encoding)
314+
.then(function(out) {
322315
assert.deepEqual(v.result, out);
323316
done();
324-
}, v.encoding);
317+
});
325318
}
326319

327320
describe('async input/output test', function() {
328321
this.timeout(100000);
329322

330-
var step = 1000;
331-
332323
it('input 0', function(done) {
333-
async_test(0, step, done);
324+
async_test(0, done);
334325
});
335326
it('input 1', function(done) {
336-
async_test(1, step, done);
327+
async_test(1, done);
337328
});
338329
it('input 2', function(done) {
339-
async_test(2, step, done);
330+
async_test(2, done);
340331
});
341332
it('input 3', function(done) {
342-
async_test(3, step, done);
333+
async_test(3, done);
343334
});
344335
it('input 4', function(done) {
345-
async_test(4, step, done);
336+
async_test(4, done);
346337
});
347338
it('input 5', function(done) {
348-
async_test(5, step, done);
339+
async_test(5, done);
349340
});
350341
it('input 6', function(done) {
351-
async_test(6, step, done);
342+
async_test(6, done);
352343
});
353344
it('input 7', function(done) {
354-
async_test(7, step, done);
345+
async_test(7, done);
355346
});
356347
it('input 8', function(done) {
357-
async_test(8, step, done);
348+
async_test(8, done);
358349
});
359350
it('input 9', function(done) {
360-
async_test(9, step, done);
351+
async_test(9, done);
361352
});
362353
it('input 10', function(done) {
363-
async_test(10, step, done);
364-
});
365-
366-
});
367-
368-
describe('async input/output test with zero interruptStep', function() {
369-
this.timeout(100000);
370-
371-
// Only shorter tests:
372-
var step = 0;
373-
374-
it('input 0', function(done) {
375-
async_test(0, step, done);
376-
});
377-
it('input 1', function(done) {
378-
async_test(1, step, done);
379-
});
380-
it('input 2', function(done) {
381-
async_test(2, step, done);
382-
});
383-
it('input 3', function(done) {
384-
async_test(3, step, done);
354+
async_test(10, done);
385355
});
386356

387357
});

0 commit comments

Comments
 (0)