diff --git a/lib/wallet/masterkey.js b/lib/wallet/masterkey.js index b7998248..4f1b4b71 100644 --- a/lib/wallet/masterkey.js +++ b/lib/wallet/masterkey.js @@ -6,26 +6,20 @@ 'use strict'; +var assert = require('assert'); var util = require('../utils/util'); var Lock = require('../utils/lock'); var co = require('../utils/co'); var crypto = require('../crypto/crypto'); -var assert = require('assert'); var BufferReader = require('../utils/reader'); var StaticWriter = require('../utils/staticwriter'); var encoding = require('../utils/encoding'); var HD = require('../hd/hd'); -/* - * Constants - */ - -var BCOIN_SALT = new Buffer('bcoin', 'ascii'); - /** * Master BIP32 key which can exist * in a timed out encrypted state. - * @exports Master + * @exports MasterKey * @constructor * @param {Object} options */ @@ -54,6 +48,14 @@ function MasterKey(options) { this.fromOptions(options); } +/** + * Key derivation salt. + * @const {Buffer} + * @default + */ + +MasterKey.SALT = new Buffer('bcoin', 'ascii'); + /** * Key derivation algorithms. * @enum {Number} @@ -72,8 +74,8 @@ MasterKey.alg = { */ MasterKey.algByVal = { - 0: 'pbkdf2', - 1: 'scrypt' + 0: 'PBKDF2', + 1: 'SCRYPT' }; /** @@ -107,7 +109,7 @@ MasterKey.prototype.fromOptions = function fromOptions(options) { if (options.alg != null) { if (typeof options.alg === 'string') { - this.alg = MasterKey.alg[options.alg.toLowerCase()]; + this.alg = MasterKey.alg[options.alg.toUpperCase()]; assert(this.alg != null, 'Unknown algorithm.'); } else { assert(typeof options.alg === 'number'); @@ -240,19 +242,24 @@ MasterKey.prototype.stop = function stop() { * @returns {Promise} */ -MasterKey.prototype.derive = function derive(passwd) { +MasterKey.prototype.derive = co(function* derive(passwd) { + var salt = MasterKey.SALT; + var N = this.N; + var r = this.r; + var p = this.p; + if (typeof passwd === 'string') passwd = new Buffer(passwd, 'utf8'); switch (this.alg) { case MasterKey.alg.PBKDF2: - return crypto.pbkdf2Async(passwd, BCOIN_SALT, this.N, 32, 'sha256'); + return yield crypto.pbkdf2Async(passwd, salt, N, 32, 'sha256'); case MasterKey.alg.SCRYPT: - return crypto.scryptAsync(passwd, BCOIN_SALT, this.N, this.r, this.p, 32); + return yield crypto.scryptAsync(passwd, salt, N, r, p, 32); default: - return Promise.reject(new Error('Unknown algorithm: ' + this.alg)); + throw new Error('Unknown algorithm: ' + this.alg); } -}; +}); /** * Encrypt data with in-memory aes key. @@ -345,10 +352,10 @@ MasterKey.prototype.destroy = co(function* destroy() { * @returns {Promise} */ -MasterKey.prototype.decrypt = co(function* decrypt(passphrase, aes) { +MasterKey.prototype.decrypt = co(function* decrypt(passphrase, clean) { var unlock = yield this.locker.lock(); try { - return yield this._decrypt(passphrase, aes); + return yield this._decrypt(passphrase, clean); } finally { unlock(); } @@ -361,7 +368,7 @@ MasterKey.prototype.decrypt = co(function* decrypt(passphrase, aes) { * @returns {Promise} */ -MasterKey.prototype._decrypt = co(function* decrypt(passphrase, aes) { +MasterKey.prototype._decrypt = co(function* decrypt(passphrase, clean) { var key, data; if (!this.encrypted) @@ -380,7 +387,7 @@ MasterKey.prototype._decrypt = co(function* decrypt(passphrase, aes) { this.iv = null; this.ciphertext = null; - if (!aes) { + if (!clean) { crypto.cleanse(key); return; } @@ -394,10 +401,10 @@ MasterKey.prototype._decrypt = co(function* decrypt(passphrase, aes) { * @returns {Promise} */ -MasterKey.prototype.encrypt = co(function* encrypt(passphrase, aes) { +MasterKey.prototype.encrypt = co(function* encrypt(passphrase, clean) { var unlock = yield this.locker.lock(); try { - return yield this._encrypt(passphrase, aes); + return yield this._encrypt(passphrase, clean); } finally { unlock(); } @@ -410,7 +417,7 @@ MasterKey.prototype.encrypt = co(function* encrypt(passphrase, aes) { * @returns {Promise} */ -MasterKey.prototype._encrypt = co(function* encrypt(passphrase, aes) { +MasterKey.prototype._encrypt = co(function* encrypt(passphrase, clean) { var key, data, iv; if (this.encrypted) @@ -432,7 +439,7 @@ MasterKey.prototype._encrypt = co(function* encrypt(passphrase, aes) { this.iv = iv; this.ciphertext = data; - if (!aes) { + if (!clean) { crypto.cleanse(key); return; } @@ -569,7 +576,7 @@ MasterKey.prototype.toJSON = function toJSON(unsafe) { until: this.until, iv: this.iv.toString('hex'), ciphertext: unsafe ? this.ciphertext.toString('hex') : undefined, - algorithm: MasterKey.algByVal[this.alg], + algorithm: MasterKey.algByVal[this.alg].toLowerCase(), N: this.N, r: this.r, p: this.p