diff --git a/lib/crypto/crypto.js b/lib/crypto/crypto.js index 3575e0d1..083c0655 100644 --- a/lib/crypto/crypto.js +++ b/lib/crypto/crypto.js @@ -9,6 +9,8 @@ var assert = require('assert'); var random = require('./random'); +var scrypt = require('./scrypt'); +var scryptAsync = require('./scrypt-async'); var native = require('../utils/native'); var nativeCrypto, supersha, hash, aes; @@ -139,7 +141,7 @@ if (native) crypto.hmac = native.hmac; /** - * Perform key stretching using PBKDF2. + * Perform key derivation using PBKDF2. * @param {Buffer} key * @param {Buffer} salt * @param {Number} iter @@ -148,7 +150,7 @@ if (native) * @returns {Buffer} */ -crypto.pbkdf2Sync = function pbkdf2Sync(key, salt, iter, len, alg) { +crypto.pbkdf2 = function pbkdf2(key, salt, iter, len, alg) { if (typeof key === 'string') key = new Buffer(key, 'utf8'); @@ -171,7 +173,7 @@ crypto.pbkdf2Sync = function pbkdf2Sync(key, salt, iter, len, alg) { * @param {Function} callback */ -crypto.pbkdf2 = function pbkdf2(key, salt, iter, len, alg, callback) { +crypto.pbkdf2Async = function pbkdf2Async(key, salt, iter, len, alg, callback) { var result; if (typeof key === 'string') @@ -192,6 +194,48 @@ crypto.pbkdf2 = function pbkdf2(key, salt, iter, len, alg, callback) { return callback(null, result); }; +/** + * Perform key derivation using scrypt. + * @param {Buffer} passwd + * @param {Buffer} salt + * @param {Number} N + * @param {Number} r + * @param {Number} p + * @param {Number} len + * @returns {Buffer} + */ + +crypto.scrypt = function _scrypt(passwd, salt, N, r, p, len) { + if (typeof passwd === 'string') + passwd = new Buffer(passwd, 'utf8'); + + if (typeof salt === 'string') + salt = new Buffer(salt, 'utf8'); + + return scrypt(passwd, salt, N, r, p, len); +}; + +/** + * Execute scrypt asynchronously. + * @param {Buffer} passwd + * @param {Buffer} salt + * @param {Number} N + * @param {Number} r + * @param {Number} p + * @param {Number} len + * @param {Function} callback + */ + +crypto.scryptAsync = function _scryptAsync(passwd, salt, N, r, p, len, callback) { + if (typeof passwd === 'string') + passwd = new Buffer(passwd, 'utf8'); + + if (typeof salt === 'string') + salt = new Buffer(salt, 'utf8'); + + return scryptAsync(passwd, salt, N, r, p, len, callback); +}; + /** * Derive a key using pbkdf2 with 50,000 iterations. * @param {Buffer|String} passphrase @@ -199,7 +243,7 @@ crypto.pbkdf2 = function pbkdf2(key, salt, iter, len, alg, callback) { */ crypto.derive = function derive(passphrase, callback) { - crypto.pbkdf2(passphrase, 'bcoin', 50000, 32, 'sha256', callback); + crypto.pbkdf2Async(passphrase, 'bcoin', 50000, 32, 'sha256', callback); }; /** @@ -304,7 +348,7 @@ crypto.decipher = function decipher(data, key, iv) { }; /** - * Perform key stretching using PBKDF2. + * Perform key derivation using PBKDF2. * @private * @param {Buffer} key * @param {Buffer} salt diff --git a/lib/crypto/scrypt-async.js b/lib/crypto/scrypt-async.js index 2eb14fd9..419f1afa 100644 --- a/lib/crypto/scrypt-async.js +++ b/lib/crypto/scrypt-async.js @@ -51,18 +51,9 @@ var U32Array = typeof Uint32Array === 'function' ? Uint32Array : Array; * @returns {Buffer} */ -function scrypt(passwd, salt, N, r, p, len, callback) { +function scryptAsync(passwd, salt, N, r, p, len, callback) { var V, XY; - if (typeof passwd === 'string') - passwd = new Buffer(passwd, 'utf8'); - - if (typeof salt === 'string') - salt = new Buffer(salt, 'utf8'); - - if (native) - return native.scryptAsync(passwd, salt, N, r, p, len, callback); - if (r * p >= (1 << 30)) return callback(new Error('EFBIG')); @@ -75,7 +66,7 @@ function scrypt(passwd, salt, N, r, p, len, callback) { XY = new Buffer(256 * r); V = new Buffer(128 * r * N); - crypto.pbkdf2(passwd, salt, 1, p * 128 * r, 'sha256', function(err, B) { + crypto.pbkdf2Async(passwd, salt, 1, p * 128 * r, 'sha256', function(err, B) { if (err) return callback(err); @@ -85,11 +76,14 @@ function scrypt(passwd, salt, N, r, p, len, callback) { if (err) return callback(err); - crypto.pbkdf2(passwd, B, 1, len, 'sha256', callback); + crypto.pbkdf2Async(passwd, B, 1, len, 'sha256', callback); }); }); } +if (native) + scryptAsync = native.scryptAsync; + function salsa20_8(B) { var B32 = new U32Array(16); var x = new U32Array(16); @@ -232,4 +226,4 @@ function forRangeSerial(from, to, iter, callback) { * Expose */ -module.exports = scrypt; +module.exports = scryptAsync; diff --git a/lib/crypto/scrypt.js b/lib/crypto/scrypt.js index 4a8294f5..873610f1 100644 --- a/lib/crypto/scrypt.js +++ b/lib/crypto/scrypt.js @@ -53,15 +53,6 @@ var U32Array = typeof Uint32Array === 'function' ? Uint32Array : Array; function scrypt(passwd, salt, N, r, p, len) { var i, B, V, XY; - if (typeof passwd === 'string') - passwd = new Buffer(passwd, 'utf8'); - - if (typeof salt === 'string') - salt = new Buffer(salt, 'utf8'); - - if (native) - return native.scrypt(passwd, salt, N, r, p, len); - if (r * p >= (1 << 30)) throw new Error('EFBIG'); @@ -74,14 +65,17 @@ function scrypt(passwd, salt, N, r, p, len) { XY = new Buffer(256 * r); V = new Buffer(128 * r * N); - B = crypto.pbkdf2Sync(passwd, salt, 1, p * 128 * r, 'sha256'); + B = crypto.pbkdf2(passwd, salt, 1, p * 128 * r, 'sha256'); for (i = 0; i < p; i++) smix(B, i * 128 * r, r, N, V, XY); - return crypto.pbkdf2Sync(passwd, B, 1, len, 'sha256'); + return crypto.pbkdf2(passwd, B, 1, len, 'sha256'); } +if (native) + scrypt = native.scrypt; + function salsa20_8(B) { var B32 = new U32Array(16); var x = new U32Array(16); diff --git a/lib/hd/mnemonic.js b/lib/hd/mnemonic.js index 93d44509..7b8dc365 100644 --- a/lib/hd/mnemonic.js +++ b/lib/hd/mnemonic.js @@ -142,7 +142,7 @@ Mnemonic.prototype.toSeed = function toSeed(passphrase) { this.passphrase = passphrase; - return crypto.pbkdf2Sync( + return crypto.pbkdf2( nfkd(this.getPhrase()), nfkd('mnemonic' + passphrase), 2048, 64, 'sha512'); diff --git a/test/aes-test.js b/test/aes-test.js index 21d62eab..d4617102 100644 --- a/test/aes-test.js +++ b/test/aes-test.js @@ -9,7 +9,7 @@ var nativeCrypto = require('crypto'); describe('AES', function() { function pbkdf2key(passphrase, iterations, dkLen, ivLen, alg) { - var key = crypto.pbkdf2Sync(passphrase, '', iterations, dkLen + ivLen, 'sha512'); + var key = crypto.pbkdf2(passphrase, '', iterations, dkLen + ivLen, 'sha512'); return { key: key.slice(0, dkLen), iv: key.slice(dkLen, dkLen + ivLen) diff --git a/test/hd-test.js b/test/hd-test.js index 89e0e72a..c6cb3865 100644 --- a/test/hd-test.js +++ b/test/hd-test.js @@ -91,7 +91,7 @@ describe('HD', function() { var master, child1, child2, child3, child4, child5, child6; it('should create a pbkdf2 seed', function() { - var checkSeed = crypto.pbkdf2Sync( + var checkSeed = crypto.pbkdf2( phrase, 'mnemonic' + 'foo', 2048, 64, 'sha512').toString('hex'); assert.equal(checkSeed, seed); }); diff --git a/test/scrypt-test.js b/test/scrypt-test.js index fd409e1b..7de5c701 100644 --- a/test/scrypt-test.js +++ b/test/scrypt-test.js @@ -1,7 +1,7 @@ 'use strict'; var assert = require('assert'); -var scrypt = require('../lib/crypto/scrypt'); +var scrypt = require('../lib/crypto/crypto').scrypt; describe('Scrypt', function() { it('should perform scrypt with N=16', function() { @@ -13,7 +13,7 @@ describe('Scrypt', function() { }); it('should perform scrypt with N=1024', function() { - var result = scrypt('password', 'NaCl', 1024, 8, 16, 64) + var result = scrypt('password', 'NaCl', 1024, 8, 16, 64); assert.equal(result.toString('hex'), '' + 'fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e773' + '76634b3731622eaf30d92e22a3886ff109279d9830dac727afb9'