rpc/http/wallet: more aggressive validation for addrs/keys.
This commit is contained in:
parent
aa869e0b6a
commit
9f09de4867
16
lib/hd/hd.js
16
lib/hd/hd.js
@ -20,13 +20,14 @@ var HD = exports;
|
||||
/**
|
||||
* Instantiate an HD key (public or private) from an base58 string.
|
||||
* @param {Base58String} xkey
|
||||
* @param {Network?} network
|
||||
* @returns {HDPrivateKey|HDPublicKey}
|
||||
*/
|
||||
|
||||
HD.fromBase58 = function fromBase58(xkey) {
|
||||
HD.fromBase58 = function fromBase58(xkey, network) {
|
||||
if (HDPrivateKey.isBase58(xkey))
|
||||
return HDPrivateKey.fromBase58(xkey);
|
||||
return HDPublicKey.fromBase58(xkey);
|
||||
return HDPrivateKey.fromBase58(xkey, network);
|
||||
return HDPublicKey.fromBase58(xkey, network);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -68,13 +69,14 @@ HD.fromMnemonic = function fromMnemonic(options, network) {
|
||||
/**
|
||||
* Instantiate an HD key from a jsonified key object.
|
||||
* @param {Object} json - The jsonified transaction object.
|
||||
* @param {Network?} network
|
||||
* @returns {HDPrivateKey|HDPublicKey}
|
||||
*/
|
||||
|
||||
HD.fromJSON = function fromJSON(json) {
|
||||
HD.fromJSON = function fromJSON(json, network) {
|
||||
if (json.xprivkey)
|
||||
return HDPrivateKey.fromJSON(json);
|
||||
return HDPublicKey.fromJSON(json);
|
||||
return HDPrivateKey.fromJSON(json, network);
|
||||
return HDPublicKey.fromJSON(json, network);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -116,7 +118,7 @@ HD.from = function from(options, network) {
|
||||
return options;
|
||||
|
||||
if (HD.isBase58(options))
|
||||
return HD.fromBase58(options);
|
||||
return HD.fromBase58(options, network);
|
||||
|
||||
if (HD.isRaw(options))
|
||||
return HD.fromRaw(options);
|
||||
|
||||
@ -615,11 +615,14 @@ HDPrivateKey.generate = function generate(network) {
|
||||
* Inject properties from base58 key.
|
||||
* @private
|
||||
* @param {Base58String} xkey
|
||||
* @param {Network?} network
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.fromBase58 = function fromBase58(xkey) {
|
||||
HDPrivateKey.prototype.fromBase58 = function fromBase58(xkey, network) {
|
||||
this.fromRaw(base58.decode(xkey));
|
||||
this._xprivkey = xkey;
|
||||
if (network && !this.verifyNetwork(network))
|
||||
throw new Error('Network mismatch for HD private key.');
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -813,11 +816,12 @@ HDPrivateKey.fromExtended = function fromExtended(data) {
|
||||
/**
|
||||
* Instantiate an HD private key from a base58 string.
|
||||
* @param {Base58String} xkey
|
||||
* @param {Network?} network
|
||||
* @returns {HDPrivateKey}
|
||||
*/
|
||||
|
||||
HDPrivateKey.fromBase58 = function fromBase58(xkey) {
|
||||
return new HDPrivateKey().fromBase58(xkey);
|
||||
HDPrivateKey.fromBase58 = function fromBase58(xkey, network) {
|
||||
return new HDPrivateKey().fromBase58(xkey, network);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -856,12 +860,13 @@ HDPrivateKey.prototype.toJSON = function toJSON() {
|
||||
* Inject properties from json object.
|
||||
* @private
|
||||
* @param {Object} json
|
||||
* @param {Network?} network
|
||||
*/
|
||||
|
||||
HDPrivateKey.prototype.fromJSON = function fromJSON(json) {
|
||||
HDPrivateKey.prototype.fromJSON = function fromJSON(json, network) {
|
||||
assert(json.xprivkey, 'Could not handle key JSON.');
|
||||
|
||||
this.fromBase58(json.xprivkey);
|
||||
this.fromBase58(json.xprivkey, network);
|
||||
|
||||
if (json.mnemonic)
|
||||
this.mnemonic = Mnemonic.fromJSON(json.mnemonic);
|
||||
@ -872,11 +877,12 @@ HDPrivateKey.prototype.fromJSON = function fromJSON(json) {
|
||||
/**
|
||||
* Instantiate an HDPrivateKey from a jsonified key object.
|
||||
* @param {Object} json - The jsonified key object.
|
||||
* @param {Network?} network
|
||||
* @returns {HDPrivateKey}
|
||||
*/
|
||||
|
||||
HDPrivateKey.fromJSON = function fromJSON(json) {
|
||||
return new HDPrivateKey().fromJSON(json);
|
||||
HDPrivateKey.fromJSON = function fromJSON(json, network) {
|
||||
return new HDPrivateKey().fromJSON(json, network);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -409,22 +409,24 @@ HDPublicKey.prototype.toJSON = function toJSON() {
|
||||
* Inject properties from json object.
|
||||
* @private
|
||||
* @param {Object} json
|
||||
* @param {Network?} network
|
||||
*/
|
||||
|
||||
HDPublicKey.prototype.fromJSON = function fromJSON(json) {
|
||||
HDPublicKey.prototype.fromJSON = function fromJSON(json, network) {
|
||||
assert(json.xpubkey, 'Could not handle HD key JSON.');
|
||||
this.fromBase58(json.xpubkey);
|
||||
this.fromBase58(json.xpubkey, network);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate an HDPrivateKey from a jsonified key object.
|
||||
* Instantiate an HDPublicKey from a jsonified key object.
|
||||
* @param {Object} json - The jsonified transaction object.
|
||||
* @param {Network?} network
|
||||
* @returns {HDPrivateKey}
|
||||
*/
|
||||
|
||||
HDPublicKey.fromJSON = function fromJSON(json) {
|
||||
return new HDPublicKey().fromJSON(json);
|
||||
HDPublicKey.fromJSON = function fromJSON(json, network) {
|
||||
return new HDPublicKey().fromJSON(json, network);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -477,11 +479,14 @@ HDPublicKey.isRaw = function isRaw(data) {
|
||||
* Inject properties from a base58 key.
|
||||
* @private
|
||||
* @param {Base58String} xkey
|
||||
* @param {Network?} network
|
||||
*/
|
||||
|
||||
HDPublicKey.prototype.fromBase58 = function fromBase58(xkey) {
|
||||
HDPublicKey.prototype.fromBase58 = function fromBase58(xkey, network) {
|
||||
this.fromRaw(base58.decode(xkey));
|
||||
this._xpubkey = xkey;
|
||||
if (network && !this.verifyNetwork(network))
|
||||
throw new Error('Network mismatch for HD public key.');
|
||||
return this;
|
||||
};
|
||||
|
||||
@ -581,11 +586,12 @@ HDPublicKey.prototype.toRaw = function toRaw(network) {
|
||||
/**
|
||||
* Instantiate an HD public key from a base58 string.
|
||||
* @param {Base58String} xkey
|
||||
* @param {Network?} network
|
||||
* @returns {HDPublicKey}
|
||||
*/
|
||||
|
||||
HDPublicKey.fromBase58 = function fromBase58(xkey) {
|
||||
return new HDPublicKey().fromBase58(xkey);
|
||||
HDPublicKey.fromBase58 = function fromBase58(xkey, network) {
|
||||
return new HDPublicKey().fromBase58(xkey, network);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -2055,7 +2055,7 @@ RPC.prototype._generatetoaddress = co(function* generatetoaddress(args, help) {
|
||||
throw new RPCError('generatetoaddress numblocks address ( maxtries )');
|
||||
|
||||
numblocks = toNumber(args[0], 1);
|
||||
address = Address.fromBase58(toString(args[1]));
|
||||
address = Address.fromBase58(toString(args[1]), this.network);
|
||||
|
||||
return yield this._generateBlocks(numblocks, address);
|
||||
});
|
||||
@ -2137,7 +2137,7 @@ RPC.prototype.createrawtransaction = co(function* createrawtransaction(args, hel
|
||||
continue;
|
||||
}
|
||||
|
||||
address = Address.fromBase58(key);
|
||||
address = Address.fromBase58(key, this.network);
|
||||
b58 = address.toBase58(this.network);
|
||||
|
||||
if (addrs[b58])
|
||||
@ -2270,7 +2270,7 @@ RPC.prototype._signrawtransaction = co(function* signrawtransaction(wallet, tx,
|
||||
if (typeof secret !== 'string')
|
||||
throw new RPCError('Invalid parameter');
|
||||
|
||||
key = KeyRing.fromSecret(secret);
|
||||
key = KeyRing.fromSecret(secret, this.network);
|
||||
keyMap[key.getPublicKey('hex')] = key;
|
||||
keys.push(key);
|
||||
}
|
||||
@ -2375,7 +2375,7 @@ RPC.prototype.fundrawtransaction = co(function* fundrawtransaction(args, help) {
|
||||
changeAddress = toString(options.changeAddress);
|
||||
|
||||
if (changeAddress)
|
||||
changeAddress = Address.fromBase58(changeAddress);
|
||||
changeAddress = Address.fromBase58(changeAddress, this.network);
|
||||
|
||||
feeRate = options.feeRate;
|
||||
|
||||
@ -2494,7 +2494,7 @@ RPC.prototype.validateaddress = co(function* validateaddress(args, help) {
|
||||
b58 = toString(args[0]);
|
||||
|
||||
try {
|
||||
address = Address.fromBase58(b58);
|
||||
address = Address.fromBase58(b58, this.network);
|
||||
} catch (e) {
|
||||
return {
|
||||
isvalid: false
|
||||
@ -2561,7 +2561,7 @@ RPC.prototype.signmessagewithprivkey = co(function* signmessagewithprivkey(args,
|
||||
key = toString(args[0]);
|
||||
msg = toString(args[1]);
|
||||
|
||||
key = KeyRing.fromSecret(key);
|
||||
key = KeyRing.fromSecret(key, this.network);
|
||||
msg = new Buffer(RPC.magic + msg, 'utf8');
|
||||
msg = crypto.hash256(msg);
|
||||
|
||||
@ -3242,7 +3242,7 @@ RPC.prototype.importprivkey = co(function* importprivkey(args, help) {
|
||||
if (rescan && this.chain.options.prune)
|
||||
throw new RPCError('Cannot rescan when pruned.');
|
||||
|
||||
key = KeyRing.fromSecret(secret);
|
||||
key = KeyRing.fromSecret(secret, this.network);
|
||||
|
||||
yield wallet.importKey(0, key);
|
||||
|
||||
@ -3291,7 +3291,7 @@ RPC.prototype.importwallet = co(function* importwallet(args, help) {
|
||||
if (parts.length < 4)
|
||||
throw new RPCError('Malformed wallet.');
|
||||
|
||||
secret = KeyRing.fromSecret(parts[0]);
|
||||
secret = KeyRing.fromSecret(parts[0], this.network);
|
||||
|
||||
time = +parts[1];
|
||||
label = parts[2];
|
||||
@ -3332,7 +3332,7 @@ RPC.prototype.importaddress = co(function* importaddress(args, help) {
|
||||
if (rescan && this.chain.options.prune)
|
||||
throw new RPCError('Cannot rescan when pruned.');
|
||||
|
||||
addr = Address.fromBase58(addr);
|
||||
addr = Address.fromBase58(addr, this.network);
|
||||
|
||||
yield wallet.importAddress(0, addr);
|
||||
|
||||
@ -3888,7 +3888,7 @@ RPC.prototype.sendfrom = co(function* sendfrom(args, help) {
|
||||
}
|
||||
|
||||
account = toString(args[0]);
|
||||
address = Address.fromBase58(toString(args[1]));
|
||||
address = Address.fromBase58(toString(args[1]), this.network);
|
||||
amount = toSatoshi(args[2]);
|
||||
|
||||
if (!account)
|
||||
@ -3940,7 +3940,7 @@ RPC.prototype.sendmany = co(function* sendmany(args, help) {
|
||||
for (i = 0; i < keys.length; i++) {
|
||||
key = keys[i];
|
||||
value = toSatoshi(sendTo[key]);
|
||||
address = Address.fromBase58(key);
|
||||
address = Address.fromBase58(key, this.network);
|
||||
hash = address.getHash('hex');
|
||||
|
||||
if (uniq[hash])
|
||||
@ -3976,7 +3976,7 @@ RPC.prototype.sendtoaddress = co(function* sendtoaddress(args, help) {
|
||||
+ ' subtractfeefromamount )');
|
||||
}
|
||||
|
||||
address = Address.fromBase58(toString(args[0]));
|
||||
address = Address.fromBase58(toString(args[0]), this.network);
|
||||
amount = toSatoshi(args[1]);
|
||||
subtractFee = toBool(args[4]);
|
||||
|
||||
|
||||
@ -345,7 +345,7 @@ HTTPServer.prototype._init = function _init() {
|
||||
if (params.accountKey) {
|
||||
enforce(typeof params.accountKey === 'string',
|
||||
'accountKey must be a string.');
|
||||
options.accountKey = HD.fromBase58(params.accountKey);
|
||||
options.accountKey = HD.fromBase58(params.accountKey, this.network);
|
||||
}
|
||||
|
||||
if (params.timeout != null) {
|
||||
@ -371,9 +371,7 @@ HTTPServer.prototype._init = function _init() {
|
||||
if (output.address) {
|
||||
enforce(typeof output.address === 'string',
|
||||
'Address must be a string.');
|
||||
output.address = Address.fromBase58(output.address);
|
||||
enforce(output.address.verifyNetwork(this.network),
|
||||
'Wrong network for address.');
|
||||
output.address = Address.fromBase58(output.address, this.network);
|
||||
} else if (output.script) {
|
||||
enforce(typeof output.script === 'string',
|
||||
'Script must be a string.');
|
||||
@ -396,13 +394,13 @@ HTTPServer.prototype._init = function _init() {
|
||||
for (i = 0; i < params.address.length; i++) {
|
||||
address = params.address[i];
|
||||
enforce(typeof address === 'string', 'Address must be a string.');
|
||||
address = Address.fromBase58(address);
|
||||
address = Address.fromBase58(address, this.network);
|
||||
options.address.push(address);
|
||||
}
|
||||
} else {
|
||||
enforce(typeof params.address === 'string',
|
||||
'Address must be a string.');
|
||||
options.address = Address.fromBase58(params.address);
|
||||
options.address = Address.fromBase58(params.address, this.network);
|
||||
}
|
||||
}
|
||||
|
||||
@ -439,7 +437,7 @@ HTTPServer.prototype._init = function _init() {
|
||||
|
||||
if (params.privateKey) {
|
||||
enforce(typeof params.privateKey === 'string', 'Key must be a string.');
|
||||
options.privateKey = KeyRing.fromSecret(params.privateKey);
|
||||
options.privateKey = KeyRing.fromSecret(params.privateKey, this.network);
|
||||
}
|
||||
|
||||
if (params.publicKey) {
|
||||
@ -450,7 +448,7 @@ HTTPServer.prototype._init = function _init() {
|
||||
|
||||
if (params.master) {
|
||||
enforce(typeof params.master === 'string', 'Key must be a string.');
|
||||
options.master = HD.fromBase58(params.master);
|
||||
options.master = HD.fromBase58(params.master, this.network);
|
||||
}
|
||||
|
||||
if (params.mnemonic) {
|
||||
|
||||
@ -284,23 +284,31 @@ Address.fromRaw = function fromRaw(data) {
|
||||
* Inject properties from base58 address.
|
||||
* @private
|
||||
* @param {Base58Address} data
|
||||
* @param {Network?} network
|
||||
* @throws Parse error
|
||||
*/
|
||||
|
||||
Address.prototype.fromBase58 = function fromBase58(data) {
|
||||
Address.prototype.fromBase58 = function fromBase58(data, network) {
|
||||
assert(typeof data === 'string');
|
||||
return this.fromRaw(base58.decode(data));
|
||||
|
||||
this.fromRaw(base58.decode(data));
|
||||
|
||||
if (network && !this.verifyNetwork(network))
|
||||
throw new Error('Network mismatch for address.');
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create an address object from a base58 address.
|
||||
* @param {Base58Address} address
|
||||
* @param {Network?} network
|
||||
* @returns {Address}
|
||||
* @throws Parse error.
|
||||
*/
|
||||
|
||||
Address.fromBase58 = function fromBase58(address) {
|
||||
return new Address().fromBase58(address);
|
||||
Address.fromBase58 = function fromBase58(address, network) {
|
||||
return new Address().fromBase58(address, network);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -323,9 +323,10 @@ KeyRing.prototype.toSecret = function toSecret() {
|
||||
* Inject properties from serialized CBitcoinSecret.
|
||||
* @private
|
||||
* @param {Base58String} secret
|
||||
* @param {Network?} network
|
||||
*/
|
||||
|
||||
KeyRing.prototype.fromSecret = function fromSecret(data) {
|
||||
KeyRing.prototype.fromSecret = function fromSecret(data, network) {
|
||||
var br = new BufferReader(base58.decode(data), true);
|
||||
var i, prefix, version, type, key, compressed;
|
||||
|
||||
@ -351,17 +352,23 @@ KeyRing.prototype.fromSecret = function fromSecret(data) {
|
||||
|
||||
br.verifyChecksum();
|
||||
|
||||
return this.fromPrivate(key, compressed, type);
|
||||
this.fromPrivate(key, compressed, type);
|
||||
|
||||
if (network && !this.verifyNetwork(network))
|
||||
throw new Error('Network mismatch for WIF.');
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Instantiate a keyring from a serialized CBitcoinSecret.
|
||||
* @param {Base58String} secret
|
||||
* @param {Network?} network
|
||||
* @returns {KeyRing}
|
||||
*/
|
||||
|
||||
KeyRing.fromSecret = function fromSecret(data) {
|
||||
return new KeyRing().fromSecret(data);
|
||||
KeyRing.fromSecret = function fromSecret(data, network) {
|
||||
return new KeyRing().fromSecret(data, network);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -280,7 +280,7 @@ Account.prototype.pushKey = function pushKey(key) {
|
||||
var index;
|
||||
|
||||
if (HD.isBase58(key))
|
||||
key = HD.fromBase58(key);
|
||||
key = HD.fromBase58(key, this.network);
|
||||
|
||||
assert(key.verifyNetwork(this.network),
|
||||
'Network mismatch for account key.');
|
||||
@ -320,7 +320,7 @@ Account.prototype.pushKey = function pushKey(key) {
|
||||
|
||||
Account.prototype.spliceKey = function spliceKey(key) {
|
||||
if (HD.isBase58(key))
|
||||
key = HD.fromBase58(key);
|
||||
key = HD.fromBase58(key, this.network);
|
||||
|
||||
assert(key.verifyNetwork(this.network),
|
||||
'Network mismatch for account key.');
|
||||
|
||||
@ -111,7 +111,7 @@ Wallet.prototype.fromOptions = function fromOptions(options) {
|
||||
key = HD.fromMnemonic(null, this.network);
|
||||
|
||||
if (HD.isBase58(key))
|
||||
key = HD.fromBase58(key);
|
||||
key = HD.fromBase58(key, this.network);
|
||||
|
||||
assert(HD.isPrivate(key),
|
||||
'Must create wallet with hd private key.');
|
||||
@ -697,7 +697,7 @@ Wallet.prototype._createAccount = co(function* createAccount(options, passphrase
|
||||
key = options.accountKey;
|
||||
|
||||
if (HD.isBase58(key))
|
||||
key = HD.fromBase58(key);
|
||||
key = HD.fromBase58(key, this.network);
|
||||
|
||||
if (!HD.isPublic(key))
|
||||
throw new Error('Must add HD public keys to watch only wallet.');
|
||||
|
||||
@ -106,11 +106,12 @@ WalletKey.fromScript = function fromScript(key, script, compressed, network) {
|
||||
/**
|
||||
* Instantiate a wallet key from a serialized CBitcoinSecret.
|
||||
* @param {Base58String} secret
|
||||
* @param {Network?} network
|
||||
* @returns {WalletKey}
|
||||
*/
|
||||
|
||||
WalletKey.fromSecret = function fromSecret(data) {
|
||||
return new WalletKey().fromSecret(data);
|
||||
WalletKey.fromSecret = function fromSecret(data, network) {
|
||||
return new WalletKey().fromSecret(data, network);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user